diff --git a/src/components/AddImages/AddImages.js b/src/components/AddImages/AddImages.js index 65096843..c5cc445e 100644 --- a/src/components/AddImages/AddImages.js +++ b/src/components/AddImages/AddImages.js @@ -8,6 +8,7 @@ * */ import React, { PropTypes } from 'react'; +import { SortableContainer, SortableElement } from 'react-sortable-hoc'; import { Promised } from '../../components'; import css from './AddImages.css'; @@ -24,47 +25,54 @@ const readImage = file => new Promise((resolve, reject) => { reader.readAsDataURL(file); }); -const AddImages = props => { +// Create sortable elments out of given thumbnail file +const SortableImage = SortableElement(props => { + const { file, id, imageId } = props; + // While image is uploading we show overlay on top of thumbnail + const uploadingOverlay = !imageId ?
Uploading
: null; + return ( + { + return ( +
  • + {encodeURIComponent(file.name)} + {uploadingOverlay} +
  • + ); + }} + renderRejected={() =>
  • Could not read file
  • } + /> + ); +}); + +// Create container where there are sortable images and passed children like "Add image" input etc. +const SortableImages = SortableContainer(props => { const { children, images } = props; return ( -
    - {images.map(i => { - // While image is uploading we show overlay on top of thumbnail - const uploadingOverlay = !i.imageId - ?
    Uploading
    - : null; - return ( - { - return ( -
    - {encodeURIComponent(i.file.name)} - {uploadingOverlay} -
    - ); - }} - renderRejected={() =>
    Could not read file
    } - /> - ); - })} +
      + {images.map((image, index) => )} {children} -
    + ); +}); + +// Configure sortable container see. https://github.com/clauderic/react-sortable-hoc +// Items can be sorted horizontally, vertically or in a grid. +// axis="xy" means grid like sorting +const AddImages = props => { + return ; }; AddImages.defaultProps = { images: [] }; -const { array, node } = PropTypes; +const { array, func, node } = PropTypes; AddImages.propTypes = { images: array, children: node.isRequired, + onSortEnd: func.isRequired, }; export default AddImages; diff --git a/src/containers/EditListingForm/EditListingForm.js b/src/containers/EditListingForm/EditListingForm.js index 40047841..5dfef8a5 100644 --- a/src/containers/EditListingForm/EditListingForm.js +++ b/src/containers/EditListingForm/EditListingForm.js @@ -2,6 +2,7 @@ import React, { Component, PropTypes } from 'react'; import { Field, reduxForm, propTypes as formPropTypes } from 'redux-form'; import { intlShape, injectIntl } from 'react-intl'; import { isEqual } from 'lodash'; +import { arrayMove } from 'react-sortable-hoc'; import { noEmptyArray, maxLength, required } from '../../util/validators'; import { AddImages } from '../../components'; import css from './EditListingForm.css'; @@ -70,6 +71,7 @@ class EditListingForm extends Component { super(props); this.handleInitialize = this.handleInitialize.bind(this); this.onImageUploadHandler = this.onImageUploadHandler.bind(this); + this.onSortEnd = this.onSortEnd.bind(this); } componentDidMount() { @@ -89,6 +91,11 @@ class EditListingForm extends Component { } } + onSortEnd({ oldIndex, newIndex }) { + const images = arrayMove(this.props.images, oldIndex, newIndex); + this.props.onUpdateImageOrder(images.map(i => i.id)); + } + handleInitialize() { const { initData = {}, initialize } = this.props; initialize(initData); @@ -122,7 +129,7 @@ class EditListingForm extends Component { />

    Images

    - + ({ + type: UPDATE_IMAGE_ORDER, + payload: { imageOrder }, +}); + // All the action creators that don't have the {Success, Error} suffix // take the params object that the corresponding SDK endpoint method // expects. diff --git a/src/containers/EditListingPage/EditListingPage.js b/src/containers/EditListingPage/EditListingPage.js index 845bcc0e..5ce65cdd 100644 --- a/src/containers/EditListingPage/EditListingPage.js +++ b/src/containers/EditListingPage/EditListingPage.js @@ -10,6 +10,7 @@ import { requestCreateListing, requestShowListing, requestImageUpload, + updateImageOrder, } from './EditListingPage.duck'; const formatRequestData = values => { @@ -39,7 +40,16 @@ export class EditListingPageComponent extends Component { } render() { - const { data, intl, onCreateListing, onImageUpload, page, params, type } = this.props; + const { + data, + intl, + onCreateListing, + onImageUpload, + onUpdateImageOrder, + page, + params, + type, + } = this.props; const isNew = type === 'new'; const id = page.submittedListingId || (params && new types.UUID(params.id)); const listingsById = getListingsById(data, [id]); @@ -77,6 +87,7 @@ export class EditListingPageComponent extends Component { initData={initData} onImageUpload={onImageUpload} onSubmit={onSubmit(onCreateListing)} + onUpdateImageOrder={onUpdateImageOrder} saveActionMsg={saveActionMsg} /> @@ -103,9 +114,10 @@ const { func, object, shape, string } = PropTypes; EditListingPageComponent.propTypes = { data: object.isRequired, intl: intlShape.isRequired, - onImageUpload: func.isRequired, - onLoadListing: func.isRequired, onCreateListing: func.isRequired, + onLoadListing: func.isRequired, + onImageUpload: func.isRequired, + onUpdateImageOrder: func.isRequired, page: object.isRequired, params: shape({ id: string, @@ -124,6 +136,7 @@ const mapDispatchToProps = dispatch => { onLoadListing: id => dispatch(requestShowListing({ id, include: ['author', 'images'] })), onCreateListing: values => dispatch(requestCreateListing(formatRequestData(values))), onImageUpload: data => dispatch(requestImageUpload(data)), + onUpdateImageOrder: imageOrder => dispatch(updateImageOrder(imageOrder)), }; }; diff --git a/src/containers/EditListingPage/EditListingPage.test.js b/src/containers/EditListingPage/EditListingPage.test.js index ba72ed3d..cd6c2ff7 100644 --- a/src/containers/EditListingPage/EditListingPage.test.js +++ b/src/containers/EditListingPage/EditListingPage.test.js @@ -12,6 +12,7 @@ describe('EditListingPageComponent', () => { onCreateListing={v => v} onLoadListing={v => v} onImageUpload={v => v} + onUpdateImageOrder={v => v} page={{ imageOrder: [], images: {} }} type="new" />, diff --git a/src/containers/EditListingPage/__snapshots__/EditListingPage.test.js.snap b/src/containers/EditListingPage/__snapshots__/EditListingPage.test.js.snap index b04b050c..a302296e 100644 --- a/src/containers/EditListingPage/__snapshots__/EditListingPage.test.js.snap +++ b/src/containers/EditListingPage/__snapshots__/EditListingPage.test.js.snap @@ -6,6 +6,7 @@ exports[`EditListingPageComponent matches snapshot 1`] = ` initData={Object {}} onImageUpload={[Function]} onSubmit={[Function]} + onUpdateImageOrder={[Function]} saveActionMsg="Create listing" /> `;