diff --git a/src/generic/alert-error/AlertError.test.tsx b/src/generic/alert-error/AlertError.test.tsx index 2f193223d..d162bf1bc 100644 --- a/src/generic/alert-error/AlertError.test.tsx +++ b/src/generic/alert-error/AlertError.test.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { render, screen } from '@testing-library/react'; +import { render } from '@testing-library/react'; import { IntlProvider } from '@edx/frontend-platform/i18n'; import AlertError from '.'; @@ -33,7 +33,6 @@ describe('', () => { }, }; const { getByText } = render(); - screen.logTestingPlaygroundURL(); expect(getByText(/this is an error message/i)).toBeInTheDocument(); expect(getByText(/\{ "message": "this is a response body" \}/i)).toBeInTheDocument(); }); diff --git a/src/library-authoring/generic/manage-collections/ManageCollections.test.tsx b/src/library-authoring/generic/manage-collections/ManageCollections.test.tsx index 71a561bd2..58b878ec7 100644 --- a/src/library-authoring/generic/manage-collections/ManageCollections.test.tsx +++ b/src/library-authoring/generic/manage-collections/ManageCollections.test.tsx @@ -121,7 +121,6 @@ describe('', () => { collections={[]} useUpdateCollectionsHook={useUpdateComponentCollections} />); - screen.logTestingPlaygroundURL(); const manageBtn = await screen.findByRole('button', { name: 'Add to Collection' }); await user.click(manageBtn); await waitFor(() => { expect(fetchMock).toHaveFetchedTimes(1, searchEndpoint, 'post'); }); diff --git a/src/library-authoring/units/LibraryUnitPage.test.tsx b/src/library-authoring/units/LibraryUnitPage.test.tsx index 4d72e56a8..1f9fe10ea 100644 --- a/src/library-authoring/units/LibraryUnitPage.test.tsx +++ b/src/library-authoring/units/LibraryUnitPage.test.tsx @@ -177,7 +177,6 @@ describe('', () => { const textBox = screen.getByRole('textbox', { name: /text input/i }); expect(textBox).toBeInTheDocument(); expect(textBox).toHaveValue('Test Unit'); - screen.logTestingPlaygroundURL(); fireEvent.change(textBox, { target: { value: 'New Unit Title' } }); fireEvent.keyDown(textBox, { key: 'Enter', code: 'Enter', charCode: 13 }); diff --git a/src/studio-home/data/apiHooks.ts b/src/studio-home/data/apiHooks.ts index 95435a3a4..d1ab2a22e 100644 --- a/src/studio-home/data/apiHooks.ts +++ b/src/studio-home/data/apiHooks.ts @@ -12,7 +12,7 @@ export const studioHomeQueryKeys = { export const useLibrariesV1Data = (enabled: boolean = true) => ( useQuery({ queryKey: studioHomeQueryKeys.librariesV1(), - queryFn: () => getStudioHomeLibraries(), + queryFn: getStudioHomeLibraries, enabled, }) ); diff --git a/src/studio-home/tabs-section/TabsSection.test.tsx b/src/studio-home/tabs-section/TabsSection.test.tsx index c63aac248..a380fa9a4 100644 --- a/src/studio-home/tabs-section/TabsSection.test.tsx +++ b/src/studio-home/tabs-section/TabsSection.test.tsx @@ -478,5 +478,42 @@ describe('', () => { tabMessages.librariesTabErrorMessage.defaultMessage, )).toBeVisible(); }); + + [true, false].forEach((isMigrated) => { + it(`should render v2 libraries migration alert when the libraries have isMigrated=${isMigrated}`, async () => { + setConfig({ + ...getConfig(), + ENABLE_LEGACY_LIBRARY_MIGRATOR: 'true', + }); + const libraries = generateGetStudioHomeLibrariesApiResponse().libraries.map( + library => ({ + ...library, + isMigrated, + }), + ); + const user = userEvent.setup(); + await axiosMock.onGet(getStudioHomeApiUrl()).reply(200, generateGetStudioHomeLibrariesApiResponse()); + await axiosMock.onGet(libraryApiLink).reply(200, { libraries }); + render(); + await executeThunk(fetchStudioHomeData(), store.dispatch); + + const librariesTab = await screen.findByRole('tab', { name: librariesBetaTabTitle }); + await user.click(librariesTab); + + expect(librariesTab).toHaveClass('active'); + + expect(await screen.findByText(/welcome to the new content libraries/i)).toBeVisible(); + + const migrationPendingText = /legacy libraries can be migrated using the migration tool/i; + + if (isMigrated) { + expect(screen.queryByText(migrationPendingText)).not.toBeInTheDocument(); + expect(screen.queryByRole('button', { name: 'Review Legacy Libraries' })).not.toBeInTheDocument(); + } else { + expect(screen.getByText(migrationPendingText)).toBeVisible(); + expect(screen.getByRole('button', { name: 'Review Legacy Libraries' })).toBeVisible(); + } + }); + }); }); }); diff --git a/src/studio-home/tabs-section/libraries-tab/MigrateLegacyLibrariesAlert.tsx b/src/studio-home/tabs-section/libraries-tab/MigrateLegacyLibrariesAlert.tsx index d4a35c95a..04c35a195 100644 --- a/src/studio-home/tabs-section/libraries-tab/MigrateLegacyLibrariesAlert.tsx +++ b/src/studio-home/tabs-section/libraries-tab/MigrateLegacyLibrariesAlert.tsx @@ -11,7 +11,7 @@ export const MigrateLegacyLibrariesAlert = () => (
- +
+
+
+ + ) : ( + + )} + + ); +}; diff --git a/src/studio-home/tabs-section/libraries-v2-tab/index.tsx b/src/studio-home/tabs-section/libraries-v2-tab/index.tsx index 605ec7141..de7a56e68 100644 --- a/src/studio-home/tabs-section/libraries-v2-tab/index.tsx +++ b/src/studio-home/tabs-section/libraries-v2-tab/index.tsx @@ -6,15 +6,17 @@ import { Alert, Button, } from '@openedx/paragon'; +import { getConfig } from '@edx/frontend-platform'; import { useIntl } from '@edx/frontend-platform/i18n'; import { Error } from '@openedx/paragon/icons'; -import { useContentLibraryV2List } from '../../../library-authoring'; -import { LoadingSpinner } from '../../../generic/Loading'; -import AlertMessage from '../../../generic/alert-message'; +import { useContentLibraryV2List } from '@src/library-authoring'; +import { LoadingSpinner } from '@src/generic/Loading'; +import AlertMessage from '@src/generic/alert-message'; import CardItem from '../../card-item'; import messages from '../messages'; import LibrariesV2Filters from './libraries-v2-filters'; +import { WelcomeLibrariesV2Alert } from './WelcomeLibrariesV2Alert'; type Props = Record; @@ -37,11 +39,11 @@ const LibrariesV2Tab: React.FC = () => { const { data, - isLoading, + isPending, isError, } = useContentLibraryV2List({ page: currentPage, ...filterParams }); - if (isLoading && !isFiltered) { + if (isPending && !isFiltered) { return ( @@ -49,23 +51,11 @@ const LibrariesV2Tab: React.FC = () => { ); } - const hasV2Libraries = !isLoading && !isError && ((data!.results.length || 0) > 0); - - // TODO: update this link when tutorial is ready. - const librariesTutorialLink = ( - - {intl.formatMessage(messages.librariesV2TabBetaTutorialLinkText)} - - ); + const hasV2Libraries = !isPending && !isError && ((data!.results.length || 0) > 0); return ( <> - - {intl.formatMessage( - messages.librariesV2TabBetaText, - { link: librariesTutorialLink }, - )} - + {getConfig().ENABLE_LEGACY_LIBRARY_MIGRATOR === 'true' && ()} {isError ? ( = () => {
- {!isLoading && !isError - && ( -

- {intl.formatMessage(messages.coursesPaginationInfo, { - length: data!.results.length, - total: data!.count, - })} -

- )} + {!isPending && !isError + && ( +

+ {intl.formatMessage(messages.coursesPaginationInfo, { + length: data.results.length, + total: data.count, + })} +

+ )}
- { hasV2Libraries + {hasV2Libraries ? data!.results.map(({ id, org, slug, title, }) => ( @@ -110,7 +100,7 @@ const LibrariesV2Tab: React.FC = () => { number={slug} path={`/library/${id}`} /> - )) : isFiltered && !isLoading && ( + )) : isFiltered && !isPending && ( {intl.formatMessage(messages.librariesV2TabLibraryNotFoundAlertTitle)} diff --git a/src/studio-home/tabs-section/libraries-v2-tab/libraries-v2-filters/index.test.tsx b/src/studio-home/tabs-section/libraries-v2-tab/libraries-v2-filters/index.test.tsx index ca78fa570..01c83523a 100644 --- a/src/studio-home/tabs-section/libraries-v2-tab/libraries-v2-filters/index.test.tsx +++ b/src/studio-home/tabs-section/libraries-v2-tab/libraries-v2-filters/index.test.tsx @@ -115,13 +115,13 @@ describe('LibrariesV2Filters', () => { }); it('should display the loading spinner when isLoading is true', () => { - renderComponent({ isLoading: true }); + renderComponent({ isPending: true }); const spinner = screen.getByText('Loading...'); expect(spinner).toBeInTheDocument(); }); it('should not display the loading spinner when isLoading is false', () => { - renderComponent({ isLoading: false }); + renderComponent({ isPending: false }); const spinner = screen.queryByText('Loading...'); expect(spinner).not.toBeInTheDocument(); }); diff --git a/src/studio-home/tabs-section/libraries-v2-tab/libraries-v2-filters/index.tsx b/src/studio-home/tabs-section/libraries-v2-tab/libraries-v2-filters/index.tsx index c071c59ef..8fe71b279 100644 --- a/src/studio-home/tabs-section/libraries-v2-tab/libraries-v2-filters/index.tsx +++ b/src/studio-home/tabs-section/libraries-v2-tab/libraries-v2-filters/index.tsx @@ -7,7 +7,7 @@ import LibrariesV2OrderFilterMenu from './libraries-v2-order-filter-menu'; import messages from '../../messages'; export interface LibrariesV2FiltersProps { - isLoading?: boolean; + isPending?: boolean; isFiltered?: boolean; filterParams: { search?: string | undefined, order?: string }; setFilterParams: React.Dispatch>; @@ -15,7 +15,7 @@ export interface LibrariesV2FiltersProps { } const LibrariesV2Filters: React.FC = ({ - isLoading = false, + isPending = false, isFiltered = false, filterParams, setFilterParams, @@ -93,7 +93,7 @@ const LibrariesV2Filters: React.FC = ({ className="mr-4" placeholder={intl.formatMessage(messages.librariesV2TabLibrarySearchPlaceholder)} /> - {isLoading && ( + {isPending && ( diff --git a/src/studio-home/tabs-section/messages.ts b/src/studio-home/tabs-section/messages.ts index 1cb1c715d..17303cb83 100644 --- a/src/studio-home/tabs-section/messages.ts +++ b/src/studio-home/tabs-section/messages.ts @@ -63,19 +63,6 @@ const messages = defineMessages({ defaultMessage: 'Beta', description: 'Text used to mark the Libraries v2 feature as "in beta"', }, - librariesV2TabBetaText: { - id: 'course-authoring.studio-home.libraries.tab.library.beta-text', - defaultMessage: 'Welcome to the new Beta Libraries experience! Libraries have been redesigned from the ground up,' - + ' making it much easier to reuse and remix course content. The new Libraries space lets you create, organize and' - + ' manage new content; reuse your content in as many courses as you\'d like; sync updates centrally; and create' - + ' and randomize problem sets. See {link} for details.', - description: 'Explanatory text shown on the Libraries v2 tab during the beta release.', - }, - librariesV2TabBetaTutorialLinkText: { - id: 'course-authoring.studio-home.libraries.tab.library.beta-link-text', - defaultMessage: 'Libraries v2 tutorial', - description: 'Text to use as the link in the "course-authoring.studio-home.libraries.tab.library.beta-text" message', - }, librariesV2TabLibrarySearchPlaceholder: { id: 'course-authoring.studio-home.libraries.tab.library.search-placeholder', defaultMessage: 'Search', @@ -89,17 +76,17 @@ const messages = defineMessages({ defaultMessage: 'There are no libraries with the current filters.', }, alertTitle: { - id: 'studio-home.legacy-libraries.migrate-alert.title', + id: 'studio-home.libraries.migrate-alert.title', defaultMessage: 'Migrate Legacy Libraries', description: 'Title for the alert message to migrate legacy libraries', }, - alertDescription: { - id: 'studio-home.legacy-libraries.migrate-alert.description', + alertDescriptionV1: { + id: 'studio-home.libraries.migrate-alert.description-v1', defaultMessage: 'In a future release, legacy libraries will no longer be supported.' + ' The new libraries experience allows you to author sections, subsections, units,' + ' and components to reuse across your courses. Content from legacy libraries can be' + ' migrated to the new experience.', - description: 'Description for the alert message to migrate legacy libraries', + description: 'Description for the alert message to migrate legacy libraries on legacy libraries tab.', }, alertReviewButton: { id: 'studio-home.legacy-libraries.migrate-alert.review-button', @@ -121,6 +108,24 @@ const messages = defineMessages({ description: 'Label text for unmigrated migration filter menu item in legacy libraries tab', defaultMessage: 'Unmigrated', }, + alertDescriptionV2: { + id: 'studio-home.libraries.migrate-alert.description-v2', + defaultMessage: 'Welcome to the new Content Libraries experience! Libraries have been redesigned' + + ' from the ground up, making it much easier to reuse content. You can create, organize and manage' + + ' new content, reuse your content in as many courses as you\'d like, publish updates, and create/randomize' + + ' problem sets. See {link} for details.', + description: 'Description for the alert message while there are no libraries pending migration on v2 tab.', + }, + alertDescriptionV2MigrationPending: { + id: 'studio-home.libraries.migrate-alert.description-v2.migration-pending', + defaultMessage: ' Legacy libraries can be migrated using the migration tool.', + description: 'Complementary description for the alert message while there are libraries pending migration.', + }, + alertLibrariesDocLinkText: { + id: 'studio-home.libraries.migrate-alert.docs', + defaultMessage: 'Libraries documentation', + description: 'Link text for the libraries documentation link.', + }, }); export default messages;