import format from 'date-fns/format'; import PropTypes from 'prop-types'; import React from 'react'; import { connect } from 'react-redux'; import { Link } from 'react-router'; import { bindActionCreators } from 'redux'; import * as ProjectActions from '../../actions/project'; import * as CollectionsActions from '../../actions/collections'; import * as IdeActions from '../../actions/ide'; import * as ToastActions from '../../actions/toast'; import DownFilledTriangleIcon from '../../../../images/down-filled-triangle.svg'; class CollectionListRowBase extends React.Component { static projectInCollection(project, collection) { return collection.items.find(item => item.project.id === project.id) != null; } constructor(props) { super(props); this.state = { optionsOpen: false, isFocused: false, renameOpen: false, renameValue: '', }; this.renameInput = React.createRef(); } onFocusComponent = () => { this.setState({ isFocused: true }); } onBlurComponent = () => { this.setState({ isFocused: false }); setTimeout(() => { if (!this.state.isFocused) { this.closeAll(); } }, 200); } openOptions = () => { this.setState({ optionsOpen: true }); } closeOptions = () => { this.setState({ optionsOpen: false }); } toggleOptions = () => { if (this.state.optionsOpen) { this.closeOptions(); } else { this.openOptions(); } } closeAll = () => { this.setState({ optionsOpen: false, renameOpen: false, }); } handleAddSketches = () => { this.closeAll(); this.props.onAddSketches(); } handleDropdownOpen = () => { this.closeAll(); this.openOptions(); } handleCollectionDelete = () => { this.closeAll(); if (window.confirm(`Are you sure you want to delete "${this.props.collection.name}"?`)) { this.props.deleteCollection(this.props.collection.id); } } handleRenameOpen = () => { this.closeAll(); this.setState({ renameOpen: true, renameValue: this.props.collection.name, }, () => this.renameInput.current.focus()); } handleRenameChange = (e) => { this.setState({ renameValue: e.target.value }); } handleRenameEnter = (e) => { if (e.key === 'Enter') { this.updateName(); this.closeAll(); } } handleRenameBlur = () => { this.updateName(); this.closeAll(); } updateName = () => { const isValid = this.state.renameValue.trim().length !== 0; if (isValid) { this.props.editCollection(this.props.collection.id, { name: this.state.renameValue.trim() }); } } renderActions = () => { const { optionsOpen } = this.state; const userIsOwner = this.props.user.username === this.props.username; return ( {optionsOpen && } ); } renderCollectionName = () => { const { collection, username } = this.props; const { renameOpen, renameValue } = this.state; return ( {renameOpen ? '' : collection.name} {renameOpen && e.stopPropagation()} ref={this.renameInput} /> } ); } render() { const { collection } = this.props; return ( {this.renderCollectionName()} {format(new Date(collection.createdAt), 'MMM D, YYYY')} {format(new Date(collection.updatedAt), 'MMM D, YYYY')} {(collection.items || []).length} {this.renderActions()} ); } } CollectionListRowBase.propTypes = { collection: PropTypes.shape({ id: PropTypes.string.isRequired, name: PropTypes.string.isRequired, owner: PropTypes.shape({ username: PropTypes.string.isRequired, }).isRequired, createdAt: PropTypes.string.isRequired, updatedAt: PropTypes.string.isRequired, items: PropTypes.arrayOf(PropTypes.shape({ project: PropTypes.shape({ id: PropTypes.string.isRequired }) })) }).isRequired, username: PropTypes.string.isRequired, user: PropTypes.shape({ username: PropTypes.string, authenticated: PropTypes.bool.isRequired }).isRequired, deleteCollection: PropTypes.func.isRequired, editCollection: PropTypes.func.isRequired, onAddSketches: PropTypes.func.isRequired, }; function mapDispatchToPropsSketchListRow(dispatch) { return bindActionCreators(Object.assign({}, CollectionsActions, ProjectActions, IdeActions, ToastActions), dispatch); } export default connect(null, mapDispatchToPropsSketchListRow)(CollectionListRowBase);