Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: show confirmation dialog before discarding library changes [FC-0062] #1428

Merged
merged 2 commits into from
Oct 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions src/generic/delete-modal/DeleteModal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,15 @@ const DeleteModal = ({
description,
variant,
btnState,
btnDefaultLabel,
btnPendingLabel,
}) => {
const intl = useIntl();

const modalTitle = title || intl.formatMessage(messages.title, { category });
const modalDescription = description || intl.formatMessage(messages.description, { category });
const defaultBtnLabel = btnDefaultLabel || intl.formatMessage(messages.deleteButton);
const pendingBtnLabel = btnPendingLabel || intl.formatMessage(messages.pendingDeleteButton);

return (
<AlertModal
Expand Down Expand Up @@ -51,8 +55,8 @@ const DeleteModal = ({
onDeleteSubmit();
}}
labels={{
default: intl.formatMessage(messages.deleteButton),
pending: intl.formatMessage(messages.pendingDeleteButton),
default: defaultBtnLabel,
pending: pendingBtnLabel,
}}
/>
</ActionRow>
Expand All @@ -69,6 +73,8 @@ DeleteModal.defaultProps = {
description: '',
variant: 'default',
btnState: 'default',
btnDefaultLabel: '',
btnPendingLabel: '',
};

DeleteModal.propTypes = {
Expand All @@ -80,6 +86,8 @@ DeleteModal.propTypes = {
description: PropTypes.string,
variant: PropTypes.string,
btnState: PropTypes.string,
btnDefaultLabel: PropTypes.string,
btnPendingLabel: PropTypes.string,
};

export default DeleteModal;
2 changes: 1 addition & 1 deletion src/library-authoring/LibraryAuthoringPage.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,7 @@ describe('<LibraryAuthoringPage />', () => {
await renderLibraryPage();

// Open menu
fireEvent.click(screen.getAllByTestId('component-card-menu-toggle')[0]);
fireEvent.click((await screen.findAllByTestId('component-card-menu-toggle'))[0]);
// Click add to collection
fireEvent.click(screen.getByRole('button', { name: 'Add to collection' }));

Expand Down
4 changes: 4 additions & 0 deletions src/library-authoring/library-info/LibraryInfo.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ describe('<LibraryInfo />', () => {

const discardButton = screen.getByRole('button', { name: /discard changes/i });
fireEvent.click(discardButton);
const confirmBtn = screen.getByRole('button', { name: /discard/i });
fireEvent.click(confirmBtn);

await waitFor(() => {
expect(axiosMock.history.delete[0].url).toEqual(url);
Expand All @@ -177,6 +179,8 @@ describe('<LibraryInfo />', () => {

const discardButton = screen.getByRole('button', { name: /discard changes/i });
fireEvent.click(discardButton);
const confirmBtn = screen.getByRole('button', { name: /discard/i });
fireEvent.click(confirmBtn);

await waitFor(() => {
expect(axiosMock.history.delete[0].url).toEqual(url);
Expand Down
33 changes: 27 additions & 6 deletions src/library-authoring/library-info/LibraryPublishStatus.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import { useCallback, useContext } from 'react';
import { useCallback, useContext, useState } from 'react';
import { useIntl } from '@edx/frontend-platform/i18n';

import { useToggle } from '@openedx/paragon';
import { ToastContext } from '../../generic/toast-context';
import { useLibraryContext } from '../common/context';
import { useCommitLibraryChanges, useRevertLibraryChanges } from '../data/apiHooks';
import StatusWidget from '../generic/status-widget';
import messages from './messages';
import DeleteModal from '../../generic/delete-modal/DeleteModal';

const LibraryPublishStatus = () => {
const intl = useIntl();
const { libraryData, readOnly } = useLibraryContext();
const [isConfirmModalOpen, openConfirmModal, closeConfirmModal] = useToggle(false);
const [confirmBtnState, setConfirmBtnState] = useState('default');

const commitLibraryChanges = useCommitLibraryChanges();
const revertLibraryChanges = useRevertLibraryChanges();
Expand All @@ -28,11 +32,15 @@ const LibraryPublishStatus = () => {

const revert = useCallback(() => {
if (libraryData) {
setConfirmBtnState('pending');
revertLibraryChanges.mutateAsync(libraryData.id)
.then(() => {
showToast(intl.formatMessage(messages.revertSuccessMsg));
}).catch(() => {
showToast(intl.formatMessage(messages.revertErrorMsg));
}).finally(() => {
setConfirmBtnState('default');
closeConfirmModal();
});
}
}, [libraryData]);
Expand All @@ -42,11 +50,24 @@ const LibraryPublishStatus = () => {
}

return (
<StatusWidget
{...libraryData}
onCommit={!readOnly ? commit : undefined}
onRevert={!readOnly ? revert : undefined}
/>
<>
<StatusWidget
{...libraryData}
onCommit={!readOnly ? commit : undefined}
onRevert={!readOnly ? openConfirmModal : undefined}
/>
<DeleteModal
isOpen={isConfirmModalOpen}
close={closeConfirmModal}
variant="warning"
title={intl.formatMessage(messages.discardChangesTitle)}
description={intl.formatMessage(messages.discardChangesDescription)}
onDeleteSubmit={revert}
btnState={confirmBtnState}
btnDefaultLabel={intl.formatMessage(messages.discardChangesDefaultBtnLabel)}
btnPendingLabel={intl.formatMessage(messages.discardChangesDefaultBtnLabel)}
/>
</>
);
};

Expand Down
15 changes: 15 additions & 0 deletions src/library-authoring/library-info/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,21 @@ const messages = defineMessages({
defaultMessage: 'There was an error updating the library',
description: 'Message when there is an error when updating the library',
},
discardChangesTitle: {
id: 'course-authoring.library-authoring.library.discardChangesTitle',
defaultMessage: 'Discard changes',
description: 'Title text for confirmation modal shown before discard library changes',
},
discardChangesDescription: {
id: 'course-authoring.library-authoring.library.discardChangesDescription',
defaultMessage: 'Are you sure you want to discard all unpublished changes in this library? This will include changes made by other users',
description: 'Description text for confirmation modal shown before discard library changes',
},
discardChangesDefaultBtnLabel: {
id: 'course-authoring.library-authoring.library.discardChangesDefaultBtnLabel',
defaultMessage: 'Discard',
description: 'Button text for confirmation modal shown before discard library changes',
},
});

export default messages;