Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
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-platform
Commits
dc78a08c
Commit
dc78a08c
authored
Mar 18, 2013
by
Chris Dodge
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of github.com:MITx/mitx into fix/cdodge/add-500-404-templates-to-Studio
parents
651465f1
9a59336b
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
134 additions
and
68 deletions
+134
-68
cms/static/coffee/files.json
+9
-9
cms/xmodule_namespace.py
+16
-0
common/lib/xmodule/xmodule/combined_open_ended_module.py
+48
-35
common/templates/jasmine/base.html
+8
-3
lms/djangoapps/instructor/views.py
+6
-0
lms/static/coffee/files.json
+0
-3
lms/static/coffee/spec/calculator_spec.coffee
+12
-8
lms/static/coffee/spec/modules/tab_spec.coffee
+8
-3
lms/static/coffee/spec/navigation_spec.coffee
+0
-3
lms/xmodule_namespace.py
+27
-4
No files found.
cms/static/coffee/files.json
View file @
dc78a08c
{
"
js
_files"
:
[
"
/static/
js/vendor/RequireJS.js"
,
"
/static/
js/vendor/jquery.min.js"
,
"
/static/
js/vendor/jquery-ui.min.js"
,
"
/static/
js/vendor/jquery.ui.draggable.js"
,
"
/static/
js/vendor/jquery.cookie.js"
,
"
/static/
js/vendor/json2.js"
,
"
/static/
js/vendor/underscore-min.js"
,
"
/static/
js/vendor/backbone-min.js"
"
static
_files"
:
[
"js/vendor/RequireJS.js"
,
"js/vendor/jquery.min.js"
,
"js/vendor/jquery-ui.min.js"
,
"js/vendor/jquery.ui.draggable.js"
,
"js/vendor/jquery.cookie.js"
,
"js/vendor/json2.js"
,
"js/vendor/underscore-min.js"
,
"js/vendor/backbone-min.js"
]
}
cms/xmodule_namespace.py
View file @
dc78a08c
"""
Namespace defining common fields used by Studio for all blocks
"""
import
datetime
from
xblock.core
import
Namespace
,
Boolean
,
Scope
,
ModelType
,
String
class
StringyBoolean
(
Boolean
):
"""
Reads strings from JSON as booleans.
If the string is 'true' (case insensitive), then return True,
otherwise False.
JSON values that aren't strings are returned as is
"""
def
from_json
(
self
,
value
):
if
isinstance
(
value
,
basestring
):
return
value
.
lower
()
==
'true'
return
value
class
DateTuple
(
ModelType
):
"""
ModelType that stores datetime objects as time tuples
...
...
@@ -24,6 +37,9 @@ class DateTuple(ModelType):
class
CmsNamespace
(
Namespace
):
"""
Namespace with fields common to all blocks in Studio
"""
is_draft
=
Boolean
(
help
=
"Whether this module is a draft"
,
default
=
False
,
scope
=
Scope
.
settings
)
published_date
=
DateTuple
(
help
=
"Date when the module was published"
,
scope
=
Scope
.
settings
)
published_by
=
String
(
help
=
"Id of the user who published this module"
,
scope
=
Scope
.
settings
)
...
...
common/lib/xmodule/xmodule/combined_open_ended_module.py
View file @
dc78a08c
...
...
@@ -8,41 +8,66 @@ from xmodule.raw_module import RawDescriptor
from
.x_module
import
XModule
from
xblock.core
import
Integer
,
Scope
,
BlockScope
,
ModelType
,
String
,
Boolean
,
Object
,
Float
,
List
from
xmodule.open_ended_grading_classes.combined_open_ended_modulev1
import
CombinedOpenEndedV1Module
,
CombinedOpenEndedV1Descriptor
from
collections
import
namedtuple
log
=
logging
.
getLogger
(
"mitx.courseware"
)
V1_SETTINGS_ATTRIBUTES
=
[
"display_name"
,
"attempts"
,
"is_graded"
,
"accept_file_upload"
,
"skip_spelling_checks"
,
"due"
,
"graceperiod"
,
"max_score"
]
"skip_spelling_checks"
,
"due"
,
"graceperiod"
,
"max_score"
]
V1_STUDENT_ATTRIBUTES
=
[
"current_task_number"
,
"task_states"
,
"state"
,
"student_attempts"
,
"ready_to_reset"
]
"student_attempts"
,
"ready_to_reset"
]
V1_ATTRIBUTES
=
V1_SETTINGS_ATTRIBUTES
+
V1_STUDENT_ATTRIBUTES
VERSION_TUPLES
=
(
(
'1'
,
CombinedOpenEndedV1Descriptor
,
CombinedOpenEndedV1Module
,
V1_SETTINGS_ATTRIBUTES
,
V1_STUDENT_ATTRIBUTES
),
)
VersionTuple
=
namedtuple
(
'VersionTuple'
,
[
'descriptor'
,
'module'
,
'settings_attributes'
,
'student_attributes'
])
VERSION_TUPLES
=
{
1
:
VersionTuple
(
CombinedOpenEndedV1Descriptor
,
CombinedOpenEndedV1Module
,
V1_SETTINGS_ATTRIBUTES
,
V1_STUDENT_ATTRIBUTES
),
}
DEFAULT_VERSION
=
1
DEFAULT_VERSION
=
str
(
DEFAULT_VERSION
)
class
VersionInteger
(
Integer
):
"""
A model type that converts from strings to integers when reading from json.
Also does error checking to see if version is correct or not.
"""
def
from_json
(
self
,
value
):
try
:
value
=
int
(
value
)
if
value
not
in
VERSION_TUPLES
:
version_error_string
=
"Could not find version {0}, using version {1} instead"
log
.
error
(
version_error_string
.
format
(
value
,
DEFAULT_VERSION
))
value
=
DEFAULT_VERSION
except
:
value
=
DEFAULT_VERSION
return
value
class
CombinedOpenEndedFields
(
object
):
display_name
=
String
(
help
=
"Display name for this module"
,
default
=
"Open Ended Grading"
,
scope
=
Scope
.
settings
)
current_task_number
=
Integer
(
help
=
"Current task that the student is on."
,
default
=
0
,
scope
=
Scope
.
student_state
)
task_states
=
List
(
help
=
"List of state dictionaries of each task within this module."
,
scope
=
Scope
.
student_state
)
state
=
String
(
help
=
"Which step within the current task that the student is on."
,
default
=
"initial"
,
scope
=
Scope
.
student_state
)
student_attempts
=
Integer
(
help
=
"Number of attempts taken by the student on this problem"
,
default
=
0
,
scope
=
Scope
.
student_state
)
ready_to_reset
=
Boolean
(
help
=
"If the problem is ready to be reset or not."
,
default
=
False
,
scope
=
Scope
.
student_state
)
state
=
String
(
help
=
"Which step within the current task that the student is on."
,
default
=
"initial"
,
scope
=
Scope
.
student_state
)
student_attempts
=
Integer
(
help
=
"Number of attempts taken by the student on this problem"
,
default
=
0
,
scope
=
Scope
.
student_state
)
ready_to_reset
=
Boolean
(
help
=
"If the problem is ready to be reset or not."
,
default
=
False
,
scope
=
Scope
.
student_state
)
attempts
=
Integer
(
help
=
"Maximum number of attempts that a student is allowed."
,
default
=
1
,
scope
=
Scope
.
settings
)
is_graded
=
Boolean
(
help
=
"Whether or not the problem is graded."
,
default
=
False
,
scope
=
Scope
.
settings
)
accept_file_upload
=
Boolean
(
help
=
"Whether or not the problem accepts file uploads."
,
default
=
False
,
scope
=
Scope
.
settings
)
skip_spelling_checks
=
Boolean
(
help
=
"Whether or not to skip initial spelling checks."
,
default
=
True
,
scope
=
Scope
.
settings
)
is_graded
=
Boolean
(
help
=
"Whether or not the problem is graded."
,
default
=
False
,
scope
=
Scope
.
settings
)
accept_file_upload
=
Boolean
(
help
=
"Whether or not the problem accepts file uploads."
,
default
=
False
,
scope
=
Scope
.
settings
)
skip_spelling_checks
=
Boolean
(
help
=
"Whether or not to skip initial spelling checks."
,
default
=
True
,
scope
=
Scope
.
settings
)
due
=
String
(
help
=
"Date that this problem is due by"
,
default
=
None
,
scope
=
Scope
.
settings
)
graceperiod
=
String
(
help
=
"Amount of time after the due date that submissions will be accepted"
,
default
=
None
,
scope
=
Scope
.
settings
)
graceperiod
=
String
(
help
=
"Amount of time after the due date that submissions will be accepted"
,
default
=
None
,
scope
=
Scope
.
settings
)
max_score
=
Integer
(
help
=
"Maximum score for the problem."
,
default
=
1
,
scope
=
Scope
.
settings
)
version
=
Integer
(
help
=
"Current version number"
,
default
=
DEFAULT_VERSION
,
scope
=
Scope
.
settings
)
version
=
Version
Integer
(
help
=
"Current version number"
,
default
=
DEFAULT_VERSION
,
scope
=
Scope
.
settings
)
data
=
String
(
help
=
"XML data for the problem"
,
scope
=
Scope
.
content
)
...
...
@@ -130,23 +155,10 @@ class CombinedOpenEndedModule(CombinedOpenEndedFields, XModule):
if
self
.
task_states
is
None
:
self
.
task_states
=
[]
versions
=
[
i
[
0
]
for
i
in
VERSION_TUPLES
]
descriptors
=
[
i
[
1
]
for
i
in
VERSION_TUPLES
]
modules
=
[
i
[
2
]
for
i
in
VERSION_TUPLES
]
settings_attributes
=
[
i
[
3
]
for
i
in
VERSION_TUPLES
]
student_attributes
=
[
i
[
4
]
for
i
in
VERSION_TUPLES
]
version_error_string
=
"Could not find version {0}, using version {1} instead"
try
:
version_index
=
versions
.
index
(
self
.
version
)
except
:
#This is a dev_facing_error
log
.
error
(
version_error_string
.
format
(
self
.
version
,
DEFAULT_VERSION
))
self
.
version
=
DEFAULT_VERSION
version_index
=
versions
.
index
(
self
.
version
)
version_tuple
=
VERSION_TUPLES
[
self
.
version
]
self
.
student_attributes
=
student_attributes
[
version_index
]
self
.
settings_attributes
=
settings_attributes
[
version_index
]
self
.
student_attributes
=
version_tuple
.
student_attributes
self
.
settings_attributes
=
version_tuple
.
settings_attributes
attributes
=
self
.
student_attributes
+
self
.
settings_attributes
...
...
@@ -154,10 +166,11 @@ class CombinedOpenEndedModule(CombinedOpenEndedFields, XModule):
'rewrite_content_links'
:
self
.
rewrite_content_links
,
}
instance_state
=
{
k
:
getattr
(
self
,
k
)
for
k
in
attributes
}
self
.
child_descriptor
=
descriptors
[
version_index
](
self
.
system
)
self
.
child_definition
=
descriptors
[
version_index
]
.
definition_from_xml
(
etree
.
fromstring
(
self
.
data
),
self
.
system
)
self
.
child_module
=
modules
[
version_index
](
self
.
system
,
location
,
self
.
child_definition
,
self
.
child_descriptor
,
instance_state
=
instance_state
,
static_data
=
static_data
,
attributes
=
attributes
)
self
.
child_descriptor
=
version_tuple
.
descriptor
(
self
.
system
)
self
.
child_definition
=
version_tuple
.
descriptor
.
definition_from_xml
(
etree
.
fromstring
(
self
.
data
),
self
.
system
)
self
.
child_module
=
version_tuple
.
module
(
self
.
system
,
location
,
self
.
child_definition
,
self
.
child_descriptor
,
instance_state
=
instance_state
,
static_data
=
static_data
,
attributes
=
attributes
)
self
.
save_instance_data
()
def
get_html
(
self
):
...
...
common/templates/jasmine/base.html
View file @
dc78a08c
...
...
@@ -13,14 +13,19 @@
<script
src=
"{% static 'js/vendor/jasmine-jquery.js' %}"
></script>
<script
src=
"{% static 'console-runner.js' %}"
></script>
{% load compressed %}
{# static files #}
{% for url in suite.static_files %}
<script
src=
"{{ STATIC_URL }}{{ url }}"
></script>
{% endfor %}
{% compressed_js 'js-test-source' %}
{# source files #}
{% for url in suite.js_files %}
<script
src=
"{{ url }}"
></script>
{% endfor %}
{% load compressed %}
{# static files #}
{% compressed_js 'js-test-source' %}
{# spec files #}
{% compressed_js 'spec' %}
...
...
lms/djangoapps/instructor/views.py
View file @
dc78a08c
...
...
@@ -92,9 +92,15 @@ def instructor_dashboard(request, course_id):
data
+=
compute_course_stats
(
course
)
.
items
()
if
request
.
user
.
is_staff
:
for
field
in
course
.
fields
:
if
getattr
(
field
.
scope
,
'student'
,
False
):
continue
data
.
append
([
field
.
name
,
json
.
dumps
(
field
.
read_json
(
course
))])
for
namespace
in
course
.
namespaces
:
for
field
in
getattr
(
course
,
namespace
)
.
fields
:
if
getattr
(
field
.
scope
,
'student'
,
False
):
continue
data
.
append
([
"{}.{}"
.
format
(
namespace
,
field
.
name
),
json
.
dumps
(
field
.
read_json
(
course
))])
datatable
[
'data'
]
=
data
...
...
lms/static/coffee/files.json
View file @
dc78a08c
...
...
@@ -5,8 +5,5 @@
"/static/js/vendor/jquery-ui.min.js"
,
"/static/js/vendor/jquery.leanModal.min.js"
,
"/static/js/vendor/flot/jquery.flot.js"
],
"static_files"
:
[
"js/application.js"
]
}
lms/static/coffee/spec/calculator_spec.coffee
View file @
dc78a08c
...
...
@@ -4,9 +4,6 @@ describe 'Calculator', ->
@
calculator
=
new
Calculator
describe
'bind'
,
->
beforeEach
->
Calculator
.
bind
()
it
'bind the calculator button'
,
->
expect
(
$
(
'.calc'
)).
toHandleWith
'click'
,
@
calculator
.
toggle
...
...
@@ -31,12 +28,19 @@ describe 'Calculator', ->
$
(
'form#calculator'
).
submit
()
describe
'toggle'
,
->
it
'toggle the calculator and focus the input'
,
->
spyOn
$
.
fn
,
'focus'
@
calculator
.
toggle
(
jQuery
.
Event
(
"click"
))
it
'focuses the input when toggled'
,
->
# Since the focus is called asynchronously, we need to
# wait until focus() is called.
didFocus
=
false
runs
->
spyOn
(
$
.
fn
,
'focus'
).
andCallFake
(
elementName
)
->
didFocus
=
true
@
calculator
.
toggle
(
jQuery
.
Event
(
"click"
))
waitsFor
(
->
didFocus
),
"focus() should have been called on the input"
,
1000
expect
(
$
(
'li.calc-main'
)).
toHaveClass
(
'open'
)
expect
(
$
(
'#calculator_wrapper #calculator_input'
).
focus
).
toHaveBeenCalled
()
runs
->
expect
(
$
(
'#calculator_wrapper #calculator_input'
).
focus
).
toHaveBeenCalled
()
it
'toggle the close button on the calculator button'
,
->
@
calculator
.
toggle
(
jQuery
.
Event
(
"click"
))
...
...
lms/static/coffee/spec/modules/tab_spec.coffee
View file @
dc78a08c
...
...
@@ -22,18 +22,23 @@ describe 'Tab', ->
it
'bind the tabs'
,
->
expect
(
$
.
fn
.
tabs
).
toHaveBeenCalledWith
show
:
@
tab
.
onShow
# As of jQuery 1.9, the onShow callback is deprecated
# http://jqueryui.com/upgrade-guide/1.9/#deprecated-show-event-renamed-to-activate
# The code below tests that onShow does what is expected,
# but note that onShow will NOT be called when the user
# clicks on the tab if we're using jQuery version >= 1.9
describe
'onShow'
,
->
beforeEach
->
@
tab
=
new
Tab
1
,
@
items
$
(
'[href="#tab-1-0"]'
).
click
(
)
@
tab
.
onShow
(
$
(
'#tab-1-0'
),
{
'index'
:
1
}
)
it
'replace content in the container'
,
->
$
(
'[href="#tab-1-1"]'
).
click
(
)
@
tab
.
onShow
(
$
(
'#tab-1-1'
),
{
'index'
:
1
}
)
expect
(
$
(
'#tab-1-0'
).
html
()).
toEqual
''
expect
(
$
(
'#tab-1-1'
).
html
()).
toEqual
'Video 2'
expect
(
$
(
'#tab-1-2'
).
html
()).
toEqual
''
it
'trigger contentChanged event on the element'
,
->
spyOnEvent
@
tab
.
el
,
'contentChanged'
$
(
'[href="#tab-1-1"]'
).
click
(
)
@
tab
.
onShow
(
$
(
'#tab-1-1'
),
{
'index'
:
1
}
)
expect
(
'contentChanged'
).
toHaveBeenTriggeredOn
@
tab
.
el
lms/static/coffee/spec/navigation_spec.coffee
View file @
dc78a08c
...
...
@@ -32,11 +32,9 @@ describe 'Navigation', ->
heightStyle
:
'content'
it
'binds the accordionchange event'
,
->
Navigation
.
bind
()
expect
(
$
(
'#accordion'
)).
toHandleWith
'accordionchange'
,
@
navigation
.
log
it
'bind the navigation toggle'
,
->
Navigation
.
bind
()
expect
(
$
(
'#open_close_accordion a'
)).
toHandleWith
'click'
,
@
navigation
.
toggle
describe
'when the #accordion does not exists'
,
->
...
...
@@ -45,7 +43,6 @@ describe 'Navigation', ->
it
'does not activate the accordion'
,
->
spyOn
$
.
fn
,
'accordion'
Navigation
.
bind
()
expect
(
$
(
'#accordion'
).
accordion
).
wasNotCalled
()
describe
'toggle'
,
->
...
...
lms/xmodule_namespace.py
View file @
dc78a08c
from
xblock.core
import
Namespace
,
Boolean
,
Scope
,
String
,
List
,
Float
"""
Namespace that defines fields common to all blocks used in the LMS
"""
from
xblock.core
import
Namespace
,
Boolean
,
Scope
,
String
,
Float
from
xmodule.fields
import
Date
,
Timedelta
class
StringyBoolean
(
Boolean
):
"""
Reads strings from JSON as booleans.
'true' (case insensitive) return True, other strings return False
Other types are returned unchanged
"""
def
from_json
(
self
,
value
):
if
isinstance
(
value
,
basestring
):
return
value
.
lower
()
==
'true'
return
value
class
StringyFloat
(
Float
):
"""
Reads values as floats. If the value parses as a float, returns
that, otherwise returns None
"""
def
from_json
(
self
,
value
):
try
:
return
float
(
value
)
...
...
@@ -17,6 +31,9 @@ class StringyFloat(Float):
class
LmsNamespace
(
Namespace
):
"""
Namespace that defines fields common to all blocks used in the LMS
"""
hide_from_toc
=
StringyBoolean
(
help
=
"Whether to display this module in the table of contents"
,
default
=
False
,
...
...
@@ -38,8 +55,14 @@ class LmsNamespace(Namespace):
source_file
=
String
(
help
=
"DO NOT USE"
,
scope
=
Scope
.
settings
)
xqa_key
=
String
(
help
=
"DO NOT USE"
,
scope
=
Scope
.
settings
)
ispublic
=
Boolean
(
help
=
"Whether this course is open to the public, or only to admins"
,
scope
=
Scope
.
settings
)
graceperiod
=
Timedelta
(
help
=
"Amount of time after the due date that submissions will be accepted"
,
scope
=
Scope
.
settings
)
graceperiod
=
Timedelta
(
help
=
"Amount of time after the due date that submissions will be accepted"
,
scope
=
Scope
.
settings
)
showanswer
=
String
(
help
=
"When to show the problem answer to the student"
,
scope
=
Scope
.
settings
,
default
=
"closed"
)
rerandomize
=
String
(
help
=
"When to rerandomize the problem"
,
default
=
"always"
,
scope
=
Scope
.
settings
)
days_early_for_beta
=
StringyFloat
(
help
=
"Number of days early to show content to beta users"
,
default
=
None
,
scope
=
Scope
.
settings
)
days_early_for_beta
=
StringyFloat
(
help
=
"Number of days early to show content to beta users"
,
default
=
None
,
scope
=
Scope
.
settings
)
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