def save_ccx(request, course, ccx=None): # lint-amnesty, pylint: disable=too-many-statements """ Save changes to CCX. """ if not ccx: raise Http404 def override_fields(parent, data, graded, earliest=None, ccx_ids_to_delete=None): """ Recursively apply CCX schedule data to CCX by overriding the `visible_to_staff_only`, `start` and `due` fields for units in the course. """ if ccx_ids_to_delete is None: ccx_ids_to_delete = [] blocks = { str(child.location): child for child in parent.get_children() } for unit in data: block = blocks[unit['location']] override_field_for_ccx(ccx, block, 'visible_to_staff_only', unit['hidden']) start = parse_date(unit['start']) if start: if not earliest or start < earliest: earliest = start override_field_for_ccx(ccx, block, 'start', start) else: ccx_ids_to_delete.append( get_override_for_ccx(ccx, block, 'start_id')) clear_ccx_field_info_from_ccx_map(ccx, block, 'start') # Only subsection (aka sequential) and unit (aka vertical) have due dates. if 'due' in unit: # checking that the key (due) exist in dict (unit). due = parse_date(unit['due']) if due: override_field_for_ccx(ccx, block, 'due', due) else: ccx_ids_to_delete.append( get_override_for_ccx(ccx, block, 'due_id')) clear_ccx_field_info_from_ccx_map(ccx, block, 'due') else: # In case of section aka chapter we do not have due date. ccx_ids_to_delete.append( get_override_for_ccx(ccx, block, 'due_id')) clear_ccx_field_info_from_ccx_map(ccx, block, 'due') if not unit['hidden'] and block.graded: graded[block.format] = graded.get(block.format, 0) + 1 children = unit.get('children', None) # For a vertical, override start and due dates of all its problems. if unit.get('category', None) == 'vertical': for component in block.get_children(): # override start and due date of problem (Copy dates of vertical into problems) if start: override_field_for_ccx(ccx, component, 'start', start) if due: override_field_for_ccx(ccx, component, 'due', due) if children: override_fields(block, children, graded, earliest, ccx_ids_to_delete) return earliest, ccx_ids_to_delete graded = {} earliest, ccx_ids_to_delete = override_fields( course, json.loads(request.body.decode('utf8')), graded, []) bulk_delete_ccx_override_fields(ccx, ccx_ids_to_delete) if earliest: override_field_for_ccx(ccx, course, 'start', earliest) # Attempt to automatically adjust grading policy changed = False policy = get_override_for_ccx(ccx, course, 'grading_policy', course.grading_policy) policy = deepcopy(policy) grader = policy['GRADER'] for section in grader: count = graded.get(section.get('type'), 0) if count < section.get('min_count', 0): changed = True section['min_count'] = count if changed: override_field_for_ccx(ccx, course, 'grading_policy', policy) # using CCX object as sender here. responses = SignalHandler.course_published.send( sender=ccx, course_key=CCXLocator.from_course_locator(course.id, str(ccx.id))) for rec, response in responses: log.info( 'Signal fired when course is published. Receiver: %s. Response: %s', rec, response) return HttpResponse( # lint-amnesty, pylint: disable=http-response-with-content-type-json, http-response-with-json-dumps json.dumps({ 'schedule': get_ccx_schedule(course, ccx), 'grading_policy': json.dumps(policy, indent=4) }), content_type='application/json', )
def save_ccx(request, course, ccx=None): """ Save changes to CCX. """ if not ccx: raise Http404 def override_fields(parent, data, graded, earliest=None, ccx_ids_to_delete=None): """ Recursively apply CCX schedule data to CCX by overriding the `visible_to_staff_only`, `start` and `due` fields for units in the course. """ if ccx_ids_to_delete is None: ccx_ids_to_delete = [] blocks = { str(child.location): child for child in parent.get_children()} for unit in data: block = blocks[unit['location']] override_field_for_ccx( ccx, block, 'visible_to_staff_only', unit['hidden']) start = parse_date(unit['start']) if start: if not earliest or start < earliest: earliest = start override_field_for_ccx(ccx, block, 'start', start) else: ccx_ids_to_delete.append(get_override_for_ccx(ccx, block, 'start_id')) clear_ccx_field_info_from_ccx_map(ccx, block, 'start') due = parse_date(unit['due']) if due: override_field_for_ccx(ccx, block, 'due', due) else: ccx_ids_to_delete.append(get_override_for_ccx(ccx, block, 'due_id')) clear_ccx_field_info_from_ccx_map(ccx, block, 'due') if not unit['hidden'] and block.graded: graded[block.format] = graded.get(block.format, 0) + 1 children = unit.get('children', None) # For a vertical, override start and due dates of all its problems. if unit.get('category', None) == u'vertical': for component in block.get_children(): # override start and due date of problem (Copy dates of vertical into problems) if start: override_field_for_ccx(ccx, component, 'start', start) if due: override_field_for_ccx(ccx, component, 'due', due) if children: override_fields(block, children, graded, earliest, ccx_ids_to_delete) return earliest, ccx_ids_to_delete graded = {} earliest, ccx_ids_to_delete = override_fields(course, json.loads(request.body), graded, []) bulk_delete_ccx_override_fields(ccx, ccx_ids_to_delete) if earliest: override_field_for_ccx(ccx, course, 'start', earliest) # Attempt to automatically adjust grading policy changed = False policy = get_override_for_ccx( ccx, course, 'grading_policy', course.grading_policy ) policy = deepcopy(policy) grader = policy['GRADER'] for section in grader: count = graded.get(section.get('type'), 0) if count < section.get('min_count', 0): changed = True section['min_count'] = count if changed: override_field_for_ccx(ccx, course, 'grading_policy', policy) return HttpResponse( json.dumps({ 'schedule': get_ccx_schedule(course, ccx), 'grading_policy': json.dumps(policy, indent=4)}), content_type='application/json', )
def save_ccx(request, course, ccx=None): """ Save changes to CCX. """ if not ccx: raise Http404 def override_fields(parent, data, graded, earliest=None, ccx_ids_to_delete=None): """ Recursively apply CCX schedule data to CCX by overriding the `visible_to_staff_only`, `start` and `due` fields for units in the course. """ if ccx_ids_to_delete is None: ccx_ids_to_delete = [] blocks = { str(child.location): child for child in parent.get_children()} for unit in data: block = blocks[unit['location']] override_field_for_ccx( ccx, block, 'visible_to_staff_only', unit['hidden']) start = parse_date(unit['start']) if start: if not earliest or start < earliest: earliest = start override_field_for_ccx(ccx, block, 'start', start) else: ccx_ids_to_delete.append(get_override_for_ccx(ccx, block, 'start_id')) clear_ccx_field_info_from_ccx_map(ccx, block, 'start') # Only subsection (aka sequential) and unit (aka vertical) have due dates. if 'due' in unit: # checking that the key (due) exist in dict (unit). due = parse_date(unit['due']) if due: override_field_for_ccx(ccx, block, 'due', due) else: ccx_ids_to_delete.append(get_override_for_ccx(ccx, block, 'due_id')) clear_ccx_field_info_from_ccx_map(ccx, block, 'due') else: # In case of section aka chapter we do not have due date. ccx_ids_to_delete.append(get_override_for_ccx(ccx, block, 'due_id')) clear_ccx_field_info_from_ccx_map(ccx, block, 'due') if not unit['hidden'] and block.graded: graded[block.format] = graded.get(block.format, 0) + 1 children = unit.get('children', None) # For a vertical, override start and due dates of all its problems. if unit.get('category', None) == u'vertical': for component in block.get_children(): # override start and due date of problem (Copy dates of vertical into problems) if start: override_field_for_ccx(ccx, component, 'start', start) if due: override_field_for_ccx(ccx, component, 'due', due) if children: override_fields(block, children, graded, earliest, ccx_ids_to_delete) return earliest, ccx_ids_to_delete graded = {} earliest, ccx_ids_to_delete = override_fields(course, json.loads(request.body), graded, []) bulk_delete_ccx_override_fields(ccx, ccx_ids_to_delete) if earliest: override_field_for_ccx(ccx, course, 'start', earliest) # Attempt to automatically adjust grading policy changed = False policy = get_override_for_ccx( ccx, course, 'grading_policy', course.grading_policy ) policy = deepcopy(policy) grader = policy['GRADER'] for section in grader: count = graded.get(section.get('type'), 0) if count < section.get('min_count', 0): changed = True section['min_count'] = count if changed: override_field_for_ccx(ccx, course, 'grading_policy', policy) return HttpResponse( json.dumps({ 'schedule': get_ccx_schedule(course, ccx), 'grading_policy': json.dumps(policy, indent=4)}), content_type='application/json', )
def save_ccx(request, course, ccx=None): """ Save changes to CCX. """ if not ccx: raise Http404 def override_fields(parent, data, graded, earliest=None, ccx_ids_to_delete=None): """ Recursively apply CCX schedule data to CCX by overriding the `visible_to_staff_only`, `start` and `due` fields for units in the course. """ if ccx_ids_to_delete is None: ccx_ids_to_delete = [] blocks = {str(child.location): child for child in parent.get_children()} for unit in data: block = blocks[unit["location"]] override_field_for_ccx(ccx, block, "visible_to_staff_only", unit["hidden"]) start = parse_date(unit["start"]) if start: if not earliest or start < earliest: earliest = start override_field_for_ccx(ccx, block, "start", start) else: ccx_ids_to_delete.append(get_override_for_ccx(ccx, block, "start_id")) clear_ccx_field_info_from_ccx_map(ccx, block, "start") due = parse_date(unit["due"]) if due: override_field_for_ccx(ccx, block, "due", due) else: ccx_ids_to_delete.append(get_override_for_ccx(ccx, block, "due_id")) clear_ccx_field_info_from_ccx_map(ccx, block, "due") if not unit["hidden"] and block.graded: graded[block.format] = graded.get(block.format, 0) + 1 children = unit.get("children", None) # For a vertical, override start and due dates of all its problems. if unit.get("category", None) == u"vertical": for component in block.get_children(): # override start and due date of problem (Copy dates of vertical into problems) if start: override_field_for_ccx(ccx, component, "start", start) if due: override_field_for_ccx(ccx, component, "due", due) if children: override_fields(block, children, graded, earliest, ccx_ids_to_delete) return earliest, ccx_ids_to_delete graded = {} earliest, ccx_ids_to_delete = override_fields(course, json.loads(request.body), graded, []) bulk_delete_ccx_override_fields(ccx, ccx_ids_to_delete) if earliest: override_field_for_ccx(ccx, course, "start", earliest) # Attempt to automatically adjust grading policy changed = False policy = get_override_for_ccx(ccx, course, "grading_policy", course.grading_policy) policy = deepcopy(policy) grader = policy["GRADER"] for section in grader: count = graded.get(section.get("type"), 0) if count < section.get("min_count", 0): changed = True section["min_count"] = count if changed: override_field_for_ccx(ccx, course, "grading_policy", policy) return HttpResponse( json.dumps({"schedule": get_ccx_schedule(course, ccx), "grading_policy": json.dumps(policy, indent=4)}), content_type="application/json", )