2019-10-20 19:59:16 +00:00
|
|
|
import PropTypes from 'prop-types';
|
|
|
|
import React from 'react';
|
|
|
|
import InlineSVG from 'react-inlinesvg';
|
|
|
|
import { connect } from 'react-redux';
|
|
|
|
import { bindActionCreators } from 'redux';
|
|
|
|
|
|
|
|
import * as CollectionsActions from '../../actions/collections';
|
|
|
|
import getSortedCollections from '../../selectors/collections';
|
|
|
|
|
|
|
|
import exitUrl from '../../../../images/exit.svg';
|
|
|
|
|
2019-10-20 23:09:05 +00:00
|
|
|
import Loader from '../../../App/components/loader';
|
2019-10-20 19:59:16 +00:00
|
|
|
import { Searchbar } from '../Searchbar';
|
|
|
|
import Item from './Item';
|
|
|
|
|
|
|
|
const NoCollections = () => (
|
2019-10-20 23:09:05 +00:00
|
|
|
<div className="collection-popover__empty">
|
2019-10-20 19:59:16 +00:00
|
|
|
<p>No collections</p>
|
|
|
|
</div>);
|
|
|
|
|
2019-10-20 22:37:37 +00:00
|
|
|
const projectInCollection = (project, collection) => (
|
|
|
|
collection.items.find(item => item.project.id === project.id) != null
|
|
|
|
);
|
|
|
|
|
2019-10-20 19:59:16 +00:00
|
|
|
|
|
|
|
const CollectionPopover = ({
|
2019-10-20 23:09:05 +00:00
|
|
|
loading, onClose, project, collections, addToCollection, removeFromCollection, getCollections, user
|
2019-10-20 19:59:16 +00:00
|
|
|
}) => {
|
2019-10-20 23:09:05 +00:00
|
|
|
const [didLoadData, setDidLoadData] = React.useState(null);
|
2019-10-20 19:59:16 +00:00
|
|
|
const [searchTerm, setSearchTerm] = React.useState('');
|
2019-10-20 21:30:06 +00:00
|
|
|
const filteredCollections = searchTerm === '' ?
|
|
|
|
collections :
|
|
|
|
collections.filter(({ name }) => name.toUpperCase().includes(searchTerm.toUpperCase()));
|
2019-10-20 19:59:16 +00:00
|
|
|
|
|
|
|
React.useEffect(() => {
|
|
|
|
getCollections(user.username);
|
|
|
|
}, [user]);
|
|
|
|
|
2019-10-20 23:09:05 +00:00
|
|
|
React.useEffect(() => {
|
|
|
|
if (didLoadData === true) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (loading && didLoadData === null) {
|
|
|
|
setDidLoadData(false);
|
|
|
|
} else if (!loading && didLoadData === false) {
|
|
|
|
setDidLoadData(true);
|
|
|
|
}
|
|
|
|
}, [loading]);
|
|
|
|
|
2019-10-20 19:59:16 +00:00
|
|
|
const handleAddToCollection = (collectionId) => {
|
|
|
|
addToCollection(collectionId, project.id);
|
|
|
|
};
|
|
|
|
|
2019-10-20 22:37:37 +00:00
|
|
|
const handleRemoveFromCollection = (collectionId) => {
|
|
|
|
removeFromCollection(collectionId, project.id);
|
|
|
|
};
|
|
|
|
|
2019-10-20 23:09:05 +00:00
|
|
|
let content = null;
|
|
|
|
|
|
|
|
if (didLoadData && collections.length === 0) {
|
|
|
|
content = <NoCollections />;
|
|
|
|
} else if (didLoadData) {
|
|
|
|
content = (
|
|
|
|
<ul>
|
|
|
|
{
|
|
|
|
filteredCollections.map((collection) => {
|
|
|
|
const inCollection = projectInCollection(project, collection);
|
|
|
|
const handleSelect = inCollection ? handleRemoveFromCollection : handleAddToCollection;
|
|
|
|
|
|
|
|
return (
|
|
|
|
<Item inCollection={inCollection} key={collection.id} collection={collection} onSelect={() => handleSelect(collection.id)} />
|
|
|
|
);
|
|
|
|
})
|
|
|
|
}
|
|
|
|
</ul>
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
content = <Loader />;
|
|
|
|
}
|
|
|
|
|
2019-10-20 19:59:16 +00:00
|
|
|
return (
|
|
|
|
<div className="collection-popover">
|
|
|
|
<div className="collection-popover__header">
|
|
|
|
<h4>Add to collection</h4>
|
|
|
|
<button className="collection-popover__exit-button" onClick={onClose}>
|
|
|
|
<InlineSVG src={exitUrl} alt="Close Add to Collection" />
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className="collection-popover__filter">
|
2019-10-20 21:30:06 +00:00
|
|
|
<Searchbar searchLabel="Search collections..." searchTerm={searchTerm} setSearchTerm={setSearchTerm} resetSearchTerm={() => setSearchTerm('')} />
|
2019-10-20 19:59:16 +00:00
|
|
|
</div>
|
|
|
|
|
|
|
|
<div className="collection-popover__items">
|
2019-10-20 23:09:05 +00:00
|
|
|
{content}
|
2019-10-20 19:59:16 +00:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
CollectionPopover.propTypes = {
|
2019-10-20 23:09:05 +00:00
|
|
|
loading: PropTypes.bool.isRequired,
|
2019-10-20 19:59:16 +00:00
|
|
|
onClose: PropTypes.func.isRequired,
|
|
|
|
getCollections: PropTypes.func.isRequired,
|
|
|
|
addToCollection: PropTypes.func.isRequired,
|
2019-10-20 22:37:37 +00:00
|
|
|
removeFromCollection: PropTypes.func.isRequired,
|
2019-10-20 19:59:16 +00:00
|
|
|
user: PropTypes.shape({
|
|
|
|
username: PropTypes.string.isRequired,
|
|
|
|
}).isRequired,
|
|
|
|
collections: PropTypes.arrayOf(PropTypes.shape({
|
|
|
|
name: PropTypes.string,
|
|
|
|
})).isRequired,
|
|
|
|
project: PropTypes.shape({
|
|
|
|
id: PropTypes.string,
|
|
|
|
}).isRequired,
|
|
|
|
};
|
|
|
|
|
|
|
|
function mapStateToProps(state, ownProps) {
|
|
|
|
return {
|
|
|
|
user: state.user,
|
|
|
|
collections: getSortedCollections(state),
|
|
|
|
loading: state.loading,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
function mapDispatchToProps(dispatch) {
|
|
|
|
return bindActionCreators(
|
|
|
|
Object.assign({}, CollectionsActions),
|
|
|
|
dispatch
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
export default connect(mapStateToProps, mapDispatchToProps)(CollectionPopover);
|