mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-26 06:47:17 +10:00
106 lines
3.2 KiB
JavaScript
106 lines
3.2 KiB
JavaScript
/**
|
|
* Creates a sortable image grid with children added to the end of the created grid.
|
|
*
|
|
* Example:
|
|
* // images = [{ id: 'tempId', imageId: 'realIdFromAPI', file: File }];
|
|
* <AddImages images={images}>
|
|
* <input type="file" accept="images/*" onChange={handleChange} />
|
|
* </AddImages>
|
|
*/
|
|
import React, { Component, PropTypes } from 'react';
|
|
import { SortableContainer, SortableElement } from 'react-sortable-hoc';
|
|
import classNames from 'classnames';
|
|
import { Promised } from '../../components';
|
|
import { uuid } from '../../util/propTypes';
|
|
import css from './AddImages.css';
|
|
|
|
// readImage returns a promise which is resolved
|
|
// when FileReader has loaded given file as dataURL
|
|
const readImage = file =>
|
|
new Promise((resolve, reject) => {
|
|
const reader = new FileReader();
|
|
reader.onload = e => resolve(e.target.result);
|
|
reader.onerror = e => {
|
|
// eslint-disable-next-line
|
|
console.error('Error (', e, `) happened while reading ${file.name}: ${e.target.result}`);
|
|
reject(new Error(`Error reading ${file.name}: ${e.target.result}`));
|
|
};
|
|
reader.readAsDataURL(file);
|
|
});
|
|
|
|
// Create sortable elments out of given thumbnail file
|
|
class Thumbnail extends Component {
|
|
constructor(props) {
|
|
super(props);
|
|
this.state = {
|
|
promisedImage: readImage(this.props.file),
|
|
};
|
|
}
|
|
|
|
render() {
|
|
const { file, id, imageId } = this.props;
|
|
// While image is uploading we show overlay on top of thumbnail
|
|
const uploadingOverlay = !imageId
|
|
? <div className={css.thumbnailLoading}>Uploading</div>
|
|
: null;
|
|
return (
|
|
<Promised
|
|
key={id}
|
|
promise={this.state.promisedImage}
|
|
renderFulfilled={dataURL => {
|
|
return (
|
|
<li className={css.thumbnail}>
|
|
<div className={css.aspectRatioWrapper}>
|
|
<img src={dataURL} alt={file.name} className={css.thumbnailImage} />
|
|
</div>
|
|
{uploadingOverlay}
|
|
</li>
|
|
);
|
|
}}
|
|
renderRejected={() => <li className={css.thumbnail}>Could not read file</li>}
|
|
/>
|
|
);
|
|
}
|
|
}
|
|
|
|
Thumbnail.defaultProps = { imageId: null };
|
|
|
|
const { any, array, func, node, string } = PropTypes;
|
|
|
|
Thumbnail.propTypes = {
|
|
file: any.isRequired,
|
|
id: string.isRequired,
|
|
imageId: uuid,
|
|
};
|
|
|
|
const SortableImage = SortableElement(Thumbnail);
|
|
|
|
// Create container where there are sortable images and passed children like "Add image" input etc.
|
|
const SortableImages = SortableContainer(props => {
|
|
const { children, className, images } = props;
|
|
const classes = classNames(css.root, className);
|
|
return (
|
|
<ol className={classes}>
|
|
{images.map((image, index) => <SortableImage {...image} index={index} key={image.id} />)}
|
|
{children}
|
|
</ol>
|
|
);
|
|
});
|
|
|
|
// 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 <SortableImages axis="xy" {...props} />;
|
|
};
|
|
|
|
AddImages.defaultProps = { className: null, images: [] };
|
|
|
|
AddImages.propTypes = {
|
|
images: array,
|
|
children: node.isRequired,
|
|
className: string,
|
|
onSortEnd: func.isRequired,
|
|
};
|
|
|
|
export default AddImages;
|