import React from 'react'; import PropTypes from 'prop-types'; import Carousel, { Modal, ModalGateway } from 'react-images'; import RefsContext from '../util/RefsContext'; /** * 1. when 'fileFormat' is image, render Attachment as an image * 2. when 'fileFormat' is not image, render Attachment as an Attachment component */ export default class ExtractedAttachments extends React.PureComponent { constructor(props) { super(props); this.state = { showCarousel: false, currentIndex: null, }; } imageClickedHandler(index) { this.setState({ showCarousel: true, currentIndex: index, }); } getAttachmentsFilteredByFormat() { return this.props.attachments .filter(attachment => attachment.fileFormat.startsWith('image/')); } getClassesAndStylesForNonGrid() { const { refsContext } = this.props; const { options } = refsContext; const { width, height, 'max-width': maxWidth, 'max-height': maxHeight, display = 'block', } = options; const containerStyles = { width, height, maxWidth, maxHeight, display, }; const imageClasses = []; const imageStyles = { width, height, maxWidth, maxHeight, }; return { containerStyles, imageClasses, imageStyles, }; } getClassesAndStylesForGrid() { const { refsContext } = this.props; const { options } = refsContext; const { 'max-width': maxWidth, 'max-height': maxHeight, } = options; const containerStyles = { width: refsContext.getOptGridWidth(), height: refsContext.getOptGridHeight(), maxWidth, maxHeight, }; const imageClasses = ['w-100', 'h-100']; const imageStyles = { objectFit: 'cover', maxWidth, maxHeight, }; return { containerStyles, imageClasses, imageStyles, }; } /** * wrapper method for getClassesAndStylesForGrid/getClassesAndStylesForNonGrid */ getClassesAndStyles() { const { refsContext } = this.props; const { options } = refsContext; return (options.grid != null) ? this.getClassesAndStylesForGrid() : this.getClassesAndStylesForNonGrid(); } renderExtractedImage(attachment, index) { const { refsContext } = this.props; const { options } = refsContext; // determine alt let alt = refsContext.isSingle ? options.alt : undefined; // use only when single mode alt = alt || attachment.originalName; // use 'originalName' if options.alt is not specified // get styles const { containerStyles, imageClasses, imageStyles, } = this.getClassesAndStyles(); // carousel settings let onClick; if (options['no-carousel'] == null) { // pointer cursor Object.assign(containerStyles, { cursor: 'pointer' }); // set click handler onClick = () => { this.imageClickedHandler(index); }; } return (
{alt}
); } renderCarousel() { const { options } = this.props.refsContext; const withCarousel = options['no-carousel'] == null; const { showCarousel, currentIndex } = this.state; const images = this.getAttachmentsFilteredByFormat() .map((attachment) => { return { src: attachment.filePathProxied }; }); // overwrite react-images modal styles const zIndex = 1030; // > grw-navbar const modalStyles = { blanket: (styleObj) => { return Object.assign(styleObj, { zIndex }); }, positioner: (styleObj) => { return Object.assign(styleObj, { zIndex }); }, }; return ( { withCarousel && showCarousel && ( { this.setState({ showCarousel: false }) }}> ) } ); } render() { const { refsContext } = this.props; const { options } = refsContext; const { grid, 'grid-gap': gridGap, } = options; const styles = {}; // Grid mode if (grid != null) { const gridTemplateColumns = (refsContext.isOptGridColumnEnabled()) ? `repeat(${refsContext.getOptGridColumnsNum()}, 1fr)` : `repeat(auto-fill, ${refsContext.getOptGridWidth()})`; Object.assign(styles, { display: 'grid', gridTemplateColumns, gridAutoRows: '1fr', gridGap, }); } const contents = this.getAttachmentsFilteredByFormat() .map((attachment, index) => this.renderExtractedImage(attachment, index)); return (
{contents}
{ this.renderCarousel() }
); } } ExtractedAttachments.propTypes = { attachments: PropTypes.arrayOf(PropTypes.object).isRequired, refsContext: PropTypes.instanceOf(RefsContext).isRequired, };