fix: Hide / error on Libraries v2 pages if !librariesV2Enabled (#1449)
Show an error message if the user tries to view a v2 Library while Libraries V2 are disabled in the platform.
This commit is contained in:
@@ -18,6 +18,8 @@ import {
|
||||
mockXBlockFields,
|
||||
} from './data/api.mocks';
|
||||
import { mockContentSearchConfig } from '../search-manager/data/api.mock';
|
||||
import { studioHomeMock } from '../studio-home/__mocks__';
|
||||
import { getStudioHomeApiUrl } from '../studio-home/data/api';
|
||||
import { mockBroadcastChannel } from '../generic/data/api.mock';
|
||||
import { LibraryLayout } from '.';
|
||||
import { getLibraryCollectionsApiUrl } from './data/api';
|
||||
@@ -79,7 +81,8 @@ const libraryTitle = mockContentLibrary.libraryData.title;
|
||||
|
||||
describe('<LibraryAuthoringPage />', () => {
|
||||
beforeEach(() => {
|
||||
initializeMocks();
|
||||
const { axiosMock } = initializeMocks();
|
||||
axiosMock.onGet(getStudioHomeApiUrl()).reply(200, studioHomeMock);
|
||||
|
||||
// The Meilisearch client-side API uses fetch, not Axios.
|
||||
fetchMock.mockReset();
|
||||
@@ -787,4 +790,16 @@ describe('<LibraryAuthoringPage />', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Shows an error if libraries V2 is disabled', async () => {
|
||||
const { axiosMock } = initializeMocks();
|
||||
axiosMock.onGet(getStudioHomeApiUrl()).reply(200, {
|
||||
...studioHomeMock,
|
||||
libraries_v2_enabled: false,
|
||||
});
|
||||
|
||||
render(<LibraryLayout />, { path, params: { libraryId: mockContentLibrary.libraryId } });
|
||||
await waitFor(() => { expect(axiosMock.history.get.length).toBe(1); });
|
||||
expect(screen.getByRole('alert')).toHaveTextContent('This page cannot be shown: Libraries v2 are disabled.');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,6 +4,7 @@ import classNames from 'classnames';
|
||||
import { StudioFooter } from '@edx/frontend-component-footer';
|
||||
import { useIntl } from '@edx/frontend-platform/i18n';
|
||||
import {
|
||||
Alert,
|
||||
Badge,
|
||||
Breadcrumb,
|
||||
Button,
|
||||
@@ -25,6 +26,7 @@ import Loading from '../generic/Loading';
|
||||
import SubHeader from '../generic/sub-header/SubHeader';
|
||||
import Header from '../header';
|
||||
import NotFoundAlert from '../generic/NotFoundAlert';
|
||||
import { useStudioHome } from '../studio-home/hooks';
|
||||
import {
|
||||
ClearFiltersButton,
|
||||
FilterByBlockType,
|
||||
@@ -143,6 +145,12 @@ const LibraryAuthoringPage = ({ returnToLibrarySelection }: LibraryAuthoringPage
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const {
|
||||
isLoadingPage: isLoadingStudioHome,
|
||||
isFailedLoadingPage: isFailedLoadingStudioHome,
|
||||
librariesV2Enabled,
|
||||
} = useStudioHome();
|
||||
|
||||
const {
|
||||
libraryId,
|
||||
libraryData,
|
||||
@@ -178,6 +186,14 @@ const LibraryAuthoringPage = ({ returnToLibrarySelection }: LibraryAuthoringPage
|
||||
return <Loading />;
|
||||
}
|
||||
|
||||
if (!isLoadingStudioHome && (!librariesV2Enabled || isFailedLoadingStudioHome)) {
|
||||
return (
|
||||
<Alert variant="danger">
|
||||
{intl.formatMessage(messages.librariesV2DisabledError)}
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
|
||||
// istanbul ignore if: this should never happen
|
||||
if (activeKey === undefined) {
|
||||
return <NotFoundAlert />;
|
||||
|
||||
@@ -19,6 +19,8 @@ import {
|
||||
} from '../data/api.mocks';
|
||||
import { mockBroadcastChannel, mockClipboardEmpty } from '../../generic/data/api.mock';
|
||||
import { mockContentSearchConfig, mockSearchResult } from '../../search-manager/data/api.mock';
|
||||
import { studioHomeMock } from '../../studio-home/__mocks__';
|
||||
import { getStudioHomeApiUrl } from '../../studio-home/data/api';
|
||||
import LibraryLayout from '../LibraryLayout';
|
||||
|
||||
mockContentSearchConfig.applyMock();
|
||||
@@ -46,8 +48,12 @@ const renderOpts = {
|
||||
};
|
||||
|
||||
describe('AddContentWorkflow test', () => {
|
||||
beforeEach(() => {
|
||||
const { axiosMock } = initializeMocks();
|
||||
axiosMock.onGet(getStudioHomeApiUrl()).reply(200, studioHomeMock);
|
||||
});
|
||||
|
||||
it('can create an HTML component', async () => {
|
||||
initializeMocks();
|
||||
render(<LibraryLayout />, renderOpts);
|
||||
|
||||
// Click "New [Component]"
|
||||
@@ -84,7 +90,6 @@ describe('AddContentWorkflow test', () => {
|
||||
});
|
||||
|
||||
it('can create a Problem component', async () => {
|
||||
initializeMocks();
|
||||
render(<LibraryLayout />, renderOpts);
|
||||
|
||||
// Click "New [Component]"
|
||||
@@ -119,7 +124,6 @@ describe('AddContentWorkflow test', () => {
|
||||
});
|
||||
|
||||
it('can create a Video component', async () => {
|
||||
initializeMocks();
|
||||
render(<LibraryLayout />, renderOpts);
|
||||
|
||||
// Click "New [Component]"
|
||||
|
||||
@@ -6,6 +6,8 @@ import {
|
||||
screen,
|
||||
initializeMocks,
|
||||
} from '../../testUtils';
|
||||
import { studioHomeMock } from '../../studio-home/__mocks__';
|
||||
import { getStudioHomeApiUrl } from '../../studio-home/data/api';
|
||||
import mockResult from '../__mocks__/library-search.json';
|
||||
import { LibraryProvider } from '../common/context';
|
||||
import { ComponentPickerModal } from '../component-picker';
|
||||
@@ -16,7 +18,6 @@ import {
|
||||
} from '../data/api.mocks';
|
||||
import { PickLibraryContentModal } from './PickLibraryContentModal';
|
||||
|
||||
initializeMocks();
|
||||
mockContentSearchConfig.applyMock();
|
||||
mockContentLibrary.applyMock();
|
||||
mockGetCollectionMetadata.applyMock();
|
||||
@@ -45,6 +46,7 @@ describe('<PickLibraryContentModal />', () => {
|
||||
beforeEach(() => {
|
||||
const mocks = initializeMocks();
|
||||
mockShowToast = mocks.mockShowToast;
|
||||
mocks.axiosMock.onGet(getStudioHomeApiUrl()).reply(200, studioHomeMock);
|
||||
});
|
||||
|
||||
it('can pick components from the modal', async () => {
|
||||
|
||||
@@ -27,6 +27,13 @@ jest.mock('react-router-dom', () => ({
|
||||
},
|
||||
}),
|
||||
}));
|
||||
jest.mock('../../studio-home/hooks', () => ({
|
||||
useStudioHome: () => ({
|
||||
isLoadingPage: false,
|
||||
isFailedLoadingPage: false,
|
||||
librariesV2Enabled: true,
|
||||
}),
|
||||
}));
|
||||
mockContentLibrary.applyMock();
|
||||
mockContentSearchConfig.applyMock();
|
||||
mockGetCollectionMetadata.applyMock();
|
||||
|
||||
@@ -111,6 +111,11 @@ const messages = defineMessages({
|
||||
defaultMessage: 'Change Library',
|
||||
description: 'Breadcrumbs link to return to library selection',
|
||||
},
|
||||
librariesV2DisabledError: {
|
||||
id: 'authoring.alert.error.libraries.v2.disabled',
|
||||
defaultMessage: 'This page cannot be shown: Libraries v2 are disabled.',
|
||||
description: 'Error message shown to users when trying to load a libraries V2 page while libraries v2 are disabled.',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
|
||||
@@ -47,7 +47,7 @@ const StudioHome = () => {
|
||||
setShowNewCourseContainer,
|
||||
librariesV1Enabled,
|
||||
librariesV2Enabled,
|
||||
} = useStudioHome(isPaginationCoursesEnabled);
|
||||
} = useStudioHome();
|
||||
|
||||
const v1LibraryTab = librariesV1Enabled && location?.pathname.split('/').pop() === 'libraries-v1';
|
||||
const showV2LibraryURL = librariesV2Enabled && !v1LibraryTab;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
|
||||
import { RequestStatus } from '../data/constants';
|
||||
import { COURSE_CREATOR_STATES } from '../constants';
|
||||
@@ -14,9 +15,10 @@ import {
|
||||
} from './data/selectors';
|
||||
import { updateSavingStatuses } from './data/slice';
|
||||
|
||||
const useStudioHome = (isPaginated = false) => {
|
||||
const useStudioHome = () => {
|
||||
const location = useLocation();
|
||||
const dispatch = useDispatch();
|
||||
const isPaginated = getConfig().ENABLE_HOME_PAGE_COURSE_API_V2;
|
||||
const studioHomeData = useSelector(getStudioHomeData);
|
||||
const studioHomeCoursesParams = useSelector(getStudioHomeCoursesParams);
|
||||
const { isFiltered } = studioHomeCoursesParams;
|
||||
|
||||
Reference in New Issue
Block a user