@zohodesk/dot
Version:
In this Library, we Provide Some Basic Components to Build Your Application
626 lines (590 loc) • 20.5 kB
JavaScript
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"
// };
// }