diff --git a/common/lib/capa/capa/capa_problem.py b/common/lib/capa/capa/capa_problem.py index 585e087b36..9c383d114d 100644 --- a/common/lib/capa/capa/capa_problem.py +++ b/common/lib/capa/capa/capa_problem.py @@ -189,10 +189,20 @@ class LoncapaProblem(object): def message_post(self,event_info): """ Handle an ajax post that contains feedback on feedback + Returns a boolean success variable + Note: This only allows for feedback to be posted back to the grading controller for the first + open ended response problem on each page. Multiple problems will cause some sync issues. + TODO: Handle multiple problems on one page sync issues. """ + success=False + message = "" + log.debug("in lcp") for responder in self.responders.values(): - if hasattr(responder, 'message_post'): - responder.message_post(event_info) + if hasattr(responder, 'handle_message_post'): + success, message = responder.handle_message_post(event_info) + if success: + break + return success, message def get_score(self): """ diff --git a/common/lib/capa/capa/responsetypes.py b/common/lib/capa/capa/responsetypes.py index f8ee12650e..038586f7f4 100644 --- a/common/lib/capa/capa/responsetypes.py +++ b/common/lib/capa/capa/responsetypes.py @@ -1848,6 +1848,7 @@ class OpenEndedResponse(LoncapaResponse): xml = self.xml self.url = xml.get('url', None) self.queue_name = xml.get('queuename', self.DEFAULT_QUEUE) + self.message_queue_name = xml.get('message-queuename', self.DEFAULT_MESSAGE_QUEUE) # The openendedparam tag encapsulates all grader settings oeparam = self.xml.find('openendedparam') @@ -1921,6 +1922,52 @@ class OpenEndedResponse(LoncapaResponse): except ValueError: self.max_score = 1 + def handle_message_post(self,event_info): + """ + Handles a student message post (a reaction to the grade they received from an open ended grader type) + Returns a boolean success/fail and an error message + """ + survey_responses=event_info['survey_responses'] + for tag in ['feedback', 'submission_id', 'grader_id']: + if tag not in survey_responses: + return False, "Could not find needed tag {0}".format(tag) + try: + submission_id=int(survey_responses['submission_id'][0]) + grader_id = int(survey_responses['grader_id'][0]) + feedback = str(survey_responses['feedback'][0]) + except: + error_message="Could not parse submission id, grader id, or feedback from message_post ajax call." + log.exception(error_message) + return False, error_message + + qinterface = self.system.xqueue['interface'] + qtime = datetime.strftime(datetime.now(), xqueue_interface.dateformat) + anonymous_student_id = self.system.anonymous_student_id + queuekey = xqueue_interface.make_hashkey(str(self.system.seed) + qtime + + anonymous_student_id + + self.answer_id) + + xheader = xqueue_interface.make_xheader(lms_key=queuekey,queue_name=self.message_queue_name) + student_info = {'anonymous_student_id': anonymous_student_id, + 'submission_time': qtime, + } + contents= { + 'feedback' : feedback, + 'submission_id' : submission_id, + 'grader_id' : grader_id, + 'student_info' : json.dumps(student_info), + } + + (error, msg) = qinterface.send_to_queue(header=xheader, + body=json.dumps(contents)) + + #Convert error to a success value + success=True + if error: + success=False + + return success, "Successfully sent to queue." + def get_score(self, student_answers): try: @@ -2068,11 +2115,18 @@ class OpenEndedResponse(LoncapaResponse): """.format(feedback_type=feedback_type, value=value) + def format_feedback_hidden(feedback_type , value): + return """ + + """.format(feedback_type=feedback_type, value=value) + # TODO (vshnayder): design and document the details of this format so # that we can do proper escaping here (e.g. are the graders allowed to # include HTML?) - for tag in ['success', 'feedback']: + for tag in ['success', 'feedback', 'submission_id', 'grader_id']: if tag not in response_items: return format_feedback('errors', 'Error getting feedback') @@ -2088,10 +2142,12 @@ class OpenEndedResponse(LoncapaResponse): return format_feedback('errors', 'No feedback available') feedback_lst = sorted(feedback.items(), key=get_priority) - return u"\n".join(format_feedback(k, v) for k, v in feedback_lst) + feedback_list_part1 = u"\n".join(format_feedback(k, v) for k, v in feedback_lst) else: - return format_feedback('errors', response_items['feedback']) + feedback_list_part1 = format_feedback('errors', response_items['feedback']) + feedback_list_part2=u"\n".join([format_feedback_hidden(k,response_items[k]) for k in response_items.keys() if k in ['submission_id', 'grader_id']]) + return u"\n".join([feedback_list_part1,feedback_list_part2]) def _format_feedback(self, response_items): """ diff --git a/common/lib/xmodule/xmodule/capa_module.py b/common/lib/xmodule/xmodule/capa_module.py index 727449ea99..8d72fdf01c 100644 --- a/common/lib/xmodule/xmodule/capa_module.py +++ b/common/lib/xmodule/xmodule/capa_module.py @@ -405,9 +405,9 @@ class CapaModule(XModule): event_info['student_id'] = self.system.anonymous_student_id event_info['survey_responses']= get - success_dict = self.lcp.message_post(event_info) + success, message = self.lcp.message_post(event_info) - return {'success' : True} + return {'success' : success} def closed(self): ''' Is the student still allowed to submit answers? ''' diff --git a/common/lib/xmodule/xmodule/js/src/capa/display.coffee b/common/lib/xmodule/xmodule/js/src/capa/display.coffee index 204080dd64..393435a2e4 100644 --- a/common/lib/xmodule/xmodule/js/src/capa/display.coffee +++ b/common/lib/xmodule/xmodule/js/src/capa/display.coffee @@ -202,8 +202,12 @@ class @Problem Logger.log 'message_post', @answers fd = new FormData() - feedback = @$('section.evaluation textarea.feedback-on-feedback')[0] - fd.append('feedback', feedback.value) + feedback = @$('section.evaluation textarea.feedback-on-feedback')[0].value + submission_id = $('div.external-grader-message div.submission_id')[0].innerHTML + grader_id = $('div.external-grader-message div.grader_id')[0].innerHTML + fd.append('feedback', feedback) + fd.append('submission_id', submission_id) + fd.append('grader_id', grader_id) settings = type: "POST"