Ejemplo n.º 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)
Ejemplo n.º 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
        })
Ejemplo n.º 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)
Ejemplo n.º 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)
Ejemplo n.º 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)
    })
Ejemplo n.º 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)
Ejemplo n.º 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)
Ejemplo n.º 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)
Ejemplo n.º 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)
Ejemplo n.º 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)
Ejemplo n.º 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)
Ejemplo n.º 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)
Ejemplo n.º 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)
Ejemplo n.º 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)
Ejemplo n.º 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
Ejemplo n.º 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)
Ejemplo n.º 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
Ejemplo n.º 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)
Ejemplo n.º 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)
Ejemplo n.º 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)
Ejemplo n.º 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)
Ejemplo n.º 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)
Ejemplo n.º 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
Ejemplo n.º 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
Ejemplo n.º 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
Ejemplo n.º 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)
Ejemplo n.º 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)
Ejemplo n.º 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
Ejemplo n.º 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)
Ejemplo n.º 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
Ejemplo n.º 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
Ejemplo n.º 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))
Ejemplo n.º 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)
Ejemplo n.º 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
Ejemplo n.º 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))
Ejemplo n.º 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)
Ejemplo n.º 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
Ejemplo n.º 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')
Ejemplo n.º 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')
Ejemplo n.º 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)
Ejemplo n.º 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
Ejemplo n.º 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))
Ejemplo n.º 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)
Ejemplo n.º 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
Ejemplo n.º 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)
Ejemplo n.º 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)
Ejemplo n.º 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
Ejemplo n.º 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
Ejemplo n.º 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
Ejemplo n.º 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')
Ejemplo n.º 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
    )
Ejemplo n.º 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
    })
Ejemplo n.º 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))
Ejemplo n.º 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)
Ejemplo n.º 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)
Ejemplo n.º 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)
Ejemplo n.º 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)
Ejemplo n.º 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)