diff --git a/src/course-outline/CourseOutline.jsx b/src/course-outline/CourseOutline.jsx index 678b721093..6811e3244b 100644 --- a/src/course-outline/CourseOutline.jsx +++ b/src/course-outline/CourseOutline.jsx @@ -1,6 +1,4 @@ -import { - React, useState, useEffect, -} from 'react'; +import { useState, useEffect } from 'react'; import PropTypes from 'prop-types'; import { useIntl } from '@edx/frontend-platform/i18n'; import { @@ -40,7 +38,9 @@ import EmptyPlaceholder from './empty-placeholder/EmptyPlaceholder'; import PublishModal from './publish-modal/PublishModal'; import ConfigureModal from './configure-modal/ConfigureModal'; import DeleteModal from './delete-modal/DeleteModal'; -import { useCourseOutline } from './hooks'; +import { + useCourseOutline, useScrollToLocatorElement, +} from './hooks'; import messages from './messages'; const CourseOutline = ({ courseId }) => { @@ -88,6 +88,8 @@ const CourseOutline = ({ courseId }) => { handleDragNDrop, } = useCourseOutline({ courseId }); + useScrollToLocatorElement({ isLoading }); + const [sections, setSections] = useState(sectionsList); const initialSections = [...sectionsList]; diff --git a/src/course-outline/CourseOutline.test.jsx b/src/course-outline/CourseOutline.test.jsx index 0f4ee33e17..77d81fc9ce 100644 --- a/src/course-outline/CourseOutline.test.jsx +++ b/src/course-outline/CourseOutline.test.jsx @@ -1,4 +1,3 @@ -import React from 'react'; import { act, render, waitFor, cleanup, fireEvent, within, } from '@testing-library/react'; @@ -46,6 +45,8 @@ let axiosMock; let store; const mockPathname = '/foo-bar'; const courseId = '123'; +const locatorSectionName = 'Demo Course Overview'; +const locatorSectionId = 'block-v1:edX+DemoX+Demo_Course+type@sequential+block@edx_introduction'; window.HTMLElement.prototype.scrollIntoView = jest.fn(); @@ -54,6 +55,7 @@ jest.mock('react-router-dom', () => ({ useLocation: () => ({ pathname: mockPathname, }), + useSearchParams: () => [new URLSearchParams({ show: locatorSectionId })], })); jest.mock('../help-urls/hooks', () => ({ @@ -380,6 +382,18 @@ describe('', () => { expect(await findAllByTestId('section-card')).toHaveLength(5); }); + it('check correct scrolling to the locator section when URL has a "show" param', async () => { + const scrollIntoViewFn = jest.fn(); + window.HTMLElement.prototype.scrollIntoView = scrollIntoViewFn; + const { getByText } = render(); + + await waitFor(() => { + expect(getByText(locatorSectionName)).toBeInTheDocument(); + expect(scrollIntoViewFn).toHaveBeenCalled(); + expect(scrollIntoViewFn).toHaveBeenCalledWith({'behavior': 'smooth'}); + }); + }); + it('check whether subsection is duplicated successfully', async () => { const { findAllByTestId } = render(); const section = courseOutlineIndexMock.courseStructure.childInfo.children[0]; diff --git a/src/course-outline/card-header/CardHeader.jsx b/src/course-outline/card-header/CardHeader.jsx index 2c06e02220..76a2c22a02 100644 --- a/src/course-outline/card-header/CardHeader.jsx +++ b/src/course-outline/card-header/CardHeader.jsx @@ -27,6 +27,7 @@ import messages from './messages'; const CardHeader = ({ title, status, + sectionId, hasChanges, isExpanded, onClickPublish, @@ -58,7 +59,11 @@ const CardHeader = ({ }); return ( -
+
{isFormOpen ? ( { }; }; -// eslint-disable-next-line import/prefer-default-export -export { useCourseOutline }; +const useScrollToLocatorElement = ({ isLoading }) => { + const [searchParams] = useSearchParams(); + + useEffect(() => { + const locator = searchParams.get('show'); + const locatorToShow = document.querySelector(`[data-locator="${locator}"]`); + + if (locator && locatorToShow) { + locatorToShow.scrollIntoView({ behavior: 'smooth' }); + } + }, [isLoading]); +}; + +export { + useCourseOutline, + useScrollToLocatorElement, +}; diff --git a/src/course-outline/section-card/SectionCard.jsx b/src/course-outline/section-card/SectionCard.jsx index 8b6730d37b..11d0315eac 100644 --- a/src/course-outline/section-card/SectionCard.jsx +++ b/src/course-outline/section-card/SectionCard.jsx @@ -122,7 +122,10 @@ const SectionCard = ({ onClickDuplicate={onDuplicateSubmit} namePrefix="section" /> -
+