def strftime_localized_html(dtime, fmt): """ Returns an html string that can be further localized in browser by JS code For example, a user's default timezone preference is "whatever the browser default is" which must be queried via Javascript. So we write out a UTC formatted date here, but tag it with enough information that dateutil_factory.js can then later update the DOM to use the proper formatting. Arguments: dtime (datetime): Datetime to format fmt (str): One of the special enum values that strftime_localized accepts. Only SHORT_DATE supported now. """ locale_prefs = user_timezone_locale_prefs(crum.get_current_request()) user_timezone = locale_prefs['user_timezone'] language = get_language() # Here we map the enums for strftime_localized into the enums used by date-utils.js when localizing on JS side. format_mapping = { 'SHORT_DATE': 'shortDate', } assert fmt in format_mapping.keys( ), 'format "%s" not yet supported in strftime_localized_html' % fmt # pylint: disable=consider-iterating-dictionary date_html = '<span class="localized-datetime" data-format="{format}" data-timezone="{user_timezone}" \ data-datetime="{formatted_date}" data-language="{language}">{formatted_date_localized}</span>' return HTML(date_html).format( language=language, user_timezone=user_timezone, format=format_mapping[fmt], formatted_date=dtime.isoformat(), formatted_date_localized=strftime_localized(dtime, fmt), )
def get(self, request, *args, **kwargs): course_key_string = kwargs.get('course_key_string') course_key = CourseKey.from_string(course_key_string) if course_home_legacy_is_active(course_key): raise Http404 # Enable NR tracing for this view based on course monitoring_utils.set_custom_attribute('course_id', course_key_string) monitoring_utils.set_custom_attribute('user_id', request.user.id) monitoring_utils.set_custom_attribute('is_staff', request.user.is_staff) course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=False) is_staff = bool(has_access(request.user, 'staff', course_key)) _, request.user = setup_masquerade( request, course_key, staff_access=is_staff, reset_masquerade_data=True, ) if not CourseEnrollment.is_enrolled(request.user, course_key) and not is_staff: return Response('User not enrolled.', status=401) blocks = get_course_date_blocks(course, request.user, request, include_access=True, include_past_dates=True) learner_is_full_access = not ContentTypeGatingConfig.enabled_for_enrollment( user=request.user, course_key=course_key, ) # User locale settings user_timezone_locale = user_timezone_locale_prefs(request) user_timezone = user_timezone_locale['user_timezone'] data = { 'has_ended': course.has_ended(), 'course_date_blocks': [block for block in blocks if not isinstance(block, TodaysDate)], 'learner_is_full_access': learner_is_full_access, 'user_timezone': user_timezone, } context = self.get_serializer_context() context['learner_is_full_access'] = learner_is_full_access serializer = self.get_serializer_class()(data, context=context) return Response(serializer.data)
def get(self, request, *args, **kwargs): course_key_string = kwargs.get('course_key_string') course_key = CourseKey.from_string(course_key_string) course_usage_key = modulestore().make_course_usage_key(course_key) # Enable NR tracing for this view based on course monitoring_utils.set_custom_metric('course_id', course_key_string) monitoring_utils.set_custom_metric('user_id', request.user.id) monitoring_utils.set_custom_metric('is_staff', request.user.is_staff) _, request.user = setup_masquerade(request, course_key, staff_access=has_access( request.user, 'staff', course_key), reset_masquerade_data=True) user_timezone_locale = user_timezone_locale_prefs(request) user_timezone = user_timezone_locale['user_timezone'] transformers = BlockStructureTransformers() transformers += course_blocks_api.get_course_block_access_transformers( request.user) transformers += [ BlocksAPITransformer(None, None, depth=3), ] course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=True) course_blocks = get_course_blocks(request.user, course_usage_key, transformers, include_completion=True) enrollment_mode, _ = CourseEnrollment.enrollment_mode_for_user( request.user, course_key) course_grade = CourseGradeFactory().read(request.user, course) courseware_summary = course_grade.chapter_grades.values() data = { 'course_blocks': course_blocks, 'courseware_summary': courseware_summary, 'enrollment_mode': enrollment_mode, 'user_timezone': user_timezone, } context = self.get_serializer_context() context['staff_access'] = bool( has_access(request.user, 'staff', course)) context['course_key'] = course_key serializer = self.get_serializer_class()(data, context=context) return Response(serializer.data)
def get(self, request, *args, **kwargs): course_key_string = kwargs.get('course_key_string') course_key = CourseKey.from_string(course_key_string) if not course_home_mfe_dates_tab_is_active(course_key): return Response(status=status.HTTP_404_NOT_FOUND) # Enable NR tracing for this view based on course monitoring_utils.set_custom_metric('course_id', course_key_string) monitoring_utils.set_custom_metric('user_id', request.user.id) monitoring_utils.set_custom_metric('is_staff', request.user.is_staff) course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=False) blocks = get_course_date_blocks(course, request.user, request, include_access=True, include_past_dates=True) missed_deadlines, missed_gated_content = dates_banner_should_display( course_key, request.user) learner_is_full_access = not ContentTypeGatingConfig.enabled_for_enrollment( user=request.user, course_key=course_key, ) # User locale settings user_timezone_locale = user_timezone_locale_prefs(request) user_timezone = user_timezone_locale['user_timezone'] data = { 'has_ended': course.has_ended(), 'course_date_blocks': [block for block in blocks if not isinstance(block, TodaysDate)], 'missed_deadlines': missed_deadlines, 'missed_gated_content': missed_gated_content, 'learner_is_full_access': learner_is_full_access, 'user_timezone': user_timezone, 'verified_upgrade_link': verified_upgrade_deadline_link(request.user, course=course), } context = self.get_serializer_context() context['learner_is_full_access'] = learner_is_full_access serializer = self.get_serializer_class()(data, context=context) return Response(serializer.data)
def get(self, request, *args, **kwargs): course_key_string = kwargs.get('course_key_string') # Enable NR tracing for this view based on course monitoring_utils.set_custom_metric('course_id', course_key_string) monitoring_utils.set_custom_metric('user_id', request.user.id) monitoring_utils.set_custom_metric('is_staff', request.user.is_staff) course_key = CourseKey.from_string(course_key_string) course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=False) blocks = get_course_date_blocks(course, request.user, request, include_access=True, include_past_dates=True) display_reset_dates_text, _ = dates_banner_should_display( course_key, request) learner_is_verified = False enrollment = get_enrollment(request.user.username, course_key_string) if enrollment: learner_is_verified = enrollment.get('mode') == 'verified' # User locale settings user_timezone_locale = user_timezone_locale_prefs(request) user_timezone = user_timezone_locale['user_timezone'] data = { 'course_date_blocks': [block for block in blocks if not isinstance(block, TodaysDate)], 'display_reset_dates_text': display_reset_dates_text, 'learner_is_verified': learner_is_verified, 'user_timezone': user_timezone, 'verified_upgrade_link': verified_upgrade_deadline_link(request.user, course=course), } context = self.get_serializer_context() context['learner_is_verified'] = learner_is_verified serializer = self.get_serializer_class()(data, context=context) return Response(serializer.data)
def test_no_language_preference(self): set_user_preference(self.user, 'time_zone', 'Asia/Tokyo') context = user_timezone_locale_prefs(self.request) self.assertIsNone(context['user_language']) self.assertIsNotNone(context['user_timezone']) self.assertEqual(context['user_timezone'], 'Asia/Tokyo')
def test_no_timezone_preference(self): set_user_preference(self.user, 'pref-lang', 'en') context = user_timezone_locale_prefs(self.request) self.assertIsNone(context['user_timezone']) self.assertIsNotNone(context['user_language']) self.assertEqual(context['user_language'], 'en')
def test_anonymous_user(self): self.request.user = AnonymousUser() context = user_timezone_locale_prefs(self.request) self.assertIsNone(context['user_timezone']) self.assertIsNone(context['user_language'])
def generate_course_expired_message(user, course): """ Generate the message for the user course expiration date if it exists. """ expiration_date = get_user_course_expiration_date(user, course) if not expiration_date: return user_timezone_locale = user_timezone_locale_prefs( crum.get_current_request()) user_timezone = user_timezone_locale['user_timezone'] now = timezone.now() if is_masquerading_as_specific_student( user, course.id) and now > expiration_date: upgrade_message = _( 'This learner does not have access to this course. ' u'Their access expired on {expiration_date}.') return HTML(upgrade_message).format(expiration_date=strftime_localized( expiration_date, EXPIRATION_DATE_FORMAT_STR)) else: enrollment = CourseEnrollment.get_enrollment(user, course.id) if enrollment is None: return upgrade_deadline = enrollment.upgrade_deadline if (not upgrade_deadline) or (upgrade_deadline < now): upgrade_deadline = enrollment.course_upgrade_deadline expiration_message = _( u'{strong_open}Audit Access Expires {expiration_date}{strong_close}' u'{line_break}You lose all access to this course, including your progress, on ' u'{expiration_date}.') upgrade_deadline_message = _( u'{line_break}Upgrade by {upgrade_deadline} to get unlimited access to the course ' u'as long as it exists on the site. {a_open}Upgrade now{sronly_span_open} to ' u'retain access past {expiration_date}{span_close}{a_close}') full_message = expiration_message if upgrade_deadline and now < upgrade_deadline: full_message += upgrade_deadline_message using_upgrade_messaging = True else: using_upgrade_messaging = False language = get_language() date_string = get_date_string() formatted_expiration_date = date_string.format( language=language, user_timezone=user_timezone, formatted_date=expiration_date.isoformat(), formatted_date_localized=strftime_localized( expiration_date, EXPIRATION_DATE_FORMAT_STR)) if using_upgrade_messaging: formatted_upgrade_deadline = date_string.format( language=language, user_timezone=user_timezone, formatted_date=upgrade_deadline.isoformat(), formatted_date_localized=strftime_localized( upgrade_deadline, EXPIRATION_DATE_FORMAT_STR)) return HTML(full_message).format( a_open=HTML(u'<a id="FBE_banner" href="{upgrade_link}">'). format(upgrade_link=verified_upgrade_deadline_link( user=user, course=course)), sronly_span_open=HTML('<span class="sr-only">'), span_close=HTML('</span>'), a_close=HTML('</a>'), expiration_date=HTML(formatted_expiration_date), strong_open=HTML('<strong>'), strong_close=HTML('</strong>'), line_break=HTML('<br>'), upgrade_deadline=HTML(formatted_upgrade_deadline)) else: return HTML(full_message).format( span_close=HTML('</span>'), expiration_date=HTML(formatted_expiration_date), strong_open=HTML('<strong>'), strong_close=HTML('</strong>'), line_break=HTML('<br>'), )
def generate_course_expired_message(user, course): """ Generate the message for the user course expiration date if it exists. """ expiration_data = get_access_expiration_data(user, course) if not expiration_data: return expiration_date = expiration_data['expiration_date'] masquerading_expired_course = expiration_data[ 'masquerading_expired_course'] upgrade_deadline = expiration_data['upgrade_deadline'] upgrade_url = expiration_data['upgrade_url'] user_timezone_locale = user_timezone_locale_prefs( crum.get_current_request()) user_timezone = user_timezone_locale['user_timezone'] if masquerading_expired_course: upgrade_message = _( 'This learner does not have access to this course. ' 'Their access expired on {expiration_date}.') return HTML(upgrade_message).format(expiration_date=strftime_localized( expiration_date, EXPIRATION_DATE_FORMAT_STR)) else: expiration_message = _( '{strong_open}Audit Access Expires {expiration_date}{strong_close}' '{line_break}You lose all access to this course, including your progress, on ' '{expiration_date}.') upgrade_deadline_message = _( '{line_break}Upgrade by {upgrade_deadline} to get unlimited access to the course ' 'as long as it exists on the site. {a_open}Upgrade now{sronly_span_open} to ' 'retain access past {expiration_date}{span_close}{a_close}') full_message = expiration_message if upgrade_deadline and upgrade_url: full_message += upgrade_deadline_message using_upgrade_messaging = True else: using_upgrade_messaging = False language = get_language() date_string = get_date_string() formatted_expiration_date = date_string.format( language=language, user_timezone=user_timezone, formatted_date=expiration_date.isoformat(), formatted_date_localized=strftime_localized( expiration_date, EXPIRATION_DATE_FORMAT_STR)) if using_upgrade_messaging: formatted_upgrade_deadline = date_string.format( language=language, user_timezone=user_timezone, formatted_date=upgrade_deadline.isoformat(), formatted_date_localized=strftime_localized( upgrade_deadline, EXPIRATION_DATE_FORMAT_STR)) return HTML(full_message).format( a_open=HTML('<a id="FBE_banner" href="{upgrade_link}">' ).format(upgrade_link=upgrade_url), sronly_span_open=HTML('<span class="sr-only">'), span_close=HTML('</span>'), a_close=HTML('</a>'), expiration_date=HTML(formatted_expiration_date), strong_open=HTML('<strong>'), strong_close=HTML('</strong>'), line_break=HTML('<br>'), upgrade_deadline=HTML(formatted_upgrade_deadline)) else: return HTML(full_message).format( span_close=HTML('</span>'), expiration_date=HTML(formatted_expiration_date), strong_open=HTML('<strong>'), strong_close=HTML('</strong>'), line_break=HTML('<br>'), )
def get(self, request, *args, **kwargs): course_key_string = kwargs.get('course_key_string') course_key = CourseKey.from_string(course_key_string) course_usage_key = modulestore().make_course_usage_key(course_key) if not course_home_mfe_outline_tab_is_active(course_key): raise Http404 # Enable NR tracing for this view based on course monitoring_utils.set_custom_metric('course_id', course_key_string) monitoring_utils.set_custom_metric('user_id', request.user.id) monitoring_utils.set_custom_metric('is_staff', request.user.is_staff) course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=False) _masquerade, request.user = setup_masquerade( request, course_key, staff_access=has_access(request.user, 'staff', course_key), reset_masquerade_data=True, ) course_overview = CourseOverview.get_from_id(course_key) enrollment = CourseEnrollment.get_enrollment(request.user, course_key) allow_anonymous = COURSE_ENABLE_UNENROLLED_ACCESS_FLAG.is_enabled( course_key) allow_public = allow_anonymous and course.course_visibility == COURSE_VISIBILITY_PUBLIC is_enrolled = enrollment and enrollment.is_active is_staff = has_access(request.user, 'staff', course_key) show_enrolled = is_enrolled or is_staff show_handouts = show_enrolled or allow_public handouts_html = get_course_info_section( request, request.user, course, 'handouts') if show_handouts else '' # TODO: TNL-7185 Legacy: Refactor to return the offer & expired data and format the message in the MFE offer_html = generate_offer_html(request.user, course_overview) course_expired_html = generate_course_expired_message( request.user, course_overview) welcome_message_html = None if get_course_tag(request.user, course_key, PREFERENCE_KEY) != 'False': if LATEST_UPDATE_FLAG.is_enabled(course_key): welcome_message_html = LatestUpdateFragmentView( ).latest_update_html(request, course) else: welcome_message_html = WelcomeMessageFragmentView( ).welcome_message_html(request, course) enroll_alert = { 'can_enroll': True, 'extra_text': None, } if not show_enrolled: if CourseMode.is_masters_only(course_key): enroll_alert['can_enroll'] = False enroll_alert['extra_text'] = _( 'Please contact your degree administrator or ' 'edX Support if you have questions.') elif course.invitation_only: enroll_alert['can_enroll'] = False course_tools = CourseToolsPluginManager.get_enabled_course_tools( request, course_key) date_blocks = get_course_date_blocks(course, request.user, request, num_assignments=1) # User locale settings user_timezone_locale = user_timezone_locale_prefs(request) user_timezone = user_timezone_locale['user_timezone'] dates_tab_link = request.build_absolute_uri( reverse('dates', args=[course.id])) if course_home_mfe_dates_tab_is_active(course.id): dates_tab_link = get_microfrontend_url(course_key=course.id, view_name='dates') transformers = BlockStructureTransformers() transformers += get_course_block_access_transformers(request.user) transformers += [ BlocksAPITransformer(None, None, depth=3), ] course_blocks = get_course_blocks(request.user, course_usage_key, transformers, include_completion=True) dates_widget = { 'course_date_blocks': [ block for block in date_blocks if not isinstance(block, TodaysDate) ], 'dates_tab_link': dates_tab_link, 'user_timezone': user_timezone, } data = { 'course_blocks': course_blocks, 'course_expired_html': course_expired_html, 'course_tools': course_tools, 'dates_widget': dates_widget, 'enroll_alert': enroll_alert, 'handouts_html': handouts_html, 'offer_html': offer_html, 'welcome_message_html': welcome_message_html, } context = self.get_serializer_context() context['course_key'] = course_key serializer = self.get_serializer_class()(data, context=context) return Response(serializer.data)
def user_timezone(self): """Returns the user's timezone setting (may be None)""" user_timezone_locale = user_timezone_locale_prefs(self.request) return user_timezone_locale['user_timezone']
def get(self, request, *args, **kwargs): course_key_string = kwargs.get('course_key_string') course_key = CourseKey.from_string(course_key_string) course_usage_key = modulestore().make_course_usage_key(course_key) if course_home_legacy_is_active(course_key): raise Http404 # Enable NR tracing for this view based on course monitoring_utils.set_custom_attribute('course_id', course_key_string) monitoring_utils.set_custom_attribute('user_id', request.user.id) monitoring_utils.set_custom_attribute('is_staff', request.user.is_staff) course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=False) masquerade_object, request.user = setup_masquerade( request, course_key, staff_access=has_access(request.user, 'staff', course_key), reset_masquerade_data=True, ) user_is_masquerading = is_masquerading( request.user, course_key, course_masquerade=masquerade_object) course_overview = CourseOverview.get_from_id(course_key) enrollment = CourseEnrollment.get_enrollment(request.user, course_key) allow_anonymous = COURSE_ENABLE_UNENROLLED_ACCESS_FLAG.is_enabled( course_key) allow_public = allow_anonymous and course.course_visibility == COURSE_VISIBILITY_PUBLIC allow_public_outline = allow_anonymous and course.course_visibility == COURSE_VISIBILITY_PUBLIC_OUTLINE # User locale settings user_timezone_locale = user_timezone_locale_prefs(request) user_timezone = user_timezone_locale['user_timezone'] if course_home_legacy_is_active(course.id): dates_tab_link = request.build_absolute_uri( reverse('dates', args=[course.id])) else: dates_tab_link = get_learning_mfe_home_url(course_key=course.id, view_name='dates') # Set all of the defaults access_expiration = None cert_data = None course_blocks = None course_goals = {'goal_options': [], 'selected_goal': None} course_tools = CourseToolsPluginManager.get_enabled_course_tools( request, course_key) dates_widget = { 'course_date_blocks': [], 'dates_tab_link': dates_tab_link, 'user_timezone': user_timezone, } enroll_alert = { 'can_enroll': True, 'extra_text': None, } handouts_html = None offer_data = None resume_course = { 'has_visited_course': False, 'url': None, } welcome_message_html = None is_enrolled = enrollment and enrollment.is_active is_staff = bool(has_access(request.user, 'staff', course_key)) show_enrolled = is_enrolled or is_staff if show_enrolled: course_blocks = get_course_outline_block_tree( request, course_key_string, request.user) date_blocks = get_course_date_blocks(course, request.user, request, num_assignments=1) dates_widget['course_date_blocks'] = [ block for block in date_blocks if not isinstance(block, TodaysDate) ] handouts_html = get_course_info_section(request, request.user, course, 'handouts') welcome_message_html = get_current_update_for_user(request, course) offer_data = generate_offer_data(request.user, course_overview) access_expiration = get_access_expiration_data( request.user, course_overview) cert_data = get_cert_data(request.user, course, enrollment.mode) if is_enrolled else None # Only show the set course goal message for enrolled, unverified # users in a course that allows for verified statuses. is_already_verified = CourseEnrollment.is_enrolled_as_verified( request.user, course_key) if not is_already_verified and has_course_goal_permission( request, course_key_string, {'is_enrolled': is_enrolled}): course_goals = { 'goal_options': valid_course_goals_ordered(include_unsure=True), 'selected_goal': None } selected_goal = get_course_goal(request.user, course_key) if selected_goal: course_goals['selected_goal'] = { 'key': selected_goal.goal_key, 'text': get_course_goal_text(selected_goal.goal_key), } try: resume_block = get_key_to_last_completed_block( request.user, course.id) resume_course['has_visited_course'] = True resume_path = reverse('jump_to', kwargs={ 'course_id': course_key_string, 'location': str(resume_block) }) resume_course['url'] = request.build_absolute_uri(resume_path) except UnavailableCompletionData: start_block = get_start_block(course_blocks) resume_course['url'] = start_block['lms_web_url'] elif allow_public_outline or allow_public or user_is_masquerading: course_blocks = get_course_outline_block_tree( request, course_key_string, None) if allow_public or user_is_masquerading: handouts_html = get_course_info_section( request, request.user, course, 'handouts') if not show_enrolled: if CourseMode.is_masters_only(course_key): enroll_alert['can_enroll'] = False enroll_alert['extra_text'] = _( 'Please contact your degree administrator or ' 'edX Support if you have questions.') elif course.invitation_only: enroll_alert['can_enroll'] = False # Sometimes there are sequences returned by Course Blocks that we # don't actually want to show to the user, such as when a sequence is # composed entirely of units that the user can't access. The Learning # Sequences API knows how to roll this up, so we use it determine which # sequences we should remove from course_blocks. # # The long term goal is to remove the Course Blocks API call entirely, # so this is a tiny first step in that migration. if course_blocks and learning_sequences_api_available( course_key, request.user): user_course_outline = get_user_course_outline( course_key, request.user, datetime.now(tz=timezone.utc)) available_seq_ids = { str(usage_key) for usage_key in user_course_outline.sequences } # course_blocks is a reference to the root of the course, so we go # through the chapters (sections) to look for sequences to remove. for chapter_data in course_blocks['children']: chapter_data['children'] = [ seq_data for seq_data in chapter_data['children'] if (seq_data['id'] in available_seq_ids or # Edge case: Sometimes we have weird course structures. # We expect only sequentials here, but if there is # another type, just skip it (don't filter it out). seq_data['type'] != 'sequential') ] if 'children' in chapter_data else [] data = { 'access_expiration': access_expiration, 'cert_data': cert_data, 'course_blocks': course_blocks, 'course_goals': course_goals, 'course_tools': course_tools, 'dates_widget': dates_widget, 'enroll_alert': enroll_alert, 'handouts_html': handouts_html, 'has_ended': course.has_ended(), 'offer': offer_data, 'resume_course': resume_course, 'welcome_message_html': welcome_message_html, } context = self.get_serializer_context() context['course_overview'] = course_overview context['enable_links'] = show_enrolled or allow_public context['enrollment'] = enrollment serializer = self.get_serializer_class()(data, context=context) return Response(serializer.data)
def get(self, request, *args, **kwargs): course_key_string = kwargs.get('course_key_string') course_key = CourseKey.from_string(course_key_string) course_usage_key = modulestore().make_course_usage_key(course_key) # Enable NR tracing for this view based on course monitoring_utils.set_custom_metric('course_id', course_key_string) monitoring_utils.set_custom_metric('user_id', request.user.id) monitoring_utils.set_custom_metric('is_staff', request.user.is_staff) course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=False) _, request.user = setup_masquerade( request, course_key, staff_access=has_access(request.user, 'staff', course_key), reset_masquerade_data=True, ) enrollment = CourseEnrollment.get_enrollment(request.user, course_key) allow_anonymous = COURSE_ENABLE_UNENROLLED_ACCESS_FLAG.is_enabled(course_key) allow_public = allow_anonymous and course.course_visibility == COURSE_VISIBILITY_PUBLIC is_enrolled = enrollment and enrollment.is_active is_staff = has_access(request.user, 'staff', course_key) show_handouts = is_enrolled or is_staff or allow_public handouts_html = get_course_info_section(request, request.user, course, 'handouts') if show_handouts else '' welcome_message_html = None if get_course_tag(request.user, course_key, PREFERENCE_KEY) != 'False': if LATEST_UPDATE_FLAG.is_enabled(course_key): welcome_message_html = LatestUpdateFragmentView().latest_update_html(request, course) else: welcome_message_html = WelcomeMessageFragmentView().welcome_message_html(request, course) course_tools = CourseToolsPluginManager.get_enabled_course_tools(request, course_key) date_blocks = get_course_date_blocks(course, request.user, request, num_assignments=1) # User locale settings user_timezone_locale = user_timezone_locale_prefs(request) user_timezone = user_timezone_locale['user_timezone'] dates_tab_link = request.build_absolute_uri(reverse('dates', args=[course.id])) if course_home_mfe_dates_tab_is_active(course.id): dates_tab_link = get_microfrontend_url(course_key=course.id, view_name='dates') transformers = BlockStructureTransformers() transformers += get_course_block_access_transformers(request.user) transformers += [ BlocksAPITransformer(None, None, depth=3), ] course_blocks = get_course_blocks(request.user, course_usage_key, transformers, include_completion=True) dates_widget = { 'course_date_blocks': [block for block in date_blocks if not isinstance(block, TodaysDate)], 'dates_tab_link': dates_tab_link, 'user_timezone': user_timezone, } data = { 'course_blocks': course_blocks, 'course_tools': course_tools, 'dates_widget': dates_widget, 'handouts_html': handouts_html, 'welcome_message_html': welcome_message_html, } context = self.get_serializer_context() context['course_key'] = course_key serializer = self.get_serializer_class()(data, context=context) return Response(serializer.data)
def test_site_wide_language_set(self, mock_get_value): mock_get_value.return_value = 'ar' set_user_preference(self.user, 'pref-lang', 'en') context = user_timezone_locale_prefs(self.request) assert context['user_language'] == 'ar'
def test_anonymous_user(self): self.request.user = AnonymousUser() context = user_timezone_locale_prefs(self.request) assert context['user_timezone'] is None assert context['user_language'] == settings.LANGUAGE_CODE
def get(self, request, *args, **kwargs): course_key_string = kwargs.get('course_key_string') course_key = CourseKey.from_string(course_key_string) course_usage_key = modulestore().make_course_usage_key(course_key) # Enable NR tracing for this view based on course monitoring_utils.set_custom_metric('course_id', course_key_string) monitoring_utils.set_custom_metric('user_id', request.user.id) monitoring_utils.set_custom_metric('is_staff', request.user.is_staff) course_tools = CourseToolsPluginManager.get_enabled_course_tools( request, course_key) course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=False) date_blocks = get_course_date_blocks(course, request.user, request, num_assignments=1) # User locale settings user_timezone_locale = user_timezone_locale_prefs(request) user_timezone = user_timezone_locale['user_timezone'] dates_tab_link = request.build_absolute_uri( reverse('dates', args=[course.id])) if course_home_mfe_dates_tab_is_active(course.id): dates_tab_link = get_microfrontend_url(course_key=course.id, view_name='dates') transformers = BlockStructureTransformers() transformers += course_blocks_api.get_course_block_access_transformers( request.user) transformers += [ BlocksAPITransformer(None, None, depth=3), ] course_blocks = get_course_blocks(request.user, course_usage_key, transformers, include_completion=True) dates_widget = { 'course_date_blocks': [ block for block in date_blocks if not isinstance(block, TodaysDate) ], 'dates_tab_link': dates_tab_link, 'user_timezone': user_timezone, } data = { 'course_tools': course_tools, 'course_blocks': course_blocks, 'dates_widget': dates_widget, } context = self.get_serializer_context() context['course_key'] = course_key serializer = self.get_serializer_class()(data, context=context) return Response(serializer.data)
def get(self, request, *args, **kwargs): course_key_string = kwargs.get('course_key_string') course_key = CourseKey.from_string(course_key_string) # Enable NR tracing for this view based on course monitoring_utils.set_custom_attribute('course_id', course_key_string) monitoring_utils.set_custom_attribute('user_id', request.user.id) monitoring_utils.set_custom_attribute('is_staff', request.user.is_staff) _, request.user = setup_masquerade(request, course_key, staff_access=has_access( request.user, 'staff', course_key), reset_masquerade_data=True) user_timezone_locale = user_timezone_locale_prefs(request) user_timezone = user_timezone_locale['user_timezone'] transformers = BlockStructureTransformers() transformers += course_blocks_api.get_course_block_access_transformers( request.user) transformers += [ BlocksAPITransformer(None, None, depth=3), ] course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=True) enrollment_mode, _ = CourseEnrollment.enrollment_mode_for_user( request.user, course_key) course_grade = CourseGradeFactory().read(request.user, course) courseware_summary = course_grade.chapter_grades.values() verification_status = IDVerificationService.user_status(request.user) verification_link = None if verification_status['status'] is None or verification_status[ 'status'] == 'expired': verification_link = IDVerificationService.get_verify_location( course_id=course_key) elif verification_status['status'] == 'must_reverify': verification_link = IDVerificationService.get_verify_location( course_id=course_key) verification_data = { 'link': verification_link, 'status': verification_status['status'], 'status_date': verification_status['status_date'], } data = { 'certificate_data': get_cert_data(request.user, course, enrollment_mode, course_grade), 'courseware_summary': courseware_summary, 'credit_course_requirements': credit_course_requirements(course_key, request.user), 'credit_support_url': CREDIT_SUPPORT_URL, 'enrollment_mode': enrollment_mode, 'studio_url': get_studio_url(course, 'settings/grading'), 'user_timezone': user_timezone, 'verification_data': verification_data, } context = self.get_serializer_context() context['staff_access'] = bool( has_access(request.user, 'staff', course)) context['course_key'] = course_key serializer = self.get_serializer_class()(data, context=context) return Response(serializer.data)
def test_no_timezone_preference(self): set_user_preference(self.user, 'pref-lang', 'en') context = user_timezone_locale_prefs(self.request) assert context['user_timezone'] is None assert context['user_language'] is not None assert context['user_language'] == 'en'
def get(self, request, *args, **kwargs): course_key_string = kwargs.get('course_key_string') course_key = CourseKey.from_string(course_key_string) course_usage_key = modulestore().make_course_usage_key(course_key) if not course_home_mfe_outline_tab_is_active(course_key): raise Http404 # Enable NR tracing for this view based on course monitoring_utils.set_custom_attribute('course_id', course_key_string) monitoring_utils.set_custom_attribute('user_id', request.user.id) monitoring_utils.set_custom_attribute('is_staff', request.user.is_staff) course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=False) _masquerade, request.user = setup_masquerade( request, course_key, staff_access=has_access(request.user, 'staff', course_key), reset_masquerade_data=True, ) course_overview = CourseOverview.get_from_id(course_key) enrollment = CourseEnrollment.get_enrollment(request.user, course_key) allow_anonymous = COURSE_ENABLE_UNENROLLED_ACCESS_FLAG.is_enabled( course_key) allow_public = allow_anonymous and course.course_visibility == COURSE_VISIBILITY_PUBLIC allow_public_outline = allow_anonymous and course.course_visibility == COURSE_VISIBILITY_PUBLIC_OUTLINE is_enrolled = enrollment and enrollment.is_active is_staff = bool(has_access(request.user, 'staff', course_key)) show_enrolled = is_enrolled or is_staff show_handouts = show_enrolled or allow_public handouts_html = get_course_info_section( request, request.user, course, 'handouts') if show_handouts else '' # TODO: TNL-7185 Legacy: Refactor to return the offer & expired data and format the message in the MFE offer_html = show_enrolled and generate_offer_html( request.user, course_overview) course_expired_html = show_enrolled and generate_course_expired_message( request.user, course_overview) welcome_message_html = None if show_enrolled: if LATEST_UPDATE_FLAG.is_enabled(course_key): welcome_message_html = LatestUpdateFragmentView( ).latest_update_html(request, course) elif get_course_tag(request.user, course_key, PREFERENCE_KEY) != 'False': welcome_message_html = WelcomeMessageFragmentView( ).welcome_message_html(request, course) enroll_alert = { 'can_enroll': True, 'extra_text': None, } if not show_enrolled: if CourseMode.is_masters_only(course_key): enroll_alert['can_enroll'] = False enroll_alert['extra_text'] = _( 'Please contact your degree administrator or ' 'edX Support if you have questions.') elif course.invitation_only: enroll_alert['can_enroll'] = False course_tools = CourseToolsPluginManager.get_enabled_course_tools( request, course_key) date_blocks = get_course_date_blocks(course, request.user, request, num_assignments=1) # User locale settings user_timezone_locale = user_timezone_locale_prefs(request) user_timezone = user_timezone_locale['user_timezone'] dates_tab_link = request.build_absolute_uri( reverse('dates', args=[course.id])) if course_home_mfe_dates_tab_is_active(course.id): dates_tab_link = get_microfrontend_url(course_key=course.id, view_name='dates') course_blocks = None if show_enrolled or allow_public or allow_public_outline: outline_user = request.user if show_enrolled else None course_blocks = get_course_outline_block_tree( request, course_key_string, outline_user) resume_course = { 'has_visited_course': False, 'url': None, } if show_enrolled: try: resume_block = get_key_to_last_completed_block( request.user, course.id) resume_course['has_visited_course'] = True except UnavailableCompletionData: resume_block = course_usage_key resume_path = reverse('jump_to', kwargs={ 'course_id': course_key_string, 'location': str(resume_block) }) resume_course['url'] = request.build_absolute_uri(resume_path) dates_widget = { 'course_date_blocks': [ block for block in date_blocks if not isinstance(block, TodaysDate) ], 'dates_tab_link': dates_tab_link, 'user_timezone': user_timezone, } # Only show the set course goal message for enrolled, unverified # users in a course that allows for verified statuses. is_already_verified = CourseEnrollment.is_enrolled_as_verified( request.user, course_key) if (not is_already_verified and has_course_goal_permission( request, course_key_string, {'is_enrolled': is_enrolled})): course_goals = { 'goal_options': valid_course_goals_ordered(include_unsure=True), 'selected_goal': None } selected_goal = get_course_goal(request.user, course_key) if selected_goal: course_goals['selected_goal'] = { 'key': selected_goal.goal_key, 'text': get_course_goal_text(selected_goal.goal_key), } else: course_goals = {'goal_options': [], 'selected_goal': None} data = { 'course_blocks': course_blocks, 'course_expired_html': course_expired_html or None, 'course_goals': course_goals, 'course_tools': course_tools, 'dates_widget': dates_widget, 'enroll_alert': enroll_alert, 'handouts_html': handouts_html or None, 'has_ended': course.has_ended(), 'offer_html': offer_html or None, 'resume_course': resume_course, 'welcome_message_html': welcome_message_html or None, } context = self.get_serializer_context() context['course_key'] = course_key context['enable_links'] = show_enrolled or allow_public serializer = self.get_serializer_class()(data, context=context) return Response(serializer.data)
def test_no_language_preference(self): set_user_preference(self.user, 'time_zone', 'Asia/Tokyo') context = user_timezone_locale_prefs(self.request) assert context['user_language'] is None assert context['user_timezone'] is not None assert context['user_timezone'] == 'Asia/Tokyo'
def get(self, request, *args, **kwargs): course_key_string = kwargs.get('course_key_string') course_key = CourseKey.from_string(course_key_string) course_usage_key = modulestore().make_course_usage_key(course_key) if not course_home_mfe_outline_tab_is_active(course_key): raise Http404 # Enable NR tracing for this view based on course monitoring_utils.set_custom_attribute('course_id', course_key_string) monitoring_utils.set_custom_attribute('user_id', request.user.id) monitoring_utils.set_custom_attribute('is_staff', request.user.is_staff) course = get_course_with_access(request.user, 'load', course_key, check_if_enrolled=False) masquerade_object, request.user = setup_masquerade( request, course_key, staff_access=has_access(request.user, 'staff', course_key), reset_masquerade_data=True, ) user_is_masquerading = is_masquerading( request.user, course_key, course_masquerade=masquerade_object) course_overview = CourseOverview.get_from_id(course_key) enrollment = CourseEnrollment.get_enrollment(request.user, course_key) allow_anonymous = COURSE_ENABLE_UNENROLLED_ACCESS_FLAG.is_enabled( course_key) allow_public = allow_anonymous and course.course_visibility == COURSE_VISIBILITY_PUBLIC allow_public_outline = allow_anonymous and course.course_visibility == COURSE_VISIBILITY_PUBLIC_OUTLINE # User locale settings user_timezone_locale = user_timezone_locale_prefs(request) user_timezone = user_timezone_locale['user_timezone'] dates_tab_link = request.build_absolute_uri( reverse('dates', args=[course.id])) if course_home_mfe_dates_tab_is_active(course.id): dates_tab_link = get_learning_mfe_home_url(course_key=course.id, view_name='dates') # Set all of the defaults access_expiration = None course_blocks = None course_goals = {'goal_options': [], 'selected_goal': None} course_tools = CourseToolsPluginManager.get_enabled_course_tools( request, course_key) dates_widget = { 'course_date_blocks': [], 'dates_tab_link': dates_tab_link, 'user_timezone': user_timezone, } enroll_alert = { 'can_enroll': True, 'extra_text': None, } handouts_html = None offer_data = None resume_course = { 'has_visited_course': False, 'url': None, } welcome_message_html = None is_enrolled = enrollment and enrollment.is_active is_staff = bool(has_access(request.user, 'staff', course_key)) show_enrolled = is_enrolled or is_staff if show_enrolled: course_blocks = get_course_outline_block_tree( request, course_key_string, request.user) date_blocks = get_course_date_blocks(course, request.user, request, num_assignments=1) dates_widget['course_date_blocks'] = [ block for block in date_blocks if not isinstance(block, TodaysDate) ] handouts_html = get_course_info_section(request, request.user, course, 'handouts') welcome_message_html = get_current_update_for_user(request, course) offer_data = generate_offer_data(request.user, course_overview) access_expiration = get_access_expiration_data( request.user, course_overview) # Only show the set course goal message for enrolled, unverified # users in a course that allows for verified statuses. is_already_verified = CourseEnrollment.is_enrolled_as_verified( request.user, course_key) if not is_already_verified and has_course_goal_permission( request, course_key_string, {'is_enrolled': is_enrolled}): course_goals = { 'goal_options': valid_course_goals_ordered(include_unsure=True), 'selected_goal': None } selected_goal = get_course_goal(request.user, course_key) if selected_goal: course_goals['selected_goal'] = { 'key': selected_goal.goal_key, 'text': get_course_goal_text(selected_goal.goal_key), } try: resume_block = get_key_to_last_completed_block( request.user, course.id) resume_course['has_visited_course'] = True resume_path = reverse('jump_to', kwargs={ 'course_id': course_key_string, 'location': str(resume_block) }) resume_course['url'] = request.build_absolute_uri(resume_path) except UnavailableCompletionData: start_block = get_start_block(course_blocks) resume_course['url'] = start_block['lms_web_url'] elif allow_public_outline or allow_public or user_is_masquerading: course_blocks = get_course_outline_block_tree( request, course_key_string, None) if allow_public or user_is_masquerading: handouts_html = get_course_info_section( request, request.user, course, 'handouts') if not show_enrolled: if CourseMode.is_masters_only(course_key): enroll_alert['can_enroll'] = False enroll_alert['extra_text'] = _( 'Please contact your degree administrator or ' 'edX Support if you have questions.') elif course.invitation_only: enroll_alert['can_enroll'] = False data = { 'access_expiration': access_expiration, 'course_blocks': course_blocks, 'course_goals': course_goals, 'course_tools': course_tools, 'dates_widget': dates_widget, 'enroll_alert': enroll_alert, 'handouts_html': handouts_html, 'has_ended': course.has_ended(), 'offer': offer_data, 'resume_course': resume_course, 'welcome_message_html': welcome_message_html, } context = self.get_serializer_context() context['course_overview'] = course_overview context['enable_links'] = show_enrolled or allow_public context['enrollment'] = enrollment serializer = self.get_serializer_class()(data, context=context) return Response(serializer.data)
def get(self, request, *args, **kwargs): course_key_string = kwargs.get('course_key_string') course_key = CourseKey.from_string(course_key_string) original_user_is_global_staff = self.request.user.is_staff original_user_is_staff = has_access(request.user, 'staff', course_key).has_access course = course_detail(request, request.user.username, course_key) # We must compute course load access *before* setting up masquerading, # else course staff (who are not enrolled) will not be able view # their course from the perspective of a learner. load_access = check_course_access( course, request.user, 'load', check_if_enrolled=True, check_if_authenticated=True, ) _, request.user = setup_masquerade( request, course_key, staff_access=original_user_is_staff, reset_masquerade_data=True, ) username = request.user.username if request.user.username else None enrollment = CourseEnrollment.get_enrollment(request.user, course_key_string) user_is_enrolled = bool(enrollment and enrollment.is_active) can_load_courseware = courseware_mfe_is_visible( course_key=course_key, is_global_staff=original_user_is_global_staff, is_course_staff=original_user_is_staff) # User locale settings user_timezone_locale = user_timezone_locale_prefs(request) user_timezone = user_timezone_locale['user_timezone'] browser_timezone = self.request.query_params.get( 'browser_timezone', None) celebrations = get_celebrations_dict( request.user, enrollment, course, user_timezone if not None else browser_timezone) # Record course goals user activity for (web) learning mfe course tabs UserActivity.record_user_activity(request.user, course_key) data = { 'course_id': course.id, 'username': username, 'is_staff': has_access(request.user, 'staff', course_key).has_access, 'original_user_is_staff': original_user_is_staff, 'number': course.display_number_with_default, 'org': course.display_org_with_default, 'start': course.start, 'tabs': get_course_tab_list(request.user, course), 'title': course.display_name_with_default, 'is_self_paced': getattr(course, 'self_paced', False), 'is_enrolled': user_is_enrolled, 'course_access': load_access.to_json(), 'can_load_courseware': can_load_courseware, 'celebrations': celebrations, 'user_timezone': user_timezone, } context = self.get_serializer_context() context['course'] = course context['course_overview'] = course context['enrollment'] = enrollment serializer = self.get_serializer_class()(data, context=context) return Response(serializer.data)