UNPKG

@zohodesk/dot

Version:

In this Library, we Provide Some Basic Components to Build Your Application

626 lines (590 loc) 20.5 kB
import React, { Component } from 'react'; import { AttachmentViewer_defaultProps } from "./props/defaultProps"; import { AttachmentViewer_propTypes } from "./props/propTypes"; import { Container, Box } from '@zohodesk/components/es/v1/Layout'; import { Icon } from '@zohodesk/icons'; import Avatar from '@zohodesk/components/es/v1/Avatar/Avatar'; import { ResponsiveReceiver } from '@zohodesk/components/es/Responsive/CustomResponsive'; import { getUniqueId } from '@zohodesk/components/es/Provider/IdProvider'; import AttachmentImage from "./AttachmentImage"; import Link from "../Link/Link"; import IconButton from "../IconButton/IconButton"; import FreezeLayer from "../FreezeLayer/FreezeLayer"; import { isAudioFile, getExtensionFromFileName } from "../../AttachmentViewer/Attachment"; import { checkFileSourcesValidation } from "../../AttachmentViewer/utils"; import audioThumbNail from "../../../images/audio_thumbnail.png"; import { shallowDiff } from "../../utils/General"; import style from "../../AttachmentViewer/AttachmentViewer.module.css"; export default class AttachmentViewer extends Component { constructor(props) { super(props); this.state = { isPViewListOpen: !!(this.props.previewObj && this.props.previewObj.previewData), selectedIndex: this.props.previewObj.selectedIndex, isZoomed: false, data: this.props.previewObj ? this.props.previewObj.previewData : [], dataList: this.getUpdateDataList({ index: this.props.previewObj.selectedIndex, data: this.props.previewObj ? this.props.previewObj.previewData : [], dataList: [] }), canOpenInNewTab: false, canZoom: false, isPreviewAttachmentValid: false }; this.togglePViewList = this.togglePViewList.bind(this); this.changeSelectedIndex = this.changeSelectedIndex.bind(this); this.closeAttachmentViewer = this.closeAttachmentViewer.bind(this); this.responsiveFunc = this.responsiveFunc.bind(this); this.zoomIn = this.zoomIn.bind(this); this.zoomOut = this.zoomOut.bind(this); this.imgPreviewView = this.imgPreviewView.bind(this); this.getNextId = getUniqueId(this); this.getUpdateDataList = this.getUpdateDataList.bind(this); this.zoomMaintain = this.zoomMaintain.bind(this); this.handleMenuValidation = this.handleMenuValidation.bind(this); } componentDidMount() { this.handleMenuValidation(); } componentDidUpdate(prevProps, prevState) { let { previewObj } = this.props; const { selectedIndex } = this.state; let indexChanged = previewObj.selectedIndex != prevProps.previewObj.selectedIndex; if (previewObj.previewData.length != prevProps.previewObj.previewData.length || indexChanged) { let objChanged = previewObj.previewData.some((value, index) => { return shallowDiff(value, prevProps.previewObj[index]); }); if (objChanged || indexChanged) { this.setState({ selectedIndex: previewObj.selectedIndex, data: previewObj ? previewObj.previewData : [], dataList: this.getUpdateDataList({ index: previewObj.selectedIndex, data: previewObj ? previewObj.previewData : [], dataList: [] }), isPViewListOpen: !!(this.props.previewObj && this.props.previewObj.previewData) }); } } if (prevState.selectedIndex != selectedIndex) { this.handleMenuValidation(); } } handleMenuValidation() { const { data, selectedIndex } = this.state; const selectedAttachment = data[selectedIndex] || {}; const selectedAttachmentViewUrl = selectedAttachment.viewUrl; const selectedAttachmentDownloadUrl = selectedAttachment.downloadUrl; const selectedAttachmentName = selectedAttachment.name; checkFileSourcesValidation({ fileName: selectedAttachmentName, viewURL: selectedAttachmentViewUrl }).then(fileSourceValidation => { const { isViewURLValid, canZoom } = fileSourceValidation; this.setState({ isPreviewAttachmentValid: isViewURLValid, canZoom, canOpenInNewTab: isViewURLValid }); }); } togglePViewList() { this.setState(prevState => ({ isPViewListOpen: !prevState.isPViewListOpen }), () => { this.focusSelectedImg(this.state.selectedIndex); }); } zoomOut(ele) { this.setState({ isZoomed: false }); // const img = document.getElementById(`img${ele}`); // if (img) { // img.classList.remove(style.zoomedImg); // img.classList.add(style.normalImg); // } } zoomIn(event, ele) { let moveToPosition = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; this.setState({ isZoomed: true }); const img = document.getElementById(`img${ele}`); const ratio = 95; let imgContainer, imgUnits, imgSize, imgRatio, imgContainerUnits, imgContainerPosition; if (moveToPosition) { imgContainer = document.getElementById(`imgBox${ele}`); imgUnits = img.getBoundingClientRect(); imgSize = { height: img.naturalHeight, width: img.naturalWidth }; imgRatio = { height: Math.floor(imgSize.height / imgUnits.height / 100 * ratio), width: Math.floor(imgSize.width / imgUnits.width / 100 * ratio) }; imgContainerUnits = imgContainer.getBoundingClientRect(); imgContainerPosition = imgContainer ? { top: imgContainerUnits.top, left: imgContainerUnits.left } : { top: 0, left: 0 }; } // if (img) { // img.classList.remove(style.normalImg); // img.classList.add(style.zoomedImg); // } if (moveToPosition) { imgContainer.scrollLeft = (event.pageX - imgContainerPosition.left - imgUnits.left) * imgRatio.width; imgContainer.scrollTop = (event.pageY - imgContainerPosition.top - imgUnits.top) * imgRatio.height; } } zoomMaintain(selectedIndex) { let { isZoomed } = this.state; isZoomed ? this.zoomIn({}, selectedIndex) : this.zoomOut(selectedIndex); } getUpdateDataList(_ref) { let { index, data, dataList } = _ref; data = data || this.state.data; dataList = dataList || this.state.dataList; const finalDataList = [...dataList]; if (index >= finalDataList.length) { for (let i = dataList.length; i <= index; i++) { finalDataList.push(data.slice(i)[0]); } } else if (index + 1 === finalDataList.length && index + 1 < data.length) { finalDataList.push(data.slice(index + 1)[0]); } return finalDataList; } updateDataList(index) { this.setState({ dataList: this.getUpdateDataList({ index }) }); } changeSelectedIndex(index) { const { data, selectedIndex } = this.state; const { maintainZoom } = this.props; maintainZoom ? this.zoomMaintain(index) : this.zoomOut(selectedIndex); if (index <= data.length - 1) { this.updateDataList(index); } this.setState({ selectedIndex: index }, () => { this.focusSelectedImg(index); }); } focusSelectedImg(index) { const ele = this[`img_${index}`]; if (ele) { const cont = this.imgListCont; cont.scrollLeft = ele.offsetLeft; } } closeAttachmentViewer() { this.setState({ isPViewListOpen: false, isZoomed: false }); this.props.hideAttachmentViewer(); } responsiveFunc(_ref2) { let { mediaQueryOR } = _ref2; return { uptoTablet: mediaQueryOR([{ maxWidth: 768 }]) }; } imgPreviewView() { var _this = this; const { dataList, selectedIndex, isZoomed, canZoom, isPreviewAttachmentValid } = this.state; const { maintainZoom, dataId } = this.props; const getImgStyle = i => { let position; if (selectedIndex < i) { position = (i - selectedIndex) * 100; return { transform: `translateX(${parseInt(position)}%)`, opacity: '0' }; } if (i === selectedIndex) { return { transform: 'translateX(0%)', opacity: '1' }; } position = (selectedIndex - i) * 100 * -1; return { transform: `translateX(${parseInt(position)}%)`, opacity: '0' }; }; return dataList.length && dataList.map(function () { let data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; let i = arguments.length > 1 ? arguments[1] : undefined; const { viewUrl, name, children, dataId = 'attachViewer', customClass = {}, customProps = {} } = data; const { audioProps = {}, imageProps = {} } = customProps; const { customImageClass = '', customChildrenClass = '' } = customClass; const retainZoom = canZoom && selectedIndex == i && maintainZoom; return /*#__PURE__*/React.createElement(Container, { className: style.imgBox, id: `imgBox${i}`, key: i, alignBox: "row", align: "both", style: getImgStyle(i) }, /*#__PURE__*/React.createElement(Box, { className: style.imgRef, id: `imgPreviewRef${i}` }, isAudioFile(name) ? selectedIndex == i ? /*#__PURE__*/React.createElement("video", { autoPlay: true, controls: true, className: style.zoomIn, "data-id": `${dataId}_videoPreview`, "data-test-id": `${dataId}_videoPreview`, ...audioProps }, /*#__PURE__*/React.createElement("source", { src: viewUrl, type: `audio/${getExtensionFromFileName(name)}` })) : null : /*#__PURE__*/React.createElement(AttachmentImage, { customClass: { customImageClass: `${style.img} ${style.altText} ${canZoom || retainZoom ? isZoomed ? `${style.zoomedImg} ${style.zoomOutCursor}` : `${style.normalImg} ${style.zoomInCursor}` : ''} ${customImageClass}`, customChildrenClass }, src: viewUrl, onClick: isPreviewAttachmentValid ? isZoomed ? _this.zoomOut.bind(_this, i) : e => { _this.zoomIn(e, i, true); } : undefined, alt: name, dataId: dataId, id: `img${i}`, isCover: false, ...imageProps }, children))); }); } render() { const { isPViewListOpen, selectedIndex, data, isZoomed, canZoom, canOpenInNewTab } = this.state; const { responsiveId, needDownload, i18nKeys, isActive, dataId } = this.props; const totalLen = data.length; const selectedAttachment = data[selectedIndex] || {}; const selectedImgUrl = selectedAttachment.viewUrl; const downloadUrl = selectedAttachment.downloadUrl; let authorHref; let authorName; const { author } = data[selectedIndex] ? data[selectedIndex] : {}; if (author) { authorHref = author.href; authorName = author.name; } const ariaId = this.getNextId(); return /*#__PURE__*/React.createElement(FreezeLayer, { isActive: isActive && totalLen >= 1, palette: "dark", animationName: "expand" }, /*#__PURE__*/React.createElement(ResponsiveReceiver, { responsiveId: responsiveId, query: this.responsiveFunc }, _ref3 => { let { uptoTablet } = _ref3; return /*#__PURE__*/React.createElement(Container, { scroll: "none", "data-scroll-palette": "dark" }, /*#__PURE__*/React.createElement(Box, null, /*#__PURE__*/React.createElement(Container, { alignBox: "row", className: style.header, align: "between", tabindex: "0" }, /*#__PURE__*/React.createElement(Box, { shrink: true, className: style.title, "data-title": selectedAttachment.name, dataId: "attachName", id: ariaId }, selectedAttachment.name), /*#__PURE__*/React.createElement(Box, { flexible: true, className: style.count, dataId: "attachCountContainer" }, selectedIndex + 1, "/", totalLen), /*#__PURE__*/React.createElement(Box, { className: uptoTablet ? style.mbleMenuBar : style.menuBar }, /*#__PURE__*/React.createElement(Container, { isInline: true, alignBox: uptoTablet ? 'column-reverse' : 'row', align: uptoTablet ? 'bottom' : 'center', wrap: "wrap", isCover: false }, canZoom ? isZoomed ? /*#__PURE__*/React.createElement("div", { className: uptoTablet ? style.mobileMenu : style.menu, onClick: this.zoomOut.bind(this, selectedIndex), "data-id": "zoomOut", "data-test-id": "zoomOut", "data-title": i18nKeys.zoomOutText }, /*#__PURE__*/React.createElement(IconButton, { iconName: "ZD-GN-zoomOut", className: style.menuIcon, iconSize: "16", hoverType: "border", a11y: { ariaLabel: i18nKeys.zoomOutText } })) : /*#__PURE__*/React.createElement("div", { className: uptoTablet ? style.mobileMenu : style.menu, onClick: e => this.zoomIn(e, selectedIndex), "data-id": "zoomIn", "data-test-id": "zoomIn", "data-title": i18nKeys.zoomInText }, /*#__PURE__*/React.createElement(IconButton, { iconName: "ZD-GN-zoomIn", className: style.menuIcon, iconSize: "16", hoverType: "border", a11y: { ariaLabel: i18nKeys.zoomInText } })) : null, canOpenInNewTab ? /*#__PURE__*/React.createElement("div", { className: uptoTablet ? style.mobileMenu : style.menu }, /*#__PURE__*/React.createElement(Link, { href: selectedImgUrl, target: "_blank", dataId: "newTabAttach", title: i18nKeys.newTabText }, /*#__PURE__*/React.createElement(IconButton, { iconName: "ZD-GN-newLink", className: style.menuIcon, iconSize: "16", hoverType: "border", needButtonTag: false, a11y: { ariaLabel: i18nKeys.newTabText } }))) : null, needDownload ? /*#__PURE__*/React.createElement("div", { className: uptoTablet ? style.mobileMenu : style.menu }, /*#__PURE__*/React.createElement(Link, { href: downloadUrl, target: "_parent", hasReload: true, download: true, title: i18nKeys.downloadText, dataId: `${dataId}_downloadAttach` }, /*#__PURE__*/React.createElement(IconButton, { iconName: "ZD-GN-download", className: style.menuIcon, iconSize: "16", hoverType: "border", needButtonTag: false, a11y: { ariaLabel: i18nKeys.downloadText } }))) : null, /*#__PURE__*/React.createElement("div", { className: uptoTablet ? style.mobileMenu : style.menu, onClick: this.closeAttachmentViewer, "data-id": "closeAttach", "data-test-id": "closeAttach", "data-title": i18nKeys.closeText }, /*#__PURE__*/React.createElement(IconButton, { iconName: "ZD-cross", iconSize: "15", hoverType: "border", className: style.menuIcon, a11y: { ariaLabel: i18nKeys.closeText }, title: i18nKeys.closeText })))))), /*#__PURE__*/React.createElement(Box, { flexible: true, role: "toolbar", tabindex: "0" }, /*#__PURE__*/React.createElement(Container, { alignBox: "row" }, /*#__PURE__*/React.createElement(Box, { className: `${style.arrowBox} ${uptoTablet ? style.mbleArrowBox : style.nrmlArrowBox} ${selectedIndex === 0 ? style.hidden : ''}`, onClick: this.changeSelectedIndex.bind(this, selectedIndex - 1), "data-title": i18nKeys.previousText, "data-title-position": "left" }, /*#__PURE__*/React.createElement("button", { className: style.btn, "aria-label": i18nKeys.previousText }, /*#__PURE__*/React.createElement(Icon, { name: "ZD-arrowLeft3", iconClass: style.arrow, dataId: "leftAttachNav", isBold: true }))), /*#__PURE__*/React.createElement(Box, { className: style.previewBox, tabindex: "0", "aria-describedby": ariaId, isShrink: false, eleRef: this.setImgBoxRef, scroll: "both", flexible: true }, this.imgPreviewView()), /*#__PURE__*/React.createElement(Box, { className: `${style.arrowBox} ${uptoTablet ? style.mbleArrowBox : style.nrmlArrowBox} ${totalLen === selectedIndex + 1 ? style.hidden : ''}`, onClick: this.changeSelectedIndex.bind(this, selectedIndex + 1), "data-title": i18nKeys.nextText, "data-title-position": "right" }, /*#__PURE__*/React.createElement("button", { className: style.btn, "aria-label": i18nKeys.nextText }, /*#__PURE__*/React.createElement(Icon, { name: "ZD-arrowRight3", iconClass: style.arrow, dataId: "rightAttachNav", isBold: true }))))), /*#__PURE__*/React.createElement(Box, { className: `${style.footer} ${isPViewListOpen && totalLen !== 1 ? style.footerHeight : style.footerHide} `, dataId: `${dataId}_attachPreviewFooter` }, /*#__PURE__*/React.createElement(Container, { align: "vertical", alignBox: "row", className: style.footerHeight }, author && /*#__PURE__*/React.createElement(Box, { className: style.author, dataId: `${dataId}_authorName` }, /*#__PURE__*/React.createElement(Container, { alignBox: "row", align: "both" }, /*#__PURE__*/React.createElement(Avatar, { name: authorName, size: "xmedium", src: authorHref, palette: "info" }), /*#__PURE__*/React.createElement(Box, { flexible: true, className: style.authorName, "data-title": authorName }, authorName))), /*#__PURE__*/React.createElement(Box, { flexible: true }, /*#__PURE__*/React.createElement(Container, { align: "vertical", alignBox: "row", scroll: "horizontal", eleRef: el => this.imgListCont = el, className: style.listContainer }, data.map((item, index) => { const { name, viewUrl, children, customClass = {}, dataId = 'AttachmentImage', customProps = {} } = item; let { thumbnail } = item; const { customImageClass = '', customChildrenClass = '' } = customClass; thumbnail = isAudioFile(name) ? thumbnail || audioThumbNail : thumbnail; //fallback thumbnail for audio return /*#__PURE__*/React.createElement(Box, { className: `${style.imgItem} ${index === selectedIndex ? style.selected : ''}`, key: index, onClick: this.changeSelectedIndex.bind(this, index), eleRef: el => this[`img_${index}`] = el, dataId: "attachPreviewList", "data-title": name }, /*#__PURE__*/React.createElement(AttachmentImage, { src: thumbnail || viewUrl, size: "small", alt: name, customClass: { customImageClass: `${style.image} ${style.altText} ${customImageClass}`, customChildrenClass: `${style.crsrPointer} ${customChildrenClass}` }, dataId: dataId, ...customProps }, children)); }))))), totalLen !== 1 && /*#__PURE__*/React.createElement(IconButton, { dataId: "attachToggle", onClick: this.togglePViewList, iconName: "ZD-GN-hideTab", iconSize: "14", hoverType: "border", iconClass: `${style.thumpIcon} ${isPViewListOpen ? style.thumpIconActive : ''}`, className: style.button, a11y: { ariaLabel: i18nKeys.hideText }, title: isPViewListOpen ? i18nKeys.hideText : i18nKeys.showText })); })); } } AttachmentViewer.propTypes = AttachmentViewer_propTypes; AttachmentViewer.defaultProps = AttachmentViewer_defaultProps; // if (__DOCS__) { // AttachmentViewer.docs = { // componentGroup: "Molecule" // }; // }