diff --git a/packages/bruno-app/src/components/Sidebar/Collections/CollectionsBadge/index.js b/packages/bruno-app/src/components/Sidebar/Collections/CollectionsBadge/index.js new file mode 100644 index 000000000..09cb7f9e4 --- /dev/null +++ b/packages/bruno-app/src/components/Sidebar/Collections/CollectionsBadge/index.js @@ -0,0 +1,81 @@ +import { useState } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { + IconArrowsSort, + IconFolders, + IconSortAscendingLetters, + IconSortDescendingLetters, + IconX, +} from '@tabler/icons'; +import { sortCollections } from 'providers/ReduxStore/slices/collections/index'; +import RemoveCollections from '../RemoveCollections/index'; + +const CollectionsBadge = () => { + const dispatch = useDispatch(); + const { collections } = useSelector(state => state.collections); + const { collectionSortOrder } = useSelector(state => state.collections); + const sortCollectionOrder = () => { + let order; + switch (collectionSortOrder) { + case 'default': + order = 'alphabetical'; + break; + case 'alphabetical': + order = 'reverseAlphabetical'; + break; + case 'reverseAlphabetical': + order = 'default'; + break; + } + dispatch(sortCollections({ order })); + }; + + let sortIcon; + if (collectionSortOrder === 'default') { + sortIcon = ; + } else if (collectionSortOrder === 'alphabetical') { + sortIcon = ; + } else { + sortIcon = ; + } + + const [collectionsToClose, setCollectionsToClose] = useState([]); + const addAllCollectionsToClose = () => { + setCollectionsToClose(collections.map(c => c.uid)); + }; + const emptyCollections = () => { + setCollectionsToClose([]); + }; + + return ( +
+
+
+ + + + Collections +
+ {collections.length >= 1 && ( +
+ + + {collectionsToClose.length > 0 && ( + + )} +
+ )} +
+
+ ); +}; + +export default CollectionsBadge; diff --git a/packages/bruno-app/src/components/Sidebar/Collections/RemoveCollections/index.js b/packages/bruno-app/src/components/Sidebar/Collections/RemoveCollections/index.js new file mode 100644 index 000000000..c659eaeef --- /dev/null +++ b/packages/bruno-app/src/components/Sidebar/Collections/RemoveCollections/index.js @@ -0,0 +1,73 @@ +import React from 'react'; +import toast from 'react-hot-toast'; +import { useDispatch, useSelector } from 'react-redux'; +import PropTypes from 'prop-types'; +import { IconFiles } from '@tabler/icons'; +import Modal from 'components/Modal'; +import { removeCollection } from 'providers/ReduxStore/slices/collections/actions'; +import { findCollectionByUid } from 'utils/collections/index'; + +const RemoveCollections = ({ collectionUids, onClose }) => { + const dispatch = useDispatch(); + const allCollections = useSelector(state => state.collections.collections || []); + + const selectedCollections = collectionUids + .map(uid => findCollectionByUid(allCollections, uid)) + .filter(Boolean); + + const collectionsNames = selectedCollections.map(c => c.name).join(', '); + const collectionsPathnames = selectedCollections.map(c => c.pathname).join(', '); + + const onConfirm = () => { + const removalPromises = selectedCollections.map(collection => { + return dispatch(removeCollection(collection.uid)); + }); + + Promise.all(removalPromises) + .then(() => { + toast.success('Collections are closed'); + }) + .catch(() => { + toast.error('An error occurred while closing collections'); + }) + .finally(() => { + if (onClose) onClose(); + }); + }; + + const getConfirmationText = () => { + if (collectionUids.length > 1) { + return `Are you sure you want to close all ${collectionUids.length} collections in Bruno?`; + } + return ( + + Are you sure you want to close the collection + {' '} + {collectionsNames} + {' '} + in Bruno? + + ); + }; + + return ( + +
+ + {collectionsNames} +
+
{collectionsPathnames}
+
{getConfirmationText()}
+
+ It will still be available in the file system at the above locations and can be re-opened later. +
+
+ ); +}; + +RemoveCollections.propTypes = { + collectionUids: PropTypes.arrayOf(PropTypes.string).isRequired, + onClose: PropTypes.func, +}; + +export default RemoveCollections; diff --git a/packages/bruno-app/src/components/Sidebar/Collections/index.js b/packages/bruno-app/src/components/Sidebar/Collections/index.js index 119318819..cbe4d42e4 100644 --- a/packages/bruno-app/src/components/Sidebar/Collections/index.js +++ b/packages/bruno-app/src/components/Sidebar/Collections/index.js @@ -1,64 +1,14 @@ -import React, { useState } from 'react'; -import { useDispatch, useSelector } from 'react-redux'; import { IconSearch, - IconFolders, - IconArrowsSort, - IconSortAscendingLetters, - IconSortDescendingLetters, - IconX + IconX, } from '@tabler/icons'; -import Collection from './Collection'; +import React, { useState } from 'react'; +import { useSelector } from 'react-redux'; import CreateCollection from '../CreateCollection'; -import StyledWrapper from './StyledWrapper'; +import Collection from './Collection'; +import CollectionsBadge from './CollectionsBadge/index'; import CreateOrOpenCollection from './CreateOrOpenCollection'; -import { sortCollections } from 'providers/ReduxStore/slices/collections/actions'; - -// todo: move this to a separate folder -// the coding convention is to keep all the components in a folder named after the component -const CollectionsBadge = () => { - const dispatch = useDispatch(); - const { collections } = useSelector((state) => state.collections); - const { collectionSortOrder } = useSelector((state) => state.collections); - const sortCollectionOrder = () => { - let order; - switch (collectionSortOrder) { - case 'default': - order = 'alphabetical'; - break; - case 'alphabetical': - order = 'reverseAlphabetical'; - break; - case 'reverseAlphabetical': - order = 'default'; - break; - } - dispatch(sortCollections({ order })); - }; - return ( -
-
-
- - - - Collections -
- {collections.length >= 1 && ( - - )} -
-
- ); -}; +import StyledWrapper from './StyledWrapper'; const Collections = () => { const [searchText, setSearchText] = useState('');