Home Reference Source

app/components/ImageGallery.jsx

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { GridList, GridTile } from 'material-ui/GridList';
import SvgAddImage from 'material-ui/svg-icons/image/add-a-photo';
import SvgDelete from 'material-ui/svg-icons/action/delete';
import { grey200 } from 'material-ui/styles/colors';
import FlatButton from 'material-ui/FlatButton';
import uuid from 'uuid';

// - Import actions
import * as imageGalleryActions from 'imageGalleryActions';
import * as globalActions from 'globalActions';

// - Import app components
import Img from 'Img';

// - Import API
import FileAPI from 'FileAPI';

export class ImageGallery extends Component {

    /**
     * Handle set image
     * @param  {event} evt  passed by on click event on add image
     * @param  {string} name is the name of the image
     */
    handleSetImage = (evt, URL, fullPath) => {
        this.props.set(URL, fullPath);
        this.close();
    }

    /**
     * Handle delete image
     * @param  {event} evt  passed by on click event on delete image
     * @param  {integer} id is the image identifier which selected to delete
     */
    handleDeleteImage = (evt, id) => {
        this.props.deleteImage(id);
    }

    componentDidMount() {
        window.addEventListener("onSendResizedImage", this.handleSendResizedImage);
    }

    componentWillUnmount() {
        window.removeEventListener("onSendResizedImage", this.handleSendResizedImage);
    }

    /**
     * Handle send image resize event that pass the resized image
     * 
     * @memberof ImageGallery
     */
    handleSendResizedImage = (event) => {
        const { resizedImage, fileName } = event.detail;

        FileAPI.uploadImage(resizedImage, fileName, (percent, status) => {
            this.props.progressChange(percent, status);
        }).then((result) => {
            /* Add image to image gallery */
            this.props.saveImageGallery(result.downloadURL, result.metadata.fullPath);
        });
    }

    // Handle on change file upload
    onFileChange = (evt) => {
        const extension = FileAPI.getExtension(evt.target.files[0].name);
        const fileName = (`${uuid()}.${extension}`);
        const image = FileAPI.constraintImage(evt.target.files[0], fileName);
    }

    // Hide image gallery
    close = () => {
        this.props.close();
    }

    imageList = () => {
        return this.props.images.map((image, index) => {
            return (<GridTile
                key={image.id}
                title={<SvgDelete hoverColor={grey200} color="white" color="white" style={{ marginLeft: "5px", cursor: "pointer" }} onClick={evt => this.handleDeleteImage(evt, image.id)} />}
                subtitle={<span></span>}
                actionIcon={<SvgAddImage hoverColor={grey200} color="white" style={{ marginRight: "5px", cursor: "pointer" }} onClick={evt => this.handleSetImage(evt, image.URL, image.fullPath)} />}
            >
                <div>
                    <div style={{ overflowY: "hidden", overflowX: "auto" }}>
                        <ul style={{ whiteSpace: "nowrap", padding: "0 6px", margin: "8px 0 0 0", verticalAlign: "bottom", flexShrink: 0, listStyleType: "none" }}>
                            <div style={{ display: "block" }}>
                                <div style={{ display: "block", marginRight: "8px", transition: "transform .25s" }}>
                                    <li style={{ width: "100%", margin: 0, verticalAlign: "bottom", position: "static", display: "inline-block" }}>
                                        <Img fileName={image.URL} style={{ width: "100%", height: "auto" }} />

                                    </li>
                                </div>
                            </div>

                        </ul>
                    </div>
                </div>
            </GridTile>)
        })
    }

    /**
     * When the post text changed
     * @param  {event} evt is an event passed by change post text callback funciton
     * @param  {string} data is the post content which user writes
     */
    render() {
        /**
         * Component styles
         * @type {Object}
         */
        const styles = {
            root: {
                display: 'flex',
                flexWrap: 'wrap',
                justifyContent: 'space-around'
            },
            gridList: {
                width: 500,
                height: 450,
                overflowY: 'auto'
            },
            uploadButton: {
                verticalAlign: 'middle'
            },
            uploadInput: {
                cursor: 'pointer',
                position: 'absolute',
                top: 0,
                bottom: 0,
                right: 0,
                left: 0,
                width: '100%',
                opacity: 0
            }
        };

        return (
            <div style={styles.root}>
                <GridList
                    cellHeight={180}
                    style={styles.gridList}
                >
                    <GridTile >
                        <div style={{ display: "flex", backgroundColor: "rgba(222, 222, 222, 0.52)", flexDirection: "column", justifyContent: "center", alignItems: "center", height: "100%" }}>
                            <FlatButton
                                label="Upload Photo"
                                labelStyle={{ fontWeight: 100 }}
                                labelPosition="before"
                                style={styles.uploadButton}
                                containerElement="label"
                            >
                                <input type="file" onChange={this.onFileChange} accept="image/*" style={styles.uploadInput} />
                            </FlatButton>
                        </div>
                    </GridTile>
                    {this.imageList()}
                </GridList>
            </div>
        )
    }
}


/**
 * Map dispatch to props
 * @param  {func} dispatch is the function to dispatch action to reducers
 * @param  {object} ownProps is the props belong to component
 * @return {object}          props of component
 */
const mapDispatchToProps = (dispatch, ownProps) => {
    return {
        saveImageGallery: (imageURL, imageFullPath) => dispatch(imageGalleryActions.dbSaveImage(imageURL, imageFullPath)),
        deleteImage: (id) => dispatch(imageGalleryActions.dbDeleteImage(id)),
        progressChange: (percent, status) => dispatch(globalActions.progressChange(percent, status))
    }
}


/**
 * Map state to props
 * @param  {object} state is the obeject from redux store
 * @param  {object} ownProps is the props belong to component
 * @return {object}          props of component
 */
const mapStateToProps = (state) => {
    return {
        images: state.imageGallery.images,
        avatar: state.user.info && state.user.info[state.authorize.uid] ? state.user.info[state.authorize.uid].avatar : ''

    }
}

// - Connect component to redux store
export default connect(mapStateToProps, mapDispatchToProps)(ImageGallery)