Add sketch to collection from collection view
This commit is contained in:
parent
709aa8eccb
commit
b980ec7854
5 changed files with 172 additions and 91 deletions
24
client/components/AddRemoveButton.jsx
Normal file
24
client/components/AddRemoveButton.jsx
Normal file
|
@ -0,0 +1,24 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import InlineSVG from 'react-inlinesvg';
|
||||
|
||||
const addIcon = require('../images/plus.svg');
|
||||
const removeIcon = require('../images/minus.svg');
|
||||
|
||||
const AddRemoveButton = ({ type, onClick }) => {
|
||||
const alt = type === 'add' ? 'add to collection' : 'remove from collection';
|
||||
const icon = type === 'add' ? addIcon : removeIcon;
|
||||
|
||||
return (
|
||||
<button className="overlay__close-button" onClick={onClick}>
|
||||
<InlineSVG src={icon} alt={alt} />
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
AddRemoveButton.propTypes = {
|
||||
type: PropTypes.oneOf(['add', 'remove']).isRequired,
|
||||
onClick: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default AddRemoveButton;
|
|
@ -9,26 +9,9 @@ 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 AddRemoveButton from '../../../../components/AddRemoveButton';
|
||||
|
||||
const downFilledTriangle = require('../../../../images/down-filled-triangle.svg');
|
||||
const addIcon = require('../../../../images/plus.svg');
|
||||
const removeIcon = require('../../../../images/minus.svg');
|
||||
|
||||
const AddRemoveButton = ({ type, onClick }) => {
|
||||
const alt = type === 'add' ? 'add to collection' : 'remove from collection';
|
||||
const icon = type === 'add' ? addIcon : removeIcon;
|
||||
|
||||
return (
|
||||
<button className="overlay__close-button" onClick={onClick}>
|
||||
<InlineSVG src={icon} alt={alt} />
|
||||
</button>
|
||||
);
|
||||
};
|
||||
|
||||
AddRemoveButton.propTypes = {
|
||||
type: PropTypes.oneOf(['add', 'remove']).isRequired,
|
||||
onClick: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class CollectionListRowBase extends React.Component {
|
||||
static projectInCollection(project, collection) {
|
||||
|
|
|
@ -9,11 +9,13 @@ import { bindActionCreators } from 'redux';
|
|||
import classNames from 'classnames';
|
||||
import * as ProjectActions from '../actions/project';
|
||||
import * as ProjectsActions from '../actions/projects';
|
||||
import * as CollectionsActions from '../actions/collections';
|
||||
import * as ToastActions from '../actions/toast';
|
||||
import * as SortingActions from '../actions/sorting';
|
||||
import * as IdeActions from '../actions/ide';
|
||||
import getSortedSketches from '../selectors/projects';
|
||||
import Loader from '../../App/components/loader';
|
||||
import AddRemoveButton from '../../../components/AddRemoveButton';
|
||||
|
||||
const arrowUp = require('../../../images/sort-arrow-up.svg');
|
||||
const arrowDown = require('../../../images/sort-arrow-down.svg');
|
||||
|
@ -133,32 +135,11 @@ class SketchListRowBase extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { sketch, username } = this.props;
|
||||
const { renameOpen, optionsOpen, renameValue } = this.state;
|
||||
renderDropdown = () => {
|
||||
const { optionsOpen } = this.state;
|
||||
const userIsOwner = this.props.user.username === this.props.username;
|
||||
|
||||
return (
|
||||
<tr
|
||||
className="sketches-table__row"
|
||||
key={sketch.id}
|
||||
>
|
||||
<th scope="row">
|
||||
<Link to={`/${username}/sketches/${sketch.id}`}>
|
||||
{renameOpen ? '' : sketch.name}
|
||||
</Link>
|
||||
{renameOpen
|
||||
&&
|
||||
<input
|
||||
value={renameValue}
|
||||
onChange={this.handleRenameChange}
|
||||
onKeyUp={this.handleRenameEnter}
|
||||
onBlur={this.resetSketchName}
|
||||
onClick={e => e.stopPropagation()}
|
||||
/>
|
||||
}
|
||||
</th>
|
||||
<td>{format(new Date(sketch.createdAt), 'MMM D, YYYY h:mm A')}</td>
|
||||
<td>{format(new Date(sketch.updatedAt), 'MMM D, YYYY h:mm A')}</td>
|
||||
<td className="sketch-list__dropdown-column">
|
||||
<button
|
||||
className="sketch-list__dropdown-button"
|
||||
|
@ -227,6 +208,50 @@ class SketchListRowBase extends React.Component {
|
|||
</li>}
|
||||
</ul>}
|
||||
</td>
|
||||
);
|
||||
}
|
||||
|
||||
renderAddRemoveButtons = () => {
|
||||
return (
|
||||
<td className="sketch-list__dropdown-column">{
|
||||
this.props.inCollection ?
|
||||
<AddRemoveButton type="remove" onClick={this.props.onCollectionRemove} /> :
|
||||
<AddRemoveButton type="add" onClick={this.props.onCollectionAdd} />
|
||||
}
|
||||
</td>
|
||||
);
|
||||
}
|
||||
|
||||
renderActions = () => {
|
||||
return this.props.addMode === true ? this.renderAddRemoveButtons() : this.renderDropdown();
|
||||
}
|
||||
|
||||
render() {
|
||||
const { sketch, username } = this.props;
|
||||
const { renameOpen, renameValue } = this.state;
|
||||
return (
|
||||
<tr
|
||||
className="sketches-table__row"
|
||||
key={sketch.id}
|
||||
>
|
||||
<th scope="row">
|
||||
<Link to={`/${username}/sketches/${sketch.id}`}>
|
||||
{renameOpen ? '' : sketch.name}
|
||||
</Link>
|
||||
{renameOpen
|
||||
&&
|
||||
<input
|
||||
value={renameValue}
|
||||
onChange={this.handleRenameChange}
|
||||
onKeyUp={this.handleRenameEnter}
|
||||
onBlur={this.resetSketchName}
|
||||
onClick={e => e.stopPropagation()}
|
||||
/>
|
||||
}
|
||||
</th>
|
||||
<td>{format(new Date(sketch.createdAt), 'MMM D, YYYY h:mm A')}</td>
|
||||
<td>{format(new Date(sketch.updatedAt), 'MMM D, YYYY h:mm A')}</td>
|
||||
{this.renderActions()}
|
||||
</tr>);
|
||||
}
|
||||
}
|
||||
|
@ -306,6 +331,14 @@ class SketchList extends React.Component {
|
|||
);
|
||||
}
|
||||
|
||||
handleCollectionAdd = (sketchId) => {
|
||||
this.props.addToCollection(this.props.collection.id, sketchId);
|
||||
}
|
||||
|
||||
handleCollectionRemove = (sketchId) => {
|
||||
this.props.removeFromCollection(this.props.collection.id, sketchId);
|
||||
}
|
||||
|
||||
render() {
|
||||
const username = this.props.username !== undefined ? this.props.username : this.props.user.username;
|
||||
return (
|
||||
|
@ -332,6 +365,10 @@ class SketchList extends React.Component {
|
|||
sketch={sketch}
|
||||
user={this.props.user}
|
||||
username={username}
|
||||
addMode={this.props.addMode}
|
||||
onCollectionAdd={() => this.handleCollectionAdd(sketch.id)}
|
||||
onCollectionRemove={() => this.handleCollectionRemove(sketch.id)}
|
||||
inCollection={this.props.collection && this.props.collection.items.find(item => item.project.id === sketch.id) != null}
|
||||
/>))}
|
||||
</tbody>
|
||||
</table>}
|
||||
|
@ -359,7 +396,8 @@ SketchList.propTypes = {
|
|||
sorting: PropTypes.shape({
|
||||
field: PropTypes.string.isRequired,
|
||||
direction: PropTypes.string.isRequired
|
||||
}).isRequired
|
||||
}).isRequired,
|
||||
addMode: PropTypes.bool,
|
||||
};
|
||||
|
||||
SketchList.defaultProps = {
|
||||
|
@ -376,7 +414,7 @@ function mapStateToProps(state) {
|
|||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return bindActionCreators(Object.assign({}, ProjectsActions, ToastActions, SortingActions), dispatch);
|
||||
return bindActionCreators(Object.assign({}, ProjectsActions, CollectionsActions, ToastActions, SortingActions), dispatch);
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(SketchList);
|
||||
|
|
|
@ -16,6 +16,8 @@ import * as IdeActions from '../../IDE/actions/ide';
|
|||
import { getCollection } from '../../IDE/selectors/collections';
|
||||
import Loader from '../../App/components/loader';
|
||||
import EditableInput from '../../IDE/components/EditableInput';
|
||||
import Overlay from '../../App/components/Overlay';
|
||||
import SketchList from '../../IDE/components/SketchList';
|
||||
|
||||
const arrowUp = require('../../../images/sort-arrow-up.svg');
|
||||
const arrowDown = require('../../../images/sort-arrow-down.svg');
|
||||
|
@ -232,6 +234,12 @@ class Collection extends React.Component {
|
|||
this.props.getCollections(this.props.username);
|
||||
this.props.resetSorting();
|
||||
this._renderFieldHeader = this._renderFieldHeader.bind(this);
|
||||
this.showAddSketches = this.showAddSketches.bind(this);
|
||||
this.hideAddSketches = this.hideAddSketches.bind(this);
|
||||
|
||||
this.state = {
|
||||
isAddingSketches: false,
|
||||
};
|
||||
}
|
||||
|
||||
getTitle() {
|
||||
|
@ -318,9 +326,21 @@ class Collection extends React.Component {
|
|||
);
|
||||
}
|
||||
|
||||
showAddSketches() {
|
||||
this.setState({
|
||||
isAddingSketches: true,
|
||||
});
|
||||
}
|
||||
|
||||
hideAddSketches() {
|
||||
this.setState({
|
||||
isAddingSketches: false,
|
||||
});
|
||||
}
|
||||
|
||||
_renderEmptyTable() {
|
||||
if (!this.hasCollectionItems()) {
|
||||
return (<p className="sketches-table__empty">No sketches in collection.</p>);
|
||||
return (<p className="sketches-table__empty">No sketches in collection. <button onClick={this.showAddSketches}>Add some sketches</button></p>);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -379,8 +399,19 @@ class Collection extends React.Component {
|
|||
/>))}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p><button onClick={this.showAddSketches}>Add more sketches</button></p>
|
||||
</div>
|
||||
}
|
||||
{
|
||||
this.state.isAddingSketches && (
|
||||
<Overlay title="Add sketches" closeOverlay={this.hideAddSketches}>
|
||||
<div className="collection-add-sketch">
|
||||
<SketchList username={this.props.username} addMode collection={this.props.collection} />
|
||||
</div>
|
||||
</Overlay>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
|
|
@ -43,3 +43,8 @@
|
|||
.collection-table-wrapper {
|
||||
margin: #{28 / $base-font-size}rem #{56 / $base-font-size}rem;
|
||||
}
|
||||
|
||||
.collection-add-sketch {
|
||||
padding: #{24 / $base-font-size}rem;
|
||||
overflow: scroll;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue