1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-15 14:49:09 +00:00
Files
seahub/frontend/src/components/dirent-grid-view/dirent-grid-item.js

338 lines
11 KiB
JavaScript
Raw Normal View History

2019-04-18 22:36:07 +08:00
import React, { Fragment } from 'react';
import PropTypes from 'prop-types';
import MD5 from 'MD5';
import { UncontrolledTooltip } from 'reactstrap';
2019-04-18 22:36:07 +08:00
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,
2019-04-22 11:34:51 +08:00
onGridItemContextMenu: PropTypes.func.isRequired,
2019-04-21 20:41:14 +08:00
onGridItemClick: PropTypes.func.isRequired,
activeDirent: PropTypes.object,
onGridItemMouseDown: PropTypes.func,
currentRepoInfo: PropTypes.object,
onItemMove: PropTypes.func.isRequired,
onItemsMove: PropTypes.func.isRequired,
selectedDirentList: PropTypes.array.isRequired,
2019-04-18 22:36:07 +08:00
};
class DirentGridItem extends React.Component {
constructor(props) {
super(props);
this.state = {
2019-04-21 20:41:14 +08:00
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);
}
}
2019-04-18 22:36:07 +08:00
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);
} else {
this.props.onItemClick(dirent);
}
};
onItemLinkClick = (e) => {
e.preventDefault();
2019-04-18 22:36:07 +08:00
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);
};
2019-04-18 22:36:07 +08:00
2019-04-19 18:40:31 +08:00
onGridItemDragStart = (e) => {
if (Utils.isIEBrowser() || !this.canDrag) {
return false;
}
const { selectedDirentList, path } = this.props;
const dragStartItemsData = selectedDirentList.length > 0 ? selectedDirentList.map(dirent => ({
nodeDirent: dirent,
nodeParentPath: path
})) : { nodeDirent: this.props.dirent, nodeParentPath: this.props.path };
const serializedData = JSON.stringify(dragStartItemsData);
2019-04-19 18:40:31 +08:00
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setData('application/drag-item-info', serializedData);
};
2019-04-19 18:40:31 +08:00
onGridItemDragEnter = (e) => {
if (Utils.isIEBrowser() || !this.canDrag) {
return false;
}
2019-04-19 18:40:31 +08:00
if (this.props.dirent.type === 'dir') {
2024-07-18 11:58:42 +08:00
this.setState({ isGridDropTipShow: true });
2019-04-19 18:40:31 +08:00
}
};
2019-04-19 18:40:31 +08:00
onGridItemDragOver = (e) => {
if (Utils.isIEBrowser() || !this.canDrag) {
return false;
}
2019-04-19 18:40:31 +08:00
e.preventDefault();
e.dataTransfer.dropEffect = 'move';
};
2019-04-19 18:40:31 +08:00
onGridItemDragLeave = (e) => {
if (Utils.isIEBrowser() || !this.canDrag) {
return false;
}
2024-07-18 11:58:42 +08:00
this.setState({ isGridDropTipShow: false });
};
2019-04-19 18:40:31 +08:00
onGridItemDragDrop = (e) => {
if (Utils.isIEBrowser() || !this.canDrag) {
return false;
}
2024-07-18 11:58:42 +08:00
this.setState({ isGridDropTipShow: false });
2019-04-19 18:40:31 +08:00
if (e.dataTransfer.files.length) { // uploaded files
return;
}
let selectedPath = Utils.joinPath(this.props.path, this.props.dirent.name);
let dragStartItemsData = e.dataTransfer.getData('application/drag-item-info');
dragStartItemsData = JSON.parse(dragStartItemsData);
if (!Array.isArray(dragStartItemsData)) {
let { nodeDirent, nodeParentPath } = dragStartItemsData;
let dropItemData = this.props.dirent;
if (nodeDirent.name === dropItemData.name) {
return;
}
if (dropItemData.type !== 'dir') {
return;
}
this.props.onItemMove(this.props.currentRepoInfo, nodeDirent, selectedPath, nodeParentPath);
} else {
// if current dirent is a dir and selected list include it, return
if (dragStartItemsData.some(item => item.nodeDirent.name === this.props.dirent.name)) {
return;
}
this.props.onItemsMove(this.props.currentRepoInfo, selectedPath);
}
};
2019-04-19 18:40:31 +08:00
2024-07-18 11:58:42 +08:00
onGridItemMouseDown = (event) => {
this.props.onGridItemMouseDown(event);
};
2019-04-18 22:36:07 +08:00
getFileUrl = (url) => {
let fileUrlArr = url.split('/');
if (fileUrlArr.indexOf('48') !== -1) {
fileUrlArr.splice(fileUrlArr.indexOf('48'), 1, '192');
}
let fileUrl = fileUrlArr.join('/');
return fileUrl;
};
2019-04-18 22:36:07 +08:00
2019-04-22 11:34:51 +08:00
onGridItemContextMenu = (event) => {
let dirent = this.props.dirent;
2019-04-22 11:34:51 +08:00
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;
};
2019-04-18 22:36:07 +08:00
render() {
let { dirent, path, repoID } = this.props;
2019-04-18 22:36:07 +08:00
let direntPath = Utils.joinPath(path, dirent.name);
let iconUrl = Utils.getDirentIcon(dirent, true);
2019-04-18 22:36:07 +08:00
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(' ');
}
2019-04-18 22:36:07 +08:00
let dirHref = '';
if (this.props.currentRepoInfo) {
dirHref = siteRoot + 'library/' + repoID + '/' + this.props.currentRepoInfo.repo_name + Utils.encodePath(direntPath);
2019-04-18 22:36:07 +08:00
}
let fileHref = siteRoot + 'lib/' + repoID + '/file' + Utils.encodePath(direntPath);
if (dirent.is_sdoc_revision && dirent.revision_id) {
fileHref = siteRoot + 'lib/' + repoID + '/revisions/' + dirent.revision_id + '/';
}
let gridClass = 'grid-file-img-link cursor-pointer';
gridClass += this.state.isGridDropTipShow ? ' grid-drop-show' : ' ';
2019-04-18 22:36:07 +08:00
2023-11-29 17:11:46 +08:00
let lockedInfo = dirent.is_freezed ? gettext('Frozen by {name}') : gettext('locked by {name}');
2019-04-23 10:49:07 +08:00
lockedInfo = lockedInfo.replace('{name}', dirent.lock_owner_name);
const lockedImageUrl = `${mediaUrl}img/file-${dirent.is_freezed ? 'freezed-32.svg' : 'locked-32.png'}`;
2023-11-21 13:53:40 +08:00
const lockedMessage = dirent.is_freezed ? gettext('freezed') : gettext('locked');
const showName = this.getRenderedText(dirent);
return (
2019-04-18 22:36:07 +08:00
<Fragment>
<li
className={`grid-item ${dirent.isSelected ? 'grid-selected-active' : ''}`}
onContextMenu={this.onGridItemContextMenu}
onMouseDown={this.onGridItemMouseDown}>
<div
2019-04-19 18:40:31 +08:00
className={gridClass}
draggable={this.canDrag}
2019-04-18 22:36:07 +08:00
onClick={this.onItemClick}
onDragStart={this.onGridItemDragStart}
onDragEnter={this.onGridItemDragEnter}
onDragOver={this.onGridItemDragOver}
onDragLeave={this.onGridItemDragLeave}
2019-04-19 18:40:31 +08:00
onDrop={this.onGridItemDragDrop}
2019-04-18 22:36:07 +08:00
>
2022-08-11 10:55:53 +08:00
{(this.canPreview && dirent.encoded_thumbnail_src) ?
2019-04-18 22:36:07 +08:00
<img src={`${siteRoot}${fileUrl}`} ref={this.gridIcon} className="thumbnail" onClick={this.onItemClick} alt=""/> :
<img src={iconUrl} ref={this.gridIcon} width="96" alt='' />
}
2023-11-21 13:53:40 +08:00
{dirent.is_locked && <img className="grid-file-locked-icon" src={lockedImageUrl} alt={lockedMessage} title={lockedInfo}/>}
2019-04-18 22:36:07 +08:00
</div>
<div className="grid-file-name" onDragStart={this.onGridItemDragStart} draggable={this.canDrag} >
{(dirent.type !== 'dir' && dirent.file_tags && dirent.file_tags.length > 0) && (
<Fragment>
2019-07-03 18:04:49 +08:00
<div id={`tag-list-title-${toolTipID}`} className="dirent-item tag-list tag-list-stacked d-inline-block align-middle">
{dirent.file_tags.map((fileTag, index) => {
let length = dirent.file_tags.length;
return (
2024-07-18 11:58:42 +08:00
<span className="file-tag" key={fileTag.id} style={{ zIndex: length - index, backgroundColor: fileTag.color }}></span>
);
})}
</div>
<UncontrolledTooltip target={`tag-list-title-${toolTipID}`} placement="bottom">
{tagTitle}
</UncontrolledTooltip>
</Fragment>
)}
{(!dirent.isDir() && !this.canPreview) ?
<a
className="sf-link grid-file-name-link"
onClick={this.onItemClick}
title={dirent.name}
2024-07-18 11:58:42 +08:00
>{showName}
</a> :
<a
className="grid-file-name-link"
href={dirent.type === 'dir' ? dirHref : fileHref}
onClick={this.onItemClick}
title={dirent.name}
2024-07-18 11:58:42 +08:00
>{showName}
</a>
}
2019-04-18 22:36:07 +08:00
</div>
</li>
</Fragment>
);
2019-04-18 22:36:07 +08:00
}
}
DirentGridItem.propTypes = propTypes;
2019-04-18 22:36:07 +08:00
export default DirentGridItem;