Skip to content

Commit

Permalink
feat!: Remove support for the (deprecated) library authoring MFE (#1327)
Browse files Browse the repository at this point in the history
  • Loading branch information
bradenmacdonald committed Sep 26, 2024
1 parent ccce44a commit 3662fad
Show file tree
Hide file tree
Showing 14 changed files with 12 additions and 201 deletions.
14 changes: 1 addition & 13 deletions src/editors/data/services/cms/api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ describe('cms api', () => {

it('should call get with normal accept header for prod', async () => {
process.env.NODE_ENV = 'production';
process.env.MFE_NAME = 'frontend-app-library-authoring';
process.env.MFE_NAME = 'frontend-app-course-authoring';
// eslint-disable-next-line no-shadow, @typescript-eslint/no-shadow
const { apiMethods } = await import('./api');
// eslint-disable-next-line no-shadow, @typescript-eslint/no-shadow
Expand All @@ -90,18 +90,6 @@ describe('cms api', () => {
apiMethods.fetchByUnitId({ blockId, studioEndpointUrl });
expect(getSpy).toHaveBeenCalledWith(urls.blockAncestor({ studioEndpointUrl, blockId }), {});
});

it('should call get with special accept header "*/*" for course-authoring', async () => {
process.env.NODE_ENV = 'development';
process.env.MFE_NAME = 'frontend-app-library-authoring';
// eslint-disable-next-line no-shadow, @typescript-eslint/no-shadow
const { apiMethods } = await import('./api');
// eslint-disable-next-line no-shadow, @typescript-eslint/no-shadow
const utils = await import('./utils');
const getSpy = jest.spyOn(utils, 'get');
apiMethods.fetchByUnitId({ blockId, studioEndpointUrl });
expect(getSpy).toHaveBeenCalledWith(urls.blockAncestor({ studioEndpointUrl, blockId }), { headers: { Accept: '*/*' } });
});
});
});

Expand Down
8 changes: 0 additions & 8 deletions src/editors/data/services/cms/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,6 @@ import { durationStringFromValue } from '../../../containers/VideoEditor/compone

const fetchByUnitIdOptions: AxiosRequestConfig = {};

// For some reason, the local webpack-dev-server of library-authoring does not accept the normal Accept header.
// This is a workaround only for that specific case; the idea is to only do this locally and only for library-authoring.
if (process.env.NODE_ENV === 'development' && process.env.MFE_NAME === 'frontend-app-library-authoring') {
fetchByUnitIdOptions.headers = {
Accept: '*/*',
};
}

interface Pagination {
start: number;
end: number;
Expand Down
10 changes: 1 addition & 9 deletions src/search-modal/SearchResult.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,11 @@ import {
Stack,
} from '@openedx/paragon';
import { OpenInNew } from '@openedx/paragon/icons';
import { useSelector } from 'react-redux';
import { useNavigate } from 'react-router-dom';

import { getItemIcon } from '../generic/block-type-utils';
import { isLibraryKey } from '../generic/key-utils';
import { useSearchContext, type ContentHit, Highlight } from '../search-manager';
import { getStudioHomeData } from '../studio-home/data/selectors';
import { constructLibraryAuthoringURL } from '../utils';
import messages from './messages';

/**
Expand Down Expand Up @@ -100,7 +97,6 @@ const SearchResult: React.FC<{ hit: ContentHit }> = ({ hit }) => {
const intl = useIntl();
const navigate = useNavigate();
const { closeSearchModal } = useSearchContext();
const { libraryAuthoringMfeUrl, redirectToLibraryAuthoringMfe } = useSelector(getStudioHomeData);

/**
* Returns the URL for the context of the hit
Expand All @@ -119,10 +115,6 @@ const SearchResult: React.FC<{ hit: ContentHit }> = ({ hit }) => {

if (isLibraryKey(contextKey)) {
const urlSuffix = getLibraryComponentUrlSuffix(hit);
if (redirectToLibraryAuthoringMfe && libraryAuthoringMfeUrl) {
return constructLibraryAuthoringURL(libraryAuthoringMfeUrl, urlSuffix);
}

if (newWindow) {
return `${getPath(getConfig().PUBLIC_PATH)}${urlSuffix}`;
}
Expand All @@ -131,7 +123,7 @@ const SearchResult: React.FC<{ hit: ContentHit }> = ({ hit }) => {

// istanbul ignore next - This case should never be reached
return undefined;
}, [libraryAuthoringMfeUrl, redirectToLibraryAuthoringMfe, hit]);
}, [hit]);

/**
* Opens the context of the hit in a new window
Expand Down
42 changes: 1 addition & 41 deletions src/search-modal/SearchUI.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@ import fetchMock from 'fetch-mock-jest';
import type { Store } from 'redux';

import initializeStore from '../store';
import { executeThunk } from '../utils';
import { getStudioHomeApiUrl } from '../studio-home/data/api';
import { fetchStudioHomeData } from '../studio-home/data/thunks';
import { generateGetStudioHomeDataApiResponse } from '../studio-home/factories/mockApiResponses';
import mockResult from './__mocks__/search-result.json';
import mockEmptyResult from './__mocks__/empty-search-result.json';
import mockTagsFacetResult from './__mocks__/facet-search.json';
Expand Down Expand Up @@ -316,43 +312,7 @@ describe('<SearchUI />', () => {
);
});

test('click lib component result navigates to the context', async () => {
const data = generateGetStudioHomeDataApiResponse();
data.redirectToLibraryAuthoringMfe = true;
axiosMock.onGet(getStudioHomeApiUrl()).reply(200, data);

await executeThunk(fetchStudioHomeData(), store.dispatch);

const { findByRole } = rendered;

const resultItem = await findByRole('button', { name: /Library Content/ });

// Clicking the "Open in new window" button should open the result in a new window:
const { open, location } = window;
window.open = jest.fn();
fireEvent.click(within(resultItem).getByRole('button', { name: 'Open in new window' }));
expect(window.open).toHaveBeenCalledWith(
'http://localhost:3001/library/lib:org1:libafter1',
'_blank',
);
window.open = open;

// @ts-ignore
window.location = { href: '' };
// Clicking in the result should navigate to the result's URL:
fireEvent.click(resultItem);
expect(window.location.href = 'http://localhost:3001/library/lib:org1:libafter1');
window.location = location;
});

test('click lib component result navigates to course-authoring/library without libraryAuthoringMfe', async () => {
const data = generateGetStudioHomeDataApiResponse();
data.redirectToLibraryAuthoringMfe = false;
data.libraryAuthoringMfeUrl = '';
axiosMock.onGet(getStudioHomeApiUrl()).reply(200, data);

await executeThunk(fetchStudioHomeData(), store.dispatch);

test('click lib component result navigates to course-authoring/library', async () => {
const { findByRole } = rendered;

const resultItem = await findByRole('button', { name: /Library Content/ });
Expand Down
23 changes: 1 addition & 22 deletions src/studio-home/StudioHome.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import MockAdapter from 'axios-mock-adapter';
import initializeStore from '../store';
import { RequestStatus } from '../data/constants';
import { COURSE_CREATOR_STATES } from '../constants';
import { executeThunk, constructLibraryAuthoringURL } from '../utils';
import { executeThunk } from '../utils';
import { studioHomeMock } from './__mocks__';
import { getStudioHomeApiUrl } from './data/api';
import { fetchStudioHomeData } from './data/thunks';
Expand Down Expand Up @@ -193,27 +193,6 @@ describe('<StudioHome />', () => {
window.open = open;
});

it('should navigate to the library authoring mfe', () => {
useSelector.mockReturnValue({
...studioHomeMock,
courseCreatorStatus: COURSE_CREATOR_STATES.granted,
splitStudioHome: true,
redirectToLibraryAuthoringMfe: true,
});
const libraryAuthoringMfeUrl = 'http://localhost:3001';

const { getByTestId } = render(<RootWrapper />);
const createNewLibraryButton = getByTestId('new-library-button');

const { open } = window;
window.open = jest.fn();
fireEvent.click(createNewLibraryButton);
expect(window.open).toHaveBeenCalledWith(
`${constructLibraryAuthoringURL(libraryAuthoringMfeUrl, 'create')}`,
);
window.open = open;
});

it('should navigate to the library authoring page in course authoring', () => {
useSelector.mockReturnValue({
...studioHomeMock,
Expand Down
11 changes: 1 addition & 10 deletions src/studio-home/StudioHome.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import { StudioFooter } from '@edx/frontend-component-footer';
import { getConfig } from '@edx/frontend-platform';
import { useLocation, useNavigate } from 'react-router-dom';

import { constructLibraryAuthoringURL } from '../utils';
import Loading from '../generic/Loading';
import InternetConnectionAlert from '../generic/internet-connection-alert';
import Header from '../header';
Expand Down Expand Up @@ -58,8 +57,6 @@ const StudioHome = () => {
userIsActive,
studioShortName,
studioRequestEmail,
libraryAuthoringMfeUrl,
redirectToLibraryAuthoringMfe,
showNewLibraryButton,
} = studioHomeData;

Expand Down Expand Up @@ -93,13 +90,7 @@ const StudioHome = () => {
if (showNewLibraryButton || showV2LibraryURL) {
const newLibraryClick = () => {
if (showV2LibraryURL) {
if (libraryAuthoringMfeUrl && redirectToLibraryAuthoringMfe) {
// Library authoring MFE
window.open(constructLibraryAuthoringURL(libraryAuthoringMfeUrl, 'create'));
} else {
// Use course-authoring route
navigate('/library/create');
}
navigate('/library/create');
} else {
// Studio home library for legacy libraries
window.open(`${getConfig().STUDIO_BASE_URL}/home_library`);
Expand Down
2 changes: 0 additions & 2 deletions src/studio-home/__mocks__/studioHomeMock.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,7 @@ module.exports = {
},
],
librariesEnabled: true,
libraryAuthoringMfeUrl: 'http://localhost:3001',
optimizationEnabled: false,
redirectToLibraryAuthoringMfe: false,
requestCourseCreatorUrl: '/request_course_creator',
rerunCreatorStatus: true,
showNewLibraryButton: true,
Expand Down
2 changes: 1 addition & 1 deletion src/studio-home/card-item/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ const CardItem: React.FC<Props> = ({
} = useSelector(getStudioHomeData);
const destinationUrl: string = path ?? new URL(url, getConfig().STUDIO_BASE_URL).toString();
const subtitle = isLibraries ? `${org} / ${number}` : `${org} / ${number} / ${run}`;
const readOnlyItem = !(lmsLink || rerunLink || url);
const readOnlyItem = !(lmsLink || rerunLink || url || path);
const showActions = !(readOnlyItem || isLibraries);
const isShowRerunLink = allowCourseReruns
&& rerunCreatorStatus
Expand Down
2 changes: 0 additions & 2 deletions src/studio-home/factories/mockApiResponses.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,7 @@ export const generateGetStudioHomeDataApiResponse = () => ({
inProcessCourseActions: [],
libraries: [],
librariesEnabled: true,
libraryAuthoringMfeUrl: 'http://localhost:3001/',
optimizationEnabled: false,
redirectToLibraryAuthoringMfe: false,
requestCourseCreatorUrl: '/request_course_creator',
rerunCreatorStatus: true,
showNewLibraryButton: true,
Expand Down
16 changes: 0 additions & 16 deletions src/studio-home/tabs-section/TabsSection.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -428,22 +428,6 @@ describe('<TabsSection />', () => {
expect(screen.queryByText(tabMessages.legacyLibrariesTabTitle.defaultMessage)).toBeNull();
});

it('should redirect to library authoring mfe', async () => {
const data = generateGetStudioHomeDataApiResponse();
data.redirectToLibraryAuthoringMfe = true;

render();
axiosMock.onGet(getStudioHomeApiUrl()).reply(200, data);
await executeThunk(fetchStudioHomeData(), store.dispatch);

const librariesTab = screen.getByText(tabMessages.legacyLibrariesTabTitle.defaultMessage);
fireEvent.click(librariesTab);

waitFor(() => {
expect(window.location.href).toBe(data.libraryAuthoringMfeUrl);
});
});

it('should render libraries fetch failure alert', async () => {
render();
axiosMock.onGet(getStudioHomeApiUrl()).reply(200, generateGetStudioHomeDataApiResponse());
Expand Down
7 changes: 1 addition & 6 deletions src/studio-home/tabs-section/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,6 @@ const TabsSection = ({
}, [pathname]);

const {
libraryAuthoringMfeUrl,
redirectToLibraryAuthoringMfe,
courses, librariesEnabled, libraries, archivedCourses,
numPages, coursesCount,
} = useSelector(getStudioHomeData);
Expand Down Expand Up @@ -125,10 +123,7 @@ const TabsSection = ({
eventKey={TABS_LIST.libraries}
title={intl.formatMessage(messages.librariesTabTitle)}
>
<LibrariesV2Tab
libraryAuthoringMfeUrl={libraryAuthoringMfeUrl}
redirectToLibraryAuthoringMfe={redirectToLibraryAuthoringMfe}
/>
<LibrariesV2Tab />
</Tab>,
);
}
Expand Down
23 changes: 4 additions & 19 deletions src/studio-home/tabs-section/libraries-v2-tab/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,18 @@ import {
Button,
} from '@openedx/paragon';
import { useIntl } from '@edx/frontend-platform/i18n';
import { getConfig, getPath } from '@edx/frontend-platform';
import { Error } from '@openedx/paragon/icons';

import { useContentLibraryV2List } from '../../../library-authoring';
import { constructLibraryAuthoringURL } from '../../../utils';
import { LoadingSpinner } from '../../../generic/Loading';
import AlertMessage from '../../../generic/alert-message';
import CardItem from '../../card-item';
import messages from '../messages';
import LibrariesV2Filters from './libraries-v2-filters';

const LibrariesV2Tab: React.FC<{
libraryAuthoringMfeUrl: string,
redirectToLibraryAuthoringMfe: boolean
}> = ({
libraryAuthoringMfeUrl,
redirectToLibraryAuthoringMfe,
}) => {
type Props = Record<never, never>;

const LibrariesV2Tab: React.FC<Props> = () => {
const intl = useIntl();

const [currentPage, setCurrentPage] = useState(1);
Expand Down Expand Up @@ -55,15 +49,6 @@ const LibrariesV2Tab: React.FC<{
);
}

const libURL = (id: string) => (
libraryAuthoringMfeUrl && redirectToLibraryAuthoringMfe
? constructLibraryAuthoringURL(libraryAuthoringMfeUrl, `library/${id}`)
// Redirection to the placeholder is done in the MFE rather than
// through the backend i.e. redirection from cms, because this this will probably change,
// hence why we use the MFE's origin
: `${window.location.origin}${getPath(getConfig().PUBLIC_PATH)}library/${id}`
);

const hasV2Libraries = !isLoading && ((data!.results.length || 0) > 0);

return (
Expand Down Expand Up @@ -109,7 +94,7 @@ const LibrariesV2Tab: React.FC<{
displayName={title}
org={org}
number={slug}
url={libURL(id)}
path={`/library/${id}`}
/>
)) : isFiltered && !isLoading && (
<Alert className="mt-4">
Expand Down
24 changes: 0 additions & 24 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -301,27 +301,3 @@ export const getFileSizeToClosestByte = (fileSize) => {
const fileSizeFixedDecimal = Number.parseFloat(size).toFixed(2);
return `${fileSizeFixedDecimal} ${units[divides]}`;
};

/**
* Constructs library authoring MFE URL with correct slashes
* @param {string} libraryAuthoringMfeUrl - the base library authoring MFE url
* @param {string} path - the library authoring MFE url path
* @returns {string} - the correct internal route path
*/
export const constructLibraryAuthoringURL = (libraryAuthoringMfeUrl, path) => {
// Remove '/' at the beginning of path if any
const trimmedPath = path.startsWith('/')
? path.slice(1, path.length)
: path;

let constructedUrl = libraryAuthoringMfeUrl;
// Remove trailing `/` from base if found
if (libraryAuthoringMfeUrl.endsWith('/')) {
constructedUrl = constructedUrl.slice(0, -1);
}

// Add the `/` and path to url
constructedUrl = `${constructedUrl}/${trimmedPath}`;

return constructedUrl;
};
Loading

0 comments on commit 3662fad

Please sign in to comment.