def _get_context(request, course_id): """ Return all course/student/user data """ course_key = CourseKey.from_string(course_id) course = get_course_with_access(request.user, "load", course_key) # Get general info of course grade_cutoff, avg_grade, min_grade, max_grade = _get_course_info( course, course_key) # masquerade and student required for preview_menu (admin) staff_access = bool(has_access(request.user, 'staff', course)) masquerade, student = setup_masquerade(request, course_key, staff_access, reset_masquerade_data=True) prefetch_related_objects([student], 'groups') if request.user.id != student.id: # refetch the course as the assumed student course = get_course_with_access(student, 'load', course_key, check_if_enrolled=True) course_grade = CourseGradeFactory().read(student, course) # Student grades courseware_summary = list(course_grade.chapter_grades.values()) course_expiration_fragment = generate_course_expired_fragment( student, course) context = { "course": course, "avg_grade": avg_grade, "min_grade": min_grade, "max_grade": max_grade, "grade_cutoff": grade_cutoff, "supports_preview_menu": True, "staff_access": staff_access, "masquerade": masquerade, "can_masquerade": staff_access, "student": student, "courseware_summary": courseware_summary, "grade_summary": course_grade.summary, "course_expiration_fragment": course_expiration_fragment, "grade_percent_scaled": grade_percent_scaled, "get_section_visibility": get_section_visibility, "get_feedback": get_feedback, "update_url": reverse('feedback_post_update'), "set_visibility_url": reverse('feedback_post_set_visibility'), } return context
def render_to_fragment(self, request, course_id=None, **kwargs): # lint-amnesty, pylint: disable=arguments-differ, too-many-statements """ 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 and enrollment.is_active, 'is_staff': has_access(request.user, 'staff', 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 # Set all the fragments outline_fragment = None update_message_fragment = None course_sock_fragment = None offer_banner_fragment = None course_expiration_fragment = None has_visited_course = None resume_course_url = None handouts_html = None course_overview = CourseOverview.get_from_id(course.id) 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) handouts_html = self._get_course_handouts(request, course) offer_banner_fragment = get_first_purchase_offer_banner_fragment( request.user, course_overview) course_expiration_fragment = generate_course_expired_fragment( request.user, course_overview) elif allow_public_outline or allow_public: outline_fragment = CourseOutlineFragmentView().render_to_fragment( request, course_id=course_id, user_is_enrolled=False, **kwargs) course_sock_fragment = CourseSockFragmentView().render_to_fragment( request, course=course, **kwargs) if allow_public: handouts_html = self._get_course_handouts(request, course) 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')) # 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 has_discount = False # TODO Add switch to control deployment if SHOW_UPGRADE_MSG_ON_COURSE_HOME.is_enabled( course_key) and can_show_verified_upgrade( request.user, enrollment, course): upgrade_url = verified_upgrade_deadline_link(request.user, course_id=course_key) upgrade_price, has_discount = format_strikeout_price( request.user, course_overview) show_search = ( settings.FEATURES.get('ENABLE_COURSEWARE_SEARCH') or (settings.FEATURES.get('ENABLE_COURSEWARE_SEARCH_FOR_COURSE_STAFF') and user_access['is_staff'])) # 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, 'offer_banner_fragment': offer_banner_fragment, 'course_expiration_fragment': course_expiration_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_bootstrap': True, 'upgrade_price': upgrade_price, 'upgrade_url': upgrade_url, 'has_discount': has_discount, 'show_search': show_search, } html = render_to_string('course_experience/course-home-fragment.html', context) return Fragment(html)
def render_to_fragment(self, request, course_id=None, discussion_id=None, thread_id=None, profile_page_context=None, **kwargs): """ Render the discussion board to a fragment. Args: request: The Django request. course_id: The id of the course in question. discussion_id: An optional discussion ID to be focused upon. thread_id: An optional ID of the thread to be shown. Returns: Fragment: The fragment representing the discussion board """ try: course_key = CourseKey.from_string(course_id) base_context = _create_base_discussion_view_context( request, course_key) # Note: # After the thread is rendered in this fragment, an AJAX # request is made and the thread is completely loaded again # (yes, this is something to fix). Because of this, we pass in # raise_event=False to _load_thread_for_viewing avoid duplicate # tracking events. thread = (_load_thread_for_viewing( request, base_context['course'], discussion_id=discussion_id, thread_id=thread_id, raise_event=False, ) if thread_id else None) context = _create_discussion_board_context(request, base_context, thread=thread) course_expiration_fragment = generate_course_expired_fragment( request.user, context['course']) context.update({ 'course_expiration_fragment': course_expiration_fragment, }) if profile_page_context: # EDUCATOR-2119: styles are hard to reconcile if the profile page isn't also a fragment html = render_to_string( 'discussion/discussion_profile_page.html', profile_page_context) else: html = render_to_string( 'discussion/discussion_board_fragment.html', context) fragment = Fragment(html) self.add_fragment_resource_urls(fragment) inline_js = render_to_string( 'discussion/discussion_board_js.template', context) fragment.add_javascript(inline_js) if not settings.REQUIRE_DEBUG: fragment.add_javascript_url( staticfiles_storage.url( 'discussion/js/discussion_board_factory.js')) return fragment except cc.utils.CommentClientMaintenanceError: log.warning('Forum is in maintenance mode') html = render_to_string('discussion/maintenance_fragment.html', { 'disable_courseware_js': True, 'uses_bootstrap': True, }) fragment = Fragment(html) self.add_fragment_resource_urls(fragment) return fragment except TeamDiscussionHiddenFromUserException: log.warning( u'User with id={user_id} tried to view private discussion with id={discussion_id}' .format(user_id=request.user.id, discussion_id=discussion_id)) html = render_to_string( 'discussion/discussion_private_fragment.html', { 'disable_courseware_js': True, 'uses_bootstrap': True, }) fragment = Fragment(html) self.add_fragment_resource_urls(fragment) return fragment
def render_to_fragment( self, request, course_id=None, discussion_id=None, thread_id=None, profile_page_context=None, **kwargs ): """ Render the discussion board to a fragment. Args: request: The Django request. course_id: The id of the course in question. discussion_id: An optional discussion ID to be focused upon. thread_id: An optional ID of the thread to be shown. Returns: Fragment: The fragment representing the discussion board """ try: course_key = CourseKey.from_string(course_id) base_context = _create_base_discussion_view_context(request, course_key) # Note: # After the thread is rendered in this fragment, an AJAX # request is made and the thread is completely loaded again # (yes, this is something to fix). Because of this, we pass in # raise_event=False to _load_thread_for_viewing avoid duplicate # tracking events. thread = ( _load_thread_for_viewing( request, base_context['course'], discussion_id=discussion_id, thread_id=thread_id, raise_event=False, ) if thread_id else None ) context = _create_discussion_board_context(request, base_context, thread=thread) course_expiration_fragment = generate_course_expired_fragment(request.user, context['course']) context.update({ 'course_expiration_fragment': course_expiration_fragment, }) if profile_page_context: # EDUCATOR-2119: styles are hard to reconcile if the profile page isn't also a fragment html = render_to_string('discussion/discussion_profile_page.html', profile_page_context) else: html = render_to_string('discussion/discussion_board_fragment.html', context) fragment = Fragment(html) self.add_fragment_resource_urls(fragment) inline_js = render_to_string('discussion/discussion_board_js.template', context) fragment.add_javascript(inline_js) if not settings.REQUIRE_DEBUG: fragment.add_javascript_url(staticfiles_storage.url('discussion/js/discussion_board_factory.js')) return fragment except cc.utils.CommentClientMaintenanceError: log.warning('Forum is in maintenance mode') html = render_to_string('discussion/maintenance_fragment.html', { 'disable_courseware_js': True, 'uses_pattern_library': True, }) fragment = Fragment(html) self.add_fragment_resource_urls(fragment) return fragment
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 and enrollment.is_active, 'is_staff': has_access(request.user, 'staff', 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 # Set all the fragments outline_fragment = None update_message_fragment = None course_sock_fragment = None offer_banner_fragment = None course_expiration_fragment = None has_visited_course = None resume_course_url = None handouts_html = None 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) handouts_html = self._get_course_handouts(request, course) course_overview = CourseOverview.get_from_id(course.id) offer_banner_fragment = get_first_purchase_offer_banner_fragment( request.user, course_overview ) course_expiration_fragment = generate_course_expired_fragment( request.user, course_overview ) elif allow_public_outline or allow_public: outline_fragment = CourseOutlineFragmentView().render_to_fragment( request, course_id=course_id, user_is_enrolled=False, **kwargs ) course_sock_fragment = CourseSockFragmentView().render_to_fragment(request, course=course, **kwargs) if allow_public: handouts_html = self._get_course_handouts(request, course) 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')) # 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, 'offer_banner_fragment': offer_banner_fragment, 'course_expiration_fragment': course_expiration_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 render_to_fragment( # lint-amnesty, pylint: disable=arguments-differ self, request, course_id=None, discussion_id=None, thread_id=None, profile_page_context=None, **kwargs): """ Render the discussion board to a fragment. Args: request: The Django request. course_id: The id of the course in question. discussion_id: An optional discussion ID to be focused upon. thread_id: An optional ID of the thread to be shown. Returns: Fragment: The fragment representing the discussion board """ course_key = CourseKey.from_string(course_id) # Force using the legacy view if a user profile is requested or the URL contains a specific topic or thread force_legacy_view = (profile_page_context or thread_id or discussion_id) is_educator_or_staff = is_course_staff( course_key, request.user) or GlobalStaff().has_user(request.user) mfe_context = _discussions_mfe_context(request.GET, course_key, is_educator_or_staff, force_legacy_view) if mfe_context["show_mfe"]: fragment = Fragment( render_to_string('discussion/discussion_mfe_embed.html', mfe_context)) fragment.add_css(""" #discussions-mfe-tab-embed { width: 100%; min-height: 800px; border: none; } """) return fragment try: base_context = _create_base_discussion_view_context( request, course_key) # Note: # After the thread is rendered in this fragment, an AJAX # request is made and the thread is completely loaded again # (yes, this is something to fix). Because of this, we pass in # raise_event=False to _load_thread_for_viewing avoid duplicate # tracking events. thread = (_load_thread_for_viewing( request, base_context['course'], discussion_id=discussion_id, thread_id=thread_id, raise_event=False, ) if thread_id else None) context = _create_discussion_board_context(request, base_context, thread=thread) course_expiration_fragment = generate_course_expired_fragment( request.user, context['course']) context.update({ 'course_expiration_fragment': course_expiration_fragment, }) context.update(mfe_context) if profile_page_context: # EDUCATOR-2119: styles are hard to reconcile if the profile page isn't also a fragment html = render_to_string( 'discussion/discussion_profile_page.html', profile_page_context) else: html = render_to_string( 'discussion/discussion_board_fragment.html', context) fragment = Fragment(html) self.add_fragment_resource_urls(fragment) inline_js = render_to_string( 'discussion/discussion_board_js.template', context) fragment.add_javascript(inline_js) if not settings.REQUIRE_DEBUG: fragment.add_javascript_url( staticfiles_storage.url( 'discussion/js/discussion_board_factory.js')) return fragment except cc.utils.CommentClientMaintenanceError: log.warning('Forum is in maintenance mode') html = render_to_string('discussion/maintenance_fragment.html', { 'disable_courseware_js': True, 'uses_bootstrap': True, }) fragment = Fragment(html) self.add_fragment_resource_urls(fragment) return fragment except TeamDiscussionHiddenFromUserException: log.warning( 'User with id={user_id} tried to view private discussion with id={discussion_id}' .format(user_id=request.user.id, discussion_id=discussion_id)) html = render_to_string( 'discussion/discussion_private_fragment.html', { 'disable_courseware_js': True, 'uses_bootstrap': True, }) fragment = Fragment(html) self.add_fragment_resource_urls(fragment) return fragment