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
a789d6c3
Commit
a789d6c3
authored
Feb 20, 2013
by
Diana Huang
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' into diana/fix-self-assessment-test
parents
6e453c2b
789db301
Show whitespace changes
Inline
Side-by-side
Showing
28 changed files
with
306 additions
and
275 deletions
+306
-275
common/lib/xmodule/xmodule/combined_open_ended_module.py
+1
-13
common/lib/xmodule/xmodule/open_ended_grading_classes/__init__.py
+1
-0
common/lib/xmodule/xmodule/open_ended_grading_classes/combined_open_ended_modulev1.py
+21
-53
common/lib/xmodule/xmodule/open_ended_grading_classes/combined_open_ended_rubric.py
+0
-0
common/lib/xmodule/xmodule/open_ended_grading_classes/grading_service_module.py
+1
-3
common/lib/xmodule/xmodule/open_ended_grading_classes/open_ended_image_submission.py
+3
-8
common/lib/xmodule/xmodule/open_ended_grading_classes/open_ended_module.py
+7
-21
common/lib/xmodule/xmodule/open_ended_grading_classes/openendedchild.py
+10
-10
common/lib/xmodule/xmodule/open_ended_grading_classes/peer_grading_service.py
+3
-34
common/lib/xmodule/xmodule/open_ended_grading_classes/self_assessment_module.py
+6
-22
common/lib/xmodule/xmodule/peer_grading_module.py
+84
-29
common/lib/xmodule/xmodule/tests/test_combined_open_ended.py
+15
-4
common/lib/xmodule/xmodule/tests/test_self_assessment.py
+6
-2
common/lib/xmodule/xmodule/tests/test_util_open_ended.py
+15
-0
common/lib/xmodule/xmodule/timeinfo.py
+39
-0
common/lib/xmodule/xmodule/x_module.py
+5
-1
lms/djangoapps/courseware/module_render.py
+26
-0
lms/djangoapps/open_ended_grading/controller_query_service.py
+3
-7
lms/djangoapps/open_ended_grading/open_ended_notifications.py
+4
-7
lms/djangoapps/open_ended_grading/open_ended_util.py
+0
-13
lms/djangoapps/open_ended_grading/staff_grading_service.py
+4
-5
lms/djangoapps/open_ended_grading/tests.py
+8
-3
lms/djangoapps/open_ended_grading/views.py
+2
-6
lms/envs/aws.py
+1
-4
lms/envs/common.py
+9
-16
lms/envs/dev.py
+10
-14
lms/templates/peer_grading/peer_grading.html
+12
-0
lms/templates/peer_grading/peer_grading_closed.html
+10
-0
No files found.
common/lib/xmodule/xmodule/combined_open_ended_module.py
View file @
a789d6c3
import
copy
from
fs.errors
import
ResourceNotFoundError
import
itertools
import
json
import
logging
from
lxml
import
etree
from
lxml.html
import
rewrite_links
from
path
import
path
import
os
import
sys
from
pkg_resources
import
resource_string
from
.capa_module
import
only_one
,
ComplexEncoder
from
.editing_module
import
EditingDescriptor
from
.html_checker
import
check_html
from
progress
import
Progress
from
.stringify
import
stringify_children
from
.x_module
import
XModule
from
.xml_module
import
XmlDescriptor
from
xmodule.modulestore
import
Location
from
combined_open_ended_modulev1
import
CombinedOpenEndedV1Module
,
CombinedOpenEndedV1Descriptor
from
xmodule.open_ended_grading_classes.combined_open_ended_modulev1
import
CombinedOpenEndedV1Module
,
CombinedOpenEndedV1Descriptor
log
=
logging
.
getLogger
(
"mitx.courseware"
)
...
...
common/lib/xmodule/xmodule/open_ended_grading_classes/__init__.py
0 → 100644
View file @
a789d6c3
__author__
=
'vik'
common/lib/xmodule/xmodule/combined_open_ended_modulev1.py
→
common/lib/xmodule/xmodule/
open_ended_grading_classes/
combined_open_ended_modulev1.py
View file @
a789d6c3
import
copy
from
fs.errors
import
ResourceNotFoundError
import
itertools
import
json
import
logging
from
lxml
import
etree
from
lxml.html
import
rewrite_links
from
path
import
path
import
os
import
sys
import
re
from
pkg_resources
import
resource_string
from
.capa_module
import
only_one
,
ComplexEncoder
from
.editing_module
import
EditingDescriptor
from
.html_checker
import
check_html
from
progress
import
Progress
from
.stringify
import
stringify_children
from
.x_module
import
XModule
from
.xml_module
import
XmlDescriptor
from
xmodule.modulestore
import
Location
from
xmodule.timeinfo
import
TimeInfo
from
xmodule.capa_module
import
only_one
,
ComplexEncoder
from
xmodule.editing_module
import
EditingDescriptor
from
xmodule.html_checker
import
check_html
from
xmodule.progress
import
Progress
from
xmodule.stringify
import
stringify_children
from
xmodule.x_module
import
XModule
from
xmodule.xml_module
import
XmlDescriptor
import
self_assessment_module
import
open_ended_module
from
combined_open_ended_rubric
import
CombinedOpenEndedRubric
,
RubricParsingError
,
GRADER_TYPE_IMAGE_DICT
,
HUMAN_GRADER_TYPE
,
LEGEND_LIST
from
.stringify
import
stringify_children
import
dateutil
import
dateutil.parser
import
datetime
from
timeparse
import
parse_timedelta
from
combined_open_ended_rubric
import
CombinedOpenEndedRubric
,
GRADER_TYPE_IMAGE_DICT
,
HUMAN_GRADER_TYPE
,
LEGEND_LIST
log
=
logging
.
getLogger
(
"mitx.courseware"
)
...
...
@@ -59,6 +44,10 @@ HUMAN_TASK_TYPE = {
'openended'
:
"edX Assessment"
,
}
#Default value that controls whether or not to skip basic spelling checks in the controller
#Metadata overrides this
SKIP_BASIC_CHECKS
=
False
class
CombinedOpenEndedV1Module
():
"""
This is a module that encapsulates all open ended grading (self assessment, peer assessment, etc).
...
...
@@ -73,7 +62,7 @@ class CombinedOpenEndedV1Module():
'save_assessment' -- Saves the student assessment (or external grader assessment)
'save_post_assessment' -- saves a post assessment (hint, feedback on feedback, etc)
ajax actions implemented by combined open ended module are:
'reset' -- resets the whole combined open ended module and returns to the first child module
'reset' -- resets the whole combined open ended module and returns to the first child module
resource_string
'next_problem' -- moves to the next child module
'get_results' -- gets results from a given child module
...
...
@@ -90,14 +79,6 @@ class CombinedOpenEndedV1Module():
INTERMEDIATE_DONE
=
'intermediate_done'
DONE
=
'done'
js
=
{
'coffee'
:
[
resource_string
(
__name__
,
'js/src/combinedopenended/display.coffee'
),
resource_string
(
__name__
,
'js/src/collapsible.coffee'
),
resource_string
(
__name__
,
'js/src/javascript_loader.coffee'
),
]}
js_module_name
=
"CombinedOpenEnded"
css
=
{
'scss'
:
[
resource_string
(
__name__
,
'css/combinedopenended/display.scss'
)]}
def
__init__
(
self
,
system
,
location
,
definition
,
descriptor
,
instance_state
=
None
,
shared_state
=
None
,
metadata
=
None
,
static_data
=
None
,
**
kwargs
):
...
...
@@ -165,28 +146,16 @@ class CombinedOpenEndedV1Module():
self
.
max_attempts
=
int
(
self
.
metadata
.
get
(
'attempts'
,
MAX_ATTEMPTS
))
self
.
is_scored
=
self
.
metadata
.
get
(
'is_graded'
,
IS_SCORED
)
in
TRUE_DICT
self
.
accept_file_upload
=
self
.
metadata
.
get
(
'accept_file_upload'
,
ACCEPT_FILE_UPLOAD
)
in
TRUE_DICT
self
.
skip_basic_checks
=
self
.
metadata
.
get
(
'skip_spelling_checks'
,
SKIP_BASIC_CHECKS
)
display_due_date_string
=
self
.
metadata
.
get
(
'due'
,
None
)
if
display_due_date_string
is
not
None
:
try
:
self
.
display_due_date
=
dateutil
.
parser
.
parse
(
display_due_date_string
)
except
ValueError
:
log
.
error
(
"Could not parse due date {0} for location {1}"
.
format
(
display_due_date_string
,
location
))
raise
else
:
self
.
display_due_date
=
None
grace_period_string
=
self
.
metadata
.
get
(
'graceperiod'
,
None
)
if
grace_period_string
is
not
None
and
self
.
display_due_date
:
try
:
self
.
grace_period
=
parse_timedelta
(
grace_period_string
)
self
.
close_date
=
self
.
display_due_date
+
self
.
grace_period
self
.
timeinfo
=
TimeInfo
(
display_due_date_string
,
grace_period_string
)
except
:
log
.
error
(
"Error parsing the grace period {0} for location {1}"
.
format
(
grace_period_string
,
location
))
log
.
error
(
"Error parsing due date information in location {0}"
.
format
(
location
))
raise
else
:
self
.
grace_period
=
None
self
.
close_date
=
self
.
display_due_date
self
.
display_due_date
=
self
.
timeinfo
.
display_due_date
# Used for progress / grading. Currently get credit just for
# completion (doesn't matter if you self-assessed correct/incorrect).
...
...
@@ -204,7 +173,9 @@ class CombinedOpenEndedV1Module():
'rubric'
:
definition
[
'rubric'
],
'display_name'
:
self
.
display_name
,
'accept_file_upload'
:
self
.
accept_file_upload
,
'close_date'
:
self
.
close_date
,
'close_date'
:
self
.
timeinfo
.
close_date
,
's3_interface'
:
self
.
system
.
s3_interface
,
'skip_basic_checks'
:
self
.
skip_basic_checks
,
}
self
.
task_xml
=
definition
[
'task_xml'
]
...
...
@@ -798,9 +769,6 @@ class CombinedOpenEndedV1Descriptor(XmlDescriptor, EditingDescriptor):
has_score
=
True
template_dir_name
=
"combinedopenended"
js
=
{
'coffee'
:
[
resource_string
(
__name__
,
'js/src/html/edit.coffee'
)]}
js_module_name
=
"HTMLEditingDescriptor"
@classmethod
def
definition_from_xml
(
cls
,
xml_object
,
system
):
"""
...
...
common/lib/xmodule/xmodule/combined_open_ended_rubric.py
→
common/lib/xmodule/xmodule/
open_ended_grading_classes/
combined_open_ended_rubric.py
View file @
a789d6c3
File moved
common/lib/xmodule/xmodule/grading_service_module.py
→
common/lib/xmodule/xmodule/
open_ended_grading_classes/
grading_service_module.py
View file @
a789d6c3
...
...
@@ -5,7 +5,7 @@ import requests
from
requests.exceptions
import
RequestException
,
ConnectionError
,
HTTPError
import
sys
from
xmodule.combined_open_ended_rubric
import
CombinedOpenEndedRubric
,
RubricParsingError
from
combined_open_ended_rubric
import
CombinedOpenEndedRubric
from
lxml
import
etree
log
=
logging
.
getLogger
(
__name__
)
...
...
@@ -22,8 +22,6 @@ class GradingService(object):
def
__init__
(
self
,
config
):
self
.
username
=
config
[
'username'
]
self
.
password
=
config
[
'password'
]
self
.
url
=
config
[
'url'
]
self
.
login_url
=
self
.
url
+
'/login/'
self
.
session
=
requests
.
session
()
self
.
system
=
config
[
'system'
]
...
...
common/lib/xmodule/xmodule/open_ended_image_submission.py
→
common/lib/xmodule/xmodule/open_ended_
grading_classes/open_ended_
image_submission.py
View file @
a789d6c3
...
...
@@ -13,11 +13,6 @@ from urlparse import urlparse
import
requests
from
boto.s3.connection
import
S3Connection
from
boto.s3.key
import
Key
#TODO: Settings import is needed now in order to specify the URL and keys for amazon s3 (to upload images).
#Eventually, the goal is to replace the global django settings import with settings specifically
#for this module. There is no easy way to do this now, so piggybacking on the django settings
#makes sense.
from
django.conf
import
settings
import
pickle
import
logging
import
re
...
...
@@ -221,7 +216,7 @@ def run_image_tests(image):
return
success
def
upload_to_s3
(
file_to_upload
,
keyname
):
def
upload_to_s3
(
file_to_upload
,
keyname
,
s3_interface
):
'''
Upload file to S3 using provided keyname.
...
...
@@ -237,8 +232,8 @@ def upload_to_s3(file_to_upload, keyname):
#im.save(out_im, 'PNG')
try
:
conn
=
S3Connection
(
s
ettings
.
AWS_ACCESS_KEY_ID
,
settings
.
AWS_SECRET_ACCESS_KEY
)
bucketname
=
str
(
s
ettings
.
AWS_STORAGE_BUCKET_NAME
)
conn
=
S3Connection
(
s
3_interface
[
'access_key'
],
s3_interface
[
'secret_access_key'
]
)
bucketname
=
str
(
s
3_interface
[
'storage_bucket_name'
]
)
bucket
=
conn
.
create_bucket
(
bucketname
.
lower
())
k
=
Key
(
bucket
)
...
...
common/lib/xmodule/xmodule/open_ended_module.py
→
common/lib/xmodule/xmodule/open_ended_
grading_classes/open_ended_
module.py
View file @
a789d6c3
...
...
@@ -5,28 +5,16 @@ hints, answers, and assessment judgment (currently only correct/incorrect).
Parses xml definition file--see below for exact format.
"""
import
copy
from
fs.errors
import
ResourceNotFoundError
import
itertools
import
json
import
logging
from
lxml
import
etree
from
lxml.html
import
rewrite_links
from
path
import
path
import
os
import
sys
import
hashlib
import
capa.xqueue_interface
as
xqueue_interface
from
pkg_resources
import
resource_string
from
.capa_module
import
only_one
,
ComplexEncoder
from
.editing_module
import
EditingDescriptor
from
.html_checker
import
check_html
from
progress
import
Progress
from
.stringify
import
stringify_children
from
.xml_module
import
XmlDescriptor
from
xmodule.modulestore
import
Location
from
xmodule.capa_module
import
ComplexEncoder
from
xmodule.editing_module
import
EditingDescriptor
from
xmodule.progress
import
Progress
from
xmodule.stringify
import
stringify_children
from
xmodule.xml_module
import
XmlDescriptor
from
capa.util
import
*
import
openendedchild
...
...
@@ -122,7 +110,8 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
'rubric'
:
rubric_string
,
'initial_display'
:
self
.
initial_display
,
'answer'
:
self
.
answer
,
'problem_id'
:
self
.
display_name
'problem_id'
:
self
.
display_name
,
'skip_basic_checks'
:
self
.
skip_basic_checks
,
})
updated_grader_payload
=
json
.
dumps
(
parsed_grader_payload
)
...
...
@@ -689,9 +678,6 @@ class OpenEndedDescriptor(XmlDescriptor, EditingDescriptor):
has_score
=
True
template_dir_name
=
"openended"
js
=
{
'coffee'
:
[
resource_string
(
__name__
,
'js/src/html/edit.coffee'
)]}
js_module_name
=
"HTMLEditingDescriptor"
@classmethod
def
definition_from_xml
(
cls
,
xml_object
,
system
):
"""
...
...
common/lib/xmodule/xmodule/openendedchild.py
→
common/lib/xmodule/xmodule/open
_ended_grading_classes/open
endedchild.py
View file @
a789d6c3
...
...
@@ -13,17 +13,15 @@ import hashlib
import
capa.xqueue_interface
as
xqueue_interface
import
re
from
pkg_resources
import
resource_string
from
.capa_module
import
only_one
,
ComplexEncoder
from
.editing_module
import
EditingDescriptor
from
.html_checker
import
check_html
from
progress
import
Progress
from
.stringify
import
stringify_children
from
.xml_module
import
XmlDescriptor
from
xmodule.capa_module
import
only_one
,
ComplexEncoder
import
open_ended_image_submission
from
xmodule.editing_module
import
EditingDescriptor
from
xmodule.html_checker
import
check_html
from
xmodule.progress
import
Progress
from
xmodule.stringify
import
stringify_children
from
xmodule.xml_module
import
XmlDescriptor
from
xmodule.modulestore
import
Location
from
capa.util
import
*
import
open_ended_image_submission
from
datetime
import
datetime
...
...
@@ -100,6 +98,8 @@ class OpenEndedChild(object):
self
.
display_name
=
static_data
[
'display_name'
]
self
.
accept_file_upload
=
static_data
[
'accept_file_upload'
]
self
.
close_date
=
static_data
[
'close_date'
]
self
.
s3_interface
=
static_data
[
's3_interface'
]
self
.
skip_basic_checks
=
static_data
[
'skip_basic_checks'
]
# Used for progress / grading. Currently get credit just for
# completion (doesn't matter if you self-assessed correct/incorrect).
...
...
@@ -319,7 +319,7 @@ class OpenEndedChild(object):
try
:
image_data
.
seek
(
0
)
success
,
s3_public_url
=
open_ended_image_submission
.
upload_to_s3
(
image_data
,
image_key
)
success
,
s3_public_url
=
open_ended_image_submission
.
upload_to_s3
(
image_data
,
image_key
,
self
.
s3_interface
)
except
:
log
.
exception
(
"Could not upload image to S3."
)
...
...
common/lib/xmodule/xmodule/peer_grading_service.py
→
common/lib/xmodule/xmodule/
open_ended_grading_classes/
peer_grading_service.py
View file @
a789d6c3
import
json
import
logging
import
requests
from
requests.exceptions
import
RequestException
,
ConnectionError
,
HTTPError
import
sys
#TODO: Settings import is needed now in order to specify the URL where to find the peer grading service.
#Eventually, the goal is to replace the global django settings import with settings specifically
#for this xmodule. There is no easy way to do this now, so piggybacking on the django settings
#makes sense.
from
django.conf
import
settings
from
combined_open_ended_rubric
import
CombinedOpenEndedRubric
,
RubricParsingError
from
lxml
import
etree
from
grading_service_module
import
GradingService
,
GradingServiceError
from
grading_service_module
import
GradingService
log
=
logging
.
getLogger
(
__name__
)
...
...
@@ -28,6 +17,8 @@ class PeerGradingService(GradingService):
def
__init__
(
self
,
config
,
system
):
config
[
'system'
]
=
system
super
(
PeerGradingService
,
self
)
.
__init__
(
config
)
self
.
url
=
config
[
'url'
]
+
config
[
'peer_grading'
]
self
.
login_url
=
self
.
url
+
'/login/'
self
.
get_next_submission_url
=
self
.
url
+
'/get_next_submission/'
self
.
save_grade_url
=
self
.
url
+
'/save_grade/'
self
.
is_student_calibrated_url
=
self
.
url
+
'/is_student_calibrated/'
...
...
@@ -143,25 +134,3 @@ class MockPeerGradingService(object):
json
.
dumps
({
'location'
:
'i4x://MITx/3.091x/problem/open_ended_demo2'
,
'problem_name'
:
"Problem 2"
,
'num_graded'
:
1
,
'num_pending'
:
5
})
]})
_service
=
None
def
peer_grading_service
(
system
):
"""
Return a peer grading service instance--if settings.MOCK_PEER_GRADING is True,
returns a mock one, otherwise a real one.
Caches the result, so changing the setting after the first call to this
function will have no effect.
"""
global
_service
if
_service
is
not
None
:
return
_service
if
settings
.
MOCK_PEER_GRADING
:
_service
=
MockPeerGradingService
()
else
:
_service
=
PeerGradingService
(
settings
.
PEER_GRADING_INTERFACE
,
system
)
return
_service
common/lib/xmodule/xmodule/self_assessment_module.py
→
common/lib/xmodule/xmodule/
open_ended_grading_classes/
self_assessment_module.py
View file @
a789d6c3
import
copy
from
fs.errors
import
ResourceNotFoundError
import
itertools
import
json
import
logging
from
lxml
import
etree
from
lxml.html
import
rewrite_links
from
path
import
path
import
os
import
sys
from
pkg_resources
import
resource_string
from
.capa_module
import
only_one
,
ComplexEncoder
from
.editing_module
import
EditingDescriptor
from
.html_checker
import
check_html
from
progress
import
Progress
from
.stringify
import
stringify_children
from
.x_module
import
XModule
from
.xml_module
import
XmlDescriptor
from
xmodule.modulestore
import
Location
from
xmodule.capa_module
import
ComplexEncoder
from
xmodule.editing_module
import
EditingDescriptor
from
xmodule.progress
import
Progress
from
xmodule.stringify
import
stringify_children
from
xmodule.xml_module
import
XmlDescriptor
import
openendedchild
from
combined_open_ended_rubric
import
CombinedOpenEndedRubric
...
...
@@ -285,10 +273,6 @@ class SelfAssessmentDescriptor(XmlDescriptor, EditingDescriptor):
has_score
=
True
template_dir_name
=
"selfassessment"
js
=
{
'coffee'
:
[
resource_string
(
__name__
,
'js/src/html/edit.coffee'
)]}
js_module_name
=
"HTMLEditingDescriptor"
css
=
{
'scss'
:
[
resource_string
(
__name__
,
'css/editor/edit.scss'
),
resource_string
(
__name__
,
'css/html/edit.scss'
)]}
@classmethod
def
definition_from_xml
(
cls
,
xml_object
,
system
):
"""
...
...
common/lib/xmodule/xmodule/peer_grading_module.py
View file @
a789d6c3
"""
This module provides an interface on the grading-service backend
for peer grading
Use peer_grading_service() to get the version specified
in settings.PEER_GRADING_INTERFACE
"""
import
json
import
logging
import
requests
import
sys
from
django.conf
import
settings
from
combined_open_ended_rubric
import
CombinedOpenEndedRubric
from
lxml
import
etree
import
copy
import
itertools
import
json
import
logging
from
lxml.html
import
rewrite_links
import
os
from
datetime
import
datetime
from
pkg_resources
import
resource_string
from
.capa_module
import
only_one
,
ComplexEncoder
from
.capa_module
import
ComplexEncoder
from
.editing_module
import
EditingDescriptor
from
.html_checker
import
check_html
from
progress
import
Progress
from
.stringify
import
stringify_children
from
.x_module
import
XModule
from
.xml_module
import
XmlDescriptor
from
xmodule.modulestore
import
Location
from
xmodule.modulestore.django
import
modulestore
from
timeinfo
import
TimeInfo
from
peer_grading_service
import
peer_grading_s
ervice
,
GradingServiceError
from
xmodule.open_ended_grading_classes.peer_grading_service
import
PeerGradingS
ervice
,
GradingServiceError
log
=
logging
.
getLogger
(
__name__
)
...
...
@@ -70,7 +51,8 @@ class PeerGradingModule(XModule):
#We need to set the location here so the child modules can use it
system
.
set
(
'location'
,
location
)
self
.
system
=
system
self
.
peer_gs
=
peer_grading_service
(
self
.
system
)
self
.
peer_gs
=
PeerGradingService
(
self
.
system
.
open_ended_grading_interface
,
self
.
system
)
self
.
use_for_single_location
=
self
.
metadata
.
get
(
'use_for_single_location'
,
USE_FOR_SINGLE_LOCATION
)
if
isinstance
(
self
.
use_for_single_location
,
basestring
):
...
...
@@ -80,10 +62,28 @@ class PeerGradingModule(XModule):
if
isinstance
(
self
.
is_graded
,
basestring
):
self
.
is_graded
=
(
self
.
is_graded
in
TRUE_DICT
)
display_due_date_string
=
self
.
metadata
.
get
(
'due'
,
None
)
grace_period_string
=
self
.
metadata
.
get
(
'graceperiod'
,
None
)
try
:
self
.
timeinfo
=
TimeInfo
(
display_due_date_string
,
grace_period_string
)
except
:
log
.
error
(
"Error parsing due date information in location {0}"
.
format
(
location
))
raise
self
.
display_due_date
=
self
.
timeinfo
.
display_due_date
self
.
link_to_location
=
self
.
metadata
.
get
(
'link_to_location'
,
USE_FOR_SINGLE_LOCATION
)
if
self
.
use_for_single_location
==
True
:
#This will raise an exception if the location is invalid
link_to_location_object
=
Location
(
self
.
link_to_location
)
try
:
self
.
linked_problem
=
modulestore
()
.
get_instance
(
self
.
system
.
course_id
,
self
.
link_to_location
)
except
:
log
.
error
(
"Linked location {0} for peer grading module {1} does not exist"
.
format
(
self
.
link_to_location
,
self
.
location
))
raise
due_date
=
self
.
linked_problem
.
metadata
.
get
(
'peer_grading_due'
,
None
)
if
due_date
:
self
.
metadata
[
'due'
]
=
due_date
self
.
ajax_url
=
self
.
system
.
ajax_url
if
not
self
.
ajax_url
.
endswith
(
"/"
):
...
...
@@ -95,6 +95,15 @@ class PeerGradingModule(XModule):
#This could result in an exception, but not wrapping in a try catch block so it moves up the stack
self
.
max_grade
=
int
(
self
.
max_grade
)
def
closed
(
self
):
return
self
.
_closed
(
self
.
timeinfo
)
def
_closed
(
self
,
timeinfo
):
if
timeinfo
.
close_date
is
not
None
and
datetime
.
utcnow
()
>
timeinfo
.
close_date
:
return
True
return
False
def
_err_response
(
self
,
msg
):
"""
Return a HttpResponse with a json dump with success=False, and the given error message.
...
...
@@ -114,6 +123,8 @@ class PeerGradingModule(XModule):
Needs to be implemented by inheritors. Renders the HTML that students see.
@return:
"""
if
self
.
closed
():
return
self
.
peer_grading_closed
()
if
not
self
.
use_for_single_location
:
return
self
.
peer_grading
()
else
:
...
...
@@ -142,7 +153,7 @@ class PeerGradingModule(XModule):
def
query_data_for_location
(
self
):
student_id
=
self
.
system
.
anonymous_student_id
location
=
self
.
system
.
location
location
=
self
.
link_to_
location
success
=
False
response
=
{}
...
...
@@ -171,7 +182,7 @@ class PeerGradingModule(XModule):
success
,
response
=
self
.
query_data_for_location
()
if
not
success
:
log
.
exception
(
"No instance data found and could not get data from controller for loc {0} student {1}"
.
format
(
self
.
system
.
location
,
self
.
system
.
anonymous_student_id
self
.
system
.
location
.
url
()
,
self
.
system
.
anonymous_student_id
))
return
None
count_graded
=
response
[
'count_graded'
]
...
...
@@ -400,6 +411,16 @@ class PeerGradingModule(XModule):
log
.
exception
(
"Error saving calibration grade, location: {0}, submission_id: {1}, submission_key: {2}, grader_id: {3}"
.
format
(
location
,
submission_id
,
submission_key
,
grader_id
))
return
self
.
_err_response
(
'Could not connect to grading service'
)
def
peer_grading_closed
(
self
):
'''
Show the Peer grading closed template
'''
html
=
self
.
system
.
render_template
(
'peer_grading/peer_grading_closed.html'
,
{
'use_for_single_location'
:
self
.
use_for_single_location
})
return
html
def
peer_grading
(
self
,
get
=
None
):
'''
Show a peer grading interface
...
...
@@ -426,6 +447,40 @@ class PeerGradingModule(XModule):
error_text
=
"Could not get problem list"
success
=
False
def
_find_corresponding_module_for_location
(
location
):
'''
find the peer grading module that links to the given location
'''
try
:
return
modulestore
()
.
get_instance
(
self
.
system
.
course_id
,
location
)
except
:
# the linked problem doesn't exist
log
.
error
(
"Problem {0} does not exist in this course"
.
format
(
location
))
raise
for
problem
in
problem_list
:
problem_location
=
problem
[
'location'
]
descriptor
=
_find_corresponding_module_for_location
(
problem_location
)
if
descriptor
:
problem
[
'due'
]
=
descriptor
.
metadata
.
get
(
'peer_grading_due'
,
None
)
grace_period_string
=
descriptor
.
metadata
.
get
(
'graceperiod'
,
None
)
try
:
problem_timeinfo
=
TimeInfo
(
problem
[
'due'
],
grace_period_string
)
except
:
log
.
error
(
"Malformed due date or grace period string for location {0}"
.
format
(
problem_location
))
raise
if
self
.
_closed
(
problem_timeinfo
):
problem
[
'closed'
]
=
True
else
:
problem
[
'closed'
]
=
False
else
:
# if we can't find the due date, assume that it doesn't have one
problem
[
'due'
]
=
None
problem
[
'closed'
]
=
False
ajax_url
=
self
.
ajax_url
html
=
self
.
system
.
render_template
(
'peer_grading/peer_grading.html'
,
{
'course_id'
:
self
.
system
.
course_id
,
...
...
common/lib/xmodule/xmodule/tests/test_combined_open_ended.py
View file @
a789d6c3
...
...
@@ -2,9 +2,9 @@ import json
from
mock
import
Mock
,
MagicMock
,
ANY
import
unittest
from
xmodule.openendedchild
import
OpenEndedChild
from
xmodule.open_ended_module
import
OpenEndedModule
from
xmodule.combined_open_ended_modulev1
import
CombinedOpenEndedV1Module
from
xmodule.open
_ended_grading_classes.open
endedchild
import
OpenEndedChild
from
xmodule.open_ended_
grading_classes.open_ended_
module
import
OpenEndedModule
from
xmodule.
open_ended_grading_classes.
combined_open_ended_modulev1
import
CombinedOpenEndedV1Module
from
xmodule.modulestore
import
Location
from
lxml
import
etree
...
...
@@ -12,6 +12,8 @@ import capa.xqueue_interface as xqueue_interface
from
datetime
import
datetime
from
.
import
test_system
import
test_util_open_ended
"""
Tests for the various pieces of the CombinedOpenEndedGrading system
...
...
@@ -43,7 +45,10 @@ class OpenEndedChildTest(unittest.TestCase):
'max_score'
:
max_score
,
'display_name'
:
'Name'
,
'accept_file_upload'
:
False
,
'close_date'
:
None
'close_date'
:
None
,
's3_interface'
:
""
,
'open_ended_grading_interface'
:
{},
'skip_basic_checks'
:
False
,
}
definition
=
Mock
()
descriptor
=
Mock
()
...
...
@@ -161,6 +166,9 @@ class OpenEndedModuleTest(unittest.TestCase):
'accept_file_upload'
:
False
,
'rewrite_content_links'
:
""
,
'close_date'
:
None
,
's3_interface'
:
test_util_open_ended
.
S3_INTERFACE
,
'open_ended_grading_interface'
:
test_util_open_ended
.
OPEN_ENDED_GRADING_INTERFACE
,
'skip_basic_checks'
:
False
,
}
oeparam
=
etree
.
XML
(
'''
...
...
@@ -293,6 +301,9 @@ class CombinedOpenEndedModuleTest(unittest.TestCase):
'accept_file_upload'
:
False
,
'rewrite_content_links'
:
""
,
'close_date'
:
""
,
's3_interface'
:
test_util_open_ended
.
S3_INTERFACE
,
'open_ended_grading_interface'
:
test_util_open_ended
.
OPEN_ENDED_GRADING_INTERFACE
,
'skip_basic_checks'
:
False
,
}
oeparam
=
etree
.
XML
(
'''
...
...
common/lib/xmodule/xmodule/tests/test_self_assessment.py
View file @
a789d6c3
...
...
@@ -2,12 +2,13 @@ import json
from
mock
import
Mock
,
MagicMock
import
unittest
from
xmodule.self_assessment_module
import
SelfAssessmentModule
from
xmodule.
open_ended_grading_classes.
self_assessment_module
import
SelfAssessmentModule
from
xmodule.modulestore
import
Location
from
lxml
import
etree
from
.
import
test_system
import
test_util_open_ended
class
SelfAssessmentTest
(
unittest
.
TestCase
):
...
...
@@ -46,7 +47,10 @@ class SelfAssessmentTest(unittest.TestCase):
'max_score'
:
1
,
'display_name'
:
"Name"
,
'accept_file_upload'
:
False
,
'close_date'
:
None
'close_date'
:
None
,
's3_interface'
:
test_util_open_ended
.
S3_INTERFACE
,
'open_ended_grading_interface'
:
test_util_open_ended
.
OPEN_ENDED_GRADING_INTERFACE
,
'skip_basic_checks'
:
False
,
}
self
.
module
=
SelfAssessmentModule
(
test_system
,
self
.
location
,
...
...
common/lib/xmodule/xmodule/tests/test_util_open_ended.py
0 → 100644
View file @
a789d6c3
OPEN_ENDED_GRADING_INTERFACE
=
{
'url'
:
'http://127.0.0.1:3033/'
,
'username'
:
'incorrect'
,
'password'
:
'incorrect'
,
'staff_grading'
:
'staff_grading'
,
'peer_grading'
:
'peer_grading'
,
'grading_controller'
:
'grading_controller'
}
S3_INTERFACE
=
{
'aws_access_key'
:
""
,
'aws_secret_key'
:
""
,
"aws_bucket_name"
:
""
,
}
\ No newline at end of file
common/lib/xmodule/xmodule/timeinfo.py
0 → 100644
View file @
a789d6c3
import
dateutil
import
dateutil.parser
import
datetime
from
timeparse
import
parse_timedelta
import
logging
log
=
logging
.
getLogger
(
__name__
)
class
TimeInfo
(
object
):
"""
This is a simple object that calculates and stores datetime information for an XModule
based on the due date string and the grace period string
So far it parses out three different pieces of time information:
self.display_due_date - the 'official' due date that gets displayed to students
self.grace_period - the length of the grace period
self.close_date - the real due date
"""
def
__init__
(
self
,
display_due_date_string
,
grace_period_string
):
if
display_due_date_string
is
not
None
:
try
:
self
.
display_due_date
=
dateutil
.
parser
.
parse
(
display_due_date_string
)
except
ValueError
:
log
.
error
(
"Could not parse due date {0}"
.
format
(
display_due_date_string
))
raise
else
:
self
.
display_due_date
=
None
if
grace_period_string
is
not
None
and
self
.
display_due_date
:
try
:
self
.
grace_period
=
parse_timedelta
(
grace_period_string
)
self
.
close_date
=
self
.
display_due_date
+
self
.
grace_period
except
:
log
.
error
(
"Error parsing the grace period {0}"
.
format
(
grace_period_string
))
raise
else
:
self
.
grace_period
=
None
self
.
close_date
=
self
.
display_due_date
common/lib/xmodule/xmodule/x_module.py
View file @
a789d6c3
...
...
@@ -879,7 +879,9 @@ class ModuleSystem(object):
xqueue
=
None
,
node_path
=
""
,
anonymous_student_id
=
''
,
course_id
=
None
):
course_id
=
None
,
open_ended_grading_interface
=
None
,
s3_interface
=
None
):
'''
Create a closure around the system environment.
...
...
@@ -930,6 +932,8 @@ class ModuleSystem(object):
self
.
anonymous_student_id
=
anonymous_student_id
self
.
course_id
=
course_id
self
.
user_is_staff
=
user
is
not
None
and
user
.
is_staff
self
.
open_ended_grading_interface
=
open_ended_grading_interface
self
.
s3_interface
=
s3_interface
def
get
(
self
,
attr
):
''' provide uniform access to attributes (like etree).'''
...
...
lms/djangoapps/courseware/module_render.py
View file @
a789d6c3
...
...
@@ -226,6 +226,30 @@ def _get_module(user, request, descriptor, student_module_cache, course_id,
'waittime'
:
settings
.
XQUEUE_WAITTIME_BETWEEN_REQUESTS
}
def
get_or_default
(
key
,
default
):
getattr
(
settings
,
key
,
default
)
#This is a hacky way to pass settings to the combined open ended xmodule
#It needs an S3 interface to upload images to S3
#It needs the open ended grading interface in order to get peer grading to be done
#TODO: refactor these settings into module-specific settings when possible.
#this first checks to see if the descriptor is the correct one, and only sends settings if it is
is_descriptor_combined_open_ended
=
(
descriptor
.
__class__
.
__name__
==
'CombinedOpenEndedDescriptor'
)
is_descriptor_peer_grading
=
(
descriptor
.
__class__
.
__name__
==
'PeerGradingDescriptor'
)
open_ended_grading_interface
=
None
s3_interface
=
None
if
is_descriptor_combined_open_ended
or
is_descriptor_peer_grading
:
open_ended_grading_interface
=
settings
.
OPEN_ENDED_GRADING_INTERFACE
open_ended_grading_interface
[
'mock_peer_grading'
]
=
settings
.
MOCK_PEER_GRADING
open_ended_grading_interface
[
'mock_staff_grading'
]
=
settings
.
MOCK_STAFF_GRADING
if
is_descriptor_combined_open_ended
:
s3_interface
=
{
'access_key'
:
get_or_default
(
'AWS_ACCESS_KEY_ID'
,
''
),
'secret_access_key'
:
get_or_default
(
'AWS_SECRET_ACCESS_KEY'
,
''
),
'storage_bucket_name'
:
get_or_default
(
'AWS_STORAGE_BUCKET_NAME'
,
''
)
}
def
inner_get_module
(
descriptor
):
"""
Delegate to get_module. It does an access check, so may return None
...
...
@@ -255,6 +279,8 @@ def _get_module(user, request, descriptor, student_module_cache, course_id,
node_path
=
settings
.
NODE_PATH
,
anonymous_student_id
=
unique_id_for_user
(
user
),
course_id
=
course_id
,
open_ended_grading_interface
=
open_ended_grading_interface
,
s3_interface
=
s3_interface
,
)
# pass position specified in URL to module through ModuleSystem
system
.
set
(
'position'
,
position
)
...
...
lms/djangoapps/open_ended_grading/controller_query_service.py
View file @
a789d6c3
import
json
import
logging
import
requests
from
requests.exceptions
import
RequestException
,
ConnectionError
,
HTTPError
import
sys
from
xmodule.grading_service_module
import
GradingService
,
GradingServiceError
from
xmodule.open_ended_grading_classes.grading_service_module
import
GradingService
from
django.conf
import
settings
from
django.http
import
HttpResponse
,
Http404
from
xmodule.x_module
import
ModuleSystem
from
mitxmako.shortcuts
import
render_to_string
...
...
@@ -20,6 +14,8 @@ class ControllerQueryService(GradingService):
def
__init__
(
self
,
config
):
config
[
'system'
]
=
ModuleSystem
(
None
,
None
,
None
,
render_to_string
,
None
)
super
(
ControllerQueryService
,
self
)
.
__init__
(
config
)
self
.
url
=
config
[
'url'
]
+
config
[
'grading_controller'
]
self
.
login_url
=
self
.
url
+
'/login/'
self
.
check_eta_url
=
self
.
url
+
'/get_submission_eta/'
self
.
is_unique_url
=
self
.
url
+
'/is_name_unique/'
self
.
combined_notifications_url
=
self
.
url
+
'/combined_notifications/'
...
...
lms/djangoapps/open_ended_grading/open_ended_notifications.py
View file @
a789d6c3
from
django.conf
import
settings
from
xmodule.open_ended_grading_classes
import
peer_grading_service
from
staff_grading_service
import
StaffGradingService
from
open_ended_grading.controller_query_service
import
ControllerQueryService
from
xmodule
import
peer_grading_service
import
json
from
student.models
import
unique_id_for_user
import
open_ended_util
from
courseware.models
import
StudentModule
import
logging
from
courseware.access
import
has_access
from
util.cache
import
cache
import
datetime
from
xmodule
import
peer_grading_service
from
xmodule.x_module
import
ModuleSystem
from
mitxmako.shortcuts
import
render_to_string
...
...
@@ -28,7 +26,7 @@ NOTIFICATION_TYPES = (
def
staff_grading_notifications
(
course
,
user
):
staff_gs
=
StaffGradingService
(
settings
.
STAFF
_GRADING_INTERFACE
)
staff_gs
=
StaffGradingService
(
settings
.
OPEN_ENDED
_GRADING_INTERFACE
)
pending_grading
=
False
img_path
=
""
course_id
=
course
.
id
...
...
@@ -61,7 +59,7 @@ def staff_grading_notifications(course, user):
def
peer_grading_notifications
(
course
,
user
):
system
=
ModuleSystem
(
None
,
None
,
None
,
render_to_string
,
None
)
peer_gs
=
peer_grading_service
.
PeerGradingService
(
settings
.
PEER
_GRADING_INTERFACE
,
system
)
peer_gs
=
peer_grading_service
.
PeerGradingService
(
settings
.
OPEN_ENDED
_GRADING_INTERFACE
,
system
)
pending_grading
=
False
img_path
=
""
course_id
=
course
.
id
...
...
@@ -93,8 +91,7 @@ def peer_grading_notifications(course, user):
def
combined_notifications
(
course
,
user
):
controller_url
=
open_ended_util
.
get_controller_url
()
controller_qs
=
ControllerQueryService
(
controller_url
)
controller_qs
=
ControllerQueryService
(
settings
.
OPEN_ENDED_GRADING_INTERFACE
)
student_id
=
unique_id_for_user
(
user
)
user_is_staff
=
has_access
(
user
,
course
,
'staff'
)
course_id
=
course
.
id
...
...
lms/djangoapps/open_ended_grading/open_ended_util.py
deleted
100644 → 0
View file @
6e453c2b
from
django.conf
import
settings
import
logging
log
=
logging
.
getLogger
(
__name__
)
def
get_controller_url
():
peer_grading_url
=
settings
.
PEER_GRADING_INTERFACE
[
'url'
]
split_url
=
peer_grading_url
.
split
(
"/"
)
controller_url
=
"http://"
+
split_url
[
2
]
+
"/grading_controller"
controller_settings
=
settings
.
PEER_GRADING_INTERFACE
.
copy
()
controller_settings
[
'url'
]
=
controller_url
return
controller_settings
lms/djangoapps/open_ended_grading/staff_grading_service.py
View file @
a789d6c3
...
...
@@ -4,10 +4,7 @@ This module provides views that proxy to the staff grading backend service.
import
json
import
logging
import
requests
from
requests.exceptions
import
RequestException
,
ConnectionError
,
HTTPError
import
sys
from
xmodule.grading_service_module
import
GradingService
,
GradingServiceError
from
xmodule.open_ended_grading_classes.grading_service_module
import
GradingService
,
GradingServiceError
from
django.conf
import
settings
from
django.http
import
HttpResponse
,
Http404
...
...
@@ -64,6 +61,8 @@ class StaffGradingService(GradingService):
def
__init__
(
self
,
config
):
config
[
'system'
]
=
ModuleSystem
(
None
,
None
,
None
,
render_to_string
,
None
)
super
(
StaffGradingService
,
self
)
.
__init__
(
config
)
self
.
url
=
config
[
'url'
]
+
config
[
'staff_grading'
]
self
.
login_url
=
self
.
url
+
'/login/'
self
.
get_next_url
=
self
.
url
+
'/get_next_submission/'
self
.
save_grade_url
=
self
.
url
+
'/save_grade/'
self
.
get_problem_list_url
=
self
.
url
+
'/get_problem_list/'
...
...
@@ -164,7 +163,7 @@ def staff_grading_service():
if
settings
.
MOCK_STAFF_GRADING
:
_service
=
MockStaffGradingService
()
else
:
_service
=
StaffGradingService
(
settings
.
STAFF
_GRADING_INTERFACE
)
_service
=
StaffGradingService
(
settings
.
OPEN_ENDED
_GRADING_INTERFACE
)
return
_service
...
...
lms/djangoapps/open_ended_grading/tests.py
View file @
a789d6c3
...
...
@@ -6,7 +6,8 @@ django-admin.py test --settings=lms.envs.test --pythonpath=. lms/djangoapps/open
from
django.test
import
TestCase
from
open_ended_grading
import
staff_grading_service
from
xmodule
import
peer_grading_service
,
peer_grading_module
from
xmodule.open_ended_grading_classes
import
peer_grading_service
from
xmodule
import
peer_grading_module
from
django.core.urlresolvers
import
reverse
from
django.contrib.auth.models
import
Group
...
...
@@ -25,6 +26,8 @@ log = logging.getLogger(__name__)
from
django.test.utils
import
override_settings
from
django.http
import
QueryDict
from
xmodule.tests
import
test_util_open_ended
@override_settings
(
MODULESTORE
=
ct
.
TEST_DATA_XML_MODULESTORE
)
class
TestStaffGradingService
(
ct
.
PageLoader
):
...
...
@@ -144,9 +147,11 @@ class TestPeerGradingService(ct.PageLoader):
location
=
"i4x://edX/toy/peergrading/init"
self
.
mock_service
=
peer_grading_service
.
MockPeerGradingService
()
self
.
system
=
ModuleSystem
(
location
,
None
,
None
,
render_to_string
,
None
)
self
.
system
=
ModuleSystem
(
location
,
None
,
None
,
render_to_string
,
None
,
s3_interface
=
test_util_open_ended
.
S3_INTERFACE
,
open_ended_grading_interface
=
test_util_open_ended
.
OPEN_ENDED_GRADING_INTERFACE
)
self
.
descriptor
=
peer_grading_module
.
PeerGradingDescriptor
(
self
.
system
)
self
.
peer_module
=
peer_grading_module
.
PeerGradingModule
(
self
.
system
,
location
,
"<peergrading/>"
,
self
.
descriptor
)
self
.
peer_module
.
peer_gs
=
self
.
mock_service
self
.
logout
()
...
...
lms/djangoapps/open_ended_grading/views.py
View file @
a789d6c3
...
...
@@ -2,7 +2,6 @@
import
logging
import
urllib
import
re
from
django.conf
import
settings
from
django.views.decorators.cache
import
cache_control
...
...
@@ -13,12 +12,10 @@ from student.models import unique_id_for_user
from
courseware.courses
import
get_course_with_access
from
controller_query_service
import
ControllerQueryService
from
xmodule.grading_service_module
import
GradingServiceError
from
xmodule.
open_ended_grading_classes.
grading_service_module
import
GradingServiceError
import
json
from
.staff_grading
import
StaffGrading
from
student.models
import
unique_id_for_user
import
open_ended_util
import
open_ended_notifications
from
xmodule.modulestore.django
import
modulestore
...
...
@@ -30,8 +27,7 @@ log = logging.getLogger(__name__)
template_imports
=
{
'urllib'
:
urllib
}
controller_url
=
open_ended_util
.
get_controller_url
()
controller_qs
=
ControllerQueryService
(
controller_url
)
controller_qs
=
ControllerQueryService
(
settings
.
OPEN_ENDED_GRADING_INTERFACE
)
"""
Reverses the URL from the name and the course id, and then adds a trailing slash if
...
...
lms/envs/aws.py
View file @
a789d6c3
...
...
@@ -100,10 +100,7 @@ XQUEUE_INTERFACE = AUTH_TOKENS['XQUEUE_INTERFACE']
MODULESTORE
=
AUTH_TOKENS
.
get
(
'MODULESTORE'
,
MODULESTORE
)
CONTENTSTORE
=
AUTH_TOKENS
.
get
(
'CONTENTSTORE'
,
CONTENTSTORE
)
STAFF_GRADING_INTERFACE
=
AUTH_TOKENS
.
get
(
'STAFF_GRADING_INTERFACE'
,
STAFF_GRADING_INTERFACE
)
PEER_GRADING_INTERFACE
=
AUTH_TOKENS
.
get
(
'PEER_GRADING_INTERFACE'
,
PEER_GRADING_INTERFACE
)
OPEN_ENDED_GRADING_INTERFACE
=
AUTH_TOKENS
.
get
(
'OPEN_ENDED_GRADING_INTERFACE'
,
OPEN_ENDED_GRADING_INTERFACE
)
PEARSON_TEST_USER
=
"pearsontest"
PEARSON_TEST_PASSWORD
=
AUTH_TOKENS
.
get
(
"PEARSON_TEST_PASSWORD"
)
...
...
lms/envs/common.py
View file @
a789d6c3
...
...
@@ -310,37 +310,30 @@ WIKI_USE_BOOTSTRAP_SELECT_WIDGET = False
WIKI_LINK_LIVE_LOOKUPS
=
False
WIKI_LINK_DEFAULT_LEVEL
=
2
################################# Staff grading config #####################
#By setting up the default settings with an incorrect user name and password,
# will get an error when attempting to connect
STAFF_GRADING_INTERFACE
=
{
'url'
:
'http://sandbox-grader-001.m.edx.org/staff_grading'
,
'username'
:
'incorrect_user'
,
'password'
:
'incorrect_pass'
,
}
# Used for testing, debugging
MOCK_STAFF_GRADING
=
False
################################# Pearson TestCenter config ################
PEARSONVUE_SIGNINPAGE_URL
=
"https://www1.pearsonvue.com/testtaker/signin/SignInPage/EDX"
# TESTCENTER_ACCOMMODATION_REQUEST_EMAIL = "exam-help@edx.org"
#################################
Peer
grading config #####################
#################################
open ended
grading config #####################
#By setting up the default settings with an incorrect user name and password,
# will get an error when attempting to connect
PEER
_GRADING_INTERFACE
=
{
OPEN_ENDED
_GRADING_INTERFACE
=
{
'url'
:
'http://sandbox-grader-001.m.edx.org/peer_grading'
,
'username'
:
'incorrect_user'
,
'password'
:
'incorrect_pass'
,
'staff_grading'
:
'staff_grading'
,
'peer_grading'
:
'peer_grading'
,
'grading_controller'
:
'grading_controller'
}
# Used for testing, debugging
# Used for testing, debugging
peer grading
MOCK_PEER_GRADING
=
False
# Used for testing, debugging staff grading
MOCK_STAFF_GRADING
=
False
################################# Jasmine ###################################
JASMINE_TEST_DIRECTORY
=
PROJECT_ROOT
+
'/static/coffee'
...
...
lms/envs/dev.py
View file @
a789d6c3
...
...
@@ -131,21 +131,17 @@ if os.path.isdir(DATA_DIR):
MITX_VERSION_STRING
=
os
.
popen
(
'cd
%
s; git describe'
%
REPO_ROOT
)
.
read
()
.
strip
()
################################# Staff grading config #####################
STAFF_GRADING_INTERFACE
=
{
'url'
:
'http://127.0.0.1:3033/staff_grading'
,
'username'
:
'lms'
,
'password'
:
'abcd'
,
}
################################# Peer grading config #####################
################################# Open ended grading config #####################
OPEN_ENDED_GRADING_INTERFACE
=
{
'url'
:
'http://127.0.0.1:3033/'
,
'username'
:
'lms'
,
'password'
:
'abcd'
,
'staff_grading'
:
'staff_grading'
,
'peer_grading'
:
'peer_grading'
,
'grading_controller'
:
'grading_controller'
}
PEER_GRADING_INTERFACE
=
{
'url'
:
'http://127.0.0.1:3033/peer_grading'
,
'username'
:
'lms'
,
'password'
:
'abcd'
,
}
################################ LMS Migration #################################
MITX_FEATURES
[
'ENABLE_LMS_MIGRATION'
]
=
True
MITX_FEATURES
[
'ACCESS_REQUIRE_STAFF_FOR_COURSE'
]
=
False
# require that user be in the staff_* group to be able to enroll
...
...
lms/templates/peer_grading/peer_grading.html
View file @
a789d6c3
...
...
@@ -14,6 +14,7 @@
<table
class=
"problem-list"
>
<tr>
<th>
Problem Name
</th>
<th>
Due date
</th>
<th>
Graded
</th>
<th>
Available
</th>
<th>
Required
</th>
...
...
@@ -22,7 +23,18 @@
%for problem in problem_list:
<tr
data-graded=
"${problem['num_graded']}"
data-required=
"${problem['num_required']}"
>
<td
class=
"problem-name"
>
%if problem['closed']:
${problem['problem_name']}
%else:
<a
href=
"#problem"
data-location=
"${problem['location']}"
class=
"problem-button"
>
${problem['problem_name']}
</a>
%endif
</td>
<td>
% if problem['due']:
${problem['due']}
% else:
No due date
% endif
</td>
<td>
${problem['num_graded']}
...
...
lms/templates/peer_grading/peer_grading_closed.html
0 → 100644
View file @
a789d6c3
<section
class=
"container peer-grading-container"
>
<h2>
Peer Grading
</h2>
<p>
The due date has passed, and
% if use_for_single_location:
peer grading for this problem is closed at this time.
%else:
peer grading is closed at this time.
%endif
</p>
</section>
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