def test_about_page_marketing_site(self): """ Get URL for about page, marketing site enabled. """ self.register_catalog_course_run_response([self.course_key_string], [self.course_run]) self.assertEquals(get_link_for_about_page(self.course_key, self.user), self.course_run["marketing_url"]) cached_data = cache.get_many([self.course_cache_key]) self.assertIn(self.course_cache_key, cached_data.keys()) with mock.patch('openedx.core.djangoapps.catalog.utils.get_edx_api_data') as mock_method: self.assertEquals(get_link_for_about_page(self.course_key, self.user), self.course_run["marketing_url"]) self.assertEqual(0, mock_method.call_count)
def test_about_page_lms(self): """ Get URL for about page, no marketing site. """ with mock.patch.dict('django.conf.settings.FEATURES', {'ENABLE_MKTG_SITE': False}): self.assertEquals( get_link_for_about_page(self.course_key, self.user), self.lms_course_about_url ) with mock.patch.dict('django.conf.settings.FEATURES', {'ENABLE_MKTG_SITE': True}): self.register_catalog_course_run_response( [self.course_key_string], [{"key": self.course_key_string, "marketing_url": None}] ) self.assertEquals(get_link_for_about_page(self.course_key, self.user), self.lms_course_about_url)
def get_course_sharing_link(self, enable_social_sharing, enable_mktg_site, use_overview=True): """ Get course sharing link. Arguments: enable_social_sharing(Boolean): To indicate whether social sharing is enabled. enable_mktg_site(Boolean): A feature flag to decide activation of marketing site. Keyword Arguments: use_overview: indicates whether course overview or course descriptor should get past to get_link_for_about_page. Returns course sharing url. """ mock_settings = { 'FEATURES': { 'ENABLE_MKTG_SITE': enable_mktg_site }, 'SOCIAL_SHARING_SETTINGS': { 'CUSTOM_COURSE_URLS': enable_social_sharing }, } with mock.patch.multiple('django.conf.settings', **mock_settings): course_sharing_link = get_link_for_about_page( self.course_overview if use_overview else self.course ) return course_sharing_link
def to_representation(self, course_overview): course_id = unicode(course_overview.id) request = self.context.get('request') return { # identifiers 'id': course_id, 'name': course_overview.display_name, 'number': course_overview.display_number_with_default, 'org': course_overview.display_org_with_default, # dates 'start': course_overview.start, 'start_display': course_overview.start_display, 'start_type': course_overview.start_type, 'end': course_overview.end, # notification info 'subscription_id': course_overview.clean_id(padding_char='_'), # access info 'courseware_access': has_access( request.user, 'load_mobile', course_overview ).to_json(), # various URLs # course_image is sent in both new and old formats # (within media to be compatible with the new Course API) 'media': { 'course_image': { 'uri': course_overview.course_image_url, 'name': 'Course Image', } }, 'course_image': course_overview.course_image_url, 'course_about': get_link_for_about_page(course_overview), 'course_sharing_utm_parameters': get_encoded_course_sharing_utm_params(), 'course_updates': reverse( 'course-updates-list', kwargs={'course_id': course_id}, request=request, ), 'course_handouts': reverse( 'course-handouts-list', kwargs={'course_id': course_id}, request=request, ), 'discussion_url': reverse( 'discussion_course', kwargs={'course_id': course_id}, request=request, ) if course_overview.is_discussion_tab_enabled() else None, 'video_outline': reverse( 'video-summary-list', kwargs={'course_id': course_id}, request=request, ), }
def to_representation(self, course_overview): course_id = six.text_type(course_overview.id) request = self.context.get('request') api_version = self.context.get('api_version') enrollment = CourseEnrollment.get_enrollment(user=self.context.get('request').user, course_key=course_id) return { # identifiers 'id': course_id, 'name': course_overview.display_name, 'number': course_overview.display_number_with_default, 'org': course_overview.display_org_with_default, # dates 'start': course_overview.start, 'start_display': course_overview.start_display, 'start_type': course_overview.start_type, 'end': course_overview.end, 'dynamic_upgrade_deadline': enrollment.upgrade_deadline, # notification info 'subscription_id': course_overview.clean_id(padding_char='_'), # access info 'courseware_access': has_access( request.user, 'load_mobile', course_overview ).to_json(), # various URLs # course_image is sent in both new and old formats # (within media to be compatible with the new Course API) 'media': { 'course_image': { 'uri': course_overview.course_image_url, 'name': 'Course Image', } }, 'course_image': course_overview.course_image_url, 'course_about': get_link_for_about_page(course_overview), 'course_sharing_utm_parameters': get_encoded_course_sharing_utm_params(), 'course_updates': reverse( 'course-updates-list', kwargs={'api_version': api_version, 'course_id': course_id}, request=request, ), 'course_handouts': reverse( 'course-handouts-list', kwargs={'api_version': api_version, 'course_id': course_id}, request=request, ), 'discussion_url': reverse( 'discussion_course', kwargs={'course_id': course_id}, request=request, ) if course_overview.is_discussion_tab_enabled() else None, # This is an old API that was removed as part of DEPR-4. We keep the # field present in case API parsers expect it, but this API is now # removed. 'video_outline': None, }
def get(self, request, **kwargs): """ Implements the GET method as described in the class docstring. """ from rest_framework.reverse import reverse params = request.GET search_key = request.GET.get("search_key") course_category = request.GET.get("subjects") org = request.GET.get("org") user_id = request.GET.get("user_id") size = 2000 if "org" in request.GET: if not request.GET.get("org"): request.GET = request.GET.copy() request.GET.pop("org") if "subjects" in request.GET: if not request.GET.get("subjects"): request.GET = request.GET.copy() request.GET.pop("subjects") search_url = request.build_absolute_uri(reverse("course_discovery")) if course_category or org: def _process_field_values(request): """ Create separate dictionary of supported filter values provided """ return { field_key: request.GET[field_key] for field_key in request.GET if field_key in course_discovery_filter_fields() } field_dictionary = _process_field_values(request) results = course_discovery_search( search_term=search_key, size=size, from_=0, field_dictionary=field_dictionary, ) else: def _process_field_values(request): """ Create separate dictionary of supported filter values provided """ return { field_key: request.POST[field_key] for field_key in request.POST if field_key in course_discovery_filter_fields() } field_dictionary = _process_field_values(request) if search_key: results = course_discovery_search( search_term=search_key, size=size, from_=0, field_dictionary=field_dictionary, ) else: results = course_discovery_search( size=size, from_=0, field_dictionary=field_dictionary, ) if results.get("total"): # logging.info("for search api have results") result = [] course_ids = [] for course in results.get("results"): course_id = course.get("_id") course_key = CourseKey.from_string(course_id) course_ids.append(course_key) course_overviews = CourseOverview.objects.filter( id__in=course_ids ).order_by("-start") # logging.info("courses list [%s]", course_overviews) course_search_enroll = [] for course_overview in course_overviews: search_course = {} course_id = str(course_overview.id) course_key = CourseKey.from_string(course_id) course_enroll = CourseEnrollment.objects.filter( course_id=course_key, user_id=user_id, is_active=True ) if course_enroll.exists(): course_enroll = course_enroll[0] try: user = User.objects.get(id=user_id) except: message = { "error": _('Does not match user for "{user_id}"').format( user_id=user_id ) } response = JsonResponse( {"status": "false", "message": message}, status=400 ) return response search_course["mode"] = course_enroll.mode search_course["is_active"] = course_enroll.is_active created = course_enroll.created created = created.strftime("%Y-%m-%dT%H:%M:%S.%fZ") search_course["created"] = created certificate_info = certificate_downloadable_status(user, course_key) if certificate_info["is_downloadable"]: certificates = { "url": request.build_absolute_uri( certificate_info["download_url"] ), } else: certificates = {} search_course["certificate"] = certificates block_id = modulestore().get_items( course_key, qualifiers={"category": "video"} ) if block_id: data = block_id[0].__dict__ if "scope_ids" in data: seq_block_id = data.get( "scope_ids" ).def_id.to_deprecated_string() else: seq_block_id = "" else: seq_block_id = "" course_extra_info = course_extrainfo.objects.get( course_id=course_key ) if course_extra_info.course_type == "2": video_blocks_in_course = modulestore().get_items( course_key, qualifiers={"category": "video"} ) if video_blocks_in_course: if video_blocks_in_course[0].html5_sources: video_url = ( video_blocks_in_course[0].html5_sources[0] if video_blocks_in_course[0].html5_sources else video_blocks_in_course[0].html5_sources ) else: video_id = ( video_blocks_in_course[0].youtube_id_1_25 or video_blocks_in_course[0].youtube_id_0_75 or video_blocks_in_course[0].youtube_id_1_0 ) if video_id: video_url = ( "https://www.youtube.com/watch?v=" + video_id ) else: video_url = "" else: video_url = "" is_lecture = "true" else: video_url = "" is_lecture = "false" start_date = course_overview.start start = start_date.strftime("%Y-%m-%dT%H:%M:%S.%fZ") end_date = course_overview.end if end_date: end_date = end_date.strftime("%Y-%m-%dT%H:%M:%S.%fZ") search_course["course"] = { "id": course_id, "is_lecture": is_lecture, "video_url": video_url, "seq_block_id": seq_block_id, "number": course_overview.display_number_with_default, "name": course_overview.display_name, "org": course_overview.display_org_with_default, # dates "start": start, "start_display": course_overview.start_display, "start_type": course_overview.start_type, "end": end_date, # notification info "subscription_id": course_overview.clean_id(padding_char="_"), # access info "courseware_access": has_access( user, "load_mobile", course_overview ).to_json(), # various URLs # course_image is sent in both new and old formats # (within media to be compatible with the new Course API) "media": { "course_image": { "uri": course_overview.course_image_url, "name": "Course Image", } }, "course_image": course_overview.course_image_url, "course_about": get_link_for_about_page(course_overview), "course_sharing_utm_parameters": get_encoded_course_sharing_utm_params(), "course_updates": reverse( "course-updates-list", kwargs={"course_id": course_id}, request=request, ), "course_handouts": reverse( "course-handouts-list", kwargs={"course_id": course_id}, request=request, ), "discussion_url": reverse( "discussion_course", kwargs={"course_id": course_id}, request=request, ) if course_overview.is_discussion_tab_enabled() else None, "video_outline": reverse( "video-summary-list", kwargs={"course_id": course_id}, request=request, ), } course_search_enroll.append(search_course) if not course_search_enroll: course_search_enroll = [] return JsonResponse(course_search_enroll, status=200, safe=False) return JsonResponse(course_search_enroll, status=200, safe=False) else: course_search_enroll = [] return JsonResponse(course_search_enroll, status=200, safe=False)
def test_about_page_marketing_url_cached(self): self.assertEquals( get_link_for_about_page(self.course_key, self.user, self.course_run), self.course_run["marketing_url"] )
def to_representation(self, course_overview): course_id = unicode(course_overview.id) request = self.context.get('request') try: course = get_course_with_access(request.user, 'load', course_overview.id) course_grade = CourseGradeFactory().read(request.user, course) progress = { 'is_pass': course_grade.passed, 'total_grade': course_grade.summary['percent'] } except Exception as e: log.error(e) progress = { 'is_pass': False, 'total_grade': 0 } return { # identifiers 'id': course_id, 'name': course_overview.display_name, 'number': course_overview.display_number_with_default, 'org': course_overview.display_org_with_default, # dates 'start': course_overview.start, 'start_display': course_overview.start_display, 'start_type': course_overview.start_type, 'end': course_overview.end, # notification info 'subscription_id': course_overview.clean_id(padding_char='_'), # access info 'courseware_access': has_access( request.user, 'load_mobile', course_overview ).to_json(), # various URLs # course_image is sent in both new and old formats # (within media to be compatible with the new Course API) 'media': { 'course_image': { 'uri': course_overview.course_image_url, 'name': 'Course Image', } }, 'course_image': course_overview.course_image_url, 'course_about': get_link_for_about_page(course_overview), 'course_sharing_utm_parameters': get_encoded_course_sharing_utm_params(), 'course_updates': reverse( 'course-updates-list', kwargs={'course_id': course_id, 'api_version': 'v1'}, request=request, ), 'course_handouts': reverse( 'course-handouts-list', kwargs={'course_id': course_id, 'api_version': 'v1'}, request=request, ), 'discussion_url': reverse( 'discussion_course', kwargs={'course_id': course_id}, request=request, ) if course_overview.is_discussion_tab_enabled() else None, 'video_outline': reverse( 'video-summary-list', kwargs={'course_id': course_id, 'api_version': 'v1'}, request=request, ), 'is_vip': VIPInfo.is_vip(request.user), 'is_normal_enroll': not VIPCourseEnrollment.objects.filter( user=request.user, course_id=course_overview.id, is_active=True ).exists(), 'has_cert': certificate_status_for_student(request.user, course_overview.id)['status'] == 'downloadable', 'progress': progress, }
def get(self, request, **kwargs): """ Implements the GET method as described in the class docstring. """ from rest_framework.reverse import reverse params = request.GET search_key = request.GET.get('search_key') course_category = request.GET.get('subjects') org = request.GET.get('org') user_id = request.GET.get('user_id') size = 2000 search_url = request.build_absolute_uri(reverse('course_discovery')) if course_category or org: def _process_field_values(request): """ Create separate dictionary of supported filter values provided """ return { field_key: request.GET[field_key] for field_key in request.GET if field_key in course_discovery_filter_fields() } field_dictionary = _process_field_values(request) results = course_discovery_search( search_term=search_key, size=size, from_=0, field_dictionary=field_dictionary, ) else: def _process_field_values(request): """ Create separate dictionary of supported filter values provided """ return { field_key: request.POST[field_key] for field_key in request.POST if field_key in course_discovery_filter_fields() } field_dictionary = _process_field_values(request) results = course_discovery_search( search_term=search_key, size=size, from_=0, field_dictionary=field_dictionary, ) if results.get('total'): result = [] course_search_enroll = [] for course in results.get('results'): search_course = {} course_id = course.get('_id') course_key = CourseKey.from_string(course_id) course_enroll = CourseEnrollment.objects.filter( course_id=course_key, user_id=user_id, is_active=True) course_overview = CourseOverview.objects.get(id=course_key) if course_enroll.exists(): course_enroll = course_enroll[0] try: user = User.objects.get(id=user_id) except: message = { "error": _('Does not match user for "{user_id}"').format( user_id=user_id) } response = JsonResponse( { 'status': 'false', 'message': message }, status=400) return response search_course['mode'] = course_enroll.mode search_course['is_active'] = course_enroll.is_active created = course_enroll.created created = created.strftime("%Y-%m-%dT%H:%M:%S.%fZ") search_course['created'] = created certificate_info = certificate_downloadable_status( user, course_key) if certificate_info['is_downloadable']: certificates = { 'url': request.build_absolute_uri( certificate_info['download_url']), } else: certificates = {} search_course['certificate'] = certificates start_date = course_overview.start start = start_date.strftime("%Y-%m-%dT%H:%M:%S.%fZ") end_date = course_overview.end if end_date: end_date = end_date.strftime("%Y-%m-%dT%H:%M:%S.%fZ") search_course['course'] = { 'id': course_id, 'number': course_overview.display_number_with_default, 'name': course_overview.display_name, 'org': course_overview.display_org_with_default, # dates 'start': start, 'start_display': course_overview.start_display, 'start_type': course_overview.start_type, 'end': end_date, # notification info 'subscription_id': course_overview.clean_id(padding_char='_'), # access info 'courseware_access': has_access(user, 'load_mobile', course_overview).to_json(), # various URLs # course_image is sent in both new and old formats # (within media to be compatible with the new Course API) 'media': { 'course_image': { 'uri': course_overview.course_image_url, 'name': 'Course Image', } }, 'course_image': course_overview.course_image_url, 'course_about': get_link_for_about_page(course_overview), 'course_sharing_utm_parameters': get_encoded_course_sharing_utm_params(), 'course_updates': reverse( 'course-updates-list', kwargs={'course_id': course_id}, request=request, ), 'course_handouts': reverse( 'course-handouts-list', kwargs={'course_id': course_id}, request=request, ), 'discussion_url': reverse( 'discussion_course', kwargs={'course_id': course_id}, request=request, ) if course_overview.is_discussion_tab_enabled() else None, 'video_outline': reverse( 'video-summary-list', kwargs={'course_id': course_id}, request=request, ) } course_search_enroll.append(search_course) if not course_search_enroll: course_search_enroll = [] return JsonResponse(course_search_enroll, status=200, safe=False) return JsonResponse(course_search_enroll, status=200, safe=False) else: course_search_enroll = [] return JsonResponse(course_search_enroll, status=200, safe=False)