Exemplo n.º 1
0
def edit_subsection(request, location):
    # check that we have permissions to edit this item
    course = get_course_for_item(location)
    if not has_access(request.user, course.location):
        raise PermissionDenied()

    item = modulestore().get_item(location, depth=1)

    lms_link = get_lms_link_for_item(
        location, course_id=course.location.course_id)
    preview_link = get_lms_link_for_item(
        location, course_id=course.location.course_id, preview=True)

    # make sure that location references a 'sequential', otherwise return
    # BadRequest
    if item.location.category != 'sequential':
        return HttpResponseBadRequest()

    parent_locs = modulestore().get_parent_locations(location, None)

    # we're for now assuming a single parent
    if len(parent_locs) != 1:
        logging.error(
            'Multiple (or none) parents have been found for {0}'.format(location))

    # this should blow up if we don't find any parents, which would be
    # erroneous
    parent = modulestore().get_item(parent_locs[0])

    # remove all metadata from the generic dictionary that is presented in a
    # more normalized UI

    policy_metadata = dict(
        (field.name, field.read_from(item))
        for field
        in item.fields
        if field.name not in ['display_name', 'start', 'due', 'format'] and field.scope == Scope.settings
    )

    can_view_live = False
    subsection_units = item.get_children()
    for unit in subsection_units:
        state = compute_unit_state(unit)
        if state == UnitState.public or state == UnitState.draft:
            can_view_live = True
            break

    return render_to_response('edit_subsection.html',
                              {'subsection': item,
                               'context_course': course,
                               'create_new_unit_template': Location('i4x', 'edx', 'templates', 'vertical', 'Empty'),
                               'lms_link': lms_link,
                               'preview_link': preview_link,
                               'course_graders': json.dumps(CourseGradingModel.fetch(course.location).graders),
                               'parent_location': course.location,
                               'parent_item': parent,
                               'policy_metadata': policy_metadata,
                               'subsection_units': subsection_units,
                               'can_view_live': can_view_live
                               })
Exemplo n.º 2
0
def edit_unit(request, location):
    """
    Display an editing page for the specified module.

    Expects a GET request with the parameter 'id'.

    id: A Location URL
    """
    try:
        course = get_course_for_item(location)
    except InvalidLocationError:
        return HttpResponseBadRequest()

    if not has_access(request.user, course.location):
        raise PermissionDenied()

    try:
        item = modulestore().get_item(location, depth=1)
    except ItemNotFoundError:
        return HttpResponseBadRequest()

    lms_link = get_lms_link_for_item(item.location,
                                     course_id=course.location.course_id)

    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_advanced_keys = course.advanced_modules

    # 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:
        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_with_default, template.location.url(),
                 hasattr(template, 'markdown')
                 and template.markdown is not None))

    components = [
        component.location.url() for component in item.get_children()
    ]

    # TODO (cpennington): If we share units between courses,
    # this will need to change to check permissions correctly so as
    # to pick the correct parent subsection

    containing_subsection_locs = modulestore().get_parent_locations(
        location, None)
    containing_subsection = modulestore().get_item(
        containing_subsection_locs[0])

    containing_section_locs = modulestore().get_parent_locations(
        containing_subsection.location, None)
    containing_section = modulestore().get_item(containing_section_locs[0])

    # cdodge hack. We're having trouble previewing drafts via jump_to redirect
    # so let's generate the link url here

    # need to figure out where this item is in the list of children as the preview will need this
    index = 1
    for child in containing_subsection.get_children():
        if child.location == item.location:
            break
        index = index + 1

    preview_lms_base = settings.MITX_FEATURES.get('PREVIEW_LMS_BASE')

    preview_lms_link = '//{preview_lms_base}/courses/{org}/{course}/{course_name}/courseware/{section}/{subsection}/{index}'.format(
        preview_lms_base=preview_lms_base,
        lms_base=settings.LMS_BASE,
        org=course.location.org,
        course=course.location.course,
        course_name=course.location.name,
        section=containing_section.location.name,
        subsection=containing_subsection.location.name,
        index=index)

    unit_state = compute_unit_state(item)

    return render_to_response(
        'unit.html', {
            'context_course':
            course,
            'active_tab':
            'courseware',
            'unit':
            item,
            'unit_location':
            location,
            'components':
            components,
            'component_templates':
            component_templates,
            'draft_preview_link':
            preview_lms_link,
            'published_preview_link':
            lms_link,
            'subsection':
            containing_subsection,
            'release_date':
            get_default_time_display(containing_subsection.lms.start)
            if containing_subsection.lms.start is not None else None,
            'section':
            containing_section,
            'create_new_unit_template':
            Location('i4x', 'edx', 'templates', 'vertical', 'Empty'),
            'unit_state':
            unit_state,
            'published_date':
            item.cms.published_date.strftime('%B %d, %Y')
            if item.cms.published_date is not None else None,
        })
Exemplo n.º 3
0
def edit_subsection(request, location):
    "Edit the subsection of a course"
    # check that we have permissions to edit this item
    try:
        course = get_course_for_item(location)
    except InvalidLocationError:
        return HttpResponseBadRequest()

    if not has_access(request.user, course.location):
        raise PermissionDenied()

    try:
        item = modulestore().get_item(location, depth=1)
    except ItemNotFoundError:
        return HttpResponseBadRequest()

    lms_link = get_lms_link_for_item(location, course_id=course.location.course_id)
    preview_link = get_lms_link_for_item(location, course_id=course.location.course_id, preview=True)

    # make sure that location references a 'sequential', otherwise return
    # BadRequest
    if item.location.category != 'sequential':
        return HttpResponseBadRequest()

    parent_locs = modulestore().get_parent_locations(location, None)

    # we're for now assuming a single parent
    if len(parent_locs) != 1:
        logging.error(
            'Multiple (or none) parents have been found for %s',
            location
        )

    # this should blow up if we don't find any parents, which would be erroneous
    parent = modulestore().get_item(parent_locs[0])

    # remove all metadata from the generic dictionary that is presented in a
    # more normalized UI. We only want to display the XBlocks fields, not
    # the fields from any mixins that have been added
    fields = getattr(item, 'unmixed_class', item.__class__).fields

    policy_metadata = dict(
        (field.name, field.read_from(item))
        for field
        in fields.values()
        if field.name not in ['display_name', 'start', 'due', 'format']
        and field.scope == Scope.settings
    )

    can_view_live = False
    subsection_units = item.get_children()
    for unit in subsection_units:
        state = compute_unit_state(unit)
        if state == UnitState.public or state == UnitState.draft:
            can_view_live = True
            break

    course_locator = loc_mapper().translate_location(
        course.location.course_id, course.location, False, True
    )
    locator = loc_mapper().translate_location(
        course.location.course_id, item.location, False, True
    )

    return render_to_response(
        'edit_subsection.html',
        {
            'subsection': item,
            'context_course': course,
            'new_unit_category': 'vertical',
            'lms_link': lms_link,
            'preview_link': preview_link,
            'course_graders': json.dumps(CourseGradingModel.fetch(course_locator).graders),
            'parent_item': parent,
            'locator': locator,
            'policy_metadata': policy_metadata,
            'subsection_units': subsection_units,
            'can_view_live': can_view_live
        }
    )
Exemplo n.º 4
0
def edit_unit(request, location):
    """
    Display an editing page for the specified module.

    Expects a GET request with the parameter `id`.

    id: A Location URL
    """
    try:
        course = get_course_for_item(location)
    except InvalidLocationError:
        return HttpResponseBadRequest()

    if not has_access(request.user, course.location):
        raise PermissionDenied()

    try:
        item = modulestore().get_item(location, depth=1)
    except ItemNotFoundError:
        return HttpResponseBadRequest()
    lms_link = get_lms_link_for_item(
        item.location,
        course_id=course.location.course_id
    )

    # Note that the unit_state (draft, public, private) does not match up with the published value
    # passed to translate_location. The two concepts are different at this point.
    unit_locator = loc_mapper().translate_location(
        course.location.course_id, Location(location), False, True
    )

    component_templates = defaultdict(list)
    for category in COMPONENT_TYPES:
        component_class = load_mixed_class(category)
        # add the default template
        # TODO: Once mixins are defined per-application, rather than per-runtime,
        # this should use a cms mixed-in class. (cpennington)
        if hasattr(component_class, 'display_name'):
            display_name = component_class.display_name.default or 'Blank'
        else:
            display_name = 'Blank'
        component_templates[category].append((
            display_name,
            category,
            False,  # No defaults have markdown (hardcoded current default)
            None  # no boilerplate for overrides
        ))
        # add boilerplates
        if hasattr(component_class, 'templates'):
            for template in component_class.templates():
                filter_templates = getattr(component_class, 'filter_templates', None)
                if not filter_templates or filter_templates(template, course):
                    component_templates[category].append((
                        template['metadata'].get('display_name'),
                        category,
                        template['metadata'].get('markdown') is not None,
                        template.get('template_id')
                    ))

    # 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_advanced_keys = course.advanced_modules

    # Set component types according to course policy file
    if isinstance(course_advanced_keys, list):
        for category in course_advanced_keys:
            if category in ADVANCED_COMPONENT_TYPES:
                # Do I need to allow for boilerplates or just defaults on the
                # class? i.e., can an advanced have more than one entry in the
                # menu? one for default and others for prefilled boilerplates?
                try:
                    component_class = load_mixed_class(category)

                    component_templates['advanced'].append((
                        component_class.display_name.default or category,
                        category,
                        False,
                        None  # don't override default data
                    ))
                except PluginMissingError:
                    # dhm: I got this once but it can happen any time the
                    # course author configures an advanced component which does
                    # not exist on the server. This code here merely
                    # prevents any authors from trying to instantiate the
                    # non-existent component type by not showing it in the menu
                    pass
    else:
        log.error(
            "Improper format for course advanced keys! %s",
            course_advanced_keys
        )

    components = [
        [
            component.location.url(),
            loc_mapper().translate_location(
                course.location.course_id, component.location, False, True
            )
        ]
        for component
        in item.get_children()
    ]

    # TODO (cpennington): If we share units between courses,
    # this will need to change to check permissions correctly so as
    # to pick the correct parent subsection

    containing_subsection_locs = modulestore().get_parent_locations(location, None)
    containing_subsection = modulestore().get_item(containing_subsection_locs[0])
    containing_section_locs = modulestore().get_parent_locations(
        containing_subsection.location, None
    )
    containing_section = modulestore().get_item(containing_section_locs[0])

    # cdodge hack. We're having trouble previewing drafts via jump_to redirect
    # so let's generate the link url here

    # need to figure out where this item is in the list of children as the
    # preview will need this
    index = 1
    for child in containing_subsection.get_children():
        if child.location == item.location:
            break
        index = index + 1

    preview_lms_base = settings.MITX_FEATURES.get('PREVIEW_LMS_BASE')

    preview_lms_link = (
        '//{preview_lms_base}/courses/{org}/{course}/'
        '{course_name}/courseware/{section}/{subsection}/{index}'
    ).format(
        preview_lms_base=preview_lms_base,
        lms_base=settings.LMS_BASE,
        org=course.location.org,
        course=course.location.course,
        course_name=course.location.name,
        section=containing_section.location.name,
        subsection=containing_subsection.location.name,
        index=index
    )

    return render_to_response('unit.html', {
        'context_course': course,
        'unit': item,
        # Still needed for creating a draft.
        'unit_location': location,
        'unit_locator': unit_locator,
        'components': components,
        'component_templates': component_templates,
        'draft_preview_link': preview_lms_link,
        'published_preview_link': lms_link,
        'subsection': containing_subsection,
        'release_date': (
            get_default_time_display(containing_subsection.start)
            if containing_subsection.start is not None else None
        ),
        'section': containing_section,
        'new_unit_category': 'vertical',
        'unit_state': compute_unit_state(item),
        'published_date': (
            get_default_time_display(item.published_date)
            if item.published_date is not None else None
        ),
    })
Exemplo n.º 5
0
def edit_subsection(request, location):
    "Edit the subsection of a course"
    # check that we have permissions to edit this item
    try:
        course = get_course_for_item(location)
    except InvalidLocationError:
        return HttpResponseBadRequest()

    if not has_access(request.user, course.location):
        raise PermissionDenied()

    try:
        item = modulestore().get_item(location, depth=1)
    except ItemNotFoundError:
        return HttpResponseBadRequest()

    lms_link = get_lms_link_for_item(
            location, course_id=course.location.course_id
    )
    preview_link = get_lms_link_for_item(
            location, course_id=course.location.course_id, preview=True
    )

    # make sure that location references a 'sequential', otherwise return
    # BadRequest
    if item.location.category != 'sequential':
        return HttpResponseBadRequest()

    parent_locs = modulestore().get_parent_locations(location, None)

    # we're for now assuming a single parent
    if len(parent_locs) != 1:
        logging.error(
                'Multiple (or none) parents have been found for %', 
                location
        )

    # this should blow up if we don't find any parents, which would be erroneous
    parent = modulestore().get_item(parent_locs[0])
    sections = modulestore().get_item(course.location, depth=3).get_children()

    #for section in sections:
    #   print section.display_name_with_default
    #    subsections = section.get_children()
    #    for subsection in subsections:
    #        print subsection.display_name_with_default


    # remove all metadata from the generic dictionary that is presented in a
    # more normalized UI

    policy_metadata = dict(
        (field.name, field.read_from(item))
        for field
        in item.fields

        if field.name not in ['display_name', 'start', 'due', 'format', 'unlock_term']
            and field.scope == Scope.settings

    )

    #item.unlock_term = '{"disjunctions":[]}'
    term = json.loads(item.unlock_term)


    # updating if term has links to already not existed sections
    for disjunction in term["disjunctions"]:
        for conjunction in disjunction["conjunctions"]:
            if not is_section_exist(conjunction["source_section_id"], sections):
                disjunction["conjunctions"].remove(conjunction)

    item.unlock_term = json.dumps(term)

    can_view_live = False
    subsection_units = item.get_children()
    for unit in subsection_units:
        state = compute_unit_state(unit)
        if state == UnitState.public or state == UnitState.draft:
            can_view_live = True
            break


    return render_to_response('edit_subsection.html',
                              {'subsection': item,
                               'context_course': course,
                               'new_unit_category': 'vertical',
                               'lms_link': lms_link,
                               'preview_link': preview_link,
                               'course_graders': json.dumps(CourseGradingModel.fetch(course.location).graders),
                               'parent_location': course.location,
                               'parent_item': parent,
                               'policy_metadata': policy_metadata,
                               'subsection_units': subsection_units,
                               'sections': sections,
                               'can_view_live': can_view_live
                               })
Exemplo n.º 6
0
def edit_subsection(request, location):
    "Edit the subsection of a course"
    # check that we have permissions to edit this item
    try:
        course = get_course_for_item(location)
    except InvalidLocationError:
        return HttpResponseBadRequest()

    if not has_access(request.user, course.location):
        raise PermissionDenied()

    try:
        item = modulestore().get_item(location, depth=1)
    except ItemNotFoundError:
        return HttpResponseBadRequest()

    lms_link = get_lms_link_for_item(location, course_id=course.location.course_id)
    preview_link = get_lms_link_for_item(location, course_id=course.location.course_id, preview=True)

    # make sure that location references a 'sequential', otherwise return BadRequest
    if item.location.category != "sequential":
        return HttpResponseBadRequest()

    parent_locs = modulestore().get_parent_locations(location, None)

    # we're for now assuming a single parent
    if len(parent_locs) != 1:
        logging.error("Multiple (or none) parents have been found for {0}".format(location))

    # this should blow up if we don't find any parents, which would be erroneous
    parent = modulestore().get_item(parent_locs[0])

    # remove all metadata from the generic dictionary that is presented in a more normalized UI

    policy_metadata = dict(
        (field.name, field.read_from(item))
        for field in item.fields
        if field.name not in ["display_name", "start", "due", "format"] and field.scope == Scope.settings
    )

    can_view_live = False
    subsection_units = item.get_children()
    for unit in subsection_units:
        state = compute_unit_state(unit)
        if state == UnitState.public or state == UnitState.draft:
            can_view_live = True
            break

    return render_to_response(
        "edit_subsection.html",
        {
            "subsection": item,
            "context_course": course,
            "new_unit_category": "vertical",
            "lms_link": lms_link,
            "preview_link": preview_link,
            "course_graders": json.dumps(CourseGradingModel.fetch(course.location).graders),
            "parent_location": course.location,
            "parent_item": parent,
            "policy_metadata": policy_metadata,
            "subsection_units": subsection_units,
            "can_view_live": can_view_live,
        },
    )
Exemplo n.º 7
0
def edit_unit(request, location):
    """
    Display an editing page for the specified module.

    Expects a GET request with the parameter 'id'.

    id: A Location URL
    """
    try:
        course = get_course_for_item(location)
    except InvalidLocationError:
        return HttpResponseBadRequest()

    if not has_access(request.user, course.location):
        raise PermissionDenied()

    try:
        item = modulestore().get_item(location, depth=1)
    except ItemNotFoundError:
        return HttpResponseBadRequest()
    lms_link = get_lms_link_for_item(item.location, course_id=course.location.course_id)

    component_templates = defaultdict(list)
    for category in COMPONENT_TYPES:
        component_class = XModuleDescriptor.load_class(category)
        # add the default template
        component_templates[category].append(
            (
                component_class.display_name.default or "Blank",
                category,
                False,  # No defaults have markdown (hardcoded current default)
                None,  # no boilerplate for overrides
            )
        )
        # add boilerplates
        for template in component_class.templates():
            component_templates[category].append(
                (
                    template["metadata"].get("display_name"),
                    category,
                    template["metadata"].get("markdown") is not None,
                    template.get("template_id"),
                )
            )

    # 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_advanced_keys = course.advanced_modules

    # Set component types according to course policy file
    if isinstance(course_advanced_keys, list):
        for category in course_advanced_keys:
            if category in ADVANCED_COMPONENT_TYPES:
                # Do I need to allow for boilerplates or just defaults on the class? i.e., can an advanced
                # have more than one entry in the menu? one for default and others for prefilled boilerplates?
                try:
                    component_class = XModuleDescriptor.load_class(category)

                    component_templates["advanced"].append(
                        (
                            component_class.display_name.default or category,
                            category,
                            False,
                            None,  # don't override default data
                        )
                    )
                except PluginMissingError:
                    # dhm: I got this once but it can happen any time the course author configures
                    # an advanced component which does not exist on the server. This code here merely
                    # prevents any authors from trying to instantiate the non-existent component type
                    # by not showing it in the menu
                    pass
    else:
        log.error("Improper format for course advanced keys! {0}".format(course_advanced_keys))

    components = [component.location.url() for component in item.get_children()]

    # TODO (cpennington): If we share units between courses,
    # this will need to change to check permissions correctly so as
    # to pick the correct parent subsection

    containing_subsection_locs = modulestore().get_parent_locations(location, None)
    containing_subsection = modulestore().get_item(containing_subsection_locs[0])

    containing_section_locs = modulestore().get_parent_locations(containing_subsection.location, None)
    containing_section = modulestore().get_item(containing_section_locs[0])

    # cdodge hack. We're having trouble previewing drafts via jump_to redirect
    # so let's generate the link url here

    # need to figure out where this item is in the list of children as the preview will need this
    index = 1
    for child in containing_subsection.get_children():
        if child.location == item.location:
            break
        index = index + 1

    preview_lms_base = settings.MITX_FEATURES.get("PREVIEW_LMS_BASE")

    preview_lms_link = "//{preview_lms_base}/courses/{org}/{course}/{course_name}/courseware/{section}/{subsection}/{index}".format(
        preview_lms_base=preview_lms_base,
        lms_base=settings.LMS_BASE,
        org=course.location.org,
        course=course.location.course,
        course_name=course.location.name,
        section=containing_section.location.name,
        subsection=containing_subsection.location.name,
        index=index,
    )

    unit_state = compute_unit_state(item)

    return render_to_response(
        "unit.html",
        {
            "context_course": course,
            "unit": item,
            "unit_location": location,
            "components": components,
            "component_templates": component_templates,
            "draft_preview_link": preview_lms_link,
            "published_preview_link": lms_link,
            "subsection": containing_subsection,
            "release_date": get_default_time_display(containing_subsection.lms.start)
            if containing_subsection.lms.start is not None
            else None,
            "section": containing_section,
            "new_unit_category": "vertical",
            "unit_state": unit_state,
            "published_date": get_default_time_display(item.cms.published_date)
            if item.cms.published_date is not None
            else None,
        },
    )
Exemplo n.º 8
0
def edit_unit(request, location):
    """
    Display an editing page for the specified module.

    Expects a GET request with the parameter 'id'.

    id: A Location URL
    """
    course = get_course_for_item(location)
    if not has_access(request.user, course.location):
        raise PermissionDenied()

    item = modulestore().get_item(location, depth=1)

    lms_link = get_lms_link_for_item(item.location, course_id=course.location.course_id)

    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_advanced_keys = course.advanced_modules

    # 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:
        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_with_default,
                template.location.url(),
                hasattr(template, 'markdown') and template.markdown is not None
            ))

    components = [
        component.location.url()
        for component
        in item.get_children()
    ]

    # TODO (cpennington): If we share units between courses,
    # this will need to change to check permissions correctly so as
    # to pick the correct parent subsection

    containing_subsection_locs = modulestore().get_parent_locations(location, None)
    containing_subsection = modulestore().get_item(containing_subsection_locs[0])

    containing_section_locs = modulestore().get_parent_locations(containing_subsection.location, None)
    containing_section = modulestore().get_item(containing_section_locs[0])

    # cdodge hack. We're having trouble previewing drafts via jump_to redirect
    # so let's generate the link url here

    # need to figure out where this item is in the list of children as the preview will need this
    index = 1
    for child in containing_subsection.get_children():
        if child.location == item.location:
            break
        index = index + 1

    preview_lms_base = settings.MITX_FEATURES.get('PREVIEW_LMS_BASE')

    preview_lms_link = '//{preview_lms_base}/courses/{org}/{course}/{course_name}/courseware/{section}/{subsection}/{index}'.format(
        preview_lms_base=preview_lms_base,
        lms_base=settings.LMS_BASE,
        org=course.location.org,
        course=course.location.course,
        course_name=course.location.name,
        section=containing_section.location.name,
        subsection=containing_subsection.location.name,
        index=index)

    unit_state = compute_unit_state(item)

    return render_to_response('unit.html', {
        'context_course': course,
        'active_tab': 'courseware',
        'unit': item,
        'unit_location': location,
        'components': components,
        'component_templates': component_templates,
        'draft_preview_link': preview_lms_link,
        'published_preview_link': lms_link,
        'subsection': containing_subsection,
        'release_date': get_default_time_display(containing_subsection.lms.start) if containing_subsection.lms.start is not None else None,
        'section': containing_section,
        'create_new_unit_template': Location('i4x', 'edx', 'templates', 'vertical', 'Empty'),
        'unit_state': unit_state,
        'published_date': item.cms.published_date.strftime('%B %d, %Y') if item.cms.published_date is not None else None,
    })
Exemplo n.º 9
0
def edit_unit(request, location):
    """
    Display an editing page for the specified module.

    Expects a GET request with the parameter `id`.

    id: A Location URL
    """
    try:
        course = get_course_for_item(location)
    except InvalidLocationError:
        return HttpResponseBadRequest()

    if not has_access(request.user, course.location):
        raise PermissionDenied()

    try:
        item = modulestore().get_item(location, depth=1)
    except ItemNotFoundError:
        return HttpResponseBadRequest()
    lms_link = get_lms_link_for_item(
            item.location,
            course_id=course.location.course_id
    )

    component_templates = defaultdict(list)
    for category in COMPONENT_TYPES:
        component_class = XModuleDescriptor.load_class(category)
        # add the default template
        component_templates[category].append((
            component_class.display_name.default or 'Blank',
            category,
            False,  # No defaults have markdown (hardcoded current default)
            None  # no boilerplate for overrides
        ))
        # add boilerplates
        for template in component_class.templates():
            component_templates[category].append((
                template['metadata'].get('display_name'),
                category,
                template['metadata'].get('markdown') is not None,
                template.get('template_id')
            ))

    # 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_advanced_keys = course.advanced_modules

    # Set component types according to course policy file
    if isinstance(course_advanced_keys, list):
        for category in course_advanced_keys:
            if category in ADVANCED_COMPONENT_TYPES:
                # Do I need to allow for boilerplates or just defaults on the
                # class? i.e., can an advanced have more than one entry in the
                # menu? one for default and others for prefilled boilerplates?
                try:
                    component_class = XModuleDescriptor.load_class(category)

                    component_templates['advanced'].append((
                        component_class.display_name.default or category,
                        category,
                        False,
                        None  # don't override default data
                        ))
                except PluginMissingError:
                    # dhm: I got this once but it can happen any time the
                    # course author configures an advanced component which does
                    # not exist on the server. This code here merely
                    # prevents any authors from trying to instantiate the
                    # non-existent component type by not showing it in the menu
                    pass
    else:
        log.error(
            "Improper format for course advanced keys! %",
            course_advanced_keys
        )

    components = [
        component.location.url()
        for component
        in item.get_children()
    ]

    # TODO (cpennington): If we share units between courses,
    # this will need to change to check permissions correctly so as
    # to pick the correct parent subsection

    containing_subsection_locs = modulestore().get_parent_locations(
            location, None
    )
    containing_subsection = modulestore().get_item(containing_subsection_locs[0])
    containing_section_locs = modulestore().get_parent_locations(
            containing_subsection.location, None
    )
    containing_section = modulestore().get_item(containing_section_locs[0])

    # cdodge hack. We're having trouble previewing drafts via jump_to redirect
    # so let's generate the link url here

    # need to figure out where this item is in the list of children as the
    # preview will need this
    index = 1
    for child in containing_subsection.get_children():
        if child.location == item.location:
            break
        index = index + 1

    preview_lms_base = settings.MITX_FEATURES.get('PREVIEW_LMS_BASE')

    preview_lms_link = (
            '//{preview_lms_base}/courses/{org}/{course}/'
            '{course_name}/courseware/{section}/{subsection}/{index}'
        ).format(
            preview_lms_base=preview_lms_base,
            lms_base=settings.LMS_BASE,
            org=course.location.org,
            course=course.location.course,
            course_name=course.location.name,
            section=containing_section.location.name,
            subsection=containing_subsection.location.name,
            index=index
        )

    unit_state = compute_unit_state(item)

    return render_to_response('unit.html', {
        'context_course': course,
        'unit': item,
        'unit_location': location,
        'components': components,
        'component_templates': component_templates,
        'draft_preview_link': preview_lms_link,
        'published_preview_link': lms_link,
        'subsection': containing_subsection,
        'release_date': get_default_time_display(containing_subsection.lms.start)
            if containing_subsection.lms.start is not None else None,
        'section': containing_section,
        'new_unit_category': 'vertical',
        'unit_state': unit_state,
        'published_date': get_default_time_display(item.cms.published_date)
            if item.cms.published_date is not None else None
    })
Exemplo n.º 10
0
def edit_subsection(request, location):
    "Edit the subsection of a course"
    # check that we have permissions to edit this item
    try:
        course = get_course_for_item(location)
    except InvalidLocationError:
        return HttpResponseBadRequest()

    if not has_access(request.user, course.location):
        raise PermissionDenied()

    try:
        item = modulestore().get_item(location, depth=1)
    except ItemNotFoundError:
        return HttpResponseBadRequest()

    lms_link = get_lms_link_for_item(
            location, course_id=course.location.course_id
    )
    preview_link = get_lms_link_for_item(
            location, course_id=course.location.course_id, preview=True
    )

    # make sure that location references a 'sequential', otherwise return
    # BadRequest
    if item.location.category != 'sequential':
        return HttpResponseBadRequest()

    parent_locs = modulestore().get_parent_locations(location, None)

    # we're for now assuming a single parent
    if len(parent_locs) != 1:
        logging.error(
                'Multiple (or none) parents have been found for %s',
                location
        )

    # this should blow up if we don't find any parents, which would be erroneous
    parent = modulestore().get_item(parent_locs[0])

    # remove all metadata from the generic dictionary that is presented in a
    # more normalized UI. We only want to display the XBlocks fields, not
    # the fields from any mixins that have been added
    fields = getattr(item, 'unmixed_class', item.__class__).fields

    policy_metadata = dict(
        (field.name, field.read_from(item))
        for field
        in fields.values()
        if field.name not in ['display_name', 'start', 'due', 'format']
            and field.scope == Scope.settings
    )

    can_view_live = False
    subsection_units = item.get_children()
    for unit in subsection_units:
        state = compute_unit_state(unit)
        if state == UnitState.public or state == UnitState.draft:
            can_view_live = True
            break

    return render_to_response(
        'edit_subsection.html',
        {
           'subsection': item,
           'context_course': course,
           'new_unit_category': 'vertical',
           'lms_link': lms_link,
           'preview_link': preview_link,
           'course_graders': json.dumps(CourseGradingModel.fetch(course.location).graders),
           'parent_location': course.location,
           'parent_item': parent,
           'policy_metadata': policy_metadata,
           'subsection_units': subsection_units,
           'can_view_live': can_view_live
        }
    )