Пример #1
0
def view_programs(request):
    """View programs in which the user is engaged."""
    show_program_listing = ProgramsApiConfig.current().show_program_listing
    if not show_program_listing:
        raise Http404

    enrollments = list(get_course_enrollments(request.user, None, []))
    meter = ProgramProgressMeter(request.user, enrollments)
    programs = meter.engaged_programs

    # TODO: Pull 'xseries' string from configuration model.
    marketing_root = urljoin(settings.MKTG_URLS.get('ROOT'), 'xseries').strip('/')
    for program in programs:
        program['display_category'] = get_display_category(program)
        program['marketing_url'] = '{root}/{slug}'.format(
            root=marketing_root,
            slug=program['marketing_slug']
        )

    context = {
        'programs': programs,
        'progress': meter.progress,
        'xseries_url': marketing_root if ProgramsApiConfig.current().show_xseries_ad else None,
        'nav_hidden': True,
        'show_program_listing': show_program_listing,
        'credentials': get_programs_credentials(request.user, category='xseries'),
        'disable_courseware_js': True,
        'uses_pattern_library': True
    }

    return render_to_response('learner_dashboard/programs.html', context)
Пример #2
0
def view_programs(request):
    """View programs in which the user is engaged."""
    show_program_listing = ProgramsApiConfig.current().show_program_listing
    if not show_program_listing:
        raise Http404

    enrollments = list(get_course_enrollments(request.user, None, []))
    programs = get_engaged_programs(request.user, enrollments)

    # TODO: Pull 'xseries' string from configuration model.
    marketing_root = urljoin(settings.MKTG_URLS.get('ROOT'),
                             'xseries').strip('/')
    for program in programs:
        program['marketing_url'] = '{root}/{slug}'.format(
            root=marketing_root, slug=program['marketing_slug'])

    return render_to_response(
        'learner_dashboard/programs.html', {
            'programs':
            programs,
            'xseries_url':
            marketing_root
            if ProgramsApiConfig.current().show_xseries_ad else None,
            'nav_hidden':
            True,
            'show_program_listing':
            show_program_listing
        })
Пример #3
0
def program_details(request, program_id):
    """View details about a specific program."""
    show_program_details = ProgramsApiConfig.current().show_program_details
    if not show_program_details:
        raise Http404

    program_data = utils.get_programs(request.user, program_id=program_id)

    if not program_data:
        raise Http404

    program_data = utils.supplement_program_data(program_data, request.user)
    show_program_listing = ProgramsApiConfig.current().show_program_listing

    urls = {
        'program_listing_url': reverse('program_listing_view'),
        'track_selection_url': strip_course_id(
            reverse('course_modes_choose', kwargs={'course_id': FAKE_COURSE_KEY})),
        'commerce_api_url': reverse('commerce_api:v0:baskets:create')
    }

    context = {
        'program_data': program_data,
        'urls': urls,
        'show_program_listing': show_program_listing,
        'nav_hidden': True,
        'disable_courseware_js': True,
        'uses_pattern_library': True
    }

    return render_to_response('learner_dashboard/program_details.html', context)
Пример #4
0
def program_details(request, program_id):
    """View details about a specific program."""
    show_program_details = ProgramsApiConfig.current().show_program_details
    if not show_program_details:
        raise Http404

    program_data = utils.get_programs(request.user, program_id=program_id)

    if not program_data:
        raise Http404

    program_data = utils.supplement_program_data(program_data, request.user)
    show_program_listing = ProgramsApiConfig.current().show_program_listing

    context = {
        'program_data': program_data,
        'program_listing_url': reverse('program_listing_view'),
        'show_program_listing': show_program_listing,
        'nav_hidden': True,
        'disable_courseware_js': True,
        'uses_pattern_library': True
    }

    return render_to_response('learner_dashboard/program_details.html',
                              context)
Пример #5
0
def view_programs(request):
    """View programs in which the user is engaged."""
    show_program_listing = ProgramsApiConfig.current().show_program_listing
    if not show_program_listing:
        raise Http404

    enrollments = list(get_course_enrollments(request.user, None, []))
    meter = ProgramProgressMeter(request.user, enrollments)
    programs = meter.engaged_programs

    # TODO: Pull 'xseries' string from configuration model.
    marketing_root = urljoin(settings.MKTG_URLS.get('ROOT'), 'xseries').strip('/')
    for program in programs:
        program['display_category'] = get_display_category(program)
        program['marketing_url'] = '{root}/{slug}'.format(
            root=marketing_root,
            slug=program['marketing_slug']
        )

    return render_to_response('learner_dashboard/programs.html', {
        'programs': programs,
        'progress': meter.progress,
        'xseries_url': marketing_root if ProgramsApiConfig.current().show_xseries_ad else None,
        'nav_hidden': True,
        'show_program_listing': show_program_listing,
        'credentials': _get_xseries_credentials(request.user)
    })
Пример #6
0
def view_programs(request):
    """View programs in which the user is engaged."""
    show_program_listing = ProgramsApiConfig.current().show_program_listing
    if not show_program_listing:
        raise Http404

    meter = utils.ProgramProgressMeter(request.user)
    programs = meter.engaged_programs

    # TODO: Pull 'xseries' string from configuration model.
    marketing_root = urljoin(settings.MKTG_URLS.get('ROOT'), 'xseries').strip('/')
    for program in programs:
        program['display_category'] = utils.get_display_category(program)
        program['marketing_url'] = '{root}/{slug}'.format(
            root=marketing_root,
            slug=program['marketing_slug']
        )

    context = {
        'programs': programs,
        'progress': meter.progress,
        'xseries_url': marketing_root if ProgramsApiConfig.current().show_xseries_ad else None,
        'nav_hidden': True,
        'show_program_listing': show_program_listing,
        'credentials': get_programs_credentials(request.user, category='xseries'),
        'disable_courseware_js': True,
        'uses_pattern_library': True
    }

    return render_to_response('learner_dashboard/programs.html', context)
Пример #7
0
    def test_is_cache_enabled_returns_false(self, enabled, cache_ttl, _mock_cache):
        """Verify that the method 'is_cache_enabled' returns false if
        'cache_ttl' value is 0 or config is not enabled.
        """
        self.assertFalse(ProgramsApiConfig.current().is_cache_enabled)

        self.create_config(enabled=enabled, cache_ttl=cache_ttl)
        self.assertFalse(ProgramsApiConfig.current().is_cache_enabled)
Пример #8
0
    def test_cache_utilization(self):
        """Verify that when enabled, the cache is used."""
        program_config = self.create_programs_config(cache_ttl=5)

        expected_collection = ['some', 'test', 'data']
        data = {
            'next': None,
            'results': expected_collection,
        }

        self._mock_programs_api([
            httpretty.Response(body=json.dumps(data),
                               content_type='application/json')
        ], )

        resource_id = 1
        url = '{api_root}/programs/{resource_id}/'.format(
            api_root=ProgramsApiConfig.current().internal_api_url.strip('/'),
            resource_id=resource_id,
        )

        expected_resource = {'key': 'value'}

        self._mock_programs_api([
            httpretty.Response(body=json.dumps(expected_resource),
                               content_type='application/json')
        ],
                                url=url)

        cache_key = ProgramsApiConfig.current().CACHE_KEY

        # Warm up the cache.
        get_edx_api_data(program_config,
                         self.user,
                         'programs',
                         cache_key=cache_key)
        get_edx_api_data(program_config,
                         self.user,
                         'programs',
                         resource_id=resource_id,
                         cache_key=cache_key)

        # Hit the cache.
        actual_collection = get_edx_api_data(program_config,
                                             self.user,
                                             'programs',
                                             cache_key=cache_key)
        self.assertEqual(actual_collection, expected_collection)

        actual_resource = get_edx_api_data(program_config,
                                           self.user,
                                           'programs',
                                           resource_id=resource_id,
                                           cache_key=cache_key)
        self.assertEqual(actual_resource, expected_resource)

        # Verify that only two requests were made, not four.
        self._assert_num_requests(2)
Пример #9
0
    def test_is_cache_enabled_returns_false(self, enabled, cache_ttl,
                                            _mock_cache):
        """Verify that the method 'is_cache_enabled' returns false if
        'cache_ttl' value is 0 or config is not enabled.
        """
        self.assertFalse(ProgramsApiConfig.current().is_cache_enabled)

        self.create_config(enabled=enabled, cache_ttl=cache_ttl)
        self.assertFalse(ProgramsApiConfig.current().is_cache_enabled)
Пример #10
0
 def test_default_state(self, _mock_cache):
     """
     Ensure the config stores empty values when no data has been inserted,
     and is completely disabled.
     """
     self.assertFalse(ProgramsApiConfig.is_enabled())
     api_config = ProgramsApiConfig.current()
     self.assertEqual(api_config.internal_service_url, '')
     self.assertEqual(api_config.public_service_url, '')
     self.assertEqual(api_config.api_version_number, None)
     self.assertFalse(api_config.is_student_dashboard_enabled)
Пример #11
0
 def test_default_state(self, _mock_cache):
     """
     Ensure the config stores empty values when no data has been inserted,
     and is completely disabled.
     """
     self.assertFalse(ProgramsApiConfig.is_enabled())
     api_config = ProgramsApiConfig.current()
     self.assertEqual(api_config.internal_service_url, '')
     self.assertEqual(api_config.public_service_url, '')
     self.assertEqual(api_config.api_version_number, None)
     self.assertFalse(api_config.is_student_dashboard_enabled)
Пример #12
0
 def test_created_state(self, _mock_cache):
     """
     Ensure the config stores correct values when created with them, but
     remains disabled.
     """
     self.create_config()
     self.assertFalse(ProgramsApiConfig.is_enabled())
     api_config = ProgramsApiConfig.current()
     self.assertEqual(api_config.internal_service_url, self.INTERNAL_URL)
     self.assertEqual(api_config.public_service_url, self.PUBLIC_URL)
     self.assertEqual(api_config.api_version_number, 1)
     self.assertFalse(api_config.is_student_dashboard_enabled)
Пример #13
0
 def test_created_state(self, _mock_cache):
     """
     Ensure the config stores correct values when created with them, but
     remains disabled.
     """
     self.create_config()
     self.assertFalse(ProgramsApiConfig.is_enabled())
     api_config = ProgramsApiConfig.current()
     self.assertEqual(api_config.internal_service_url, self.INTERNAL_URL)
     self.assertEqual(api_config.public_service_url, self.PUBLIC_URL)
     self.assertEqual(api_config.api_version_number, 1)
     self.assertFalse(api_config.is_student_dashboard_enabled)
Пример #14
0
def program_details(request, program_id):
    """View details about a specific program."""
    programs_config = ProgramsApiConfig.current()
    if not programs_config.show_program_details:
        raise Http404

    program_data = utils.get_programs(request.user, program_id=program_id)

    if not program_data:
        raise Http404

    program_data = utils.ProgramDataExtender(program_data, request.user).extend()

    urls = {
        'program_listing_url': reverse('program_listing_view'),
        'track_selection_url': '',
        'commerce_api_url': reverse('commerce_api:v0:baskets:create'),
    }

    context = {
        'program_data': program_data,
        'urls': urls,
        'show_program_listing': programs_config.show_program_listing,
        'nav_hidden': True,
        'disable_courseware_js': True,
        'uses_pattern_library': False
    }

    return render_to_response('learner_dashboard/program_details.html', context)
Пример #15
0
 def get(self, request, *args, **kwargs):
     """Generate and return a token, if the integration is enabled."""
     if ProgramsApiConfig.current().is_studio_tab_enabled:
         id_token = get_id_token(request.user, 'programs')
         return JsonResponse({'id_token': id_token})
     else:
         raise Http404
Пример #16
0
def program_details(request, program_id):
    """View details about a specific program."""
    programs_config = ProgramsApiConfig.current()
    if not programs_config.show_program_details:
        raise Http404

    program_data = utils.get_programs(request.user, program_id=program_id)

    if not program_data:
        raise Http404

    program_data = utils.supplement_program_data(program_data, request.user)

    urls = {
        "program_listing_url": reverse("program_listing_view"),
        "track_selection_url": strip_course_id(reverse("course_modes_choose", kwargs={"course_id": FAKE_COURSE_KEY})),
        "commerce_api_url": reverse("commerce_api:v0:baskets:create"),
    }

    context = {
        "program_data": program_data,
        "urls": urls,
        "show_program_listing": programs_config.show_program_listing,
        "nav_hidden": True,
        "disable_courseware_js": True,
        "uses_pattern_library": True,
    }

    return render_to_response("learner_dashboard/program_details.html", context)
Пример #17
0
def attach_program_detail_url(programs):
    """Extend program representations by attaching a URL to be used when linking to program details.

    Facilitates the building of context to be passed to templates containing program data.

    Arguments:
        programs (list): Containing dicts representing programs.

    Returns:
        list, containing extended program dicts
    """
    programs_config = ProgramsApiConfig.current()
    marketing_url = get_program_marketing_url(programs_config)

    for program in programs:
        if programs_config.show_program_details:
            base = reverse('program_details_view',
                           kwargs={
                               'program_id': program['id']
                           }).rstrip('/')
            slug = slugify(program['name'])
        else:
            # TODO: Remove. Learners should always be sent to the LMS' program details page.
            base = marketing_url
            slug = program['marketing_slug']

        program['detail_url'] = '{base}/{slug}'.format(base=base, slug=slug)

    return programs
Пример #18
0
def program_listing(request):
    """View a list of programs in which the user is engaged."""
    programs_config = ProgramsApiConfig.current()
    if not programs_config.show_program_listing:
        raise Http404

    meter = utils.ProgramProgressMeter(request.user)
    programs = meter.engaged_programs

    marketing_url = urljoin(settings.MKTG_URLS.get('ROOT'), programs_config.marketing_path).rstrip('/')

    for program in programs:
        program['detail_url'] = utils.get_program_detail_url(program, marketing_url)

    context = {
        'credentials': get_programs_credentials(request.user),
        'disable_courseware_js': True,
        'marketing_url': marketing_url,
        'nav_hidden': True,
        'programs': programs,
        'progress': meter.progress,
        'show_program_listing': programs_config.show_program_listing,
        'uses_pattern_library': True,
    }

    return render_to_response('learner_dashboard/programs.html', context)
Пример #19
0
def program_details(request, program_uuid):
    """View details about a specific program."""
    programs_config = ProgramsApiConfig.current()
    if not programs_config.enabled:
        raise Http404

    program_data = get_programs(uuid=program_uuid)
    if not program_data:
        raise Http404

    program_data = ProgramDataExtender(program_data, request.user).extend()

    urls = {
        'program_listing_url': reverse('program_listing_view'),
        'track_selection_url': strip_course_id(
            reverse('course_modes_choose', kwargs={'course_id': FAKE_COURSE_KEY})
        ),
        'commerce_api_url': reverse('commerce_api:v0:baskets:create'),
    }

    context = {
        'program_data': program_data,
        'urls': urls,
        'show_program_listing': programs_config.enabled,
        'nav_hidden': True,
        'disable_courseware_js': True,
        'uses_pattern_library': True,
        'user_preferences': get_user_preferences(request.user)
    }

    return render_to_response('learner_dashboard/program_details.html', context)
Пример #20
0
def program_listing(request):
    """View a list of programs in which the user is engaged."""
    programs_config = ProgramsApiConfig.current()
    if not programs_config.show_program_listing:
        raise Http404

    meter = ProgramProgressMeter(request.user)
    engaged_programs = [
        munge_catalog_program(program) for program in meter.engaged_programs
    ]
    progress = [
        munge_progress_map(progress_map) for progress_map in meter.progress
    ]

    context = {
        'credentials': get_programs_credentials(request.user),
        'disable_courseware_js': True,
        'marketing_url': get_program_marketing_url(programs_config),
        'nav_hidden': True,
        'programs': engaged_programs,
        'progress': progress,
        'show_program_listing': programs_config.show_program_listing,
        'uses_pattern_library': True,
    }

    return render_to_response('learner_dashboard/programs.html', context)
Пример #21
0
def view_programs(request):
    """View programs in which the user is engaged."""
    programs_config = ProgramsApiConfig.current()
    if not programs_config.show_program_listing:
        raise Http404

    meter = utils.ProgramProgressMeter(request.user)
    programs = meter.engaged_programs

    # TODO: Pull 'xseries' string from configuration model.
    marketing_root = urljoin(settings.MKTG_URLS.get("ROOT"), "xseries").rstrip("/")

    for program in programs:
        program["detail_url"] = utils.get_program_detail_url(program, marketing_root)
        program["display_category"] = utils.get_display_category(program)

    context = {
        "programs": programs,
        "progress": meter.progress,
        "xseries_url": marketing_root if programs_config.show_xseries_ad else None,
        "nav_hidden": True,
        "show_program_listing": programs_config.show_program_listing,
        "credentials": get_programs_credentials(request.user, category="xseries"),
        "disable_courseware_js": True,
        "uses_pattern_library": True,
    }

    return render_to_response("learner_dashboard/programs.html", context)
Пример #22
0
def get_programs(user, program_id=None):
    """Given a user, get programs from the Programs service.
    Returned value is cached depending on user permissions. Staff users making requests
    against Programs will receive unpublished programs, while regular users will only receive
    published programs.

    Arguments:
        user (User): The user to authenticate as when requesting programs.

    Keyword Arguments:
        program_id (int): Identifies a specific program for which to retrieve data.

    Returns:
        list of dict, representing programs returned by the Programs service.
    """
    programs_config = ProgramsApiConfig.current()

    # Bypass caching for staff users, who may be creating Programs and want
    # to see them displayed immediately.
    cache_key = programs_config.CACHE_KEY if programs_config.is_cache_enabled and not user.is_staff else None
    return get_edx_api_data(programs_config,
                            user,
                            'programs',
                            resource_id=program_id,
                            cache_key=cache_key)
Пример #23
0
    def render_to_fragment(self, request, **kwargs):
        """
        Render the program listing fragment.
        """
        user = request.user
        try:
            mobile_only = json.loads(request.GET.get('mobile_only', 'false'))
        except ValueError:
            mobile_only = False

        programs_config = kwargs.get(
            'programs_config') or ProgramsApiConfig.current()
        if not programs_config.enabled or not user.is_authenticated:
            raise Http404

        meter = ProgramProgressMeter(request.site,
                                     user,
                                     mobile_only=mobile_only)

        context = {
            'marketing_url':
            get_program_marketing_url(programs_config, mobile_only),
            'programs':
            meter.engaged_programs,
            'progress':
            meter.progress()
        }
        html = render_to_string('learner_dashboard/programs_fragment.html',
                                context)
        programs_fragment = Fragment(html)
        self.add_fragment_resource_urls(programs_fragment)

        return programs_fragment
Пример #24
0
def get_programs(user, program_id=None):
    """Given a user, get programs from the Programs service.

    Returned value is cached depending on user permissions. Staff users making requests
    against Programs will receive unpublished programs, while regular users will only receive
    published programs.

    Arguments:
        user (User): The user to authenticate as when requesting programs.

    Keyword Arguments:
        program_id (int): Identifies a specific program for which to retrieve data.

    Returns:
        list of dict, representing programs returned by the Programs service.
        dict, if a specific program is requested.
    """
    programs_config = ProgramsApiConfig.current()

    # Bypass caching for staff users, who may be creating Programs and want
    # to see them displayed immediately.
    cache_key = programs_config.CACHE_KEY if programs_config.is_cache_enabled and not user.is_staff else None

    programs = get_edx_api_data(programs_config, user, 'programs', resource_id=program_id, cache_key=cache_key)

    # Mix in munged MicroMasters data from the catalog.
    if not program_id:
        programs += [
            munge_catalog_program(micromaster) for micromaster in get_catalog_programs(user, type='MicroMasters')
        ]

    return programs
Пример #25
0
def attach_program_detail_url(programs):
    """Extend program representations by attaching a URL to be used when linking to program details.

    Facilitates the building of context to be passed to templates containing program data.

    Arguments:
        programs (list): Containing dicts representing programs.

    Returns:
        list, containing extended program dicts
    """
    programs_config = ProgramsApiConfig.current()
    marketing_url = get_program_marketing_url(programs_config)

    for program in programs:
        if programs_config.show_program_details:
            base = reverse('program_details_view', kwargs={'program_id': program['id']}).rstrip('/')
            slug = slugify(program['name'])
        else:
            # TODO: Remove. Learners should always be sent to the LMS' program details page.
            base = marketing_url
            slug = program['marketing_slug']

        program['detail_url'] = '{base}/{slug}'.format(base=base, slug=slug)

    return programs
Пример #26
0
    def test_get_specific_resource(self):
        """Verify that a specific resource can be retrieved."""
        program_config = self.create_programs_config()

        resource_id = 1
        url = '{api_root}/programs/{resource_id}/'.format(
            api_root=ProgramsApiConfig.current().internal_api_url.strip('/'),
            resource_id=resource_id,
        )

        expected_resource = {'key': 'value'}

        self._mock_programs_api([
            httpretty.Response(body=json.dumps(expected_resource),
                               content_type='application/json')
        ],
                                url=url)

        actual_resource = get_edx_api_data(program_config,
                                           self.user,
                                           'programs',
                                           resource_id=resource_id)
        self.assertEqual(actual_resource, expected_resource)

        self._assert_num_requests(1)
Пример #27
0
def program_listing(request):
    """View a list of programs in which the user is engaged."""
    programs_config = ProgramsApiConfig.current()
    if not programs_config.show_program_listing:
        raise Http404

    meter = utils.ProgramProgressMeter(request.user)
    programs = meter.engaged_programs

    marketing_url = urljoin(settings.MKTG_URLS.get('ROOT'),
                            programs_config.marketing_path).rstrip('/')

    for program in programs:
        program['detail_url'] = utils.get_program_detail_url(
            program, marketing_url)

    context = {
        'credentials': get_programs_credentials(request.user),
        'disable_courseware_js': True,
        'marketing_url': marketing_url,
        'nav_hidden': True,
        'programs': programs,
        'progress': meter.progress,
        'show_program_listing': programs_config.show_program_listing,
        'uses_pattern_library': True,
    }

    return render_to_response('learner_dashboard/programs.html', context)
Пример #28
0
    def render_to_fragment(self, request, **kwargs):
        """
        Render the program listing fragment.
        """
        user = request.user
        try:
            mobile_only = json.loads(request.GET.get('mobile_only', 'false'))
        except ValueError:
            mobile_only = False

        programs_config = kwargs.get('programs_config') or ProgramsApiConfig.current()
        if not programs_config.enabled or not user.is_authenticated:
            raise Http404

        meter = ProgramProgressMeter(request.site, user, mobile_only=mobile_only)

        context = {
            'marketing_url': get_program_marketing_url(programs_config),
            'programs': meter.engaged_programs,
            'progress': meter.progress()
        }
        html = render_to_string('learner_dashboard/programs_fragment.html', context)
        programs_fragment = Fragment(html)
        self.add_fragment_resource_urls(programs_fragment)

        return programs_fragment
Пример #29
0
def view_programs(request):
    """View programs in which the user is engaged."""
    programs_config = ProgramsApiConfig.current()
    if not programs_config.show_program_listing:
        raise Http404

    meter = utils.ProgramProgressMeter(request.user)
    programs = meter.engaged_programs

    # TODO: Pull 'xseries' string from configuration model.
    marketing_root = urljoin(settings.MKTG_URLS.get('ROOT'),
                             'xseries').rstrip('/')

    for program in programs:
        program['detail_url'] = utils.get_program_detail_url(
            program, marketing_root)
        program['display_category'] = utils.get_display_category(program)

    context = {
        'programs': programs,
        'progress': meter.progress,
        'xseries_url':
        marketing_root if programs_config.show_xseries_ad else None,
        'nav_hidden': True,
        'show_program_listing': programs_config.show_program_listing,
        'credentials': get_programs_credentials(request.user,
                                                category='xseries'),
        'disable_courseware_js': True,
        'uses_pattern_library': True
    }

    return render_to_response('learner_dashboard/programs.html', context)
    def _mock_programs_api(self, responses, url=None):
        """Helper for mocking out Programs API URLs."""
        self.assertTrue(httpretty.is_enabled(), msg='httpretty must be enabled to mock Programs API calls.')

        url = url if url else ProgramsApiConfig.current().internal_api_url.strip('/') + '/programs/'

        httpretty.register_uri(httpretty.GET, url, responses=responses)
Пример #31
0
def get_programs(user, program_id=None):
    """Given a user, get programs from the Programs service.
    Returned value is cached depending on user permissions. Staff users making requests
    against Programs will receive unpublished programs, while regular users will only receive
    published programs.

    Arguments:
        user (User): The user to authenticate as when requesting programs.

    Keyword Arguments:
        program_id (int): Identifies a specific program for which to retrieve data.

    Returns:
        list of dict, representing programs returned by the Programs service.
    """
    programs_config = ProgramsApiConfig.current()

    # Bypass caching for staff users, who may be creating Programs and want
    # to see them displayed immediately.
    cache_key = programs_config.CACHE_KEY if programs_config.is_cache_enabled and not user.is_staff else None

    data = get_edx_api_data(programs_config, user, 'programs', resource_id=program_id, cache_key=cache_key)

    # TODO: Temporary, to be removed once category names are cased for display. ECOM-5018.
    if data and program_id:
        data['category'] = data['category'].lower()
    else:
        for program in data:
            program['category'] = program['category'].lower()

    return data
Пример #32
0
def get_programs_for_dashboard(user, course_keys):
    """Build a dictionary of programs, keyed by course.

    Given a user and an iterable of course keys, find all the programs relevant
    to the user's dashboard and return them in a dictionary keyed by course key.

    Arguments:
        user (User): The user to authenticate as when requesting programs.
        course_keys (list): List of course keys representing the courses in which
            the given user has active enrollments.

    Returns:
        dict, containing programs keyed by course. Empty if programs cannot be retrieved.
    """
    programs_config = ProgramsApiConfig.current()
    course_programs = {}

    if not programs_config.is_student_dashboard_enabled:
        log.debug('Display of programs on the student dashboard is disabled.')
        return course_programs

    programs = get_programs(user)
    if not programs:
        log.debug('No programs found for the user with ID %d.', user.id)
        return course_programs

    course_ids = [unicode(c) for c in course_keys]
    course_programs = flatten_programs(programs, course_ids)

    return course_programs
Пример #33
0
def get_programs_for_dashboard(user, course_keys):
    """Build a dictionary of programs, keyed by course.

    Given a user and an iterable of course keys, find all the programs relevant
    to the user's dashboard and return them in a dictionary keyed by course key.

    Arguments:
        user (User): The user to authenticate as when requesting programs.
        course_keys (list): List of course keys representing the courses in which
            the given user has active enrollments.

    Returns:
        dict, containing programs keyed by course. Empty if programs cannot be retrieved.
    """
    programs_config = ProgramsApiConfig.current()
    course_programs = {}

    if not programs_config.is_student_dashboard_enabled:
        log.debug('Display of programs on the student dashboard is disabled.')
        return course_programs

    programs = get_programs(user)
    if not programs:
        log.debug('No programs found for the user with ID %d.', user.id)
        return course_programs

    course_ids = [unicode(c) for c in course_keys]
    course_programs = flatten_programs(programs, course_ids)

    return course_programs
    def test_get_paginated_data(self):
        """Verify that paginated data can be retrieved."""
        program_config = self.create_programs_config()

        expected_collection = ['some', 'test', 'data']
        url = ProgramsApiConfig.current().internal_api_url.strip('/') + '/programs/?page={}'

        responses = []
        for page, record in enumerate(expected_collection, start=1):
            data = {
                'next': url.format(page + 1) if page < len(expected_collection) else None,
                'results': [record],
            }

            body = json.dumps(data)
            responses.append(
                httpretty.Response(body=body, content_type='application/json')
            )

        self._mock_programs_api(responses)

        actual_collection = get_edx_api_data(program_config, self.user, 'programs')
        self.assertEqual(actual_collection, expected_collection)

        self._assert_num_requests(len(expected_collection))
Пример #35
0
def program_details(request, program_id):
    """View details about a specific program."""
    programs_config = ProgramsApiConfig.current()
    if not programs_config.show_program_details:
        raise Http404

    program_data = utils.get_programs(request.user, program_id=program_id)

    if not program_data:
        raise Http404

    program_data = utils.supplement_program_data(program_data, request.user)

    urls = {
        'program_listing_url':
        reverse('program_listing_view'),
        'track_selection_url':
        strip_course_id(
            reverse('course_modes_choose',
                    kwargs={'course_id': FAKE_COURSE_KEY})),
        'commerce_api_url':
        reverse('commerce_api:v0:baskets:create'),
    }

    context = {
        'program_data': program_data,
        'urls': urls,
        'show_program_listing': programs_config.show_program_listing,
        'nav_hidden': True,
        'disable_courseware_js': True,
        'uses_pattern_library': True
    }

    return render_to_response('learner_dashboard/program_details.html',
                              context)
Пример #36
0
 def get(self, request, *args, **kwargs):
     """Generate and return a token, if the integration is enabled."""
     if ProgramsApiConfig.current().is_studio_tab_enabled:
         id_token = get_id_token(request.user, 'programs')
         return JsonResponse({'id_token': id_token})
     else:
         raise Http404
Пример #37
0
    def test_get_paginated_data(self):
        """Verify that paginated data can be retrieved."""
        program_config = self.create_programs_config()

        expected_collection = ['some', 'test', 'data']
        url = ProgramsApiConfig.current().internal_api_url.strip('/') + '/programs/?page={}'

        responses = []
        for page, record in enumerate(expected_collection, start=1):
            data = {
                'next': url.format(page + 1) if page < len(expected_collection) else None,
                'results': [record],
            }

            body = json.dumps(data)
            responses.append(
                httpretty.Response(body=body, content_type='application/json')
            )

        self._mock_programs_api(responses)

        actual_collection = get_edx_api_data(program_config, self.user, 'programs')
        self.assertEqual(actual_collection, expected_collection)

        self._assert_num_requests(len(expected_collection))
Пример #38
0
    def _mock_programs_api(self, responses, url=None):
        """Helper for mocking out Programs API URLs."""
        self.assertTrue(httpretty.is_enabled(), msg='httpretty must be enabled to mock Programs API calls.')

        url = url if url else ProgramsApiConfig.current().internal_api_url.strip('/') + '/programs/'

        httpretty.register_uri(httpretty.GET, url, responses=responses)
Пример #39
0
    def render_to_fragment(self, request, program_uuid, **kwargs):  # lint-amnesty, pylint: disable=arguments-differ
        """View details about a specific program."""
        programs_config = kwargs.get('programs_config') or ProgramsApiConfig.current()
        user = request.user
        site = request.site
        if not programs_config.enabled or not request.user.is_authenticated:
            raise Http404
        try:
            mobile_only = json.loads(request.GET.get('mobile_only', 'false'))
        except ValueError:
            mobile_only = False

        program_data, course_data = get_program_and_course_data(site, user, program_uuid, mobile_only)

        if not program_data:
            raise Http404

        certificate_data = get_certificates(user, program_data)
        program_data.pop('courses')

        urls = get_program_urls(program_data)
        if not certificate_data:
            urls['program_record_url'] = None

        industry_pathways, credit_pathways = get_industry_and_credit_pathways(program_data, site)

        program_discussion_lti = ProgramDiscussionLTI(program_uuid, request)
        program_live_lti = ProgramLiveLTI(program_uuid, request)

        def program_tab_view_enabled() -> bool:
            return program_tab_view_is_enabled() and (
                industry_pathways or
                credit_pathways or
                program_discussion_lti.is_configured or
                program_live_lti.is_configured
            )

        context = {
            'urls': urls,
            'user_preferences': get_user_preferences(user),
            'program_data': program_data,
            'course_data': course_data,
            'certificate_data': certificate_data,
            'industry_pathways': industry_pathways,
            'credit_pathways': credit_pathways,
            'program_tab_view_enabled': program_tab_view_enabled(),
            'discussion_fragment': {
                'configured': program_discussion_lti.is_configured,
                'iframe': program_discussion_lti.render_iframe()
            },
            'live_fragment': {
                'configured': program_live_lti.is_configured,
                'iframe': program_live_lti.render_iframe()
            }
        }

        html = render_to_string('learner_dashboard/program_details_fragment.html', context)
        program_details_fragment = Fragment(html)
        self.add_fragment_resource_urls(program_details_fragment)
        return program_details_fragment
Пример #40
0
    def mock_programs_api(self, data):
        """Helper for mocking out Programs API URLs."""
        self.assertTrue(httpretty.is_enabled(), msg='httpretty must be enabled to mock Programs API calls.')

        url = ProgramsApiConfig.current().internal_api_url.strip('/') + '/programs/'
        body = json.dumps({'results': data})

        httpretty.register_uri(httpretty.GET, url, body=body, content_type='application/json')
Пример #41
0
    def _mock_programs_api(self, data):
        """Helper for mocking out Programs API URLs."""
        self.assertTrue(httpretty.is_enabled(), msg='httpretty must be enabled to mock Programs API calls.')

        url = ProgramsApiConfig.current().internal_api_url.strip('/') + '/programs/'
        body = json.dumps({'results': data})

        httpretty.register_uri(httpretty.GET, url, body=body, content_type='application/json')
Пример #42
0
def set_cached_programs_response(programs_data):
    """ Set cache value for the programs data with specific ttl.

    Arguments:
        programs_data (dict): Programs data in dictionary format
    """
    cache.set(ProgramsApiConfig.PROGRAMS_API_CACHE_KEY, programs_data,
              ProgramsApiConfig.current().cache_ttl)
Пример #43
0
    def render_to_fragment(self, request, program_uuid, **kwargs):
        """View details about a specific program."""
        programs_config = kwargs.get(
            'programs_config') or ProgramsApiConfig.current()
        if not programs_config.enabled or not request.user.is_authenticated():
            raise Http404

        meter = ProgramProgressMeter(request.site,
                                     request.user,
                                     uuid=program_uuid)
        program_data = meter.programs[0]

        if not program_data:
            raise Http404

        try:
            mobile_only = json.loads(request.GET.get('mobile_only', 'false'))
        except ValueError:
            mobile_only = False

        program_data = ProgramDataExtender(program_data,
                                           request.user,
                                           mobile_only=mobile_only).extend()
        course_data = meter.progress(programs=[program_data],
                                     count_only=False)[0]
        certificate_data = get_certificates(request.user, program_data)

        program_data.pop('courses')
        skus = program_data.get('skus')
        ecommerce_service = EcommerceService()

        urls = {
            'program_listing_url':
            reverse('program_listing_view'),
            'track_selection_url':
            strip_course_id(
                reverse('course_modes_choose',
                        kwargs={'course_id': FAKE_COURSE_KEY})),
            'commerce_api_url':
            reverse('commerce_api:v0:baskets:create'),
            'buy_button_url':
            ecommerce_service.get_checkout_page_url(*skus)
        }

        context = {
            'urls': urls,
            'user_preferences': get_user_preferences(request.user),
            'program_data': program_data,
            'course_data': course_data,
            'certificate_data': certificate_data
        }

        html = render_to_string(
            'learner_dashboard/program_details_fragment.html', context)
        program_details_fragment = Fragment(html)
        self.add_fragment_resource_urls(program_details_fragment)
        return program_details_fragment
Пример #44
0
 def test_api_urls(self, _mock_cache):
     """
     Ensure the api url methods return correct concatenations of service
     URLs and version numbers.
     """
     self.create_config()
     api_config = ProgramsApiConfig.current()
     self.assertEqual(api_config.internal_api_url, "{}api/v1/".format(self.INTERNAL_URL))
     self.assertEqual(api_config.public_api_url, "{}api/v1/".format(self.PUBLIC_URL))
Пример #45
0
    def test_cache_utilization(self):
        """Verify that when enabled, the cache is used."""
        program_config = self.create_programs_config(cache_ttl=5)

        expected_collection = ['some', 'test', 'data']
        data = {
            'next': None,
            'results': expected_collection,
        }

        self._mock_programs_api(
            [httpretty.Response(body=json.dumps(data), content_type='application/json')],
        )

        resource_id = 1
        url = '{api_root}/programs/{resource_id}/'.format(
            api_root=ProgramsApiConfig.current().internal_api_url.strip('/'),
            resource_id=resource_id,
        )

        expected_resource = {'key': 'value'}

        self._mock_programs_api(
            [httpretty.Response(body=json.dumps(expected_resource), content_type='application/json')],
            url=url
        )

        cache_key = ProgramsApiConfig.current().CACHE_KEY

        # Warm up the cache.
        get_edx_api_data(program_config, self.user, 'programs', cache_key=cache_key)
        get_edx_api_data(program_config, self.user, 'programs', resource_id=resource_id, cache_key=cache_key)

        # Hit the cache.
        actual_collection = get_edx_api_data(program_config, self.user, 'programs', cache_key=cache_key)
        self.assertEqual(actual_collection, expected_collection)

        actual_resource = get_edx_api_data(
            program_config, self.user, 'programs', resource_id=resource_id, cache_key=cache_key
        )
        self.assertEqual(actual_resource, expected_resource)

        # Verify that only two requests were made, not four.
        self._assert_num_requests(2)
Пример #46
0
def learner_profile_context(request, profile_username, user_is_staff):
    """Context for the learner profile page.

    Args:
        logged_in_user (object): Logged In user.
        profile_username (str): username of user whose profile is requested.
        user_is_staff (bool): Logged In user has staff access.
        build_absolute_uri_func ():

    Returns:
        dict

    Raises:
        ObjectDoesNotExist: the specified profile_username does not exist.
    """
    profile_user = User.objects.get(username=profile_username)
    logged_in_user = request.user

    own_profile = (logged_in_user.username == profile_username)

    account_settings_data = get_account_settings(request, profile_username)

    preferences_data = get_user_preferences(profile_user, profile_username)

    context = {
        'data': {
            'profile_user_id': profile_user.id,
            'default_public_account_fields': settings.ACCOUNT_VISIBILITY_CONFIGURATION['public_fields'],
            'default_visibility': settings.ACCOUNT_VISIBILITY_CONFIGURATION['default_visibility'],
            'accounts_api_url': reverse("accounts_api", kwargs={'username': profile_username}),
            'preferences_api_url': reverse('preferences_api', kwargs={'username': profile_username}),
            'preferences_data': preferences_data,
            'account_settings_data': account_settings_data,
            'profile_image_upload_url': reverse('profile_image_upload', kwargs={'username': profile_username}),
            'profile_image_remove_url': reverse('profile_image_remove', kwargs={'username': profile_username}),
            'profile_image_max_bytes': settings.PROFILE_IMAGE_MAX_BYTES,
            'profile_image_min_bytes': settings.PROFILE_IMAGE_MIN_BYTES,
            'account_settings_page_url': reverse('account_settings'),
            'has_preferences_access': (logged_in_user.username == profile_username or user_is_staff),
            'own_profile': own_profile,
            'country_options': list(countries),
            'find_courses_url': marketing_link('COURSES'),
            'language_options': settings.ALL_LANGUAGES,
            'badges_logo': staticfiles_storage.url('certificates/images/backpack-logo.png'),
            'badges_icon': staticfiles_storage.url('certificates/images/ico-mozillaopenbadges.png'),
            'backpack_ui_img': staticfiles_storage.url('certificates/images/backpack-ui.png'),
            'platform_name': microsite.get_value('platform_name', settings.PLATFORM_NAME),
        },
        'disable_courseware_js': True,
        'show_program_listing': ProgramsApiConfig.current().show_program_listing,
    }

    if badges_enabled():
        context['data']['badges_api_url'] = reverse("badges_api:user_assertions", kwargs={'username': profile_username})

    return context
Пример #47
0
    def test_is_student_dashboard_enabled(self, _mock_cache):
        """
        Ensure that is_student_dashboard_enabled only returns True when the
        current config has both 'enabled' and 'enable_student_dashboard' set to
        True.
        """
        self.assertFalse(ProgramsApiConfig.current().is_student_dashboard_enabled)

        self.create_config()
        self.assertFalse(ProgramsApiConfig.current().is_student_dashboard_enabled)

        self.create_config(enabled=True)
        self.assertFalse(ProgramsApiConfig.current().is_student_dashboard_enabled)

        self.create_config(enable_student_dashboard=True)
        self.assertFalse(ProgramsApiConfig.current().is_student_dashboard_enabled)

        self.create_config(enabled=True, enable_student_dashboard=True)
        self.assertTrue(ProgramsApiConfig.current().is_student_dashboard_enabled)
Пример #48
0
def get_course_programs_for_dashboard(user, course_keys):  # pylint: disable=invalid-name
    """ Return all programs related to a user.

    Given a user and an iterable of course keys, find all
    the programs relevant to the user's dashboard and return them in a
    dictionary keyed by the course_key.

    Arguments:
        user (user object): Currently logged-in User for which we need to get
            JWT ID-Token
        course_keys (list): List of course keys in which user is enrolled

    Returns:
        Dictionary response containing programs or None
    """
    course_programs = {}
    if not is_student_dashboard_programs_enabled():
        log.warning("Programs service for student dashboard is disabled.")
        return course_programs

    # unicode-ify the course keys for efficient lookup
    course_keys = map(unicode, course_keys)

    # If cache config is enabled then get the response from cache first.
    if is_cache_enabled_for_programs():
        cached_programs = get_cached_programs_response()
        if cached_programs is not None:
            return _get_user_course_programs(cached_programs, course_keys)

    # get programs slumber-based client 'EdxRestApiClient'
    try:
        api_client = programs_api_client(
            ProgramsApiConfig.current().internal_api_url,
            get_id_token(user, CLIENT_NAME))
    except Exception:  # pylint: disable=broad-except
        log.exception('Failed to initialize the Programs API client.')
        return course_programs

    # get programs from api client
    try:
        response = api_client.programs.get()
    except Exception:  # pylint: disable=broad-except
        log.exception('Failed to retrieve programs from the Programs API.')
        return course_programs

    programs = response.get('results', [])
    if not programs:
        log.warning("No programs found for the user '%s'.", user.id)
        return course_programs

    # If cache config is enabled than set the cache.
    if is_cache_enabled_for_programs():
        set_cached_programs_response(programs)

    return _get_user_course_programs(programs, course_keys)
Пример #49
0
def get_course_programs_for_dashboard(user, course_keys):   # pylint: disable=invalid-name
    """ Return all programs related to a user.

    Given a user and an iterable of course keys, find all
    the programs relevant to the user's dashboard and return them in a
    dictionary keyed by the course_key.

    Arguments:
        user (user object): Currently logged-in User for which we need to get
            JWT ID-Token
        course_keys (list): List of course keys in which user is enrolled

    Returns:
        Dictionary response containing programs or None
    """
    course_programs = {}
    if not is_student_dashboard_programs_enabled():
        log.warning("Programs service for student dashboard is disabled.")
        return course_programs

    # unicode-ify the course keys for efficient lookup
    course_keys = map(unicode, course_keys)

    # get programs slumber-based client 'EdxRestApiClient'
    try:
        api_client = programs_api_client(ProgramsApiConfig.current().internal_api_url, get_id_token(user, CLIENT_NAME))
    except Exception:   # pylint: disable=broad-except
        log.exception('Failed to initialize the Programs API client.')
        return course_programs

    # get programs from api client
    try:
        response = api_client.programs.get()
    except Exception:  # pylint: disable=broad-except
        log.exception('Failed to retrieve programs from the Programs API.')
        return course_programs

    programs = response.get('results', [])
    if not programs:
        log.warning("No programs found for the user '%s'.", user.id)
        return course_programs

    # reindex the result from pgm -> course code -> course run
    #  to
    # course run -> program, ignoring course runs not present in the dashboard enrollments
    for program in programs:
        try:
            for course_code in program['course_codes']:
                for run in course_code['run_modes']:
                    if run['course_key'] in course_keys:
                        course_programs[run['course_key']] = program
        except KeyError:
            log.exception('Unable to parse Programs API response: %r', program)

    return course_programs
Пример #50
0
    def render_to_fragment(self, request, program_uuid, **kwargs):
        """View details about a specific program."""
        programs_config = kwargs.get('programs_config') or ProgramsApiConfig.current()
        if not programs_config.enabled or not request.user.is_authenticated:
            raise Http404

        meter = ProgramProgressMeter(request.site, request.user, uuid=program_uuid)
        program_data = meter.programs[0]

        if not program_data:
            raise Http404

        try:
            mobile_only = json.loads(request.GET.get('mobile_only', 'false'))
        except ValueError:
            mobile_only = False

        program_data = ProgramDataExtender(program_data, request.user, mobile_only=mobile_only).extend()
        course_data = meter.progress(programs=[program_data], count_only=False)[0]
        certificate_data = get_certificates(request.user, program_data)

        program_data.pop('courses')
        skus = program_data.get('skus')
        ecommerce_service = EcommerceService()

        # TODO: Don't have business logic of course-certificate==record-available here in LMS.
        # Eventually, the UI should ask Credentials if there is a record available and get a URL from it.
        # But this is here for now so that we can gate this URL behind both this business logic and
        # a waffle flag. This feature is in active developoment.
        program_record_url = get_credentials_records_url(program_uuid=program_uuid)
        if not certificate_data:
            program_record_url = None

        urls = {
            'program_listing_url': reverse('program_listing_view'),
            'track_selection_url': strip_course_id(
                reverse('course_modes_choose', kwargs={'course_id': FAKE_COURSE_KEY})
            ),
            'commerce_api_url': reverse('commerce_api:v0:baskets:create'),
            'buy_button_url': ecommerce_service.get_checkout_page_url(*skus),
            'program_record_url': program_record_url,
        }

        context = {
            'urls': urls,
            'user_preferences': get_user_preferences(request.user),
            'program_data': program_data,
            'course_data': course_data,
            'certificate_data': certificate_data
        }

        html = render_to_string('learner_dashboard/program_details_fragment.html', context)
        program_details_fragment = Fragment(html)
        self.add_fragment_resource_urls(program_details_fragment)
        return program_details_fragment
Пример #51
0
    def render_to_fragment(self, request, program_uuid, **kwargs):
        """View details about a specific program."""
        programs_config = kwargs.get('programs_config') or ProgramsApiConfig.current()
        if not programs_config.enabled or not request.user.is_authenticated:
            raise Http404

        meter = ProgramProgressMeter(request.site, request.user, uuid=program_uuid)
        program_data = meter.programs[0]

        if not program_data:
            raise Http404

        try:
            mobile_only = json.loads(request.GET.get('mobile_only', 'false'))
        except ValueError:
            mobile_only = False

        program_data = ProgramDataExtender(program_data, request.user, mobile_only=mobile_only).extend()
        course_data = meter.progress(programs=[program_data], count_only=False)[0]
        certificate_data = get_certificates(request.user, program_data)

        program_data.pop('courses')
        skus = program_data.get('skus')
        ecommerce_service = EcommerceService()

        # TODO: Don't have business logic of course-certificate==record-available here in LMS.
        # Eventually, the UI should ask Credentials if there is a record available and get a URL from it.
        # But this is here for now so that we can gate this URL behind both this business logic and
        # a waffle flag. This feature is in active developoment.
        program_record_url = get_credentials_records_url(program_uuid=program_uuid)
        if not certificate_data:
            program_record_url = None

        urls = {
            'program_listing_url': reverse('program_listing_view'),
            'track_selection_url': strip_course_id(
                reverse('course_modes_choose', kwargs={'course_id': FAKE_COURSE_KEY})
            ),
            'commerce_api_url': reverse('commerce_api:v0:baskets:create'),
            'buy_button_url': ecommerce_service.get_checkout_page_url(*skus),
            'program_record_url': program_record_url,
        }

        context = {
            'urls': urls,
            'user_preferences': get_user_preferences(request.user),
            'program_data': program_data,
            'course_data': course_data,
            'certificate_data': certificate_data
        }

        html = render_to_string('learner_dashboard/program_details_fragment.html', context)
        program_details_fragment = Fragment(html)
        self.add_fragment_resource_urls(program_details_fragment)
        return program_details_fragment
Пример #52
0
    def _mock_programs_api(self):
        """Helper for mocking out Programs API URLs."""
        self.assertTrue(httpretty.is_enabled(), msg='httpretty must be enabled to mock Programs API calls.')

        url = '{api_root}/programs/{id}/'.format(
            api_root=ProgramsApiConfig.current().internal_api_url.strip('/'),
            id=self.program_id
        )
        body = json.dumps(self.data)

        httpretty.register_uri(httpretty.GET, url, body=body, content_type='application/json')
Пример #53
0
def set_cached_programs_response(programs_data):
    """ Set cache value for the programs data with specific ttl.

    Arguments:
        programs_data (dict): Programs data in dictionary format
    """
    cache.set(
        ProgramsApiConfig.PROGRAMS_API_CACHE_KEY,
        programs_data,
        ProgramsApiConfig.current().cache_ttl
    )
Пример #54
0
def view_programs(request):
    """View programs in which the user is engaged."""
    if not ProgramsApiConfig.current().is_student_dashboard_enabled:
        raise Http404

    enrollments = list(get_course_enrollments(request.user, None, []))
    programs = get_engaged_programs(request.user, enrollments)

    # TODO: Pull 'xseries' string from configuration model.
    marketing_root = urljoin(settings.MKTG_URLS.get('ROOT'), 'xseries').strip('/')
    for program in programs:
        program['marketing_url'] = '{root}/{slug}'.format(
            root=marketing_root,
            slug=program['marketing_slug']
        )

    return render_to_response('learner_dashboard/programs.html', {
        'programs': programs,
        'xseries_url': marketing_root if ProgramsApiConfig.current().show_xseries_ad else None
    })
Пример #55
0
 def test_api_urls(self, _mock_cache):
     """
     Ensure the api url methods return correct concatenations of service
     URLs and version numbers.
     """
     self.create_config()
     api_config = ProgramsApiConfig.current()
     self.assertEqual(api_config.internal_api_url,
                      "{}api/v1/".format(self.INTERNAL_URL))
     self.assertEqual(api_config.public_api_url,
                      "{}api/v1/".format(self.PUBLIC_URL))
Пример #56
0
def program_details(request, program_uuid):
    """View details about a specific program."""
    programs_config = ProgramsApiConfig.current()
    if not programs_config.enabled:
        raise Http404

    meter = ProgramProgressMeter(request.user, uuid=program_uuid)
    program_data = meter.programs[0]

    if not program_data:
        raise Http404

    program_data = ProgramDataExtender(program_data, request.user).extend()

    urls = {
        'program_listing_url':
        reverse('program_listing_view'),
        'track_selection_url':
        strip_course_id(
            reverse('course_modes_choose',
                    kwargs={'course_id': FAKE_COURSE_KEY})),
        'commerce_api_url':
        reverse('commerce_api:v0:baskets:create'),
    }

    context = {
        'urls': urls,
        'show_program_listing': programs_config.enabled,
        'nav_hidden': True,
        'disable_courseware_js': True,
        'uses_pattern_library': True,
        'user_preferences': get_user_preferences(request.user)
    }

    if waffle.switch_is_active('new_program_progress'):
        course_data = meter.progress(programs=[program_data],
                                     count_only=False)[0]
        certificate_data = get_certificates(request.user, program_data)

        program_data.pop('courses')

        context.update({
            'program_data': program_data,
            'course_data': course_data,
            'certificate_data': certificate_data,
        })

        return render_to_response(
            'learner_dashboard/program_details_2017.html', context)
    else:
        context.update({'program_data': program_data})

        return render_to_response('learner_dashboard/program_details.html',
                                  context)
Пример #57
0
def public_program_listing(request):
    """View a list of all programs."""
    programs_config = ProgramsApiConfig.current()
    if not programs_config.show_program_listing:
        raise Http404

    meter = utils.ProgramProgressMeter(request.user)

    context = {
        'programs': meter.programs,
    }
    return render_to_response('learner_dashboard/public_programs.html', context)
Пример #58
0
def get_course_programs_for_dashboard(user, course_keys):   # pylint: disable=invalid-name
    """ Return all programs related to a user.

    Given a user and an iterable of course keys, find all
    the programs relevant to the user's dashboard and return them in a
    dictionary keyed by the course_key.

    Arguments:
        user (user object): Currently logged-in User for which we need to get
            JWT ID-Token
        course_keys (list): List of course keys in which user is enrolled

    Returns:
        Dictionary response containing programs or None
    """
    course_programs = {}
    if not is_student_dashboard_programs_enabled():
        log.warning("Programs service for student dashboard is disabled.")
        return course_programs

    # unicode-ify the course keys for efficient lookup
    course_keys = map(unicode, course_keys)

    # If cache config is enabled then get the response from cache first.
    if is_cache_enabled_for_programs():
        cached_programs = get_cached_programs_response()
        if cached_programs is not None:
            return _get_user_course_programs(cached_programs, course_keys)

    # get programs slumber-based client 'EdxRestApiClient'
    try:
        api_client = programs_api_client(ProgramsApiConfig.current().internal_api_url, get_id_token(user, CLIENT_NAME))
    except Exception:   # pylint: disable=broad-except
        log.exception('Failed to initialize the Programs API client.')
        return course_programs

    # get programs from api client
    try:
        response = api_client.programs.get()
    except Exception:  # pylint: disable=broad-except
        log.exception('Failed to retrieve programs from the Programs API.')
        return course_programs

    programs = response.get('results', [])
    if not programs:
        log.warning("No programs found for the user '%s'.", user.id)
        return course_programs

    # If cache config is enabled than set the cache.
    if is_cache_enabled_for_programs():
        set_cached_programs_response(programs)

    return _get_user_course_programs(programs, course_keys)
Пример #59
0
    def mock_programs_api(self, data=None, status_code=200):
        """Utility for mocking out Programs API URLs."""
        self.assertTrue(httpretty.is_enabled(), msg='httpretty must be enabled to mock Programs API calls.')

        url = ProgramsApiConfig.current().internal_api_url.strip('/') + '/programs/'

        if data is None:
            data = self.PROGRAMS_API_RESPONSE

        body = json.dumps(data)

        httpretty.reset()
        httpretty.register_uri(httpretty.GET, url, body=body, content_type='application/json', status=status_code)
Пример #60
0
def text_me_the_app(request):
    """
    Text me the app view.
    """
    text_me_fragment = TextMeTheAppFragmentView().render_to_fragment(request)
    context = {
        'nav_hidden': True,
        'show_dashboard_tabs': True,
        'show_program_listing': ProgramsApiConfig.is_enabled(),
        'fragment': text_me_fragment
    }

    return render_to_response('text-me-the-app.html', context)