Files
frontend-app-authoring/src/library-authoring/components/CollectionCard.tsx
Navin Karkera 434fea3a95 feat: delete collection [FC-0062] (#1333)
* feat: delete collection

* feat: update button status on delete

* test: add tests for collection delete
2024-10-08 16:59:06 +00:00

141 lines
4.5 KiB
TypeScript

import { useCallback, useContext, useState } from 'react';
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
import {
ActionRow,
Dropdown,
Icon,
IconButton,
useToggle,
} from '@openedx/paragon';
import { MoreVert } from '@openedx/paragon/icons';
import { Link } from 'react-router-dom';
import { type CollectionHit } from '../../search-manager';
import { useLibraryContext } from '../common/context';
import BaseComponentCard from './BaseComponentCard';
import { ToastContext } from '../../generic/toast-context';
import { useDeleteCollection, useRestoreCollection } from '../data/apiHooks';
import DeleteModal from '../../generic/delete-modal/DeleteModal';
import messages from './messages';
type CollectionMenuProps = {
collectionHit: CollectionHit,
};
const CollectionMenu = ({ collectionHit } : CollectionMenuProps) => {
const intl = useIntl();
const { showToast } = useContext(ToastContext);
const [isDeleteModalOpen, openDeleteModal, closeDeleteModal] = useToggle(false);
const [confirmBtnState, setConfirmBtnState] = useState('default');
const { closeLibrarySidebar, currentCollectionId } = useLibraryContext();
const restoreCollectionMutation = useRestoreCollection(collectionHit.contextKey, collectionHit.blockId);
const restoreCollection = useCallback(() => {
restoreCollectionMutation.mutateAsync()
.then(() => {
showToast(intl.formatMessage(messages.undoDeleteCollectionToastMessage));
}).catch(() => {
showToast(intl.formatMessage(messages.undoDeleteCollectionToastFailed));
});
}, []);
const deleteCollectionMutation = useDeleteCollection(collectionHit.contextKey, collectionHit.blockId);
const deleteCollection = useCallback(() => {
setConfirmBtnState('pending');
if (currentCollectionId === collectionHit.blockId) {
// Close sidebar if current collection is open to avoid displaying
// deleted collection in sidebar
closeLibrarySidebar();
}
deleteCollectionMutation.mutateAsync()
.then(() => {
showToast(
intl.formatMessage(messages.deleteCollectionSuccess),
{
label: intl.formatMessage(messages.undoDeleteCollectionToastAction),
onClick: restoreCollection,
},
);
}).catch(() => {
showToast(intl.formatMessage(messages.deleteCollectionFailed));
}).finally(() => {
setConfirmBtnState('default');
closeDeleteModal();
});
}, [currentCollectionId]);
return (
<>
<Dropdown id="collection-card-dropdown" onClick={(e) => e.stopPropagation()}>
<Dropdown.Toggle
id="collection-card-menu-toggle"
as={IconButton}
src={MoreVert}
iconAs={Icon}
variant="primary"
alt={intl.formatMessage(messages.collectionCardMenuAlt)}
data-testid="collection-card-menu-toggle"
/>
<Dropdown.Menu>
<Dropdown.Item
as={Link}
to={`/library/${collectionHit.contextKey}/collection/${collectionHit.blockId}/`}
>
<FormattedMessage {...messages.menuOpen} />
</Dropdown.Item>
<Dropdown.Item onClick={openDeleteModal}>
<FormattedMessage {...messages.deleteCollection} />
</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
<DeleteModal
isOpen={isDeleteModalOpen}
close={closeDeleteModal}
variant="warning"
category={collectionHit.type}
description={intl.formatMessage(messages.deleteCollectionConfirm, {
collectionTitle: collectionHit.displayName,
})}
onDeleteSubmit={deleteCollection}
btnState={confirmBtnState}
/>
</>
);
};
type CollectionCardProps = {
collectionHit: CollectionHit,
};
const CollectionCard = ({ collectionHit } : CollectionCardProps) => {
const {
openCollectionInfoSidebar,
} = useLibraryContext();
const {
type: componentType,
formatted,
tags,
numChildren,
} = collectionHit;
const { displayName = '', description = '' } = formatted;
return (
<BaseComponentCard
componentType={componentType}
displayName={displayName}
description={description}
tags={tags}
numChildren={numChildren}
actions={(
<ActionRow>
<CollectionMenu collectionHit={collectionHit} />
</ActionRow>
)}
openInfoSidebar={() => openCollectionInfoSidebar(collectionHit.blockId)}
/>
);
};
export default CollectionCard;