def get_verification_context(self, request, course): course_key = CourseKey.from_string(unicode(course.id)) # Establish whether the course has a verified mode available_modes = CourseMode.modes_for_course_dict(unicode(course.id)) has_verified_mode = CourseMode.has_verified_mode(available_modes) # Establish whether the user is already enrolled is_already_verified = CourseEnrollment.is_enrolled_as_verified(request.user, course_key) # Establish whether the verification deadline has already passed verification_deadline = VerifiedUpgradeDeadlineDate(course, request.user) deadline_has_passed = verification_deadline.deadline_has_passed() # If this proves its worth, we can internationalize and display for more than English speakers. show_course_sock = ( has_verified_mode and not is_already_verified and not deadline_has_passed and get_language() == 'en' ) # Get information about the upgrade course_price = get_cosmetic_verified_display_price(course) upgrade_url = EcommerceService().upgrade_url(request.user, course_key) context = { 'show_course_sock': show_course_sock, 'course_price': course_price, 'course_id': course.id, 'upgrade_url': upgrade_url, } return context
def register_alerts(self, request, course): """ Registers an alert if the verification deadline is approaching. """ upgrade_price = get_cosmetic_verified_display_price(course) if not UPGRADE_DEADLINE_MESSAGE.is_enabled(course.id) or not self.is_enabled or not upgrade_price: return days_left_to_upgrade = (self.date - self.current_time).days if self.date > self.current_time and days_left_to_upgrade <= settings.COURSE_MESSAGE_ALERT_DURATION_IN_DAYS: CourseHomeMessages.register_info_message( request, Text(_( 'In order to qualify for a certificate, you must meet all course grading ' 'requirements, upgrade before the course deadline, and successfully verify ' 'your identity on {platform_name} if you have not done so already.{button_panel}' )).format( platform_name=settings.PLATFORM_NAME, button_panel=HTML( '<div class="message-actions">' '<a class="btn btn-upgrade"' 'data-creative="original_message" data-position="course_message"' 'href="{upgrade_url}">{upgrade_label}</a>' '</div>' ).format( upgrade_url=self.link, upgrade_label=Text(_('Upgrade ({upgrade_price})')).format(upgrade_price=upgrade_price), ) ), title=Text(_( "Don't forget, you have {time_remaining_string} left to upgrade to a Verified Certificate." )).format( time_remaining_string=self.time_remaining_string, ) )
def get_experiment_user_metadata_context(course, user): """ Return a context dictionary with the keys used by the user_metadata.html. """ enrollment_mode = None enrollment_time = None enrollment = None try: enrollment = CourseEnrollment.objects.select_related( 'course' ).get(user_id=user.id, course_id=course.id) if enrollment.is_active: enrollment_mode = enrollment.mode enrollment_time = enrollment.created except CourseEnrollment.DoesNotExist: pass # Not enrolled, used the default None values upgrade_link, upgrade_date = check_and_get_upgrade_link_and_date(user, enrollment, course) has_staff_access = has_staff_access_to_preview_mode(user, course) return { 'upgrade_link': upgrade_link, 'upgrade_price': unicode(get_cosmetic_verified_display_price(course)), 'enrollment_mode': enrollment_mode, 'enrollment_time': enrollment_time, 'pacing_type': 'self_paced' if course.self_paced else 'instructor_paced', 'upgrade_deadline': upgrade_date, 'course_key': course.id, 'course_start': course.start, 'course_end': course.end, 'has_staff_access': has_staff_access, }
def get_base_experiment_metadata_context(course, user, enrollment, user_enrollments, audit_enrollments): """ Return a context dictionary with the keys used by dashboard_metadata.html and user_metadata.html """ enrollment_mode = None enrollment_time = None # TODO: clean up as part of REVEM-199 (START) program_key = get_program_context(course, user_enrollments, audit_enrollments) # TODO: clean up as part of REVEM-199 (END) if enrollment and enrollment.is_active: enrollment_mode = enrollment.mode enrollment_time = enrollment.created # upgrade_link and upgrade_date should be None if user has passed their dynamic pacing deadline. upgrade_link, upgrade_date = check_and_get_upgrade_link_and_date(user, enrollment, course) return { 'upgrade_link': upgrade_link, 'upgrade_price': six.text_type(get_cosmetic_verified_display_price(course)), 'enrollment_mode': enrollment_mode, 'enrollment_time': enrollment_time, 'pacing_type': 'self_paced' if course.self_paced else 'instructor_paced', 'upgrade_deadline': upgrade_date, 'audit_access_deadline': get_audit_access_expiration(user, course), 'course_key': course.id, 'course_start': course.start, 'course_end': course.end, # TODO: clean up as part of REVEM-199 (START) 'program_key_fields': program_key, # TODO: clean up as part of REVEM-199 (END) }
def get_verification_context(self, request, course): course_key = CourseKey.from_string(unicode(course.id)) # Establish whether the course has a verified mode available_modes = CourseMode.modes_for_course_dict(unicode(course.id)) has_verified_mode = CourseMode.has_verified_mode(available_modes) # Establish whether the user is already enrolled is_already_verified = CourseEnrollment.is_enrolled_as_verified(request.user, course_key) # Establish whether the verification deadline has already passed verification_deadline = VerifiedUpgradeDeadlineDate(course, request.user) deadline_has_passed = verification_deadline.deadline_has_passed() # If this proves its worth, we can internationalize and display for more than English speakers. show_course_sock = ( has_verified_mode and not is_already_verified and not deadline_has_passed and get_language() == 'en' ) # Get the price of the course and format correctly course_price = get_cosmetic_verified_display_price(course) context = { 'show_course_sock': show_course_sock, 'course_price': course_price, 'course_id': course.id } return context
def get_experiment_user_metadata_context(course, user): """ Return a context dictionary with the keys used by the user_metadata.html. """ enrollment_mode = None enrollment_time = None try: enrollment = CourseEnrollment.objects.get(user_id=user.id, course_id=course.id) if enrollment.is_active: enrollment_mode = enrollment.mode enrollment_time = enrollment.created except CourseEnrollment.DoesNotExist: pass # Not enrolled, used the default None values upgrade_data = check_and_get_upgrade_link(user, course.id) return { 'upgrade_link': upgrade_data and upgrade_data.link, 'upgrade_price': get_cosmetic_verified_display_price(course), 'enrollment_mode': enrollment_mode, 'enrollment_time': enrollment_time, 'pacing_type': 'self_paced' if course.self_paced else 'instructor_paced', 'upgrade_deadline': upgrade_data and upgrade_data.date, 'course_key': course.id, 'course_start': course.start, 'course_end': course.end, }
def register_alerts(self, request, course): """ Registers an alert if the verification deadline is approaching. """ upgrade_price = get_cosmetic_verified_display_price(course) if not UPGRADE_DEADLINE_MESSAGE.is_enabled( course.id) or not self.is_enabled or not upgrade_price: return days_left_to_upgrade = (self.date - self.current_time).days if self.date > self.current_time and days_left_to_upgrade <= settings.COURSE_MESSAGE_ALERT_DURATION_IN_DAYS: CourseHomeMessages.register_info_message( request, Text( _('In order to qualify for a certificate, you must meet all course grading ' 'requirements, upgrade before the course deadline, and successfully verify ' 'your identity on {platform_name} if you have not done so already.{button_panel}' ) ).format( platform_name=settings.PLATFORM_NAME, button_panel=HTML( '<div class="message-actions">' '<a class="btn btn-upgrade"' 'data-creative="original_message" data-position="course_message"' 'href="{upgrade_url}">{upgrade_label}</a>' '</div>').format( upgrade_url=self.link, upgrade_label=Text( _('Upgrade ({upgrade_price})')).format( upgrade_price=upgrade_price), )), title=Text( _("Don't forget, you have {time_remaining_string} left to upgrade to a Verified Certificate." )).format( time_remaining_string=self.time_remaining_string, ))
def get_experiment_user_metadata_context(course, user): """ Return a context dictionary with the keys used by the user_metadata.html. """ enrollment_mode = None enrollment_time = None enrollment = None # TODO: clean up as part of REVO-28 (START) has_non_audit_enrollments = None # TODO: clean up as part of REVO-28 (END) try: # TODO: clean up as part of REVO-28 (START) user_enrollments = CourseEnrollment.objects.select_related( 'course').filter(user_id=user.id) audit_enrollments = user_enrollments.filter(mode='audit') has_non_audit_enrollments = (len(audit_enrollments) != len(user_enrollments)) # TODO: clean up as part of REVO-28 (END) enrollment = CourseEnrollment.objects.select_related('course').get( user_id=user.id, course_id=course.id) if enrollment.is_active: enrollment_mode = enrollment.mode enrollment_time = enrollment.created except CourseEnrollment.DoesNotExist: pass # Not enrolled, used the default None values upgrade_link, upgrade_date = check_and_get_upgrade_link_and_date( user, enrollment, course) has_staff_access = has_staff_access_to_preview_mode(user, course.id) forum_roles = [] if user.is_authenticated: forum_roles = list( Role.objects.filter( users=user, course_id=course.id).values_list('name').distinct()) # get user partition data partition_groups = get_all_partitions_for_course(course) user_partitions = get_user_partition_groups(course.id, partition_groups, user, 'name') return { 'upgrade_link': upgrade_link, 'upgrade_price': unicode(get_cosmetic_verified_display_price(course)), 'enrollment_mode': enrollment_mode, 'enrollment_time': enrollment_time, 'pacing_type': 'self_paced' if course.self_paced else 'instructor_paced', 'upgrade_deadline': upgrade_date, 'course_key': course.id, 'course_start': course.start, 'course_end': course.end, 'has_staff_access': has_staff_access, 'forum_roles': forum_roles, 'partition_groups': user_partitions, # TODO: clean up as part of REVO-28 (START) 'has_non_audit_enrollments': has_non_audit_enrollments, # TODO: clean up as part of REVO-28 (END) }
def get_verification_context(request, course): enrollment = CourseEnrollment.get_enrollment(request.user, course.id) show_course_sock = verified_upgrade_link_is_valid( enrollment) and get_language() == 'en' upgrade_url = verified_upgrade_deadline_link(request.user, course=course) course_price = get_cosmetic_verified_display_price(course) context = { 'show_course_sock': show_course_sock, 'course_price': course_price, 'course_id': course.id, 'upgrade_url': upgrade_url, } return context
def get_verification_context(request, course): enrollment = CourseEnrollment.get_enrollment(request.user, course.id) show_course_sock = verified_upgrade_link_is_valid(enrollment) and get_language() == 'en' if show_course_sock: upgrade_url = verified_upgrade_deadline_link(request.user, course=course) course_price = get_cosmetic_verified_display_price(course) else: upgrade_url = '' course_price = '' context = { 'show_course_sock': show_course_sock, 'course_price': course_price, 'course_id': course.id, 'upgrade_url': upgrade_url, } return context
def get_experiment_user_metadata_context(course, user): """ Return a context dictionary with the keys used by the user_metadata.html. """ enrollment_mode = None enrollment_time = None enrollment = None try: enrollment = CourseEnrollment.objects.select_related( 'course' ).get(user_id=user.id, course_id=course.id) if enrollment.is_active: enrollment_mode = enrollment.mode enrollment_time = enrollment.created except CourseEnrollment.DoesNotExist: pass # Not enrolled, used the default None values upgrade_link, upgrade_date = check_and_get_upgrade_link_and_date(user, enrollment, course) has_staff_access = has_staff_access_to_preview_mode(user, course.id) forum_roles = [] if user.is_authenticated: forum_roles = list(Role.objects.filter(users=user, course_id=course.id).values_list('name').distinct()) # get user partition data partition_groups = get_all_partitions_for_course(course) user_partitions = get_user_partition_groups(course.id, partition_groups, user, 'name') return { 'upgrade_link': upgrade_link, 'upgrade_price': unicode(get_cosmetic_verified_display_price(course)), 'enrollment_mode': enrollment_mode, 'enrollment_time': enrollment_time, 'pacing_type': 'self_paced' if course.self_paced else 'instructor_paced', 'upgrade_deadline': upgrade_date, 'course_key': course.id, 'course_start': course.start, 'course_end': course.end, 'has_staff_access': has_staff_access, 'forum_roles': forum_roles, 'partition_groups': user_partitions, }
def get_experiment_user_metadata_context(course, user): """ Return a context dictionary with the keys used by the user_metadata.html. """ enrollment_mode = None enrollment_time = None enrollment = None try: enrollment = CourseEnrollment.objects.select_related('course').get( user_id=user.id, course_id=course.id) if enrollment.is_active: enrollment_mode = enrollment.mode enrollment_time = enrollment.created except CourseEnrollment.DoesNotExist: pass # Not enrolled, used the default None values upgrade_link, upgrade_date = check_and_get_upgrade_link_and_date( user, enrollment, course) has_staff_access = has_staff_access_to_preview_mode(user, course) forum_roles = [] if user.is_authenticated: forum_roles = list( Role.objects.filter( users=user, course_id=course.id).values_list('name').distinct()) return { 'upgrade_link': upgrade_link, 'upgrade_price': unicode(get_cosmetic_verified_display_price(course)), 'enrollment_mode': enrollment_mode, 'enrollment_time': enrollment_time, 'pacing_type': 'self_paced' if course.self_paced else 'instructor_paced', 'upgrade_deadline': upgrade_date, 'course_key': course.id, 'course_start': course.start, 'course_end': course.end, 'has_staff_access': has_staff_access, 'forum_roles': forum_roles }
def get(self, request, course_id): """ Displays the user's Learner Analytics for the specified course. Arguments: request: HTTP request course_id (unicode): course id """ course_key = CourseKey.from_string(course_id) if not ENABLE_DASHBOARD_TAB.is_enabled(course_key): raise Http404 course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=True) course_url_name = default_course_url_name(course.id) course_url = reverse(course_url_name, kwargs={'course_id': unicode(course.id)}) is_verified = CourseEnrollment.is_enrolled_as_verified( request.user, course_key) has_access = is_verified or request.user.is_staff enrollment = CourseEnrollment.get_enrollment(request.user, course_key) upgrade_price = None upgrade_url = None if enrollment and enrollment.upgrade_deadline: upgrade_url = EcommerceService().upgrade_url( request.user, course_key) upgrade_price = get_cosmetic_verified_display_price(course) context = { 'upgrade_price': upgrade_price, 'upgrade_link': upgrade_url, 'course': course, 'course_url': course_url, 'disable_courseware_js': True, 'uses_pattern_library': True, 'is_self_paced': course.self_paced, 'is_verified': is_verified, 'has_access': has_access, } if (has_access): grading_policy = course.grading_policy (raw_grade_data, answered_percent, percent_grade) = self.get_grade_data( request.user, course_key, grading_policy['GRADE_CUTOFFS']) raw_schedule_data = self.get_assignments_with_due_date( request, course_key) grade_data, schedule_data = self.sort_grade_and_schedule_data( raw_grade_data, raw_schedule_data) # TODO: LEARNER-3854: Fix hacked defaults with real error handling if implementing Learner Analytics. try: weekly_active_users = self.get_weekly_course_activity_count( course_key) week_streak = self.consecutive_weeks_of_course_activity_for_user( request.user.username, course_key) except Exception as e: logging.exception(e) weekly_active_users = 134 week_streak = 1 context.update({ 'grading_policy': grading_policy, 'assignment_grades': grade_data, 'answered_percent': answered_percent, 'assignment_schedule': schedule_data, 'assignment_schedule_raw': raw_schedule_data, 'profile_image_urls': get_profile_image_urls_for_user(request.user, request), 'discussion_info': self.get_discussion_data(request, course_key), 'passing_grade': math.ceil(100 * course.lowest_passing_grade), 'percent_grade': math.ceil(100 * percent_grade), 'weekly_active_users': weekly_active_users, 'week_streak': week_streak, }) return render_to_response('learner_analytics/dashboard.html', context)
def get(self, request): """ Return the if the course should be upsold in the mobile app, if the user has appropriate permissions. """ if not MOBILE_UPSELL_FLAG.is_enabled(): return Response({ 'show_upsell': False, 'upsell_flag': False, }) course_id = request.GET.get('course_id') try: course_key = CourseKey.from_string(course_id) except InvalidKeyError: return HttpResponseBadRequest("Missing or invalid course_id") course = CourseOverview.get_from_id(course_key) if not course.has_started() or course.has_ended(): return Response({ 'show_upsell': False, 'upsell_flag': MOBILE_UPSELL_FLAG.is_enabled(), 'course_running': False, }) user = request.user try: enrollment = CourseEnrollment.objects.select_related('course').get( user_id=user.id, course_id=course.id) user_upsell = verified_upgrade_link_is_valid(enrollment) except CourseEnrollment.DoesNotExist: user_upsell = True basket_url = EcommerceService().upgrade_url(user, course.id) upgrade_price = six.text_type( get_cosmetic_verified_display_price(course)) could_upsell = bool(user_upsell and basket_url) bucket = stable_bucketing_hash_group(MOBILE_UPSELL_EXPERIMENT, 2, user.username) if could_upsell and hasattr( request, 'session') and MOBILE_UPSELL_EXPERIMENT not in request.session: properties = { 'site': request.site.domain, 'app_label': 'experiments', 'bucket': bucket, 'experiment': 'REV-934', } segment.track( user_id=user.id, event_name='edx.bi.experiment.user.bucketed', properties=properties, ) # Mark that we've recorded this bucketing, so that we don't do it again this session request.session[MOBILE_UPSELL_EXPERIMENT] = True show_upsell = bool(bucket != 0 and could_upsell) if show_upsell: return Response({ 'show_upsell': show_upsell, 'price': upgrade_price, 'basket_url': basket_url, }) else: return Response({ 'show_upsell': show_upsell, 'upsell_flag': MOBILE_UPSELL_FLAG.is_enabled(), 'experiment_bucket': bucket, 'user_upsell': user_upsell, 'basket_url': basket_url, })
def render_to_fragment(self, request, course_id=None, **kwargs): """ Renders the course's home page as a fragment. """ course_key = CourseKey.from_string(course_id) course = get_course_with_access(request.user, 'load', course_key) # Render the course dates as a fragment dates_fragment = CourseDatesFragmentView().render_to_fragment(request, course_id=course_id, **kwargs) # Render the full content to enrolled users, as well as to course and global staff. # Unenrolled users who are not course or global staff are given only a subset. enrollment = CourseEnrollment.get_enrollment(request.user, course_key) user_access = { 'is_anonymous': request.user.is_anonymous(), 'is_enrolled': enrollment is not None, 'is_staff': has_access(request.user, 'staff', course_key), } if user_access['is_enrolled'] or user_access['is_staff']: outline_fragment = CourseOutlineFragmentView().render_to_fragment(request, course_id=course_id, **kwargs) if LATEST_UPDATE_FLAG.is_enabled(course_key): update_message_fragment = LatestUpdateFragmentView().render_to_fragment( request, course_id=course_id, **kwargs ) else: update_message_fragment = WelcomeMessageFragmentView().render_to_fragment( request, course_id=course_id, **kwargs ) course_sock_fragment = CourseSockFragmentView().render_to_fragment(request, course=course, **kwargs) has_visited_course, resume_course_url = self._get_resume_course_info(request, course_id) else: # Redirect the user to the dashboard if they are not enrolled and # this is a course that does not support direct enrollment. if not can_self_enroll_in_course(course_key): raise CourseAccessRedirect(reverse('dashboard')) # Set all the fragments outline_fragment = None update_message_fragment = None course_sock_fragment = None has_visited_course = None resume_course_url = None # Get the handouts handouts_html = self._get_course_handouts(request, course) # Get the course tools enabled for this user and course course_tools = CourseToolsPluginManager.get_enabled_course_tools(request, course_key) # Check if the user can access the course goal functionality has_goal_permission = has_course_goal_permission(request, course_id, user_access) # Grab the current course goal and the acceptable course goal keys mapped to translated values current_goal = get_course_goal(request.user, course_key) goal_options = get_course_goal_options() # Get the course goals api endpoint goal_api_url = get_goal_api_url(request) # Grab the course home messages fragment to render any relevant django messages course_home_message_fragment = CourseHomeMessageFragmentView().render_to_fragment( request, course_id=course_id, user_access=user_access, **kwargs ) # Get info for upgrade messaging upgrade_price = None upgrade_url = None # TODO Add switch to control deployment if SHOW_UPGRADE_MSG_ON_COURSE_HOME.is_enabled(course_key) and enrollment and enrollment.upgrade_deadline: upgrade_url = EcommerceService().upgrade_url(request.user, course_key) upgrade_price = get_cosmetic_verified_display_price(course) # Render the course home fragment context = { 'request': request, 'csrf': csrf(request)['csrf_token'], 'course': course, 'course_key': course_key, 'outline_fragment': outline_fragment, 'handouts_html': handouts_html, 'course_home_message_fragment': course_home_message_fragment, 'has_visited_course': has_visited_course, 'resume_course_url': resume_course_url, 'course_tools': course_tools, 'dates_fragment': dates_fragment, 'username': request.user.username, 'goal_api_url': goal_api_url, 'has_goal_permission': has_goal_permission, 'goal_options': goal_options, 'current_goal': current_goal, 'update_message_fragment': update_message_fragment, 'course_sock_fragment': course_sock_fragment, 'disable_courseware_js': True, 'uses_pattern_library': True, 'upgrade_price': upgrade_price, 'upgrade_url': upgrade_url, } html = render_to_string('course_experience/course-home-fragment.html', context) return Fragment(html)
def get_deprecated_experiment_user_metadata_context(course, user): """ Return a context dictionary with the keys used by the user_metadata.html. This is deprecated and will be removed once we have confirmed that its replacement functions as intended. """ enrollment_mode = None enrollment_time = None enrollment = None # TODO: clean up as part of REVO-28 (START) has_non_audit_enrollments = None # TODO: clean up as part of REVO-28 (END) # TODO: clean up as part of REVEM-199 (START) program_key = None # TODO: clean up as part of REVEM-199 (END) try: # TODO: clean up as part of REVO-28 (START) user_enrollments = CourseEnrollment.objects.select_related('course').filter(user_id=user.id) audit_enrollments = user_enrollments.filter(mode='audit') has_non_audit_enrollments = (len(audit_enrollments) != len(user_enrollments)) # TODO: clean up as part of REVO-28 (END) # TODO: clean up as part of REVEM-199 (START) if PROGRAM_INFO_FLAG.is_enabled(): programs = get_programs(course=course.id) if programs: # A course can be in multiple programs, but we're just grabbing the first one program = programs[0] complete_enrollment = False has_courses_left_to_purchase = False total_courses = None courses = program.get('courses') courses_left_to_purchase_price = None courses_left_to_purchase_url = None program_uuid = program.get('uuid') status = None is_eligible_for_one_click_purchase = None if courses is not None: total_courses = len(courses) complete_enrollment = is_enrolled_in_all_courses(courses, user_enrollments) status = program.get('status') is_eligible_for_one_click_purchase = program.get('is_program_eligible_for_one_click_purchase') # Get the price and purchase URL of the program courses the user has yet to purchase. Say a # program has 3 courses (A, B and C), and the user previously purchased a certificate for A. # The user is enrolled in audit mode for B. The "left to purchase price" should be the price of # B+C. non_audit_enrollments = [en for en in user_enrollments if en not in audit_enrollments] courses_left_to_purchase = get_unenrolled_courses(courses, non_audit_enrollments) if courses_left_to_purchase: has_courses_left_to_purchase = True if is_eligible_for_one_click_purchase: courses_left_to_purchase_price, courses_left_to_purchase_skus = \ get_program_price_and_skus(courses_left_to_purchase) if courses_left_to_purchase_skus: courses_left_to_purchase_url = EcommerceService().get_checkout_page_url( *courses_left_to_purchase_skus, program_uuid=program_uuid) program_key = { 'uuid': program_uuid, 'title': program.get('title'), 'marketing_url': program.get('marketing_url'), 'status': status, 'is_eligible_for_one_click_purchase': is_eligible_for_one_click_purchase, 'total_courses': total_courses, 'complete_enrollment': complete_enrollment, 'has_courses_left_to_purchase': has_courses_left_to_purchase, 'courses_left_to_purchase_price': courses_left_to_purchase_price, 'courses_left_to_purchase_url': courses_left_to_purchase_url, } # TODO: clean up as part of REVEM-199 (END) enrollment = CourseEnrollment.objects.select_related( 'course' ).get(user_id=user.id, course_id=course.id) if enrollment.is_active: enrollment_mode = enrollment.mode enrollment_time = enrollment.created except CourseEnrollment.DoesNotExist: pass # Not enrolled, used the default None values # upgrade_link and upgrade_date should be None if user has passed their dynamic pacing deadline. upgrade_link, upgrade_date = check_and_get_upgrade_link_and_date(user, enrollment, course) has_staff_access = has_staff_access_to_preview_mode(user, course.id) forum_roles = [] if user.is_authenticated: forum_roles = list(Role.objects.filter(users=user, course_id=course.id).values_list('name').distinct()) # get user partition data if user.is_authenticated(): partition_groups = get_all_partitions_for_course(course) user_partitions = get_user_partition_groups(course.id, partition_groups, user, 'name') else: user_partitions = {} return { 'upgrade_link': upgrade_link, 'upgrade_price': six.text_type(get_cosmetic_verified_display_price(course)), 'enrollment_mode': enrollment_mode, 'enrollment_time': enrollment_time, 'pacing_type': 'self_paced' if course.self_paced else 'instructor_paced', 'upgrade_deadline': upgrade_date, 'audit_access_deadline': get_audit_access_expiration(user, course), 'course_key': course.id, 'course_start': course.start, 'course_end': course.end, 'has_staff_access': has_staff_access, 'forum_roles': forum_roles, 'partition_groups': user_partitions, # TODO: clean up as part of REVO-28 (START) 'has_non_audit_enrollments': has_non_audit_enrollments, # TODO: clean up as part of REVO-28 (END) # TODO: clean up as part of REVEM-199 (START) 'program_key_fields': program_key, # TODO: clean up as part of REVEM-199 (END) }
def get_experiment_user_metadata_context(course, user): """ Return a context dictionary with the keys used by the user_metadata.html. """ enrollment_mode = None enrollment_time = None enrollment = None # TODO: clean up as part of REVO-28 (START) has_non_audit_enrollments = None # TODO: clean up as part of REVO-28 (END) # TODO: clean up as part of REVEM-106 (START) program_key = None # TODO: clean up as part of REVEM-106 (END) try: # TODO: clean up as part of REVO-28 (START) user_enrollments = CourseEnrollment.objects.select_related( 'course').filter(user_id=user.id) audit_enrollments = user_enrollments.filter(mode='audit') has_non_audit_enrollments = (len(audit_enrollments) != len(user_enrollments)) # TODO: clean up as part of REVO-28 (END) enrollment = CourseEnrollment.objects.select_related('course').get( user_id=user.id, course_id=course.id) if enrollment.is_active: enrollment_mode = enrollment.mode enrollment_time = enrollment.created # TODO: clean up as part of REVEM-106 (START) # get program data for this course request = get_current_request() if request: enrollment_list = [enrollment] meter = ProgramProgressMeter(request.site, user, enrollments=enrollment_list) if meter.engaged_programs and meter.engaged_programs[0]: org_name = None courses_not_started = 0 courses_in_progress = 0 courses_completed = 0 program_data = meter.engaged_programs[0] program_data = ProgramDataExtender( program_data, user, mobile_only=False).extend() program_orgs = program_data.get( 'credit_backing_organizations') if program_orgs and program_orgs[0]: org = program_orgs[0] org_name = org.get('name') if meter.progress() and meter.progress()[0]: progress = meter.progress()[0] courses_not_started = progress.get('not_started') courses_in_progress = progress.get('in_progress') courses_completed = progress.get('completed') program_key = { 'uuid': program_data.get('uuid'), 'title': program_data.get('title'), 'marketing_url': program_data.get('marketing_url'), 'org_name': org_name, 'courses_not_started': courses_not_started, 'courses_in_progress': courses_in_progress, 'courses_completed': courses_completed, } # TODO: clean up as part of REVEM-106 (END) except CourseEnrollment.DoesNotExist: pass # Not enrolled, used the default None values # upgrade_link and upgrade_date should be None if user has passed their dynamic pacing deadline. upgrade_link, upgrade_date = check_and_get_upgrade_link_and_date( user, enrollment, course) has_staff_access = has_staff_access_to_preview_mode(user, course.id) forum_roles = [] if user.is_authenticated: forum_roles = list( Role.objects.filter( users=user, course_id=course.id).values_list('name').distinct()) # get user partition data if user.is_authenticated(): partition_groups = get_all_partitions_for_course(course) user_partitions = get_user_partition_groups(course.id, partition_groups, user, 'name') else: user_partitions = {} return { 'upgrade_link': upgrade_link, 'upgrade_price': unicode(get_cosmetic_verified_display_price(course)), 'enrollment_mode': enrollment_mode, 'enrollment_time': enrollment_time, 'pacing_type': 'self_paced' if course.self_paced else 'instructor_paced', 'upgrade_deadline': upgrade_date, 'course_key': course.id, 'course_start': course.start, 'course_end': course.end, 'has_staff_access': has_staff_access, 'forum_roles': forum_roles, 'partition_groups': user_partitions, # TODO: clean up as part of REVO-28 (START) 'has_non_audit_enrollments': has_non_audit_enrollments, # TODO: clean up as part of REVO-28 (END) # TODO: clean up as part of REVEM-106 (START) 'program_key_fields': program_key, # TODO: clean up as part of REVEM-106 (END) }
def get(self, request, course_id): """ Displays the user's Learner Analytics for the specified course. Arguments: request: HTTP request course_id (unicode): course id """ course_key = CourseKey.from_string(course_id) if not ENABLE_DASHBOARD_TAB.is_enabled(course_key): raise Http404 course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=True) course_url_name = default_course_url_name(course.id) course_url = reverse(course_url_name, kwargs={'course_id': unicode(course.id)}) is_verified = CourseEnrollment.is_enrolled_as_verified(request.user, course_key) has_access = is_verified or request.user.is_staff enrollment = CourseEnrollment.get_enrollment(request.user, course_key) upgrade_price = None upgrade_url = None if enrollment and enrollment.upgrade_deadline: upgrade_url = EcommerceService().upgrade_url(request.user, course_key) upgrade_price = get_cosmetic_verified_display_price(course) context = { 'upgrade_price': upgrade_price, 'upgrade_link': upgrade_url, 'course': course, 'course_url': course_url, 'disable_courseware_js': True, 'uses_pattern_library': True, 'is_self_paced': course.self_paced, 'is_verified': is_verified, 'has_access': has_access, } if (has_access): grading_policy = course.grading_policy (raw_grade_data, answered_percent, percent_grade) = self.get_grade_data(request.user, course_key, grading_policy['GRADE_CUTOFFS']) raw_schedule_data = self.get_assignments_with_due_date(request, course_key) grade_data, schedule_data = self.sort_grade_and_schedule_data(raw_grade_data, raw_schedule_data) # TODO: LEARNER-3854: Fix hacked defaults with real error handling if implementing Learner Analytics. try: weekly_active_users = self.get_weekly_course_activity_count(course_key) week_streak = self.consecutive_weeks_of_course_activity_for_user( request.user.username, course_key ) except Exception as e: logging.exception(e) weekly_active_users = 134 week_streak = 1 context.update({ 'grading_policy': grading_policy, 'assignment_grades': grade_data, 'answered_percent': answered_percent, 'assignment_schedule': schedule_data, 'assignment_schedule_raw': raw_schedule_data, 'profile_image_urls': get_profile_image_urls_for_user(request.user, request), 'discussion_info': self.get_discussion_data(request, course_key), 'passing_grade': math.ceil(100 * course.lowest_passing_grade), 'percent_grade': math.ceil(100 * percent_grade), 'weekly_active_users': weekly_active_users, 'week_streak': week_streak, }) return render_to_response('learner_analytics/dashboard.html', context)
def render_to_fragment(self, request, course_id=None, **kwargs): """ Renders the course's home page as a fragment. """ course_key = CourseKey.from_string(course_id) course = get_course_with_access(request.user, 'load', course_key) # Render the course dates as a fragment dates_fragment = CourseDatesFragmentView().render_to_fragment(request, course_id=course_id, **kwargs) # Render the full content to enrolled users, as well as to course and global staff. # Unenrolled users who are not course or global staff are given only a subset. enrollment = CourseEnrollment.get_enrollment(request.user, course_key) user_access = { 'is_anonymous': request.user.is_anonymous(), 'is_enrolled': enrollment is not None, 'is_staff': has_access(request.user, 'staff', course_key), } if user_access['is_enrolled'] or user_access['is_staff']: outline_fragment = CourseOutlineFragmentView().render_to_fragment(request, course_id=course_id, **kwargs) if LATEST_UPDATE_FLAG.is_enabled(course_key): update_message_fragment = LatestUpdateFragmentView().render_to_fragment( request, course_id=course_id, **kwargs ) else: update_message_fragment = WelcomeMessageFragmentView().render_to_fragment( request, course_id=course_id, **kwargs ) course_sock_fragment = CourseSockFragmentView().render_to_fragment(request, course=course, **kwargs) has_visited_course, resume_course_url = self._get_resume_course_info(request, course_id) else: # Redirect the user to the dashboard if they are not enrolled and # this is a course that does not support direct enrollment. if not can_self_enroll_in_course(course_key): raise CourseAccessRedirect(reverse('dashboard')) # Set all the fragments outline_fragment = None update_message_fragment = None course_sock_fragment = None has_visited_course = None resume_course_url = None # Get the handouts handouts_html = self._get_course_handouts(request, course) # Get the course tools enabled for this user and course course_tools = CourseToolsPluginManager.get_enabled_course_tools(request, course_key) # Check if the user can access the course goal functionality has_goal_permission = has_course_goal_permission(request, course_id, user_access) # Grab the current course goal and the acceptable course goal keys mapped to translated values current_goal = get_course_goal(request.user, course_key) goal_options = get_course_goal_options() # Get the course goals api endpoint goal_api_url = get_goal_api_url(request) # Grab the course home messages fragment to render any relevant django messages course_home_message_fragment = CourseHomeMessageFragmentView().render_to_fragment( request, course_id=course_id, user_access=user_access, **kwargs ) # Get info for upgrade messaging upgrade_price = None upgrade_url = None # TODO Add switch to control deployment if SHOW_UPGRADE_MSG_ON_COURSE_HOME.is_enabled(course_key) and enrollment and enrollment.upgrade_deadline: upgrade_url = EcommerceService().upgrade_url(request.user, course_key) upgrade_price = get_cosmetic_verified_display_price(course) # Render the course home fragment context = { 'request': request, 'csrf': csrf(request)['csrf_token'], 'course': course, 'course_key': course_key, 'outline_fragment': outline_fragment, 'handouts_html': handouts_html, 'course_home_message_fragment': course_home_message_fragment, 'has_visited_course': has_visited_course, 'resume_course_url': resume_course_url, 'course_tools': course_tools, 'dates_fragment': dates_fragment, 'username': request.user.username, 'goal_api_url': goal_api_url, 'has_goal_permission': has_goal_permission, 'goal_options': goal_options, 'current_goal': current_goal, 'update_message_fragment': update_message_fragment, 'course_sock_fragment': course_sock_fragment, 'disable_courseware_js': True, 'uses_pattern_library': True, 'upgrade_price': upgrade_price, 'upgrade_url': upgrade_url, } html = render_to_string('course_experience/course-home-fragment.html', context) return Fragment(html)
def get_experiment_user_metadata_context(course, user): """ Return a context dictionary with the keys used by the user_metadata.html. """ enrollment_mode = None enrollment_time = None enrollment = None # TODO: clean up as part of REVO-28 (START) has_non_audit_enrollments = None # TODO: clean up as part of REVO-28 (END) # TODO: clean up as part of REVEM-199 (START) program_key = None # TODO: clean up as part of REVEM-199 (END) try: # TODO: clean up as part of REVO-28 (START) user_enrollments = CourseEnrollment.objects.select_related( 'course').filter(user_id=user.id) audit_enrollments = user_enrollments.filter(mode='audit') has_non_audit_enrollments = (len(audit_enrollments) != len(user_enrollments)) # TODO: clean up as part of REVO-28 (END) enrollment = CourseEnrollment.objects.select_related('course').get( user_id=user.id, course_id=course.id) if enrollment.is_active: enrollment_mode = enrollment.mode enrollment_time = enrollment.created # TODO: clean up as part of REVEM-199 (START) if PROGRAM_INFO_FLAG.is_enabled(): programs = get_programs(course=course.id) if programs: # A course can be in multiple programs, but we're just grabbing the first one program = programs[0] complete_enrollment = False total_courses = None courses = program.get('courses') if courses is not None: total_courses = len(courses) complete_enrollment = is_enrolled_in_all_courses_in_program( courses, user_enrollments) program_key = { 'uuid': program.get('uuid'), 'title': program.get('title'), 'marketing_url': program.get('marketing_url'), 'total_courses': total_courses, 'complete_enrollment': complete_enrollment, } # TODO: clean up as part of REVEM-199 (END) except CourseEnrollment.DoesNotExist: pass # Not enrolled, used the default None values # upgrade_link and upgrade_date should be None if user has passed their dynamic pacing deadline. upgrade_link, upgrade_date = check_and_get_upgrade_link_and_date( user, enrollment, course) has_staff_access = has_staff_access_to_preview_mode(user, course.id) forum_roles = [] if user.is_authenticated: forum_roles = list( Role.objects.filter( users=user, course_id=course.id).values_list('name').distinct()) # get user partition data if user.is_authenticated(): partition_groups = get_all_partitions_for_course(course) user_partitions = get_user_partition_groups(course.id, partition_groups, user, 'name') else: user_partitions = {} return { 'upgrade_link': upgrade_link, 'upgrade_price': unicode(get_cosmetic_verified_display_price(course)), 'enrollment_mode': enrollment_mode, 'enrollment_time': enrollment_time, 'pacing_type': 'self_paced' if course.self_paced else 'instructor_paced', 'upgrade_deadline': upgrade_date, 'course_key': course.id, 'course_start': course.start, 'course_end': course.end, 'has_staff_access': has_staff_access, 'forum_roles': forum_roles, 'partition_groups': user_partitions, # TODO: clean up as part of REVO-28 (START) 'has_non_audit_enrollments': has_non_audit_enrollments, # TODO: clean up as part of REVO-28 (END) # TODO: clean up as part of REVEM-199 (START) 'program_key_fields': program_key, # TODO: clean up as part of REVEM-199 (END) }