Skip to content

Commit 3089d0b

Browse files
authored
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
1 parent 47cec6e commit 3089d0b

File tree

3 files changed

+70
-15
lines changed

3 files changed

+70
-15
lines changed

src/library-authoring/data/apiHooks.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
1+
import {
2+
useQuery, useMutation, useQueryClient, Query,
3+
} from '@tanstack/react-query';
24

35
import {
46
type GetLibrariesV2CustomParams,
@@ -122,6 +124,22 @@ export const useRevertLibraryChanges = () => {
122124
mutationFn: revertLibraryChanges,
123125
onSettled: (_data, _error, libraryId) => {
124126
queryClient.invalidateQueries({ queryKey: libraryAuthoringQueryKeys.contentLibrary(libraryId) });
127+
queryClient.invalidateQueries({
128+
// Invalidate all content queries related to this library.
129+
// If we allow searching "all courses and libraries" in the future,
130+
// then we'd have to invalidate all `["content_search", "results"]`
131+
// queries, and not just the ones for this library, because items from
132+
// this library could be included in an "all courses and libraries"
133+
// search. For now we only allow searching individual libraries.
134+
predicate: /* istanbul ignore next */ (query: Query): boolean => {
135+
// extraFilter contains library id
136+
const extraFilter = query.queryKey[5];
137+
if (!(Array.isArray(extraFilter) || typeof extraFilter === 'string')) {
138+
return false;
139+
}
140+
return query.queryKey[0] === 'content_search' && extraFilter?.includes(`context_key = "${libraryId}"`);
141+
},
142+
});
125143
},
126144
});
127145
};

src/library-authoring/library-info/LibraryInfo.test.tsx

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,4 +204,44 @@ describe('<LibraryInfo />', () => {
204204

205205
await waitFor(() => expect(axiosMock.history.post[0].url).toEqual(url));
206206
});
207+
208+
it('should discard changes', async () => {
209+
const url = getCommitLibraryChangesUrl(libraryData.id);
210+
axiosMock.onDelete(url).reply(200);
211+
212+
render(<RootWrapper data={libraryData} />);
213+
const discardButton = screen.getByRole('button', { name: /discard changes/i });
214+
fireEvent.click(discardButton);
215+
216+
expect(await screen.findByText('Library changes reverted successfully')).toBeInTheDocument();
217+
218+
await waitFor(() => expect(axiosMock.history.delete[0].url).toEqual(url));
219+
});
220+
221+
it('should show error on discard changes', async () => {
222+
const url = getCommitLibraryChangesUrl(libraryData.id);
223+
axiosMock.onDelete(url).reply(500);
224+
225+
render(<RootWrapper data={libraryData} />);
226+
const discardButton = screen.getByRole('button', { name: /discard changes/i });
227+
fireEvent.click(discardButton);
228+
229+
expect(await screen.findByText('There was an error reverting changes in the library.')).toBeInTheDocument();
230+
231+
await waitFor(() => expect(axiosMock.history.delete[0].url).toEqual(url));
232+
});
233+
234+
it('discard changes btn should be disabled for new libraries', async () => {
235+
render(<RootWrapper data={{ ...libraryData, lastPublished: null, numBlocks: 0 }} />);
236+
const discardButton = screen.getByRole('button', { name: /discard changes/i });
237+
238+
expect(discardButton).toBeDisabled();
239+
});
240+
241+
it('discard changes btn should be enabled for new libraries if components are added', async () => {
242+
render(<RootWrapper data={{ ...libraryData, lastPublished: null, numBlocks: 2 }} />);
243+
const discardButton = screen.getByRole('button', { name: /discard changes/i });
244+
245+
expect(discardButton).not.toBeDisabled();
246+
});
207247
});

src/library-authoring/library-info/LibraryPublishStatus.tsx

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React, { useCallback, useContext, useMemo } from 'react';
22
import classNames from 'classnames';
33
import { Button, Container, Stack } from '@openedx/paragon';
44
import { FormattedDate, FormattedTime, useIntl } from '@edx/frontend-platform/i18n';
5-
import { useCommitLibraryChanges } from '../data/apiHooks';
5+
import { useCommitLibraryChanges, useRevertLibraryChanges } from '../data/apiHooks';
66
import { ContentLibrary } from '../data/api';
77
import { ToastContext } from '../../generic/toast-context';
88
import messages from './messages';
@@ -14,6 +14,7 @@ type LibraryPublishStatusProps = {
1414
const LibraryPublishStatus = ({ library } : LibraryPublishStatusProps) => {
1515
const intl = useIntl();
1616
const commitLibraryChanges = useCommitLibraryChanges();
17+
const revertLibraryChanges = useRevertLibraryChanges();
1718
const { showToast } = useContext(ToastContext);
1819

1920
const commit = useCallback(() => {
@@ -25,9 +26,6 @@ const LibraryPublishStatus = ({ library } : LibraryPublishStatusProps) => {
2526
});
2627
}, []);
2728

28-
/**
29-
* TODO, the discard changes breaks the library.
30-
* Discomment this when discard changes is fixed.
3129
const revert = useCallback(() => {
3230
revertLibraryChanges.mutateAsync(library.id)
3331
.then(() => {
@@ -36,15 +34,16 @@ const LibraryPublishStatus = ({ library } : LibraryPublishStatusProps) => {
3634
showToast(intl.formatMessage(messages.revertErrorMsg));
3735
});
3836
}, []);
39-
*/
4037

4138
const {
4239
isPublished,
40+
isNew,
4341
statusMessage,
4442
extraStatusMessage,
4543
bodyMessage,
4644
} = useMemo(() => {
4745
let isPublishedResult: boolean;
46+
let isNewResult = false;
4847
let statusMessageResult : string;
4948
let extraStatusMessageResult : string | undefined;
5049
let bodyMessageResult : string | undefined;
@@ -94,6 +93,7 @@ const LibraryPublishStatus = ({ library } : LibraryPublishStatusProps) => {
9493

9594
if (!library.lastPublished) {
9695
// Library is never published (new)
96+
isNewResult = library.numBlocks === 0; // allow discarding if components are added
9797
isPublishedResult = false;
9898
statusMessageResult = intl.formatMessage(messages.draftStatusLabel);
9999
extraStatusMessageResult = intl.formatMessage(messages.neverPublishedLabel);
@@ -123,6 +123,7 @@ const LibraryPublishStatus = ({ library } : LibraryPublishStatusProps) => {
123123
}
124124
return {
125125
isPublished: isPublishedResult,
126+
isNew: isNewResult,
126127
statusMessage: statusMessageResult,
127128
extraStatusMessage: extraStatusMessageResult,
128129
bodyMessage: bodyMessageResult,
@@ -153,15 +154,11 @@ const LibraryPublishStatus = ({ library } : LibraryPublishStatusProps) => {
153154
<Button disabled={isPublished} onClick={commit}>
154155
{intl.formatMessage(messages.publishButtonLabel)}
155156
</Button>
156-
{ /*
157-
* TODO, the discard changes breaks the library.
158-
* Discomment this when discard changes is fixed.
159-
<div className="d-flex justify-content-end">
160-
<Button disabled={isPublished} variant="link" onClick={revert}>
161-
{intl.formatMessage(messages.discardChangesButtonLabel)}
162-
</Button>
163-
</div>
164-
*/ }
157+
<div className="d-flex justify-content-end">
158+
<Button disabled={isPublished || isNew} variant="link" onClick={revert}>
159+
{intl.formatMessage(messages.discardChangesButtonLabel)}
160+
</Button>
161+
</div>
165162
</Stack>
166163
</Container>
167164
</Stack>

0 commit comments

Comments
 (0)