import React, { Fragment } from 'react'; import PropTypes from 'prop-types'; import MD5 from 'MD5'; import { UncontrolledTooltip } from 'reactstrap'; import { gettext, siteRoot, mediaUrl } from '../../utils/constants'; import { Utils } from '../../utils/utils'; const propTypes = { path: PropTypes.string.isRequired, repoID: PropTypes.string.isRequired, dirent: PropTypes.object.isRequired, onItemClick: PropTypes.func.isRequired, showImagePopup: PropTypes.func.isRequired, onGridItemContextMenu: PropTypes.func.isRequired, onGridItemClick: PropTypes.func.isRequired, activeDirent: PropTypes.object, onGridItemMouseDown: PropTypes.func, currentRepoInfo: PropTypes.object, onItemMove: PropTypes.func.isRequired, }; class DirentGridItem extends React.Component { constructor(props) { super(props); this.state = { isGridDropTipShow: false, }; const { dirent } = this.props; const { isCustomPermission, customPermission } = Utils.getUserPermission(dirent.permission); this.isCustomPermission = isCustomPermission; this.customPermission = customPermission; this.canPreview = true; this.canDrag = dirent.permission === 'rw'; if (isCustomPermission) { const { preview, modify } = customPermission.permission; this.canPreview = preview || modify; this.canDrag = modify; } this.clickTimeout = null; } componentWillUnmount() { if (this.clickTimeout) { clearTimeout(this.clickTimeout); } } onItemMove = (destRepo, dirent, selectedPath, currentPath) => { this.props.onItemMove(destRepo, dirent, selectedPath, currentPath); }; onItemClick = (e) => { e.preventDefault(); e.stopPropagation(); const { dirent } = this.props; if (this.clickTimeout) { clearTimeout(this.clickTimeout); this.clickTimeout = null; this.handleSingleClick(dirent, e); return; } this.clickTimeout = setTimeout(() => { this.clickTimeout = null; this.handleSingleClick(dirent, e); }, 100); // Clicks within 100 milliseconds is considered a single click. }; handleSingleClick = (dirent, event) => { if (!this.canPreview) { return; } if (dirent.isSelected && !event.metaKey && !event.ctrlKey) { this.handleDoubleClick(dirent, event); } else { this.props.onGridItemClick(dirent, event); } }; handleDoubleClick = (dirent, event) => { if (Utils.imageCheck(dirent.name)) { this.props.showImagePopup(dirent); this.props.onGridItemClick(null, event); } else { this.props.onItemClick(dirent); } }; onItemLinkClick = (e) => { e.preventDefault(); const dirent = this.props.dirent; if (dirent.isDir()) { this.props.onItemClick(dirent); return; } // is have preview permission if (!this.canPreview) { return; } this.handleDoubleClick(dirent, e); }; onGridItemDragStart = (e) => { if (Utils.isIEBrower() || !this.canDrag) { return false; } let dragStartItemData = { nodeDirent: this.props.dirent, nodeParentPath: this.props.path }; dragStartItemData = JSON.stringify(dragStartItemData); e.dataTransfer.effectAllowed = 'move'; e.dataTransfer.setData('application/drag-item-info', dragStartItemData); }; onGridItemDragEnter = (e) => { if (Utils.isIEBrower() || !this.canDrag) { return false; } if (this.props.dirent.type === 'dir') { this.setState({ isGridDropTipShow: true }); } }; onGridItemDragOver = (e) => { if (Utils.isIEBrower() || !this.canDrag) { return false; } e.preventDefault(); e.dataTransfer.dropEffect = 'move'; }; onGridItemDragLeave = (e) => { if (Utils.isIEBrower() || !this.canDrag) { return false; } this.setState({ isGridDropTipShow: false }); }; onGridItemDragDrop = (e) => { if (Utils.isIEBrower() || !this.canDrag) { return false; } this.setState({ isGridDropTipShow: false }); if (e.dataTransfer.files.length) { // uploaded files return; } let dragStartItemData = e.dataTransfer.getData('application/drag-item-info'); dragStartItemData = JSON.parse(dragStartItemData); let { nodeDirent, nodeParentPath } = dragStartItemData; let dropItemData = this.props.dirent; if (nodeDirent.name === dropItemData.name) { return; } if (dropItemData.type !== 'dir') { return; } let selectedPath = Utils.joinPath(this.props.path, this.props.dirent.name); this.onItemMove(this.props.currentRepoInfo, nodeDirent, selectedPath, nodeParentPath); }; onGridItemMouseDown = (event) => { this.props.onGridItemMouseDown(event); }; getFileUrl = (url) => { let fileUrlArr = url.split('/'); if (fileUrlArr.indexOf('48') !== -1) { fileUrlArr.splice(fileUrlArr.indexOf('48'), 1, '192'); } let fileUrl = fileUrlArr.join('/'); return fileUrl; }; onGridItemContextMenu = (event) => { let dirent = this.props.dirent; this.props.onGridItemContextMenu(event, dirent); }; getTextRenderWidth = (text, font) => { const canvas = document.createElement('canvas'); const context = canvas.getContext('2d'); context.font = font || '14px Arial'; const metrics = context.measureText(text); return metrics.width; }; getRenderedText = (dirent) => { const containerWidth = 230; let tagRenderWidth = 0; if (dirent.file_tags && dirent.file_tags.length > 0) { if (dirent.file_tags.length === 1) { tagRenderWidth = 16; } else { tagRenderWidth = 16 + (dirent.file_tags.length - 1) * 8; } } let remainWidth = containerWidth - tagRenderWidth; let nameRenderWidth = this.getTextRenderWidth(dirent.name); let showName = ''; if (nameRenderWidth > remainWidth) { let dotIndex = dirent.name.lastIndexOf('.'); let frontName = dirent.name.slice(0, dotIndex - 2); let backName = dirent.name.slice(dotIndex - 2); let sum = 0; for (let i = 0; i < frontName.length; i++) { // Use charCodeAt(i) > 127 to check Chinese and English. // English and symbols occupy 1 position, Chinese and others occupy 2 positions. frontName.charCodeAt(i) > 127 ? (sum = sum + 2) : (sum = sum + 1); // When sum position exceeds 20, back string will not be displayed. if (sum > 20) { frontName = frontName.slice(0, i) + '...'; break; } } showName = frontName + backName; } else { showName = dirent.name; } return showName; }; render() { let { dirent, path } = this.props; let direntPath = Utils.joinPath(path, dirent.name); let iconUrl = Utils.getDirentIcon(dirent, true); let fileUrl = dirent.encoded_thumbnail_src ? this.getFileUrl(dirent.encoded_thumbnail_src) : ''; let toolTipID = ''; let tagTitle = ''; if (dirent.file_tags && dirent.file_tags.length > 0) { toolTipID = MD5(dirent.name).slice(0, 7); tagTitle = dirent.file_tags.map(item => item.name).join(' '); } let dirHref = ''; if (this.props.currentRepoInfo) { dirHref = siteRoot + 'library/' + this.props.repoID + '/' + this.props.currentRepoInfo.repo_name + Utils.encodePath(direntPath); } let fileHref = siteRoot + 'lib/' + this.props.repoID + '/file' + Utils.encodePath(direntPath); if (dirent.is_sdoc_revision && dirent.revision_id) { fileHref = siteRoot + 'lib/' + this.props.repoID + '/revisions/' + dirent.revision_id + '/'; } let gridClass = 'grid-file-img-link cursor-pointer'; gridClass += this.state.isGridDropTipShow ? ' grid-drop-show' : ' '; let lockedInfo = dirent.is_freezed ? gettext('Frozen by {name}') : gettext('locked by {name}'); lockedInfo = lockedInfo.replace('{name}', dirent.lock_owner_name); const lockedImageUrl = `${mediaUrl}img/file-${dirent.is_freezed ? 'freezed' : 'locked'}-32.png`; const lockedMessage = dirent.is_freezed ? gettext('freezed') : gettext('locked'); const showName = this.getRenderedText(dirent); return (
  • {(this.canPreview && dirent.encoded_thumbnail_src) ? : } {dirent.is_locked && {lockedMessage}}
    {(dirent.type !== 'dir' && dirent.file_tags && dirent.file_tags.length > 0) && (
    {dirent.file_tags.map((fileTag, index) => { let length = dirent.file_tags.length; return ( ); })}
    {tagTitle}
    )} {(!dirent.isDir() && !this.canPreview) ? {showName} : {showName} }
  • ); } } DirentGridItem.propTypes = propTypes; export default DirentGridItem;