diff --git a/cms/djangoapps/contentstore/views.py b/cms/djangoapps/contentstore/views.py
index 2d3c90d6b8..34003d71a4 100644
--- a/cms/djangoapps/contentstore/views.py
+++ b/cms/djangoapps/contentstore/views.py
@@ -68,6 +68,10 @@ log = logging.getLogger(__name__)
COMPONENT_TYPES = ['customtag', 'discussion', 'html', 'problem', 'video']
+ADVANCED_COMPONENT_TYPES = ['annotatable','combinedopenended', 'peergrading']
+ADVANCED_COMPONENT_CATEGORY = 'advanced'
+ADVANCED_COMPONENT_POLICY_KEY = 'advanced_modules'
+
# cdodge: these are categories which should not be parented, they are detached from the hierarchy
DETACHED_CATEGORIES = ['about', 'static_tab', 'course_info']
@@ -281,10 +285,31 @@ def edit_unit(request, location):
component_templates = defaultdict(list)
+ # Check if there are any advanced modules specified in the course policy. These modules
+ # should be specified as a list of strings, where the strings are the names of the modules
+ # in ADVANCED_COMPONENT_TYPES that should be enabled for the course.
+ course_metadata = CourseMetadata.fetch(course.location)
+ course_advanced_keys = course_metadata.get(ADVANCED_COMPONENT_POLICY_KEY, [])
+
+ # Set component types according to course policy file
+ component_types = list(COMPONENT_TYPES)
+ if isinstance(course_advanced_keys, list):
+ course_advanced_keys = [c for c in course_advanced_keys if c in ADVANCED_COMPONENT_TYPES]
+ if len(course_advanced_keys) > 0:
+ component_types.append(ADVANCED_COMPONENT_CATEGORY)
+ else:
+ log.error("Improper format for course advanced keys! {0}".format(course_advanced_keys))
+
templates = modulestore().get_items(Location('i4x', 'edx', 'templates'))
for template in templates:
- if template.location.category in COMPONENT_TYPES:
- component_templates[template.location.category].append((
+ category = template.location.category
+
+ if category in course_advanced_keys:
+ category = ADVANCED_COMPONENT_CATEGORY
+
+ if category in component_types:
+ #This is a hack to create categories for different xmodules
+ component_templates[category].append((
template.display_name,
template.location.url(),
'markdown' in template.metadata,
diff --git a/cms/static/img/large-advanced-icon.png b/cms/static/img/large-advanced-icon.png
new file mode 100644
index 0000000000..c6a19ea5a9
Binary files /dev/null and b/cms/static/img/large-advanced-icon.png differ
diff --git a/cms/static/img/large-annotations-icon.png b/cms/static/img/large-annotations-icon.png
new file mode 100644
index 0000000000..249193521f
Binary files /dev/null and b/cms/static/img/large-annotations-icon.png differ
diff --git a/cms/static/img/large-openended-icon.png b/cms/static/img/large-openended-icon.png
new file mode 100644
index 0000000000..4d31815413
Binary files /dev/null and b/cms/static/img/large-openended-icon.png differ
diff --git a/cms/static/sass/_graphics.scss b/cms/static/sass/_graphics.scss
index 4ed22c570d..300cf3b692 100644
--- a/cms/static/sass/_graphics.scss
+++ b/cms/static/sass/_graphics.scss
@@ -254,6 +254,30 @@
background: url(../img/html-icon.png) center no-repeat;
}
+.large-openended-icon {
+ display: inline-block;
+ width: 100px;
+ height: 60px;
+ margin-right: 5px;
+ background: url(../img/large-openended-icon.png) center no-repeat;
+}
+
+.large-annotations-icon {
+ display: inline-block;
+ width: 100px;
+ height: 60px;
+ margin-right: 5px;
+ background: url(../img/large-annotations-icon.png) center no-repeat;
+}
+
+.large-advanced-icon {
+ display: inline-block;
+ width: 100px;
+ height: 60px;
+ margin-right: 5px;
+ background: url(../img/large-advanced-icon.png) center no-repeat;
+}
+
.large-textbook-icon {
display: inline-block;
width: 100px;
diff --git a/common/lib/xmodule/xmodule/open_ended_grading_classes/combined_open_ended_modulev1.py b/common/lib/xmodule/xmodule/open_ended_grading_classes/combined_open_ended_modulev1.py
index 171441c562..5c3bfa5b2a 100644
--- a/common/lib/xmodule/xmodule/open_ended_grading_classes/combined_open_ended_modulev1.py
+++ b/common/lib/xmodule/xmodule/open_ended_grading_classes/combined_open_ended_modulev1.py
@@ -79,6 +79,9 @@ class CombinedOpenEndedV1Module():
INTERMEDIATE_DONE = 'intermediate_done'
DONE = 'done'
+ #Where the templates live for this problem
+ TEMPLATE_DIR = "combinedopenended"
+
def __init__(self, system, location, definition, descriptor,
instance_state=None, shared_state=None, metadata = None, static_data = None, **kwargs):
@@ -343,7 +346,7 @@ class CombinedOpenEndedV1Module():
Output: rendered html
"""
context = self.get_context()
- html = self.system.render_template('combined_open_ended.html', context)
+ html = self.system.render_template('{0}/combined_open_ended.html'.format(self.TEMPLATE_DIR), context)
return html
def get_html_nonsystem(self):
@@ -354,7 +357,7 @@ class CombinedOpenEndedV1Module():
Output: HTML rendered directly via Mako
"""
context = self.get_context()
- html = self.system.render_template('combined_open_ended.html', context)
+ html = self.system.render_template('{0}/combined_open_ended.html'.format(self.TEMPLATE_DIR), context)
return html
def get_html_base(self):
@@ -531,7 +534,7 @@ class CombinedOpenEndedV1Module():
'task_name' : 'Scored Rubric',
'class_name' : 'combined-rubric-container'
}
- html = self.system.render_template('combined_open_ended_results.html', context)
+ html = self.system.render_template('{0}/combined_open_ended_results.html'.format(self.TEMPLATE_DIR), context)
return {'html': html, 'success': True}
def get_legend(self, get):
@@ -543,7 +546,7 @@ class CombinedOpenEndedV1Module():
context = {
'legend_list' : LEGEND_LIST,
}
- html = self.system.render_template('combined_open_ended_legend.html', context)
+ html = self.system.render_template('{0}/combined_open_ended_legend.html'.format(self.TEMPLATE_DIR), context)
return {'html': html, 'success': True}
def get_results(self, get):
@@ -574,7 +577,7 @@ class CombinedOpenEndedV1Module():
'submission_id' : ri['submission_ids'][i],
}
context_list.append(context)
- feedback_table = self.system.render_template('open_ended_result_table.html', {
+ feedback_table = self.system.render_template('{0}/open_ended_result_table.html'.format(self.TEMPLATE_DIR), {
'context_list' : context_list,
'grader_type_image_dict' : GRADER_TYPE_IMAGE_DICT,
'human_grader_types' : HUMAN_GRADER_TYPE,
@@ -586,7 +589,7 @@ class CombinedOpenEndedV1Module():
'task_name' : "Feedback",
'class_name' : "result-container",
}
- html = self.system.render_template('combined_open_ended_results.html', context)
+ html = self.system.render_template('{0}/combined_open_ended_results.html'.format(self.TEMPLATE_DIR), context)
return {'html': html, 'success': True}
def get_status_ajax(self, get):
@@ -700,7 +703,7 @@ class CombinedOpenEndedV1Module():
'legend_list' : LEGEND_LIST,
'render_via_ajax' : render_via_ajax,
}
- status_html = self.system.render_template("combined_open_ended_status.html", context)
+ status_html = self.system.render_template("{0}/combined_open_ended_status.html".format(self.TEMPLATE_DIR), context)
return status_html
diff --git a/common/lib/xmodule/xmodule/open_ended_grading_classes/combined_open_ended_rubric.py b/common/lib/xmodule/xmodule/open_ended_grading_classes/combined_open_ended_rubric.py
index f756b2b853..8d1bd376fb 100644
--- a/common/lib/xmodule/xmodule/open_ended_grading_classes/combined_open_ended_rubric.py
+++ b/common/lib/xmodule/xmodule/open_ended_grading_classes/combined_open_ended_rubric.py
@@ -30,6 +30,8 @@ class RubricParsingError(Exception):
class CombinedOpenEndedRubric(object):
+ TEMPLATE_DIR = "combinedopenended/openended"
+
def __init__ (self, system, view_only = False):
self.has_score = False
self.view_only = view_only
@@ -57,9 +59,9 @@ class CombinedOpenEndedRubric(object):
rubric_scores = [cat['score'] for cat in rubric_categories]
max_scores = map((lambda cat: cat['options'][-1]['points']), rubric_categories)
max_score = max(max_scores)
- rubric_template = 'open_ended_rubric.html'
+ rubric_template = '{0}/open_ended_rubric.html'.format(self.TEMPLATE_DIR)
if self.view_only:
- rubric_template = 'open_ended_view_only_rubric.html'
+ rubric_template = '{0}/open_ended_view_only_rubric.html'.format(self.TEMPLATE_DIR)
html = self.system.render_template(rubric_template,
{'categories': rubric_categories,
'has_score': self.has_score,
@@ -207,7 +209,7 @@ class CombinedOpenEndedRubric(object):
for grader_type in tuple[3]:
rubric_categories[i]['options'][j]['grader_types'].append(grader_type)
- html = self.system.render_template('open_ended_combined_rubric.html',
+ html = self.system.render_template('{0}/open_ended_combined_rubric.html'.format(self.TEMPLATE_DIR),
{'categories': rubric_categories,
'has_score': True,
'view_only': True,
diff --git a/common/lib/xmodule/xmodule/open_ended_grading_classes/open_ended_module.py b/common/lib/xmodule/xmodule/open_ended_grading_classes/open_ended_module.py
index 974d23965f..aa805a5290 100644
--- a/common/lib/xmodule/xmodule/open_ended_grading_classes/open_ended_module.py
+++ b/common/lib/xmodule/xmodule/open_ended_grading_classes/open_ended_module.py
@@ -40,6 +40,8 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
"""
+ TEMPLATE_DIR = "combinedopenended/openended"
+
def setup_response(self, system, location, definition, descriptor):
"""
Sets up the response type.
@@ -397,10 +399,10 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
rubric_scores = rubric_dict['rubric_scores']
if not response_items['success']:
- return system.render_template("open_ended_error.html",
+ return system.render_template("{0}/open_ended_error.html".format(self.TEMPLATE_DIR),
{'errors': feedback})
- feedback_template = system.render_template("open_ended_feedback.html", {
+ feedback_template = system.render_template("{0}/open_ended_feedback.html".format(self.TEMPLATE_DIR), {
'grader_type': response_items['grader_type'],
'score': "{0} / {1}".format(response_items['score'], self.max_score()),
'feedback': feedback,
@@ -558,7 +560,7 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
@return: Rendered html
"""
context = {'msg': feedback, 'id': "1", 'rows': 50, 'cols': 50}
- html = system.render_template('open_ended_evaluation.html', context)
+ html = system.render_template('{0}/open_ended_evaluation.html'.format(self.TEMPLATE_DIR), context)
return html
def handle_ajax(self, dispatch, get, system):
@@ -692,7 +694,7 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
'accept_file_upload': self.accept_file_upload,
'eta_message' : eta_string,
}
- html = system.render_template('open_ended.html', context)
+ html = system.render_template('{0}/open_ended.html'.format(self.TEMPLATE_DIR), context)
return html
diff --git a/common/lib/xmodule/xmodule/open_ended_grading_classes/self_assessment_module.py b/common/lib/xmodule/xmodule/open_ended_grading_classes/self_assessment_module.py
index 7ecb3c4d5e..f4be426667 100644
--- a/common/lib/xmodule/xmodule/open_ended_grading_classes/self_assessment_module.py
+++ b/common/lib/xmodule/xmodule/open_ended_grading_classes/self_assessment_module.py
@@ -32,6 +32,8 @@ class SelfAssessmentModule(openendedchild.OpenEndedChild):
"""
+ TEMPLATE_DIR = "combinedopenended/selfassessment"
+
def setup_response(self, system, location, definition, descriptor):
"""
Sets up the module
@@ -68,7 +70,7 @@ class SelfAssessmentModule(openendedchild.OpenEndedChild):
'accept_file_upload': self.accept_file_upload,
}
- html = system.render_template('self_assessment_prompt.html', context)
+ html = system.render_template('{0}/self_assessment_prompt.html'.format(self.TEMPLATE_DIR), context)
return html
@@ -129,7 +131,7 @@ class SelfAssessmentModule(openendedchild.OpenEndedChild):
#This is a dev_facing_error
raise ValueError("Self assessment module is in an illegal state '{0}'".format(self.state))
- return system.render_template('self_assessment_rubric.html', context)
+ return system.render_template('{0}/self_assessment_rubric.html'.format(self.TEMPLATE_DIR), context)
def get_hint_html(self, system):
"""
@@ -155,7 +157,7 @@ class SelfAssessmentModule(openendedchild.OpenEndedChild):
#This is a dev_facing_error
raise ValueError("Self Assessment module is in an illegal state '{0}'".format(self.state))
- return system.render_template('self_assessment_hint.html', context)
+ return system.render_template('{0}/self_assessment_hint.html'.format(self.TEMPLATE_DIR), context)
def save_answer(self, get, system):
diff --git a/common/lib/xmodule/xmodule/peer_grading_module.py b/common/lib/xmodule/xmodule/peer_grading_module.py
index 97abfdbfba..1e52dcf070 100644
--- a/common/lib/xmodule/xmodule/peer_grading_module.py
+++ b/common/lib/xmodule/xmodule/peer_grading_module.py
@@ -471,6 +471,9 @@ class PeerGradingModule(XModule):
#This is a student_facing_error
error_text = "Could not get list of problems to peer grade. Please notify course staff."
success = False
+ except:
+ log.exception("Could not contact peer grading service.")
+ success = False
def _find_corresponding_module_for_location(location):
@@ -589,7 +592,6 @@ class PeerGradingDescriptor(XmlDescriptor, EditingDescriptor):
'task_xml': dictionary of xml strings,
}
"""
- log.debug("In definition")
expected_children = []
for child in expected_children:
if len(xml_object.xpath(child)) == 0:
diff --git a/common/lib/xmodule/xmodule/templates/combinedopenended/default.yaml b/common/lib/xmodule/xmodule/templates/combinedopenended/default.yaml
new file mode 100644
index 0000000000..f2aba0e18b
--- /dev/null
+++ b/common/lib/xmodule/xmodule/templates/combinedopenended/default.yaml
@@ -0,0 +1,44 @@
+---
+metadata:
+ display_name: Open Ended Response
+ max_attempts: 1
+ max_score: 1
+ is_graded: False
+ version: 1
+ display_name: Open Ended Response
+ skip_spelling_checks: False
+ accept_file_upload: False
+data: |
+
+
+
+
+ Category 1
+
+
+
+
+
+
+
Why is the sky blue?
+
+
+
+
+
+
+
+ Enter essay here.
+ This is the answer.
+ {"grader_settings" : "peer_grading.conf", "problem_id" : "700x/Demo"}
+
+
+
+
+
+
+children: []
diff --git a/common/lib/xmodule/xmodule/templates/peer_grading/default.yaml b/common/lib/xmodule/xmodule/templates/peer_grading/default.yaml
new file mode 100644
index 0000000000..cb8e29dfa2
--- /dev/null
+++ b/common/lib/xmodule/xmodule/templates/peer_grading/default.yaml
@@ -0,0 +1,13 @@
+---
+metadata:
+ display_name: Peer Grading Interface
+ attempts: 1
+ use_for_single_location: False
+ link_to_location: None
+ is_graded: False
+ max_grade: 1
+data: |
+
+
+
+children: []
diff --git a/lms/djangoapps/open_ended_grading/views.py b/lms/djangoapps/open_ended_grading/views.py
index 76919d4103..55e8088c3f 100644
--- a/lms/djangoapps/open_ended_grading/views.py
+++ b/lms/djangoapps/open_ended_grading/views.py
@@ -89,14 +89,24 @@ def peer_grading(request, course_id):
Show a peer grading interface
'''
+ #Get the current course
course = get_course_with_access(request.user, course_id, 'load')
course_id_parts = course.id.split("/")
- course_id_norun = "/".join(course_id_parts[0:2])
- pg_location = "i4x://" + course_id_norun + "/peergrading/init"
+ false_dict = [False,"False", "false", "FALSE"]
+ #Reverse the base course url
base_course_url = reverse('courses')
try:
- problem_url_parts = search.path_to_location(modulestore(), course.id, pg_location)
+ #TODO: This will not work with multiple runs of a course. Make it work. The last key in the Location passed
+ #to get_items is called revision. Is this the same as run?
+ #Get the peer grading modules currently in the course
+ items = modulestore().get_items(['i4x', None, course_id_parts[1], 'peergrading', None])
+ #See if any of the modules are centralized modules (ie display info from multiple problems)
+ items = [i for i in items if i.metadata.get("use_for_single_location", True) in false_dict]
+ #Get the first one
+ item_location = items[0].location
+ #Generate a url for the first module and redirect the user to it
+ problem_url_parts = search.path_to_location(modulestore(), course.id, item_location)
problem_url = generate_problem_url(problem_url_parts, base_course_url)
return HttpResponseRedirect(problem_url)
diff --git a/lms/templates/combined_open_ended.html b/lms/templates/combinedopenended/combined_open_ended.html
similarity index 100%
rename from lms/templates/combined_open_ended.html
rename to lms/templates/combinedopenended/combined_open_ended.html
diff --git a/lms/templates/combined_open_ended_legend.html b/lms/templates/combinedopenended/combined_open_ended_legend.html
similarity index 100%
rename from lms/templates/combined_open_ended_legend.html
rename to lms/templates/combinedopenended/combined_open_ended_legend.html
diff --git a/lms/templates/combined_open_ended_results.html b/lms/templates/combinedopenended/combined_open_ended_results.html
similarity index 100%
rename from lms/templates/combined_open_ended_results.html
rename to lms/templates/combinedopenended/combined_open_ended_results.html
diff --git a/lms/templates/combined_open_ended_status.html b/lms/templates/combinedopenended/combined_open_ended_status.html
similarity index 100%
rename from lms/templates/combined_open_ended_status.html
rename to lms/templates/combinedopenended/combined_open_ended_status.html
diff --git a/lms/templates/open_ended_result_table.html b/lms/templates/combinedopenended/open_ended_result_table.html
similarity index 100%
rename from lms/templates/open_ended_result_table.html
rename to lms/templates/combinedopenended/open_ended_result_table.html
diff --git a/lms/templates/open_ended.html b/lms/templates/combinedopenended/openended/open_ended.html
similarity index 100%
rename from lms/templates/open_ended.html
rename to lms/templates/combinedopenended/openended/open_ended.html
diff --git a/lms/templates/open_ended_combined_rubric.html b/lms/templates/combinedopenended/openended/open_ended_combined_rubric.html
similarity index 100%
rename from lms/templates/open_ended_combined_rubric.html
rename to lms/templates/combinedopenended/openended/open_ended_combined_rubric.html
diff --git a/lms/templates/open_ended_error.html b/lms/templates/combinedopenended/openended/open_ended_error.html
similarity index 100%
rename from lms/templates/open_ended_error.html
rename to lms/templates/combinedopenended/openended/open_ended_error.html
diff --git a/lms/templates/open_ended_evaluation.html b/lms/templates/combinedopenended/openended/open_ended_evaluation.html
similarity index 100%
rename from lms/templates/open_ended_evaluation.html
rename to lms/templates/combinedopenended/openended/open_ended_evaluation.html
diff --git a/lms/templates/open_ended_feedback.html b/lms/templates/combinedopenended/openended/open_ended_feedback.html
similarity index 100%
rename from lms/templates/open_ended_feedback.html
rename to lms/templates/combinedopenended/openended/open_ended_feedback.html
diff --git a/lms/templates/open_ended_rubric.html b/lms/templates/combinedopenended/openended/open_ended_rubric.html
similarity index 100%
rename from lms/templates/open_ended_rubric.html
rename to lms/templates/combinedopenended/openended/open_ended_rubric.html
diff --git a/lms/templates/open_ended_view_only_rubric.html b/lms/templates/combinedopenended/openended/open_ended_view_only_rubric.html
similarity index 100%
rename from lms/templates/open_ended_view_only_rubric.html
rename to lms/templates/combinedopenended/openended/open_ended_view_only_rubric.html
diff --git a/lms/templates/self_assessment_hint.html b/lms/templates/combinedopenended/selfassessment/self_assessment_hint.html
similarity index 100%
rename from lms/templates/self_assessment_hint.html
rename to lms/templates/combinedopenended/selfassessment/self_assessment_hint.html
diff --git a/lms/templates/self_assessment_prompt.html b/lms/templates/combinedopenended/selfassessment/self_assessment_prompt.html
similarity index 100%
rename from lms/templates/self_assessment_prompt.html
rename to lms/templates/combinedopenended/selfassessment/self_assessment_prompt.html
diff --git a/lms/templates/self_assessment_rubric.html b/lms/templates/combinedopenended/selfassessment/self_assessment_rubric.html
similarity index 100%
rename from lms/templates/self_assessment_rubric.html
rename to lms/templates/combinedopenended/selfassessment/self_assessment_rubric.html