Ejemplo n.º 1
0
def edit_course_view(request, course, ccx, **kwargs):
    context = {
        'course': course,
        'ccx': ccx,
        'delivery_mode_choices': CustomCourseForEdX.DELIVERY_MODE_CHOICES,
        'enrollment_choices': CustomCourseForEdX.ENROLLMENT_TYPE_CHOICES,
    }

    context.update(get_ccx_creation_dict(course))
    context.update(edit_ccx_context(course, ccx, request.user))
    context['edit_current'] = True
    return render_to_response('ccx/coach_dashboard.html', context)
Ejemplo n.º 2
0
def dashboard(request, course, ccx=None):
    """
    Display the CCX Coach Dashboard.
    """
    # right now, we can only have one ccx per user and course
    # so, if no ccx is passed in, we can sefely redirect to that
    if ccx is None:
        ccx = get_ccx_for_coach(course, request.user)
        if ccx:
            url = reverse('ccx_coach_dashboard',
                          kwargs={
                              'course_id':
                              CCXLocator.from_course_locator(
                                  course.id, ccx.id)
                          })
            return redirect(url)

    context = {
        'course': course,
        'ccx': ccx,
    }
    context.update(get_ccx_creation_dict(course))

    if ccx:
        ccx_locator = CCXLocator.from_course_locator(course.id,
                                                     unicode(ccx.id))
        # At this point we are done with verification that current user is ccx coach.
        assign_coach_role_to_ccx(ccx_locator, request.user, course.id)

        schedule = get_ccx_schedule(course, ccx)
        grading_policy = get_override_for_ccx(ccx, course, 'grading_policy',
                                              course.grading_policy)
        context['schedule'] = json.dumps(schedule, indent=4)
        context['save_url'] = reverse('save_ccx',
                                      kwargs={'course_id': ccx_locator})
        context['ccx_members'] = CourseEnrollment.objects.filter(
            course_id=ccx_locator, is_active=True)
        context['gradebook_url'] = reverse('ccx_gradebook',
                                           kwargs={'course_id': ccx_locator})
        context['grades_csv_url'] = reverse('ccx_grades_csv',
                                            kwargs={'course_id': ccx_locator})
        context['grading_policy'] = json.dumps(grading_policy, indent=4)
        context['grading_policy_url'] = reverse(
            'ccx_set_grading_policy', kwargs={'course_id': ccx_locator})

        with ccx_course(ccx_locator) as course:
            context['course'] = course

    else:
        context['create_ccx_url'] = reverse('create_ccx',
                                            kwargs={'course_id': course.id})
    return render_to_response('ccx/coach_dashboard.html', context)
Ejemplo n.º 3
0
def dashboard(request, course, ccx=None):
    """
    Display the CCX Coach Dashboard.
    """
    # right now, we can only have one ccx per user and course
    # so, if no ccx is passed in, we can sefely redirect to that
    if ccx is None:
        ccx = get_ccx_for_coach(course, request.user)
        if ccx:
            url = reverse(
                'ccx_coach_dashboard',
                kwargs={
                    'course_id':
                    CCXLocator.from_course_locator(course.id, unicode(ccx.id))
                })
            return redirect(url)

    context = {
        'course': course,
        'ccx': ccx,
    }
    context.update(get_ccx_creation_dict(course))

    if ccx:
        ccx_locator = CCXLocator.from_course_locator(course.id,
                                                     unicode(ccx.id))
        # At this point we are done with verification that current user is ccx coach.
        assign_staff_role_to_ccx(ccx_locator, request.user, course.id)
        schedule = get_ccx_schedule(course, ccx)
        grading_policy = get_override_for_ccx(ccx, course, 'grading_policy',
                                              course.grading_policy)
        context['schedule'] = json.dumps(schedule, indent=4)
        context['save_url'] = reverse(
            'save_ccx', kwargs={'course_id': ccx_locator})
        context['ccx_members'] = CourseEnrollment.objects.filter(
            course_id=ccx_locator, is_active=True)
        context['gradebook_url'] = reverse(
            'ccx_gradebook', kwargs={'course_id': ccx_locator})
        context['grades_csv_url'] = reverse(
            'ccx_grades_csv', kwargs={'course_id': ccx_locator})
        context['grading_policy'] = json.dumps(grading_policy, indent=4)
        context['grading_policy_url'] = reverse(
            'ccx_set_grading_policy', kwargs={'course_id': ccx_locator})

        with ccx_course(ccx_locator) as course:
            context['course'] = course

    else:
        context['create_ccx_url'] = reverse(
            'create_ccx', kwargs={'course_id': course.id})
    return render_to_response('ccx/coach_dashboard.html', context)
def create_ccx(request, course, ccx=None):
    """
    Create a new CCX
    """
    name = request.POST.get('name')

    if hasattr(course, 'ccx_connector') and course.ccx_connector:
        # if ccx connector url is set in course settings then inform user that he can
        # only create ccx by using ccx connector url.
        context = get_ccx_creation_dict(course)
        messages.error(request, context['use_ccx_con_error_message'])
        return render_to_response('ccx/coach_dashboard.html', context)

    # prevent CCX objects from being created for deprecated course ids.
    if course.id.deprecated:
        messages.error(
            request,
            _("You cannot create a CCX from a course using a deprecated id. "
              "Please create a rerun of this course in the studio to allow "
              "this action."))
        url = reverse('ccx_coach_dashboard', kwargs={'course_id': course.id})
        return redirect(url)

    ccx = CustomCourseForEdX(course_id=course.id,
                             coach=request.user,
                             display_name=name)
    ccx.save()

    # Make sure start/due are overridden for entire course
    start = TODAY().replace(tzinfo=pytz.UTC)
    override_field_for_ccx(ccx, course, 'start', start)
    override_field_for_ccx(ccx, course, 'due', None)

    # Enforce a static limit for the maximum amount of students that can be enrolled
    override_field_for_ccx(ccx, course, 'max_student_enrollments_allowed',
                           settings.CCX_MAX_STUDENTS_ALLOWED)
    # Save display name explicitly
    override_field_for_ccx(ccx, course, 'display_name', name)

    # Hide anything that can show up in the schedule
    hidden = 'visible_to_staff_only'
    for chapter in course.get_children():
        override_field_for_ccx(ccx, chapter, hidden, True)
        for sequential in chapter.get_children():
            override_field_for_ccx(ccx, sequential, hidden, True)
            for vertical in sequential.get_children():
                override_field_for_ccx(ccx, vertical, hidden, True)

    ccx_id = CCXLocator.from_course_locator(course.id, str(ccx.id))

    # Create forum roles
    seed_permissions_roles(ccx_id)
    # Assign administrator forum role to CCX coach
    assign_role(ccx_id, request.user, FORUM_ROLE_ADMINISTRATOR)

    url = reverse('ccx_coach_dashboard', kwargs={'course_id': ccx_id})

    # Enroll the coach in the course
    email_params = get_email_params(course,
                                    auto_enroll=True,
                                    course_key=ccx_id,
                                    display_name=ccx.display_name)
    enroll_email(
        course_id=ccx_id,
        student_email=request.user.email,
        auto_enroll=True,
        email_students=True,
        email_params=email_params,
    )

    assign_staff_role_to_ccx(ccx_id, request.user, course.id)
    add_master_course_staff_to_ccx(course, ccx_id, ccx.display_name)

    # 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 redirect(url)
Ejemplo n.º 5
0
def create_ccx(request, course, ccx=None):
    """
    Create a new CCX
    """
    name = request.POST.get('name')

    if hasattr(course, 'ccx_connector') and course.ccx_connector:
        # if ccx connector url is set in course settings then inform user that he can
        # only create ccx by using ccx connector url.
        context = get_ccx_creation_dict(course)
        messages.error(request, context['use_ccx_con_error_message'])
        return render_to_response('ccx/coach_dashboard.html', context)

    # prevent CCX objects from being created for deprecated course ids.
    if course.id.deprecated:
        messages.error(request, _(
            "You cannot create a CCX from a course using a deprecated id. "
            "Please create a rerun of this course in the studio to allow "
            "this action."))
        url = reverse('ccx_coach_dashboard', kwargs={'course_id': course.id})
        return redirect(url)

    ccx = CustomCourseForEdX(
        course_id=course.id,
        coach=request.user,
        display_name=name)
    ccx.save()

    # Make sure start/due are overridden for entire course
    start = TODAY().replace(tzinfo=pytz.UTC)
    override_field_for_ccx(ccx, course, 'start', start)
    override_field_for_ccx(ccx, course, 'due', None)

    # Enforce a static limit for the maximum amount of students that can be enrolled
    override_field_for_ccx(ccx, course, 'max_student_enrollments_allowed', settings.CCX_MAX_STUDENTS_ALLOWED)

    # Hide anything that can show up in the schedule
    hidden = 'visible_to_staff_only'
    for chapter in course.get_children():
        override_field_for_ccx(ccx, chapter, hidden, True)
        for sequential in chapter.get_children():
            override_field_for_ccx(ccx, sequential, hidden, True)
            for vertical in sequential.get_children():
                override_field_for_ccx(ccx, vertical, hidden, True)

    ccx_id = CCXLocator.from_course_locator(course.id, unicode(ccx.id))

    # Create forum roles
    seed_permissions_roles(ccx_id)
    # Assign administrator forum role to CCX coach
    assign_role(ccx_id, request.user, FORUM_ROLE_ADMINISTRATOR)

    url = reverse('ccx_coach_dashboard', kwargs={'course_id': ccx_id})

    # Enroll the coach in the course
    email_params = get_email_params(course, auto_enroll=True, course_key=ccx_id, display_name=ccx.display_name)
    enroll_email(
        course_id=ccx_id,
        student_email=request.user.email,
        auto_enroll=True,
        email_students=True,
        email_params=email_params,
    )

    assign_staff_role_to_ccx(ccx_id, request.user, course.id)
    add_master_course_staff_to_ccx(course, ccx_id, ccx.display_name)

    # using CCX object as sender here.
    responses = SignalHandler.course_published.send(
        sender=ccx,
        course_key=CCXLocator.from_course_locator(course.id, unicode(ccx.id))
    )
    for rec, response in responses:
        log.info('Signal fired when course is published. Receiver: %s. Response: %s', rec, response)

    return redirect(url)
Ejemplo n.º 6
0
def create_ccx(request, course, ccx=None, **kwargs):
    """
    Create a new CCX
    """
    if not is_ccx_coach_on_master_course(
            request.user, course) or not request.user.profile.affiliate:
        return HttpResponseForbidden()

    affiliate_slug = request.POST.get('affiliate')
    name = request.POST.get('name')
    delivery_mode = request.POST.get('delivery_mode')
    location_city = request.POST.get('city')
    location_state = request.POST.get('state')
    location_postal_code = request.POST.get('postal_code')
    time = '{} {}Z'.format(request.POST.get('date'), request.POST.get('time'))
    enrollment_end_date = '{} {}Z'.format(
        request.POST.get('enrollment_end_date'),
        request.POST.get('enrollment_end_time'))
    end_date = '{} {}Z'.format(request.POST.get('end_date'),
                               request.POST.get('end_time'))
    fee = request.POST.get('fee')
    course_description = request.POST.get('course_description')
    enrollment_type = request.POST.get('enrollment_type')
    facilitators = dict(request.POST).get('facilitators')

    context = get_ccx_creation_dict(course)

    if not affiliate_slug:
        messages.error(request, 'Affiliate not selected.')
        return render_to_response('ccx/coach_dashboard.html', context)

    if not facilitators:
        messages.error(request, 'No facilitators added.')
        return render_to_response('ccx/coach_dashboard.html', context)

    if hasattr(course, 'ccx_connector') and course.ccx_connector:
        # if ccx connector url is set in course settings then inform user that he can
        # only create ccx by using ccx connector url.
        messages.error(request, context['use_ccx_con_error_message'])
        return render_to_response('ccx/coach_dashboard.html', context)

    # prevent CCX objects from being created for deprecated course ids.
    if course.id.deprecated:
        messages.error(
            request,
            _("You cannot create a CCX from a course using a deprecated id. "
              "Please create a rerun of this course in the studio to allow "
              "this action."))
        url = reverse('ccx_coach_dashboard', kwargs={'course_id': course.id})
        return redirect(url)

    affiliate = AffiliateEntity.objects.get(slug=affiliate_slug)
    if not request.user.is_staff and not AffiliateMembership.objects.filter(
            member=request.user,
            affiliate=affiliate,
            role__in=AffiliateMembership.STAFF_ROLES).exists():
        return HttpResponseForbidden()

    ccx = CustomCourseForEdX(affiliate=affiliate,
                             course_id=course.id,
                             coach=request.user,
                             display_name=name,
                             delivery_mode=delivery_mode,
                             location_city=location_city,
                             location_state=location_state,
                             location_postal_code=location_postal_code,
                             time=time,
                             enrollment_end_date=enrollment_end_date,
                             end_date=end_date,
                             fee=ast.literal_eval(fee),
                             enrollment_type=enrollment_type,
                             course_description=course_description)
    ccx.save()

    # we need this for authorization
    ccx.save()

    # Make sure start/due are overridden for entire course
    start = TODAY().replace(tzinfo=pytz.UTC)
    override_field_for_ccx(ccx, course, 'start', start)
    override_field_for_ccx(ccx, course, 'due', None)

    # Enforce a static limit for the maximum amount of students that can be enrolled
    override_field_for_ccx(ccx, course, 'max_student_enrollments_allowed',
                           settings.CCX_MAX_STUDENTS_ALLOWED)

    # Hide anything that can show up in the schedule
    hidden = 'visible_to_staff_only'
    for chapter in course.get_children():
        override_field_for_ccx(ccx, chapter, hidden, True)
        for sequential in chapter.get_children():
            override_field_for_ccx(ccx, sequential, hidden, True)
            for vertical in sequential.get_children():
                override_field_for_ccx(ccx, vertical, hidden, True)

    ccx_id = CCXLocator.from_course_locator(course.id, ccx.pk)

    url = reverse('ccx_coach_dashboard', kwargs={'course_id': ccx_id})

    # Enroll the coach in the course
    email_params = get_email_params(course,
                                    auto_enroll=True,
                                    course_key=ccx_id,
                                    display_name=ccx.display_name)
    enroll_email(
        course_id=ccx_id,
        student_email=request.user.email,
        auto_enroll=True,
        email_students=True,
        email_params=email_params,
    )

    # Add facilitators
    if facilitators:
        course_obj = get_course_by_id(ccx.ccx_course_id, depth=None)
        facilitator_ids = [int(i) for i in facilitators]

        for user_id in facilitator_ids:
            user = User.objects.get(id=user_id)
            enroll_email(course_id=ccx_id,
                         student_email=user.email,
                         auto_enroll=True,
                         email_students=True,
                         email_params=email_params)
            allow_access(course_obj, user, AffiliateMembership.CCX_COACH,
                         False)

    return redirect(url)
Ejemplo n.º 7
0
def dashboard(request, course, ccx=None, **kwargs):
    """
    Display the CCX Coach Dashboard
    """
    partial_course_key = settings.FASTTRAC_COURSE_KEY.split(':')[1]
    affiliate_slug = request.GET.get('affiliate')
    affiliate = None
    facilitators = None
    if affiliate_slug:
        affiliate = AffiliateEntity.objects.get(slug=affiliate_slug)
        facilitators = get_facilitators(affiliate)

    context = {
        'course': course,
        'ccx': ccx,
        'STATE_CHOICES': STATE_CHOICES,
        'delivery_mode_choices': CustomCourseForEdX.DELIVERY_MODE_CHOICES,
        'enrollment_choices': CustomCourseForEdX.ENROLLMENT_TYPE_CHOICES,
        'is_instructor': False,
        'is_ccx_coach': False,
        'is_staff': False,
        'is_from_fasttrac_course': partial_course_key in unicode(course.id),
        'facilitators': facilitators,
        'affiliate': affiliate
    }

    context.update(get_ccx_creation_dict(course))

    if ccx:
        context.update(edit_ccx_context(course, ccx, request.user))
        ccx_locator = ccx.ccx_course_id

        context['affiliate_entity'] = ccx.affiliate
        context['is_ccx_coach'] = ccx.coach == request.user
        context['is_instructor'] = ccx.is_instructor(request.user)
        context['is_staff'] = ccx.is_staff(request.user)

        context['ccx_coach_permissions'] = CourseAccessRole.objects.filter(
            course_id=ccx_locator, role='ccx_coach')

        context['edit_current'] = False

        non_student_user_ids = CourseAccessRole.objects.filter(
            course_id=ccx_locator).values_list('user_id', flat=True)
        ccx_student_enrollments = CourseEnrollment.objects.filter(
            course_id=ccx_locator).exclude(user_id__in=non_student_user_ids)

        # show students on Student Admin tab
        context['ccx_student_enrollments'] = ccx_student_enrollments

        # show enrolled not existing students on Enrollments tab
        context[
            'ccx_student_invitations'] = CourseEnrollmentAllowed.objects.filter(
                course_id=ccx_locator)

        # facilitator dropdown choices
        facilitator_ids = [
            ccx_coach_permissions.user.id
            for ccx_coach_permissions in context['ccx_coach_permissions']
        ]
        facilitator_choices_ids = AffiliateMembership.objects.filter(
            affiliate=ccx.affiliate,
            role=AffiliateMembership.CCX_COACH).exclude(
                member_id__in=facilitator_ids).values_list('member_id',
                                                           flat=True)
        context['facilitator_dropdown_choices'] = User.objects.filter(
            id__in=facilitator_choices_ids)
    else:
        context['create_ccx_url'] = reverse('create_ccx',
                                            kwargs={'course_id': course.id})

    return render_to_response('ccx/coach_dashboard.html', context)