Add sketch to collection from collection view

This commit is contained in:
Andrew Nicolaou 2019-09-17 20:48:37 +02:00 committed by Cassie Tarakajian
parent 7f78fda073
commit 27804acd6a
5 changed files with 171 additions and 96 deletions

View 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;

View File

@ -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) {

View File

@ -10,11 +10,13 @@ import classNames from 'classnames';
import slugify from 'slugify';
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');
@ -134,10 +136,100 @@ class SketchListRowBase extends React.Component {
}
}
renderDropdown = () => {
const { optionsOpen } = this.state;
const userIsOwner = this.props.user.username === this.props.username;
return (
<td className="sketch-list__dropdown-column">
<button
className="sketch-list__dropdown-button"
onClick={this.toggleOptions}
onBlur={this.onBlurComponent}
onFocus={this.onFocusComponent}
>
<InlineSVG src={downFilledTriangle} alt="Menu" />
</button>
{optionsOpen &&
<ul
className="sketch-list__action-dialogue"
>
{userIsOwner &&
<li>
<button
className="sketch-list__action-option"
onClick={this.handleRenameOpen}
onBlur={this.onBlurComponent}
onFocus={this.onFocusComponent}
>
Rename
</button>
</li>}
<li>
<button
className="sketch-list__action-option"
onClick={this.handleSketchDownload}
onBlur={this.onBlurComponent}
onFocus={this.onFocusComponent}
>
Download
</button>
</li>
{this.props.user.authenticated &&
<li>
<button
className="sketch-list__action-option"
onClick={this.handleSketchDuplicate}
onBlur={this.onBlurComponent}
onFocus={this.onFocusComponent}
>
Duplicate
</button>
</li>}
{ /* <li>
<button
className="sketch-list__action-option"
onClick={this.handleSketchShare}
onBlur={this.onBlurComponent}
onFocus={this.onFocusComponent}
>
Share
</button>
</li> */ }
{userIsOwner &&
<li>
<button
className="sketch-list__action-option"
onClick={this.handleSketchDelete}
onBlur={this.onBlurComponent}
onFocus={this.onFocusComponent}
>
Delete
</button>
</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, optionsOpen, renameValue } = this.state;
const userIsOwner = this.props.user.username === this.props.username;
const { renameOpen, renameValue } = this.state;
let url = `/${username}/sketches/${sketch.id}`;
if (username === 'p5') {
url = `/${username}/sketches/${slugify(sketch.name, '_')}`;
@ -164,74 +256,7 @@ class SketchListRowBase extends React.Component {
</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"
onClick={this.toggleOptions}
onBlur={this.onBlurComponent}
onFocus={this.onFocusComponent}
>
<InlineSVG src={downFilledTriangle} alt="Menu" />
</button>
{optionsOpen &&
<ul
className="sketch-list__action-dialogue"
>
{userIsOwner &&
<li>
<button
className="sketch-list__action-option"
onClick={this.handleRenameOpen}
onBlur={this.onBlurComponent}
onFocus={this.onFocusComponent}
>
Rename
</button>
</li>}
<li>
<button
className="sketch-list__action-option"
onClick={this.handleSketchDownload}
onBlur={this.onBlurComponent}
onFocus={this.onFocusComponent}
>
Download
</button>
</li>
{this.props.user.authenticated &&
<li>
<button
className="sketch-list__action-option"
onClick={this.handleSketchDuplicate}
onBlur={this.onBlurComponent}
onFocus={this.onFocusComponent}
>
Duplicate
</button>
</li>}
{ /* <li>
<button
className="sketch-list__action-option"
onClick={this.handleSketchShare}
onBlur={this.onBlurComponent}
onFocus={this.onFocusComponent}
>
Share
</button>
</li> */ }
{userIsOwner &&
<li>
<button
className="sketch-list__action-option"
onClick={this.handleSketchDelete}
onBlur={this.onBlurComponent}
onFocus={this.onFocusComponent}
>
Delete
</button>
</li>}
</ul>}
</td>
{this.renderActions()}
</tr>);
}
}
@ -311,6 +336,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 (
@ -337,6 +370,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>}
@ -365,12 +402,7 @@ SketchList.propTypes = {
field: PropTypes.string.isRequired,
direction: PropTypes.string.isRequired
}).isRequired,
project: PropTypes.shape({
id: PropTypes.string,
owner: PropTypes.shape({
id: PropTypes.string
})
})
addMode: PropTypes.bool,
};
SketchList.defaultProps = {
@ -392,7 +424,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);

View File

@ -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>
);

View File

@ -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;
}