def get_course_tab_list(user, course): """ Retrieves the course tab list from xmodule.tabs and manipulates the set as necessary """ xmodule_tab_list = CourseTabList.iterate_displayable(course, user=user) # Now that we've loaded the tabs for this course, perform the Entrance Exam work. # If the user has to take an entrance exam, we'll need to hide away all but the # "Courseware" tab. The tab is then renamed as "Entrance Exam". course_tab_list = [] must_complete_ee = not user_can_skip_entrance_exam(user, course) for tab in xmodule_tab_list: if must_complete_ee: # Hide all of the tabs except for 'Courseware' # Rename 'Courseware' tab to 'Entrance Exam' if tab.type != 'courseware': continue tab.name = _("Entrance Exam") # TODO: LEARNER-611 - once the course_info tab is removed, remove this code if UNIFIED_COURSE_TAB_FLAG.is_enabled(course.id) and tab.type == 'course_info': continue if tab.type == 'static_tab' and tab.course_staff_only and \ not bool(user and has_access(user, 'staff', course, course.id)): continue # We had initially created a CourseTab.load() for dates that ended up # persisting the dates tab tomodulestore on Course Run creation, but # ignoring any static dates tab here we can fix forward without # allowing the bug to continue to surface if tab.type == 'dates': continue course_tab_list.append(tab) # Add in any dynamic tabs, i.e. those that are not persisted course_tab_list += _get_dynamic_tabs(course, user) return course_tab_list
def get_course_tab_list(request, course): """ Retrieves the course tab list from xmodule.tabs and manipulates the set as necessary """ user = request.user xmodule_tab_list = CourseTabList.iterate_displayable(course, user=user) # Now that we've loaded the tabs for this course, perform the Entrance Exam work. # If the user has to take an entrance exam, we'll need to hide away all but the # "Courseware" tab. The tab is then renamed as "Entrance Exam". course_tab_list = [] must_complete_ee = user_must_complete_entrance_exam(request, user, course) for tab in xmodule_tab_list: if must_complete_ee: # Hide all of the tabs except for 'Courseware' # Rename 'Courseware' tab to 'Entrance Exam' if tab.type != 'courseware': continue tab.name = _("Entrance Exam") if tab.type == 'static_tab' and tab.course_staff_only and \ not bool(user and has_access(user, 'staff', course, course.id)): continue course_tab_list.append(tab) # Add in any dynamic tabs, i.e. those that are not persisted course_tab_list += _get_dynamic_tabs(course, user) return course_tab_list
def get_course_tab_list(request, course): """ Retrieves the course tab list from xmodule.tabs and manipulates the set as necessary """ user = request.user is_user_enrolled = user.is_authenticated() and CourseEnrollment.is_enrolled(user, course.id) xmodule_tab_list = CourseTabList.iterate_displayable( course, user=user, settings=settings, is_user_authenticated=user.is_authenticated(), is_user_staff=has_access(user, 'staff', course, course.id), is_user_enrolled=is_user_enrolled, is_user_sneakpeek=not UserProfile.has_registered(user), ) # Now that we've loaded the tabs for this course, perform the Entrance Exam work. # If the user has to take an entrance exam, we'll need to hide away all but the # "Courseware" tab. The tab is then renamed as "Entrance Exam". course_tab_list = [] must_complete_ee = user_must_complete_entrance_exam(request, user, course) for tab in xmodule_tab_list: if must_complete_ee: # Hide all of the tabs except for 'Courseware' # Rename 'Courseware' tab to 'Entrance Exam' if tab.type is not 'courseware': continue tab.name = _("Entrance Exam") course_tab_list.append(tab) # Add in any dynamic tabs, i.e. those that are not persisted course_tab_list += _get_dynamic_tabs(course, user) return course_tab_list
def get_course_tab_list(request, course): """ Retrieves the course tab list from xmodule.tabs and manipulates the set as necessary """ user = request.user xmodule_tab_list = CourseTabList.iterate_displayable(course, user=user) # Now that we've loaded the tabs for this course, perform the Entrance Exam work. # If the user has to take an entrance exam, we'll need to hide away all but the # "Courseware" tab. The tab is then renamed as "Entrance Exam". course_tab_list = [] must_complete_ee = user_must_complete_entrance_exam(request, user, course) for tab in xmodule_tab_list: # Rename 'Home' tab to 'Information' if tab.type is 'course_info': tab.name = _("Information") if must_complete_ee: # Hide all of the tabs except for 'Courseware' # Rename 'Courseware' tab to 'Entrance Exam' if tab.type is not 'courseware': continue tab.name = _("Entrance Exam") course_tab_list.append(tab) # Add in any dynamic tabs, i.e. those that are not persisted course_tab_list += _get_dynamic_tabs(course, user) # Add course welcome tab if feature is enabled if settings.FEATURES.get('TMA_ENABLE_COURSE_WELCOME_PAGE' ) and CourseWelcomeTab.is_enabled(course, user): course_tab_list.insert(0, CourseWelcomeTab({})) return course_tab_list
def get_course_tab_list(course, user): """ Retrieves the course tab list from xmodule.tabs and manipulates the set as necessary """ user_is_enrolled = user.is_authenticated( ) and CourseEnrollment.is_enrolled(user, course.id) xmodule_tab_list = CourseTabList.iterate_displayable( course, settings, user.is_authenticated(), has_access(user, 'staff', course, course.id), user_is_enrolled) # Now that we've loaded the tabs for this course, perform the Entrance Exam work # If the user has to take an entrance exam, we'll need to hide away all of the tabs # except for the Courseware and Instructor tabs (latter is only viewed if applicable) # We don't have access to the true request object in this context, but we can use a mock request = RequestFactory().request() request.user = user course_tab_list = [] for tab in xmodule_tab_list: if user_must_complete_entrance_exam(request, user, course): # Hide all of the tabs except for 'Courseware' and 'Instructor' # Rename 'Courseware' tab to 'Entrance Exam' if tab.type not in ['courseware', 'instructor']: continue if tab.type == 'courseware': tab.name = _("Entrance Exam") course_tab_list.append(tab) return course_tab_list
def get_course_tab_list(course, user): """ Retrieves the course tab list from xmodule.tabs and manipulates the set as necessary """ user_is_enrolled = user.is_authenticated() and CourseEnrollment.is_enrolled(user, course.id) xmodule_tab_list = CourseTabList.iterate_displayable( course, settings, user.is_authenticated(), has_access(user, 'staff', course, course.id), user_is_enrolled ) # Now that we've loaded the tabs for this course, perform the Entrance Exam work # If the user has to take an entrance exam, we'll need to hide away all of the tabs # except for the Courseware and Instructor tabs (latter is only viewed if applicable) # We don't have access to the true request object in this context, but we can use a mock request = RequestFactory().request() request.user = user course_tab_list = [] for tab in xmodule_tab_list: if user_must_complete_entrance_exam(request, user, course): # Hide all of the tabs except for 'Courseware' and 'Instructor' # Rename 'Courseware' tab to 'Entrance Exam' if tab.type not in ['courseware', 'instructor']: continue if tab.type == 'courseware': tab.name = _("Entrance Exam") course_tab_list.append(tab) return course_tab_list
def tabs_handler(request, course_key_string): """ The restful handler for static tabs. GET html: return page for editing static tabs json: not supported PUT or POST json: update the tab order. It is expected that the request body contains a JSON-encoded dict with entry "tabs". The value for "tabs" is an array of tab locators, indicating the desired order of the tabs. Creating a tab, deleting a tab, or changing its contents is not supported through this method. Instead use the general xblock URL (see item.xblock_handler). """ course_key = CourseKey.from_string(course_key_string) if not has_course_author_access(request.user, course_key): raise PermissionDenied() course_item = modulestore().get_course(course_key) if 'application/json' in request.META.get('HTTP_ACCEPT', 'application/json'): if request.method == 'GET': raise NotImplementedError('coming soon') else: if 'tabs' in request.json: return reorder_tabs_handler(course_item, request) elif 'tab_id_locator' in request.json: return edit_tab_handler(course_item, request) else: raise NotImplementedError( 'Creating or changing tab content is not supported.') elif request.method == 'GET': # assume html # get all tabs from the tabs list: static tabs (a.k.a. user-created tabs) and built-in tabs # present in the same order they are displayed in LMS tabs_to_render = [] for tab in CourseTabList.iterate_displayable(course_item, user=request.user, inline_collections=False, include_hidden=True): if isinstance(tab, StaticTab): # static tab needs its locator information to render itself as an xmodule static_tab_loc = course_key.make_usage_key( 'static_tab', tab.url_slug) tab.locator = static_tab_loc tabs_to_render.append(tab) return render_to_response( 'edit-tabs.html', { 'context_course': course_item, 'tabs_to_render': tabs_to_render, 'lms_link': get_lms_link_for_item(course_item.location), }) else: return HttpResponseNotFound()
def tabs_handler(request, course_key_string): """ The restful handler for static tabs. GET html: return page for editing static tabs json: not supported PUT or POST json: update the tab order. It is expected that the request body contains a JSON-encoded dict with entry "tabs". The value for "tabs" is an array of tab locators, indicating the desired order of the tabs. Creating a tab, deleting a tab, or changing its contents is not supported through this method. Instead use the general xblock URL (see item.xblock_handler). """ course_key = CourseKey.from_string(course_key_string) if not has_course_author_access(request.user, course_key): raise PermissionDenied() course_item = modulestore().get_course(course_key) if "application/json" in request.META.get("HTTP_ACCEPT", "application/json"): if request.method == "GET": raise NotImplementedError("coming soon") else: if "tabs" in request.json: return reorder_tabs_handler(course_item, request) elif "tab_id_locator" in request.json: return edit_tab_handler(course_item, request) else: raise NotImplementedError("Creating or changing tab content is not supported.") elif request.method == "GET": # assume html # get all tabs from the tabs list: static tabs (a.k.a. user-created tabs) and built-in tabs # present in the same order they are displayed in LMS tabs_to_render = [] for tab in CourseTabList.iterate_displayable(course_item, inline_collections=False): if isinstance(tab, StaticTab): # static tab needs its locator information to render itself as an xmodule static_tab_loc = course_key.make_usage_key("static_tab", tab.url_slug) tab.locator = static_tab_loc tabs_to_render.append(tab) return render_to_response( "edit-tabs.html", { "context_course": course_item, "tabs_to_render": tabs_to_render, "lms_link": get_lms_link_for_item(course_item.location), }, ) else: return HttpResponseNotFound()
def redirect_view(request, course_key_string=None): course_key = CourseKey.from_string(course_key_string) if not has_course_author_access(request.user, course_key): raise PermissionDenied() course_item = modulestore().get_course(course_key) if request.method == 'GET': for tab in CourseTabList.iterate_displayable(course_item, inline_collections=False): if isinstance(tab, ExternalLinkCourseTab): data = {'name': tab.name, 'link_value': tab.link_value} form = ExternalLinkTabForm(data=data) csrf_token = csrf(request)['csrf_token'] return render_to_response('external_blog.html', { 'form': form, 'csrf': csrf_token }) elif request.method == 'POST': for tab in CourseTabList.iterate_displayable(course_item, inline_collections=False): if isinstance(tab, ExternalLinkCourseTab): data = request.POST form = ExternalLinkTabForm(data=data) if form.is_valid(): tab.link_value = form.cleaned_data.get('link_value') tab.name = form.cleaned_data.get('name') modulestore().update_item(course_item, request.user.id) return HttpResponseRedirect( reverse( 'contentstore.views.tabs_handler', kwargs={'course_key_string': course_key_string})) csrf_token = csrf(request)['csrf_token'] return render_to_response('external_blog.html', { 'form': form, 'csrf': csrf_token })
def get_course_tab_list(course, user): """ Retrieves the course tab list from xmodule.tabs and manipulates the set as necessary """ user_is_enrolled = user.is_authenticated() and CourseEnrollment.is_enrolled(user, course.id) xmodule_tab_list = CourseTabList.iterate_displayable( course, settings, user.is_authenticated(), has_access(user, 'staff', course, course.id), user_is_enrolled ) # Entrance Exams Feature # If the course has an entrance exam, we'll need to see if the user has not passed it # If so, we'll need to hide away all of the tabs except for Courseware and Instructor entrance_exam_mode = False if settings.FEATURES.get('ENTRANCE_EXAMS', False): if getattr(course, 'entrance_exam_enabled', False): course_milestones_paths = get_course_milestones_fulfillment_paths( unicode(course.id), serialize_user(user) ) for __, value in course_milestones_paths.iteritems(): if len(value.get('content', [])): for content in value['content']: if content == course.entrance_exam_id \ and not EntranceExamConfiguration.user_can_skip_entrance_exam(user, course.id): entrance_exam_mode = True break # Now that we've loaded the tabs for this course, perform the Entrance Exam mode work # Majority case is no entrance exam defined course_tab_list = [] for tab in xmodule_tab_list: if entrance_exam_mode: # Hide all of the tabs except for 'Courseware' and 'Instructor' # Rename 'Courseware' tab to 'Entrance Exam' if tab.type not in ['courseware', 'instructor']: continue if tab.type == 'courseware': tab.name = _("Entrance Exam") course_tab_list.append(tab) return course_tab_list
def get_course_tab_list(user, course): """ Retrieves the course tab list from xmodule.tabs and manipulates the set as necessary """ xmodule_tab_list = CourseTabList.iterate_displayable(course, user=user) # Now that we've loaded the tabs for this course, perform the Entrance Exam work. # If the user has to take an entrance exam, we'll need to hide away all but the # "Courseware" tab. The tab is then renamed as "Entrance Exam". course_tab_list = [] must_complete_ee = not user_can_skip_entrance_exam(user, course) for tab in xmodule_tab_list: if must_complete_ee: # Hide all of the tabs except for 'Courseware' # Rename 'Courseware' tab to 'Entrance Exam' if tab.type != 'courseware': continue tab.name = _("Entrance Exam") tab.title = _("Entrance Exam") # TODO: LEARNER-611 - once the course_info tab is removed, remove this code if not DISABLE_UNIFIED_COURSE_TAB_FLAG.is_enabled( course.id) and tab.type == 'course_info': continue if tab.type == 'static_tab' and tab.course_staff_only and \ not bool(user and has_access(user, 'staff', course, course.id)): continue # We are phasing this out in https://github.com/openedx/edx-platform/pull/30045/, but need this # until the backfill course tabs command is completed if tab.type == 'dates': continue course_tab_list.append(tab) # Add in any dynamic tabs, i.e. those that are not persisted course_tab_list += _get_dynamic_tabs(course, user) # Sorting here because although the CourseTabPluginManager.get_tab_types function # does do sorting on priority, we only use it for getting the dynamic tabs. # We can't switch this function to just use the CourseTabPluginManager without # further investigation since CourseTabList.iterate_displayable returns # Static Tabs that are not returned by the CourseTabPluginManager. course_tab_list.sort(key=lambda tab: tab.priority or float('inf')) return course_tab_list
def get_course_tabs(course_item: CourseBlock, user: User) -> Iterable[CourseTab]: """ Yields all the course tabs in a course including hidden tabs. Args: course_item (CourseBlock): The course object from which to get the tabs user (User): The user fetching the course tabs. Returns: Iterable[CourseTab]: An iterable containing course tab objects from the course """ for tab in CourseTabList.iterate_displayable(course_item, user=user, inline_collections=False, include_hidden=True): if isinstance(tab, StaticTab): # static tab needs its locator information to render itself as an xmodule static_tab_loc = course_item.id.make_usage_key( "static_tab", tab.url_slug) tab.locator = static_tab_loc yield tab
def tabs_handler(request, tag=None, package_id=None, branch=None, version_guid=None, block=None): """ The restful handler for static tabs. GET html: return page for editing static tabs json: not supported PUT or POST json: update the tab order. It is expected that the request body contains a JSON-encoded dict with entry "tabs". The value for "tabs" is an array of tab locators, indicating the desired order of the tabs. Creating a tab, deleting a tab, or changing its contents is not supported through this method. Instead use the general xblock URL (see item.xblock_handler). """ locator = BlockUsageLocator(package_id=package_id, branch=branch, version_guid=version_guid, block_id=block) if not has_course_access(request.user, locator): raise PermissionDenied() old_location = loc_mapper().translate_locator_to_location(locator) store = get_modulestore(old_location) course_item = store.get_item(old_location) if 'application/json' in request.META.get('HTTP_ACCEPT', 'application/json'): if request.method == 'GET': raise NotImplementedError('coming soon') else: if 'tabs' in request.json: def get_location_for_tab(tab): """ Returns the location (old-style) for a tab. """ return loc_mapper().translate_locator_to_location(BlockUsageLocator(tab)) tabs = request.json['tabs'] # get list of existing static tabs in course # make sure they are the same lengths (i.e. the number of passed in tabs equals the number # that we know about) otherwise we will inadvertently drop some! existing_static_tabs = [t for t in course_item.tabs if t['type'] == 'static_tab'] if len(existing_static_tabs) != len(tabs): return JsonResponse( {"error": "number of tabs must be {}".format(len(existing_static_tabs))}, status=400 ) # load all reference tabs, return BadRequest if we can't find any of them tab_items = [] for tab in tabs: item = modulestore('direct').get_item(get_location_for_tab(tab)) if item is None: return JsonResponse( {"error": "no tab for found location {}".format(tab)}, status=400 ) tab_items.append(item) # now just go through the existing course_tabs and re-order the static tabs reordered_tabs = [] static_tab_idx = 0 for tab in course_item.tabs: if isinstance(tab, StaticTab): reordered_tabs.append( StaticTab( name=tab_items[static_tab_idx].display_name, url_slug=tab_items[static_tab_idx].location.name, ) ) static_tab_idx += 1 else: reordered_tabs.append(tab) # OK, re-assemble the static tabs in the new order course_item.tabs = reordered_tabs modulestore('direct').update_item(course_item, request.user.id) return JsonResponse() else: raise NotImplementedError('Creating or changing tab content is not supported.') elif request.method == 'GET': # assume html # get all tabs from the tabs list: static tabs (a.k.a. user-created tabs) and built-in tabs # we do this because this is also the order in which items are displayed in the LMS static_tabs = [] built_in_tabs = [] for tab in CourseTabList.iterate_displayable(course_item, settings, include_instructor_tab=False): if isinstance(tab, StaticTab): static_tab_loc = old_location.replace(category='static_tab', name=tab.url_slug) static_tabs.append(modulestore('direct').get_item(static_tab_loc)) else: built_in_tabs.append(tab) # create a list of components for each static tab components = [ loc_mapper().translate_location( course_item.location.course_id, static_tab.location, False, True ) for static_tab in static_tabs ] return render_to_response('edit-tabs.html', { 'context_course': course_item, 'built_in_tabs': built_in_tabs, 'components': components, 'course_locator': locator }) else: return HttpResponseNotFound()