Skip to content

Commit

Permalink
feat: Add lib v2/legacy tabs in studio home
Browse files Browse the repository at this point in the history
When lib mode is set to "mixed", both "Libraries" and "Legacy Libraries" tabs are show in the Studio Home. When "Libraries" is clicked, v2 libraries are fetched, when "Legacy Libraries" is clicked, v1 libraries are fetched.

When lib mode is set to "v1 only" or "v2 only", only one tab "Libraries" is show and only the respective libraries are fetched when the tab is clicked.
  • Loading branch information
yusuf-musleh committed May 29, 2024
1 parent a585a13 commit 418e561
Show file tree
Hide file tree
Showing 8 changed files with 134 additions and 24 deletions.
9 changes: 6 additions & 3 deletions src/studio-home/StudioHome.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import Header from '../header';
import SubHeader from '../generic/sub-header/SubHeader';
import HomeSidebar from './home-sidebar';
import TabsSection from './tabs-section';
import { isMixedOrV2LibrariesMode } from './tabs-section/utils';
import OrganizationSection from './organization-section';
import VerifyEmailLayout from './verify-email-layout';
import CreateNewCourseForm from './create-new-course-form';
Expand All @@ -43,12 +44,14 @@ const StudioHome = ({ intl }) => {
dispatch,
} = useStudioHome(isPaginationCoursesEnabled);

// TODO: this should be a flag in the backend
const LIB_MODE = 'mixed';

const {
userIsActive,
studioShortName,
studioRequestEmail,
libraryAuthoringMfeUrl,
redirectToLibraryAuthoringMfe,
} = studioHomeData;

function getHeaderButtons() {
Expand Down Expand Up @@ -79,8 +82,8 @@ const StudioHome = ({ intl }) => {
}

let libraryHref = `${getConfig().STUDIO_BASE_URL}/home_library`;
if (redirectToLibraryAuthoringMfe) {
libraryHref = `${libraryAuthoringMfeUrl}/create`;
if (isMixedOrV2LibrariesMode(LIB_MODE)) {
libraryHref = `${libraryAuthoringMfeUrl}create`;
}

headerButtons.push(
Expand Down
5 changes: 5 additions & 0 deletions src/studio-home/data/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ export async function getStudioHomeLibraries() {
return camelCaseObject(data);
}

export async function getStudioHomeLibrariesV2() {
const { data } = await getAuthenticatedHttpClient().get(`${getApiBaseUrl()}/api/libraries/v2/`);
return camelCaseObject(data);
}

/**
* Handle course notification requests.
* @param {string} url
Expand Down
13 changes: 13 additions & 0 deletions src/studio-home/data/apiHooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { useQuery } from '@tanstack/react-query';

import { getStudioHomeLibrariesV2 } from './api';

/**
* Builds the query to fetch list of V2 Libraries
*/
export const useListStudioHomeV2Libraries = () => (
useQuery({
queryKey: ['listV2Libraries'],
queryFn: () => getStudioHomeLibrariesV2(),
})
);
12 changes: 6 additions & 6 deletions src/studio-home/tabs-section/TabsSection.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ describe('<TabsSection />', () => {

expect(screen.getByText(tabMessages.coursesTabTitle.defaultMessage)).toBeInTheDocument();

expect(screen.getByText(tabMessages.librariesTabTitle.defaultMessage)).toBeInTheDocument();
expect(screen.getByText(tabMessages.legacyLibrariesTabTitle.defaultMessage)).toBeInTheDocument();

expect(screen.getByText(tabMessages.archivedTabTitle.defaultMessage)).toBeInTheDocument();
});
Expand Down Expand Up @@ -222,7 +222,7 @@ describe('<TabsSection />', () => {

expect(screen.getByText(tabMessages.coursesTabTitle.defaultMessage)).toBeInTheDocument();

expect(screen.getByText(tabMessages.librariesTabTitle.defaultMessage)).toBeInTheDocument();
expect(screen.getByText(tabMessages.legacyLibrariesTabTitle.defaultMessage)).toBeInTheDocument();

expect(screen.queryByText(tabMessages.archivedTabTitle.defaultMessage)).toBeNull();
});
Expand All @@ -236,7 +236,7 @@ describe('<TabsSection />', () => {
await executeThunk(fetchStudioHomeData(), store.dispatch);
await executeThunk(fetchLibraryData(), store.dispatch);

const librariesTab = screen.getByText(tabMessages.librariesTabTitle.defaultMessage);
const librariesTab = screen.getByText(tabMessages.legacyLibrariesTabTitle.defaultMessage);
await act(async () => {
fireEvent.click(librariesTab);
});
Expand All @@ -257,7 +257,7 @@ describe('<TabsSection />', () => {
await executeThunk(fetchStudioHomeData(), store.dispatch);

expect(screen.getByText(tabMessages.coursesTabTitle.defaultMessage)).toBeInTheDocument();
expect(screen.queryByText(tabMessages.librariesTabTitle.defaultMessage)).toBeNull();
expect(screen.queryByText(tabMessages.legacyLibrariesTabTitle.defaultMessage)).toBeNull();
});

it('should redirect to library authoring mfe', async () => {
Expand All @@ -268,7 +268,7 @@ describe('<TabsSection />', () => {
axiosMock.onGet(getStudioHomeApiUrl()).reply(200, data);
await executeThunk(fetchStudioHomeData(), store.dispatch);

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

waitFor(() => {
Expand All @@ -283,7 +283,7 @@ describe('<TabsSection />', () => {
await executeThunk(fetchStudioHomeData(), store.dispatch);
await executeThunk(fetchLibraryData(), store.dispatch);

const librariesTab = screen.getByText(tabMessages.librariesTabTitle.defaultMessage);
const librariesTab = screen.getByText(tabMessages.legacyLibrariesTabTitle.defaultMessage);
await act(async () => {
fireEvent.click(librariesTab);
});
Expand Down
47 changes: 34 additions & 13 deletions src/studio-home/tabs-section/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ import { useNavigate } from 'react-router-dom';
import { getLoadingStatuses, getStudioHomeData } from '../data/selectors';
import messages from './messages';
import LibrariesTab from './libraries-tab';
import LibrariesV2Tab from './libraries-v2-tab/index.tsx';
import ArchivedTab from './archived-tab';
import CoursesTab from './courses-tab';
import { RequestStatus } from '../../data/constants';
import { fetchLibraryData } from '../data/thunks';
import { isMixedOrV1LibrariesMode, isMixedOrV2LibrariesMode } from './utils';

const TabsSection = ({
intl,
Expand All @@ -23,9 +25,14 @@ const TabsSection = ({
isPaginationCoursesEnabled,
}) => {
const navigate = useNavigate();

// TODO: this should be a flag in the backend
const LIB_MODE = 'mixed';

const TABS_LIST = {
courses: 'courses',
libraries: 'libraries',
legacyLibraries: 'legacyLibraries',
archived: 'archived',
taxonomies: 'taxonomies',
};
Expand Down Expand Up @@ -87,21 +94,37 @@ const TabsSection = ({
}

if (librariesEnabled) {
tabs.push(
<Tab
key={TABS_LIST.libraries}
eventKey={TABS_LIST.libraries}
title={intl.formatMessage(messages.librariesTabTitle)}
>
{!redirectToLibraryAuthoringMfe && (
if (isMixedOrV2LibrariesMode(LIB_MODE)) {
tabs.push(
<Tab
key={TABS_LIST.libraries}
eventKey={TABS_LIST.libraries}
title={intl.formatMessage(messages.librariesTabTitle)}
>
<LibrariesV2Tab />
</Tab>,
);
}

if (isMixedOrV1LibrariesMode(LIB_MODE)) {
tabs.push(
<Tab
key={TABS_LIST.legacyLibraries}
eventKey={TABS_LIST.legacyLibraries}
title={intl.formatMessage(
LIB_MODE === 'v1 only'
? messages.librariesTabTitle
: messages.legacyLibrariesTabTitle,
)}
>
<LibrariesTab
libraries={libraries}
isLoading={isLoadingLibraries}
isFailed={isFailedLibrariesPage}
/>
)}
</Tab>,
);
</Tab>,
);
}
}

if (getConfig().ENABLE_TAGGING_TAXONOMY_PAGES === 'true') {
Expand All @@ -118,9 +141,7 @@ const TabsSection = ({
}, [archivedCourses, librariesEnabled, showNewCourseContainer, isLoadingCourses, isLoadingLibraries]);

const handleSelectTab = (tab) => {
if (tab === TABS_LIST.libraries && redirectToLibraryAuthoringMfe) {
window.location.assign(libraryAuthoringMfeUrl);
} else if (tab === TABS_LIST.libraries && !redirectToLibraryAuthoringMfe) {
if (tab === TABS_LIST.legacyLibraries) {
dispatch(fetchLibraryData());
} else if (tab === TABS_LIST.taxonomies) {
navigate('/taxonomies');
Expand Down
58 changes: 58 additions & 0 deletions src/studio-home/tabs-section/libraries-v2-tab/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import React from 'react';
import { Icon, Row } from '@openedx/paragon';
import { useIntl } from '@edx/frontend-platform/i18n';

import { useListStudioHomeV2Libraries } from '../../data/apiHooks';
import { LoadingSpinner } from '../../../generic/Loading';
import AlertMessage from '../../../generic/alert-message';
import CardItem from '../../card-item';
import messages from '../messages';

const LibrariesV2Tab = () => {
const intl = useIntl();
const {
data,
isLoading,
isError,
} = useListStudioHomeV2Libraries();

if (isLoading) {
return (
<Row className="m-0 mt-4 justify-content-center">
<LoadingSpinner />
</Row>
);
}

return (
isError ? (
<AlertMessage
title={intl.formatMessage(messages.librariesTabErrorMessage)}
variant="danger"
description={(
<Row className="m-0 align-items-center">
<Icon src={Error} className="text-danger-500 mr-1" />
<span>{intl.formatMessage(messages.librariesTabErrorMessage)}</span>
</Row>
)}
/>
) : (
<div className="courses-tab">
{data.map(({ org, slug, title }) => (
<CardItem
key={`${org}+${slug}`}
isLibraries
displayName={title}
org={org}
number={slug}
// TODO: Pass in the URL
// url={url}
/>
))}
</div>
)
);
};


export default LibrariesV2Tab;
4 changes: 4 additions & 0 deletions src/studio-home/tabs-section/messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ const messages = defineMessages({
id: 'course-authoring.studio-home.libraries.tab.title',
defaultMessage: 'Libraries',
},
legacyLibrariesTabTitle: {
id: 'course-authoring.studio-home.legacy.libraries.tab.title',
defaultMessage: 'Legacy Libraries',
},
archivedTabTitle: {
id: 'course-authoring.studio-home.archived.tab.title',
defaultMessage: 'Archived courses',
Expand Down
10 changes: 8 additions & 2 deletions src/studio-home/tabs-section/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,11 @@ const sortAlphabeticallyArray = (arr) => [...arr]
.sort((firstArrayData, secondArrayData) => firstArrayData
.displayName.localeCompare(secondArrayData.displayName));

// eslint-disable-next-line import/prefer-default-export
export { sortAlphabeticallyArray };
const isMixedOrV1LibrariesMode = (libMode) => ['mixed', 'v1 only'].includes(libMode);
const isMixedOrV2LibrariesMode = (libMode) => ['mixed', 'v2 only'].includes(libMode);

export {
sortAlphabeticallyArray,
isMixedOrV1LibrariesMode,
isMixedOrV2LibrariesMode,
};

0 comments on commit 418e561

Please sign in to comment.