From 3089d0b993fbb55e9a49c85a0d67bec4bd96994b Mon Sep 17 00:00:00 2001 From: Navin Karkera Date: Wed, 21 Aug 2024 07:42:06 +0530 Subject: [PATCH] fix: discard button [FC-0062] (#1214) * fix: discard changes * refactor: disable discard btn for new libs Enable it if components are added. * refactor: invalidate library related content queries * chore: add comment about content search query invalidation --- src/library-authoring/data/apiHooks.ts | 20 +++++++++- .../library-info/LibraryInfo.test.tsx | 40 +++++++++++++++++++ .../library-info/LibraryPublishStatus.tsx | 25 +++++------- 3 files changed, 70 insertions(+), 15 deletions(-) diff --git a/src/library-authoring/data/apiHooks.ts b/src/library-authoring/data/apiHooks.ts index 1e9a92bf84..64420a71bb 100644 --- a/src/library-authoring/data/apiHooks.ts +++ b/src/library-authoring/data/apiHooks.ts @@ -1,4 +1,6 @@ -import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; +import { + useQuery, useMutation, useQueryClient, Query, +} from '@tanstack/react-query'; import { type GetLibrariesV2CustomParams, @@ -122,6 +124,22 @@ export const useRevertLibraryChanges = () => { mutationFn: revertLibraryChanges, onSettled: (_data, _error, libraryId) => { queryClient.invalidateQueries({ queryKey: libraryAuthoringQueryKeys.contentLibrary(libraryId) }); + queryClient.invalidateQueries({ + // Invalidate all content queries related to this library. + // If we allow searching "all courses and libraries" in the future, + // then we'd have to invalidate all `["content_search", "results"]` + // queries, and not just the ones for this library, because items from + // this library could be included in an "all courses and libraries" + // search. For now we only allow searching individual libraries. + predicate: /* istanbul ignore next */ (query: Query): boolean => { + // extraFilter contains library id + const extraFilter = query.queryKey[5]; + if (!(Array.isArray(extraFilter) || typeof extraFilter === 'string')) { + return false; + } + return query.queryKey[0] === 'content_search' && extraFilter?.includes(`context_key = "${libraryId}"`); + }, + }); }, }); }; diff --git a/src/library-authoring/library-info/LibraryInfo.test.tsx b/src/library-authoring/library-info/LibraryInfo.test.tsx index 5ace15eb94..09c8350e08 100644 --- a/src/library-authoring/library-info/LibraryInfo.test.tsx +++ b/src/library-authoring/library-info/LibraryInfo.test.tsx @@ -204,4 +204,44 @@ describe('', () => { await waitFor(() => expect(axiosMock.history.post[0].url).toEqual(url)); }); + + it('should discard changes', async () => { + const url = getCommitLibraryChangesUrl(libraryData.id); + axiosMock.onDelete(url).reply(200); + + render(); + const discardButton = screen.getByRole('button', { name: /discard changes/i }); + fireEvent.click(discardButton); + + expect(await screen.findByText('Library changes reverted successfully')).toBeInTheDocument(); + + await waitFor(() => expect(axiosMock.history.delete[0].url).toEqual(url)); + }); + + it('should show error on discard changes', async () => { + const url = getCommitLibraryChangesUrl(libraryData.id); + axiosMock.onDelete(url).reply(500); + + render(); + const discardButton = screen.getByRole('button', { name: /discard changes/i }); + fireEvent.click(discardButton); + + expect(await screen.findByText('There was an error reverting changes in the library.')).toBeInTheDocument(); + + await waitFor(() => expect(axiosMock.history.delete[0].url).toEqual(url)); + }); + + it('discard changes btn should be disabled for new libraries', async () => { + render(); + const discardButton = screen.getByRole('button', { name: /discard changes/i }); + + expect(discardButton).toBeDisabled(); + }); + + it('discard changes btn should be enabled for new libraries if components are added', async () => { + render(); + const discardButton = screen.getByRole('button', { name: /discard changes/i }); + + expect(discardButton).not.toBeDisabled(); + }); }); diff --git a/src/library-authoring/library-info/LibraryPublishStatus.tsx b/src/library-authoring/library-info/LibraryPublishStatus.tsx index e497042657..a45ddccf66 100644 --- a/src/library-authoring/library-info/LibraryPublishStatus.tsx +++ b/src/library-authoring/library-info/LibraryPublishStatus.tsx @@ -2,7 +2,7 @@ import React, { useCallback, useContext, useMemo } from 'react'; import classNames from 'classnames'; import { Button, Container, Stack } from '@openedx/paragon'; import { FormattedDate, FormattedTime, useIntl } from '@edx/frontend-platform/i18n'; -import { useCommitLibraryChanges } from '../data/apiHooks'; +import { useCommitLibraryChanges, useRevertLibraryChanges } from '../data/apiHooks'; import { ContentLibrary } from '../data/api'; import { ToastContext } from '../../generic/toast-context'; import messages from './messages'; @@ -14,6 +14,7 @@ type LibraryPublishStatusProps = { const LibraryPublishStatus = ({ library } : LibraryPublishStatusProps) => { const intl = useIntl(); const commitLibraryChanges = useCommitLibraryChanges(); + const revertLibraryChanges = useRevertLibraryChanges(); const { showToast } = useContext(ToastContext); const commit = useCallback(() => { @@ -25,9 +26,6 @@ const LibraryPublishStatus = ({ library } : LibraryPublishStatusProps) => { }); }, []); - /** - * TODO, the discard changes breaks the library. - * Discomment this when discard changes is fixed. const revert = useCallback(() => { revertLibraryChanges.mutateAsync(library.id) .then(() => { @@ -36,15 +34,16 @@ const LibraryPublishStatus = ({ library } : LibraryPublishStatusProps) => { showToast(intl.formatMessage(messages.revertErrorMsg)); }); }, []); - */ const { isPublished, + isNew, statusMessage, extraStatusMessage, bodyMessage, } = useMemo(() => { let isPublishedResult: boolean; + let isNewResult = false; let statusMessageResult : string; let extraStatusMessageResult : string | undefined; let bodyMessageResult : string | undefined; @@ -94,6 +93,7 @@ const LibraryPublishStatus = ({ library } : LibraryPublishStatusProps) => { if (!library.lastPublished) { // Library is never published (new) + isNewResult = library.numBlocks === 0; // allow discarding if components are added isPublishedResult = false; statusMessageResult = intl.formatMessage(messages.draftStatusLabel); extraStatusMessageResult = intl.formatMessage(messages.neverPublishedLabel); @@ -123,6 +123,7 @@ const LibraryPublishStatus = ({ library } : LibraryPublishStatusProps) => { } return { isPublished: isPublishedResult, + isNew: isNewResult, statusMessage: statusMessageResult, extraStatusMessage: extraStatusMessageResult, bodyMessage: bodyMessageResult, @@ -153,15 +154,11 @@ const LibraryPublishStatus = ({ library } : LibraryPublishStatusProps) => { - { /* - * TODO, the discard changes breaks the library. - * Discomment this when discard changes is fixed. -
- -
- */ } +
+ +