Add sketch to collection from collection view
This commit is contained in:
parent
7f78fda073
commit
27804acd6a
5 changed files with 171 additions and 96 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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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