2018-11-27 06:47:19 +00:00
|
|
|
import React, { Fragment } from 'react';
|
2018-10-13 09:07:54 +00:00
|
|
|
import PropTypes from 'prop-types';
|
2023-09-13 15:12:23 +00:00
|
|
|
import MediaQuery from 'react-responsive';
|
|
|
|
import { v4 as uuidv4 } from 'uuid';
|
2021-10-26 03:59:33 +00:00
|
|
|
import moment from 'moment';
|
2023-09-13 15:12:23 +00:00
|
|
|
import { Dropdown, DropdownToggle, DropdownItem, UncontrolledTooltip } from 'reactstrap';
|
2021-08-31 10:00:02 +00:00
|
|
|
import { gettext, siteRoot, mediaUrl, username, useGoFileserver, fileServerRoot } from '../../utils/constants';
|
2018-11-30 03:52:19 +00:00
|
|
|
import { Utils } from '../../utils/utils';
|
2018-12-06 03:28:16 +00:00
|
|
|
import { seafileAPI } from '../../utils/seafile-api';
|
2018-10-25 05:36:06 +00:00
|
|
|
import URLDecorator from '../../utils/url-decorator';
|
2019-04-22 06:00:16 +00:00
|
|
|
import ItemDropdownMenu from '../dropdown-menu/item-dropdown-menu';
|
2019-01-30 09:37:13 +00:00
|
|
|
import Rename from '../rename';
|
2018-11-27 06:47:19 +00:00
|
|
|
import ModalPortal from '../modal-portal';
|
|
|
|
import MoveDirentDialog from '../dialog/move-dirent-dialog';
|
|
|
|
import CopyDirentDialog from '../dialog/copy-dirent-dialog';
|
2018-12-06 03:28:16 +00:00
|
|
|
import ShareDialog from '../dialog/share-dialog';
|
2019-04-12 07:54:05 +00:00
|
|
|
import ZipDownloadDialog from '../dialog/zip-download-dialog';
|
2019-04-17 02:48:44 +00:00
|
|
|
import EditFileTagDialog from '../dialog/edit-filetag-dialog';
|
2023-09-13 15:12:23 +00:00
|
|
|
import EditFileTagPopover from '../popover/edit-filetag-popover';
|
2019-05-15 00:01:48 +00:00
|
|
|
import LibSubFolderPermissionDialog from '../dialog/lib-sub-folder-permission-dialog';
|
2019-07-16 02:01:09 +00:00
|
|
|
import toaster from '../toast';
|
2023-09-13 00:40:50 +00:00
|
|
|
import '../../css/dirent-list-item.css';
|
2018-12-28 03:12:24 +00:00
|
|
|
|
2018-10-13 09:07:54 +00:00
|
|
|
const propTypes = {
|
2018-11-22 03:26:00 +00:00
|
|
|
path: PropTypes.string.isRequired,
|
2018-11-28 04:41:49 +00:00
|
|
|
repoID: PropTypes.string.isRequired,
|
2018-10-13 09:07:54 +00:00
|
|
|
isItemFreezed: PropTypes.bool.isRequired,
|
|
|
|
dirent: PropTypes.object.isRequired,
|
|
|
|
onItemClick: PropTypes.func.isRequired,
|
2019-04-22 04:18:35 +00:00
|
|
|
freezeItem: PropTypes.func.isRequired,
|
|
|
|
unfreezeItem: PropTypes.func.isRequired,
|
2018-11-23 12:19:42 +00:00
|
|
|
onItemRenameToggle: PropTypes.func.isRequired,
|
|
|
|
onItemSelected: PropTypes.func.isRequired,
|
2018-10-13 09:07:54 +00:00
|
|
|
onItemDelete: PropTypes.func.isRequired,
|
2018-10-25 05:36:06 +00:00
|
|
|
onItemRename: PropTypes.func.isRequired,
|
2018-11-27 06:47:19 +00:00
|
|
|
onItemMove: PropTypes.func.isRequired,
|
|
|
|
onItemCopy: PropTypes.func.isRequired,
|
2023-09-14 06:36:58 +00:00
|
|
|
onItemConvert: PropTypes.func.isRequired,
|
2019-01-17 09:05:08 +00:00
|
|
|
onDirentClick: PropTypes.func.isRequired,
|
2018-11-22 03:26:00 +00:00
|
|
|
updateDirent: PropTypes.func.isRequired,
|
2019-03-11 03:14:49 +00:00
|
|
|
showImagePopup: PropTypes.func.isRequired,
|
2018-12-18 09:21:01 +00:00
|
|
|
currentRepoInfo: PropTypes.object,
|
2018-11-01 10:40:18 +00:00
|
|
|
isRepoOwner: PropTypes.bool,
|
2019-03-11 03:14:49 +00:00
|
|
|
isAdmin: PropTypes.bool.isRequired,
|
|
|
|
repoEncrypted: PropTypes.bool.isRequired,
|
|
|
|
isGroupOwnedRepo: PropTypes.bool.isRequired,
|
2019-04-11 13:04:47 +00:00
|
|
|
onItemMouseDown: PropTypes.func.isRequired,
|
|
|
|
onItemContextMenu: PropTypes.func.isRequired,
|
2019-04-13 02:45:11 +00:00
|
|
|
selectedDirentList: PropTypes.array.isRequired,
|
|
|
|
activeDirent: PropTypes.object,
|
2019-04-21 02:43:34 +00:00
|
|
|
getDirentItemMenuList: PropTypes.func.isRequired,
|
2019-05-14 02:15:09 +00:00
|
|
|
onFileTagChanged: PropTypes.func,
|
|
|
|
enableDirPrivateShare: PropTypes.bool.isRequired,
|
2019-05-29 04:02:07 +00:00
|
|
|
showDirentDetail: PropTypes.func.isRequired,
|
2019-06-17 08:11:54 +00:00
|
|
|
onItemsMove: PropTypes.func.isRequired,
|
2019-07-26 06:55:09 +00:00
|
|
|
onShowDirentsDraggablePreview: PropTypes.func,
|
2023-09-13 00:40:50 +00:00
|
|
|
loadDirentList: PropTypes.func.isRequired,
|
2018-10-13 09:07:54 +00:00
|
|
|
};
|
|
|
|
|
2020-05-06 10:24:16 +00:00
|
|
|
class DirentListItem extends React.Component {
|
2018-10-13 09:07:54 +00:00
|
|
|
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
2023-08-17 00:57:09 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2018-10-13 09:07:54 +00:00
|
|
|
this.state = {
|
|
|
|
isOperationShow: false,
|
2018-10-25 05:36:06 +00:00
|
|
|
highlight: false,
|
2019-04-12 07:54:05 +00:00
|
|
|
isZipDialogOpen: false,
|
2018-11-27 06:47:19 +00:00
|
|
|
isMoveDialogShow: false,
|
|
|
|
isCopyDialogShow: false,
|
2018-12-06 03:28:16 +00:00
|
|
|
isShareDialogShow: false,
|
2018-11-27 06:47:19 +00:00
|
|
|
isMutipleOperation: false,
|
2023-08-17 00:57:09 +00:00
|
|
|
canDrag: this.canDrag,
|
2018-12-18 01:02:16 +00:00
|
|
|
isShowTagTooltip: false,
|
2019-03-27 03:25:27 +00:00
|
|
|
isDragTipShow: false,
|
|
|
|
isDropTipshow: false,
|
2019-04-17 02:48:44 +00:00
|
|
|
isEditFileTagShow: false,
|
2019-05-15 00:01:48 +00:00
|
|
|
isPermissionDialogOpen: false,
|
2019-08-30 10:10:48 +00:00
|
|
|
isOpMenuOpen: false // for mobile
|
2018-10-13 09:07:54 +00:00
|
|
|
};
|
2023-09-13 15:12:23 +00:00
|
|
|
this.tagListTitleID = `tag-list-title-${uuidv4()}`;
|
2018-10-13 09:07:54 +00:00
|
|
|
}
|
|
|
|
|
2019-04-11 13:04:47 +00:00
|
|
|
componentWillReceiveProps(nextProps) {
|
2020-04-11 09:54:52 +00:00
|
|
|
if (nextProps.isItemFreezed !== this.props.isItemFreezed && !nextProps.isItemFreezed) {
|
2019-04-08 03:35:46 +00:00
|
|
|
this.setState({
|
|
|
|
highlight: false,
|
|
|
|
isOperationShow: false,
|
2019-04-13 08:56:06 +00:00
|
|
|
}, () => {
|
|
|
|
if (nextProps.activeDirent && nextProps.activeDirent.name === nextProps.dirent.name) {
|
|
|
|
this.setState({isOperationShow: true});
|
|
|
|
}
|
2019-04-11 13:04:47 +00:00
|
|
|
});
|
2019-04-08 03:35:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-30 10:10:48 +00:00
|
|
|
toggleOpMenu = () => {
|
|
|
|
this.setState({
|
|
|
|
isOpMenuOpen: !this.state.isOpMenuOpen
|
|
|
|
});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2019-08-30 10:10:48 +00:00
|
|
|
|
2018-10-13 09:07:54 +00:00
|
|
|
//UI Interactive
|
|
|
|
onMouseEnter = () => {
|
|
|
|
if (!this.props.isItemFreezed) {
|
|
|
|
this.setState({
|
|
|
|
highlight: true,
|
|
|
|
isOperationShow: true,
|
|
|
|
});
|
|
|
|
}
|
2023-08-17 00:57:09 +00:00
|
|
|
if (this.state.canDrag) {
|
2021-09-13 02:37:07 +00:00
|
|
|
this.setState({isDragTipShow: true});
|
|
|
|
}
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2018-10-13 09:07:54 +00:00
|
|
|
|
|
|
|
onMouseOver = () => {
|
|
|
|
if (!this.props.isItemFreezed) {
|
|
|
|
this.setState({
|
|
|
|
highlight: true,
|
|
|
|
isOperationShow: true,
|
|
|
|
});
|
|
|
|
}
|
2023-08-17 00:57:09 +00:00
|
|
|
if (this.state.canDrag) {
|
2021-09-13 02:37:07 +00:00
|
|
|
this.setState({isDragTipShow: true});
|
|
|
|
}
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2018-10-13 09:07:54 +00:00
|
|
|
|
|
|
|
onMouseLeave = () => {
|
|
|
|
if (!this.props.isItemFreezed) {
|
|
|
|
this.setState({
|
|
|
|
highlight: false,
|
|
|
|
isOperationShow: false,
|
|
|
|
});
|
|
|
|
}
|
2019-04-11 13:04:47 +00:00
|
|
|
this.setState({isDragTipShow: false});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2018-10-13 09:07:54 +00:00
|
|
|
|
2019-04-22 04:18:35 +00:00
|
|
|
unfreezeItem = () => {
|
2018-10-13 09:07:54 +00:00
|
|
|
this.setState({
|
2019-01-16 09:44:44 +00:00
|
|
|
highlight: false,
|
2018-10-13 09:07:54 +00:00
|
|
|
isOperationShow: false,
|
|
|
|
});
|
2019-04-22 04:18:35 +00:00
|
|
|
this.props.unfreezeItem();
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2018-10-13 09:07:54 +00:00
|
|
|
|
|
|
|
//buiness handler
|
|
|
|
onItemSelected = () => {
|
2018-11-23 12:19:42 +00:00
|
|
|
this.props.onItemSelected(this.props.dirent);
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2018-11-22 03:26:00 +00:00
|
|
|
|
2021-09-29 07:23:02 +00:00
|
|
|
onItemStarred = (e) => {
|
2018-10-25 05:36:06 +00:00
|
|
|
let dirent = this.props.dirent;
|
2018-11-28 04:41:49 +00:00
|
|
|
let repoID = this.props.repoID;
|
2018-10-25 05:36:06 +00:00
|
|
|
let filePath = this.getDirentPath(dirent);
|
2019-02-18 12:26:55 +00:00
|
|
|
|
2021-09-29 07:23:02 +00:00
|
|
|
e.preventDefault();
|
|
|
|
|
2018-10-25 05:36:06 +00:00
|
|
|
if (dirent.starred) {
|
2019-03-27 03:28:00 +00:00
|
|
|
seafileAPI.unstarItem(repoID, filePath).then(() => {
|
2018-11-28 00:57:42 +00:00
|
|
|
this.props.updateDirent(this.props.dirent, 'starred', false);
|
2019-07-16 02:01:09 +00:00
|
|
|
}).catch(error => {
|
|
|
|
let errMessage = Utils.getErrorMsg(error);
|
|
|
|
toaster.danger(errMessage);
|
2018-10-25 05:36:06 +00:00
|
|
|
});
|
|
|
|
} else {
|
2019-02-18 12:26:55 +00:00
|
|
|
seafileAPI.starItem(repoID, filePath).then(() => {
|
2018-11-28 00:57:42 +00:00
|
|
|
this.props.updateDirent(this.props.dirent, 'starred', true);
|
2019-07-16 02:01:09 +00:00
|
|
|
}).catch(error => {
|
|
|
|
let errMessage = Utils.getErrorMsg(error);
|
|
|
|
toaster.danger(errMessage);
|
2018-10-25 05:36:06 +00:00
|
|
|
});
|
|
|
|
}
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2018-11-22 03:26:00 +00:00
|
|
|
|
2019-01-17 09:05:08 +00:00
|
|
|
// on '<tr>'
|
|
|
|
onDirentClick = (e) => {
|
|
|
|
// '<td>' is clicked
|
2019-04-13 05:35:33 +00:00
|
|
|
e.stopPropagation();
|
2019-01-17 09:05:08 +00:00
|
|
|
if (e.target.tagName == 'TD') {
|
|
|
|
this.props.onDirentClick(this.props.dirent);
|
|
|
|
}
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2019-01-17 09:05:08 +00:00
|
|
|
|
2018-11-30 03:52:19 +00:00
|
|
|
onItemClick = (e) => {
|
|
|
|
e.preventDefault();
|
2019-01-16 09:45:46 +00:00
|
|
|
const dirent = this.props.dirent;
|
2021-01-09 10:36:26 +00:00
|
|
|
if (this.state.isRenameing) {
|
|
|
|
return;
|
|
|
|
}
|
2021-09-13 02:37:07 +00:00
|
|
|
|
|
|
|
if (dirent.isDir()) {
|
|
|
|
this.props.onItemClick(dirent);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!this.canPreview) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-01-16 09:45:46 +00:00
|
|
|
if (Utils.imageCheck(dirent.name)) {
|
|
|
|
this.props.showImagePopup(dirent);
|
|
|
|
} else {
|
|
|
|
this.props.onItemClick(dirent);
|
|
|
|
}
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2018-10-25 05:36:06 +00:00
|
|
|
|
|
|
|
onItemDelete = (e) => {
|
2021-09-29 07:23:02 +00:00
|
|
|
e.preventDefault();
|
2018-10-25 05:36:06 +00:00
|
|
|
e.nativeEvent.stopImmediatePropagation(); //for document event
|
2018-11-22 03:26:00 +00:00
|
|
|
this.props.onItemDelete(this.props.dirent);
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2018-10-25 05:36:06 +00:00
|
|
|
|
2018-12-06 03:28:16 +00:00
|
|
|
onItemShare = (e) => {
|
2021-09-29 07:23:02 +00:00
|
|
|
e.preventDefault();
|
2018-12-06 03:28:16 +00:00
|
|
|
e.nativeEvent.stopImmediatePropagation(); //for document event
|
|
|
|
this.setState({isShareDialogShow: !this.state.isShareDialogShow});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2018-12-06 03:28:16 +00:00
|
|
|
|
2019-01-05 12:40:41 +00:00
|
|
|
closeSharedDialog = () => {
|
|
|
|
this.setState({isShareDialogShow: !this.state.isShareDialogShow});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2019-01-05 12:40:41 +00:00
|
|
|
|
2019-08-30 10:10:48 +00:00
|
|
|
onMobileMenuItemClick = (e) => {
|
|
|
|
const operation = e.target.getAttribute('data-op');
|
|
|
|
this.onMenuItemClick(operation, e);
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2019-08-30 10:10:48 +00:00
|
|
|
|
2019-04-21 09:56:55 +00:00
|
|
|
onMenuItemClick = (operation, event) => {
|
2018-10-25 05:36:06 +00:00
|
|
|
switch(operation) {
|
2020-11-02 05:56:35 +00:00
|
|
|
case 'Download':
|
2019-04-11 13:04:47 +00:00
|
|
|
this.onItemDownload(event);
|
|
|
|
break;
|
|
|
|
case 'Share':
|
|
|
|
this.onItemShare(event);
|
|
|
|
break;
|
2020-11-02 05:56:35 +00:00
|
|
|
case 'Delete':
|
2019-04-11 13:04:47 +00:00
|
|
|
this.onItemDelete(event);
|
|
|
|
break;
|
2019-01-31 09:37:02 +00:00
|
|
|
case 'Rename':
|
|
|
|
this.onItemRenameToggle();
|
|
|
|
break;
|
|
|
|
case 'Move':
|
|
|
|
this.onItemMoveToggle();
|
|
|
|
break;
|
|
|
|
case 'Copy':
|
|
|
|
this.onItemCopyToggle();
|
|
|
|
break;
|
2019-04-17 02:48:44 +00:00
|
|
|
case 'Tags':
|
|
|
|
this.onEditFileTagToggle();
|
|
|
|
break;
|
2019-01-31 09:37:02 +00:00
|
|
|
case 'Permission':
|
|
|
|
this.onPermissionItem();
|
|
|
|
break;
|
|
|
|
case 'Unlock':
|
|
|
|
this.onUnlockItem();
|
|
|
|
break;
|
|
|
|
case 'Lock':
|
|
|
|
this.onLockItem();
|
|
|
|
break;
|
2023-09-14 06:36:58 +00:00
|
|
|
case 'Convert to Markdown':
|
|
|
|
this.onItemConvert(event, 'markdown');
|
|
|
|
break;
|
|
|
|
case 'Convert to sdoc':
|
|
|
|
this.onItemConvert(event, 'sdoc');
|
|
|
|
break;
|
2023-07-17 08:18:14 +00:00
|
|
|
case 'Mark as draft':
|
|
|
|
this.onMarkAsDraft();
|
2023-06-20 13:18:07 +00:00
|
|
|
break;
|
2023-07-17 08:18:14 +00:00
|
|
|
case 'Unmark as draft':
|
|
|
|
this.onUnmarkAsDraft();
|
2023-06-20 13:18:07 +00:00
|
|
|
break;
|
2019-01-31 09:37:02 +00:00
|
|
|
case 'Comment':
|
2019-05-30 06:48:25 +00:00
|
|
|
this.props.onDirentClick(this.props.dirent);
|
2019-05-29 04:02:07 +00:00
|
|
|
this.props.showDirentDetail('comments');
|
2019-01-31 09:37:02 +00:00
|
|
|
break;
|
|
|
|
case 'History':
|
|
|
|
this.onHistory();
|
|
|
|
break;
|
|
|
|
case 'Access Log':
|
|
|
|
this.onAccessLog();
|
|
|
|
break;
|
2023-08-10 11:39:58 +00:00
|
|
|
case 'Properties':
|
|
|
|
this.props.onDirentClick(this.props.dirent);
|
|
|
|
this.props.showDirentDetail('info');
|
|
|
|
break;
|
2019-01-31 09:37:02 +00:00
|
|
|
case 'Open via Client':
|
|
|
|
this.onOpenViaClient();
|
|
|
|
break;
|
2021-09-13 08:37:15 +00:00
|
|
|
case 'Convert with ONLYOFFICE':
|
|
|
|
this.onConvertWithONLYOFFICE();
|
|
|
|
break;
|
2019-01-31 09:37:02 +00:00
|
|
|
default:
|
|
|
|
break;
|
2018-10-25 05:36:06 +00:00
|
|
|
}
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2018-10-25 05:36:06 +00:00
|
|
|
|
2023-09-14 06:36:58 +00:00
|
|
|
onItemConvert = (e, dstType)=> {
|
|
|
|
e.preventDefault();
|
|
|
|
e.nativeEvent.stopImmediatePropagation(); //for document event
|
|
|
|
this.props.onItemConvert(this.props.dirent, dstType);
|
|
|
|
}
|
|
|
|
|
2019-04-17 02:48:44 +00:00
|
|
|
onEditFileTagToggle = () => {
|
|
|
|
this.setState({
|
|
|
|
isEditFileTagShow: !this.state.isEditFileTagShow
|
|
|
|
});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2019-04-17 02:48:44 +00:00
|
|
|
|
|
|
|
onFileTagChanged = () => {
|
|
|
|
let direntPath = this.getDirentPath(this.props.dirent);
|
|
|
|
this.props.onFileTagChanged(this.props.dirent, direntPath);
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2019-04-17 02:48:44 +00:00
|
|
|
|
2018-11-23 12:19:42 +00:00
|
|
|
onItemRenameToggle = () => {
|
|
|
|
this.props.onItemRenameToggle(this.props.dirent);
|
2018-10-25 05:36:06 +00:00
|
|
|
this.setState({
|
|
|
|
isOperationShow: false,
|
|
|
|
isRenameing: true,
|
2023-08-17 00:57:09 +00:00
|
|
|
canDrag: false
|
2018-10-25 05:36:06 +00:00
|
|
|
});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2018-10-25 05:36:06 +00:00
|
|
|
|
|
|
|
onRenameConfirm = (newName) => {
|
2018-11-22 03:26:00 +00:00
|
|
|
this.props.onItemRename(this.props.dirent, newName);
|
2018-10-25 05:36:06 +00:00
|
|
|
this.onRenameCancel();
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2018-10-25 05:36:06 +00:00
|
|
|
|
|
|
|
onRenameCancel = () => {
|
2023-08-17 00:57:09 +00:00
|
|
|
this.setState({
|
|
|
|
isRenameing: false,
|
|
|
|
canDrag: this.canDrag // set it back to the initial value
|
|
|
|
});
|
2019-04-22 04:18:35 +00:00
|
|
|
this.unfreezeItem();
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2018-11-22 03:26:00 +00:00
|
|
|
|
2018-11-23 12:19:42 +00:00
|
|
|
onItemMoveToggle = () => {
|
2018-11-27 06:47:19 +00:00
|
|
|
this.setState({isMoveDialogShow: !this.state.isMoveDialogShow});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2018-10-25 05:36:06 +00:00
|
|
|
|
2018-11-23 12:19:42 +00:00
|
|
|
onItemCopyToggle = () => {
|
2018-11-27 06:47:19 +00:00
|
|
|
this.setState({isCopyDialogShow: !this.state.isCopyDialogShow});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2018-10-13 09:07:54 +00:00
|
|
|
|
2018-10-25 05:36:06 +00:00
|
|
|
onPermissionItem = () => {
|
2019-05-15 00:01:48 +00:00
|
|
|
this.setState({isPermissionDialogOpen: !this.state.isPermissionDialogOpen});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2018-10-13 09:07:54 +00:00
|
|
|
|
2018-10-25 05:36:06 +00:00
|
|
|
onLockItem = () => {
|
2018-11-28 04:41:49 +00:00
|
|
|
let repoID = this.props.repoID;
|
2018-10-25 05:36:06 +00:00
|
|
|
let filePath = this.getDirentPath(this.props.dirent);
|
|
|
|
seafileAPI.lockfile(repoID, filePath).then(() => {
|
2018-11-28 00:57:42 +00:00
|
|
|
this.props.updateDirent(this.props.dirent, 'is_locked', true);
|
|
|
|
this.props.updateDirent(this.props.dirent, 'locked_by_me', true);
|
2019-04-23 02:32:12 +00:00
|
|
|
let lockName = username.split('@');
|
|
|
|
this.props.updateDirent(this.props.dirent, 'lock_owner_name', lockName[0]);
|
2019-07-16 02:01:09 +00:00
|
|
|
}).catch(error => {
|
|
|
|
let errMessage = Utils.getErrorMsg(error);
|
|
|
|
toaster.danger(errMessage);
|
2018-10-25 05:36:06 +00:00
|
|
|
});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2020-11-02 05:56:35 +00:00
|
|
|
|
2018-10-25 05:36:06 +00:00
|
|
|
onUnlockItem = () => {
|
2018-11-28 04:41:49 +00:00
|
|
|
let repoID = this.props.repoID;
|
2018-10-25 05:36:06 +00:00
|
|
|
let filePath = this.getDirentPath(this.props.dirent);
|
|
|
|
seafileAPI.unlockfile(repoID, filePath).then(() => {
|
2018-11-28 00:57:42 +00:00
|
|
|
this.props.updateDirent(this.props.dirent, 'is_locked', false);
|
|
|
|
this.props.updateDirent(this.props.dirent, 'locked_by_me', false);
|
2019-04-23 02:32:12 +00:00
|
|
|
this.props.updateDirent(this.props.dirent, 'lock_owner_name', '');
|
2019-07-16 02:01:09 +00:00
|
|
|
}).catch(error => {
|
|
|
|
let errMessage = Utils.getErrorMsg(error);
|
|
|
|
toaster.danger(errMessage);
|
2018-10-25 05:36:06 +00:00
|
|
|
});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2018-10-25 05:36:06 +00:00
|
|
|
|
2023-07-17 08:18:14 +00:00
|
|
|
onMarkAsDraft = () => {
|
2023-06-20 13:18:07 +00:00
|
|
|
let repoID = this.props.repoID;
|
|
|
|
let filePath = this.getDirentPath(this.props.dirent);
|
2023-07-22 07:54:25 +00:00
|
|
|
seafileAPI.sdocMarkAsDraft(repoID, filePath).then((res) => {
|
2023-06-20 13:18:07 +00:00
|
|
|
this.props.updateDirent(this.props.dirent, 'is_sdoc_draft', true);
|
|
|
|
}).catch(error => {
|
|
|
|
let errMessage = Utils.getErrorMsg(error);
|
|
|
|
toaster.danger(errMessage);
|
|
|
|
});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2023-06-20 13:18:07 +00:00
|
|
|
|
2023-07-17 08:18:14 +00:00
|
|
|
onUnmarkAsDraft = () => {
|
2023-06-20 13:18:07 +00:00
|
|
|
let repoID = this.props.repoID;
|
|
|
|
let filePath = this.getDirentPath(this.props.dirent);
|
2023-07-22 07:54:25 +00:00
|
|
|
seafileAPI.sdocUnmarkAsDraft(repoID, filePath).then((res) => {
|
2023-06-20 13:18:07 +00:00
|
|
|
this.props.updateDirent(this.props.dirent, 'is_sdoc_draft', false);
|
|
|
|
}).catch(error => {
|
|
|
|
let errMessage = Utils.getErrorMsg(error);
|
|
|
|
toaster.danger(errMessage);
|
|
|
|
});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2023-06-20 13:18:07 +00:00
|
|
|
|
2018-10-25 05:36:06 +00:00
|
|
|
onHistory = () => {
|
2018-11-28 04:41:49 +00:00
|
|
|
let repoID = this.props.repoID;
|
2018-10-25 05:36:06 +00:00
|
|
|
let filePath = this.getDirentPath(this.props.dirent);
|
2019-02-11 09:38:28 +00:00
|
|
|
let url = URLDecorator.getUrl({type: 'file_revisions', repoID: repoID, filePath: filePath});
|
2018-10-25 05:36:06 +00:00
|
|
|
location.href = url;
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2020-11-02 05:56:35 +00:00
|
|
|
|
2018-10-25 05:36:06 +00:00
|
|
|
onAccessLog = () => {
|
2019-05-28 02:43:17 +00:00
|
|
|
let filePath = this.getDirentPath(this.props.dirent);
|
|
|
|
let path = siteRoot + 'repo/file-access/' + this.props.repoID + '/?p=' + encodeURIComponent(filePath) ;
|
|
|
|
window.open(path);
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2018-10-25 05:36:06 +00:00
|
|
|
|
|
|
|
onOpenViaClient = () => {
|
2018-11-28 04:41:49 +00:00
|
|
|
let repoID = this.props.repoID;
|
2018-10-25 05:36:06 +00:00
|
|
|
let filePath = this.getDirentPath(this.props.dirent);
|
|
|
|
let url = URLDecorator.getUrl({type: 'open_via_client', repoID: repoID, filePath: filePath});
|
|
|
|
location.href = url;
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2018-10-25 05:36:06 +00:00
|
|
|
|
2021-09-13 08:37:15 +00:00
|
|
|
onConvertWithONLYOFFICE = ()=> {
|
|
|
|
let repoID = this.props.repoID;
|
2023-09-13 00:40:50 +00:00
|
|
|
let filePath = this.getDirentPath(this.props.dirent);
|
2021-09-18 04:35:23 +00:00
|
|
|
seafileAPI.onlyofficeConvert(repoID, filePath).then(res => {
|
2023-09-13 00:40:50 +00:00
|
|
|
this.props.loadDirentList(res.data.parent_dir);
|
2021-09-18 04:35:23 +00:00
|
|
|
}).catch(error => {
|
|
|
|
let errMessage = Utils.getErrorMsg(error);
|
|
|
|
toaster.danger(errMessage);
|
|
|
|
});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2021-09-13 08:37:15 +00:00
|
|
|
|
2018-11-27 06:47:19 +00:00
|
|
|
onItemDownload = (e) => {
|
2021-09-29 07:23:02 +00:00
|
|
|
e.preventDefault();
|
2018-11-27 06:47:19 +00:00
|
|
|
e.nativeEvent.stopImmediatePropagation();
|
|
|
|
let dirent = this.props.dirent;
|
2018-11-28 04:41:49 +00:00
|
|
|
let repoID = this.props.repoID;
|
2018-11-27 06:47:19 +00:00
|
|
|
let direntPath = this.getDirentPath(dirent);
|
|
|
|
if (dirent.type === 'dir') {
|
2021-08-31 10:00:02 +00:00
|
|
|
if (!useGoFileserver) {
|
|
|
|
this.setState({
|
|
|
|
isZipDialogOpen: true
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
seafileAPI.zipDownload(repoID, this.props.path, this.props.dirent.name).then((res) => {
|
|
|
|
const zipToken = res.data['zip_token'];
|
|
|
|
location.href = `${fileServerRoot}zip/${zipToken}`;
|
|
|
|
}).catch((error) => {
|
|
|
|
let errorMsg = Utils.getErrorMsg(error);
|
|
|
|
this.setState({
|
|
|
|
isLoading: false,
|
|
|
|
errorMsg: errorMsg
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
2018-11-27 06:47:19 +00:00
|
|
|
} else {
|
|
|
|
let url = URLDecorator.getUrl({type: 'download_file_url', repoID: repoID, filePath: direntPath});
|
|
|
|
location.href = url;
|
|
|
|
}
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2018-11-27 06:47:19 +00:00
|
|
|
|
2019-04-12 07:54:05 +00:00
|
|
|
closeZipDialog = () => {
|
|
|
|
this.setState({
|
|
|
|
isZipDialogOpen: false
|
2018-11-27 06:47:19 +00:00
|
|
|
});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2018-11-27 06:47:19 +00:00
|
|
|
|
2018-10-25 05:36:06 +00:00
|
|
|
getDirentPath = (dirent) => {
|
2018-11-22 03:26:00 +00:00
|
|
|
let path = this.props.path;
|
2018-10-25 05:36:06 +00:00
|
|
|
return path === '/' ? path + dirent.name : path + '/' + dirent.name;
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2018-10-13 09:07:54 +00:00
|
|
|
|
2018-12-18 01:02:16 +00:00
|
|
|
onTagTooltipToggle = (e) => {
|
|
|
|
e.stopPropagation();
|
2019-01-31 09:37:02 +00:00
|
|
|
this.setState({isShowTagTooltip: !this.state.isShowTagTooltip});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2018-12-18 01:02:16 +00:00
|
|
|
|
2019-03-27 03:25:27 +00:00
|
|
|
onItemMove = (destRepo, dirent, selectedPath, currentPath) => {
|
|
|
|
this.props.onItemMove(destRepo, dirent, selectedPath, currentPath);
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2019-03-27 03:25:27 +00:00
|
|
|
|
|
|
|
onItemDragStart = (e) => {
|
2023-08-17 00:57:09 +00:00
|
|
|
if (Utils.isIEBrower() || !this.state.canDrag) {
|
2019-06-04 07:59:25 +00:00
|
|
|
return false;
|
|
|
|
}
|
2019-04-12 07:54:05 +00:00
|
|
|
e.dataTransfer.effectAllowed = 'move';
|
2019-06-17 08:11:54 +00:00
|
|
|
let { selectedDirentList } = this.props;
|
|
|
|
if (selectedDirentList.length > 0 && selectedDirentList.includes(this.props.dirent)) { // drag items and selectedDirentList include item
|
2019-07-26 06:55:09 +00:00
|
|
|
this.props.onShowDirentsDraggablePreview();
|
|
|
|
e.dataTransfer.setDragImage(this.refs.empty_content, 0, 0); // Show an empty content
|
2019-06-18 13:35:39 +00:00
|
|
|
let selectedList = selectedDirentList.map(item => {
|
|
|
|
let nodeRootPath = this.getDirentPath(item);
|
|
|
|
let dragStartItemData = {nodeDirent: item, nodeParentPath: this.props.path, nodeRootPath: nodeRootPath};
|
2019-06-18 09:55:57 +00:00
|
|
|
return dragStartItemData;
|
|
|
|
});
|
2019-06-17 08:11:54 +00:00
|
|
|
selectedList = JSON.stringify(selectedList);
|
|
|
|
e.dataTransfer.setData('applicaiton/drag-item-info', selectedList);
|
|
|
|
return ;
|
|
|
|
}
|
|
|
|
|
2019-07-26 06:55:09 +00:00
|
|
|
if (e.dataTransfer && e.dataTransfer.setDragImage) {
|
|
|
|
e.dataTransfer.setDragImage(this.refs.drag_icon, 15, 15);
|
|
|
|
}
|
|
|
|
|
2019-06-18 13:35:39 +00:00
|
|
|
let nodeRootPath = this.getDirentPath(this.props.dirent);
|
|
|
|
let dragStartItemData = {nodeDirent: this.props.dirent, nodeParentPath: this.props.path, nodeRootPath: nodeRootPath};
|
2019-06-17 08:11:54 +00:00
|
|
|
dragStartItemData = JSON.stringify(dragStartItemData);
|
|
|
|
|
2019-03-27 03:25:27 +00:00
|
|
|
e.dataTransfer.setData('applicaiton/drag-item-info', dragStartItemData);
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2019-03-27 03:25:27 +00:00
|
|
|
|
2019-06-21 06:07:52 +00:00
|
|
|
onItemDragEnter = (e) => {
|
2023-08-17 00:57:09 +00:00
|
|
|
if (Utils.isIEBrower() || !this.state.canDrag) {
|
2019-06-04 07:59:25 +00:00
|
|
|
return false;
|
|
|
|
}
|
2019-03-27 03:25:27 +00:00
|
|
|
if (this.props.dirent.type === 'dir') {
|
2019-06-21 06:07:52 +00:00
|
|
|
e.stopPropagation();
|
2019-03-27 03:25:27 +00:00
|
|
|
this.setState({isDropTipshow: true});
|
|
|
|
}
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2020-11-02 05:56:35 +00:00
|
|
|
|
2019-03-27 03:25:27 +00:00
|
|
|
onItemDragOver = (e) => {
|
2023-08-17 00:57:09 +00:00
|
|
|
if (Utils.isIEBrower() || !this.state.canDrag) {
|
2019-06-04 07:59:25 +00:00
|
|
|
return false;
|
|
|
|
}
|
2019-08-09 09:04:48 +00:00
|
|
|
if (e.dataTransfer.dropEffect === 'copy') {
|
|
|
|
return;
|
|
|
|
}
|
2019-03-27 03:25:27 +00:00
|
|
|
e.preventDefault();
|
|
|
|
e.dataTransfer.dropEffect = 'move';
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2019-03-27 03:25:27 +00:00
|
|
|
|
2019-06-21 06:07:52 +00:00
|
|
|
onItemDragLeave = (e) => {
|
2023-08-17 00:57:09 +00:00
|
|
|
if (Utils.isIEBrower() || !this.state.canDrag) {
|
2019-06-04 07:59:25 +00:00
|
|
|
return false;
|
|
|
|
}
|
2019-06-21 06:07:52 +00:00
|
|
|
|
|
|
|
if (this.props.dirent.type === 'dir') {
|
|
|
|
e.stopPropagation();
|
|
|
|
}
|
2019-03-27 03:25:27 +00:00
|
|
|
this.setState({isDropTipshow: false});
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2019-03-27 03:25:27 +00:00
|
|
|
|
|
|
|
onItemDragDrop = (e) => {
|
2023-08-17 00:57:09 +00:00
|
|
|
if (Utils.isIEBrower() || !this.state.canDrag) {
|
2019-06-04 07:59:25 +00:00
|
|
|
return false;
|
|
|
|
}
|
2019-03-27 03:25:27 +00:00
|
|
|
this.setState({isDropTipshow: false});
|
|
|
|
if (e.dataTransfer.files.length) { // uploaded files
|
|
|
|
return;
|
|
|
|
}
|
2019-06-21 06:07:52 +00:00
|
|
|
if (this.props.dirent.type === 'dir') {
|
|
|
|
e.stopPropagation();
|
2019-07-26 06:55:09 +00:00
|
|
|
} else {
|
|
|
|
return;
|
2019-06-21 06:07:52 +00:00
|
|
|
}
|
2019-03-27 03:25:27 +00:00
|
|
|
let dragStartItemData = e.dataTransfer.getData('applicaiton/drag-item-info');
|
|
|
|
dragStartItemData = JSON.parse(dragStartItemData);
|
2019-06-17 08:11:54 +00:00
|
|
|
if (Array.isArray(dragStartItemData)) { //move items
|
2019-06-18 13:35:39 +00:00
|
|
|
let direntPaths = dragStartItemData.map(draggedItem => {
|
2019-06-21 05:59:17 +00:00
|
|
|
return draggedItem.nodeRootPath;
|
2019-06-17 08:11:54 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
let selectedPath = Utils.joinPath(this.props.path, this.props.dirent.name);
|
|
|
|
|
|
|
|
if (direntPaths.some(direntPath => { return direntPath === selectedPath;})) { //eg; A/B, A/C --> A/B
|
|
|
|
return;
|
|
|
|
}
|
2020-11-02 05:56:35 +00:00
|
|
|
|
2019-06-17 08:11:54 +00:00
|
|
|
this.props.onItemsMove(this.props.currentRepoInfo, selectedPath);
|
|
|
|
return ;
|
|
|
|
}
|
|
|
|
|
2019-06-18 04:06:24 +00:00
|
|
|
let { nodeDirent, nodeParentPath, nodeRootPath } = dragStartItemData;
|
2019-03-27 03:25:27 +00:00
|
|
|
let dropItemData = this.props.dirent;
|
|
|
|
|
|
|
|
if (nodeDirent.name === dropItemData.name) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// copy the dirent to it's child. eg: A/B -> A/B/C
|
|
|
|
if (dropItemData.type === 'dir' && nodeDirent.type === 'dir') {
|
|
|
|
if (nodeParentPath !== this.props.path) {
|
|
|
|
if (this.props.path.indexOf(nodeRootPath) !== -1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let selectedPath = Utils.joinPath(this.props.path, this.props.dirent.name);
|
|
|
|
this.onItemMove(this.props.currentRepoInfo, nodeDirent, selectedPath, nodeParentPath);
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2019-03-27 03:25:27 +00:00
|
|
|
|
2019-04-11 13:04:47 +00:00
|
|
|
onItemMouseDown = (event) => {
|
|
|
|
this.props.onItemMouseDown(event);
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2019-04-11 13:04:47 +00:00
|
|
|
|
|
|
|
onItemContextMenu = (event) => {
|
|
|
|
let dirent = this.props.dirent;
|
|
|
|
this.props.onItemContextMenu(event, dirent);
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2019-04-11 13:04:47 +00:00
|
|
|
|
2019-04-18 09:32:34 +00:00
|
|
|
renderItemOperation = () => {
|
2019-12-23 04:03:06 +00:00
|
|
|
let { dirent, currentRepoInfo, selectedDirentList } = this.props;
|
2021-09-13 02:37:07 +00:00
|
|
|
let canDownload = true;
|
|
|
|
let canDelete = true;
|
|
|
|
const { isCustomPermission, customPermission } = this;
|
|
|
|
if (isCustomPermission) {
|
|
|
|
const { permission } = customPermission;
|
|
|
|
canDownload = permission.download;
|
|
|
|
canDelete = permission.delete;
|
|
|
|
}
|
2019-10-12 06:54:25 +00:00
|
|
|
|
|
|
|
// https://dev.seafile.com/seahub/lib/d6f300e7-bb2b-4722-b83e-cf45e370bfbc/file/seaf-server%20%E5%8A%9F%E8%83%BD%E8%AE%BE%E8%AE%A1/%E6%9D%83%E9%99%90%E7%9B%B8%E5%85%B3/%E8%B5%84%E6%96%99%E5%BA%93%E6%9D%83%E9%99%90%E8%A7%84%E8%8C%83.md
|
2019-12-23 04:03:06 +00:00
|
|
|
let showShareBtn = Utils.isHasPermissionToShare(currentRepoInfo, dirent.permission, dirent);
|
2019-06-21 02:44:41 +00:00
|
|
|
|
2019-04-18 09:32:34 +00:00
|
|
|
return (
|
|
|
|
<Fragment>
|
2020-11-02 05:56:35 +00:00
|
|
|
{selectedDirentList.length > 1 ?
|
2019-04-18 09:32:34 +00:00
|
|
|
<Fragment>
|
|
|
|
{this.state.isOperationShow && !dirent.isSelected &&
|
|
|
|
<div className="operations">
|
2021-09-29 07:23:02 +00:00
|
|
|
{(dirent.permission === 'rw' || dirent.permission === 'r' || (isCustomPermission && canDownload)) && (
|
|
|
|
<a href="#" className="op-icon sf2-icon-download" title={gettext('Download')} role="button" aria-label={gettext('Download')} onClick={this.onItemDownload}></a>
|
|
|
|
)}
|
|
|
|
{showShareBtn && (
|
|
|
|
<a href="#" className="op-icon sf2-icon-share" title={gettext('Share')} role="button" aria-label={gettext('Share')} onClick={this.onItemShare}></a>
|
|
|
|
)}
|
2023-08-01 07:27:19 +00:00
|
|
|
{(dirent.permission === 'rw' || dirent.permission === 'cloud-edit' || (isCustomPermission && canDelete)) && (
|
2021-09-29 07:23:02 +00:00
|
|
|
<a href="#" className="op-icon sf2-icon-delete" title={gettext('Delete')} role="button" aria-label={gettext('Delete')} onClick={this.onItemDelete}></a>
|
|
|
|
)}
|
|
|
|
<ItemDropdownMenu
|
|
|
|
item={this.props.dirent}
|
|
|
|
toggleClass={'sf2-icon-caret-down'}
|
|
|
|
isHandleContextMenuEvent={true}
|
|
|
|
getMenuList={this.props.getDirentItemMenuList}
|
|
|
|
onMenuItemClick={this.onMenuItemClick}
|
|
|
|
unfreezeItem={this.unfreezeItem}
|
|
|
|
freezeItem={this.props.freezeItem}
|
|
|
|
/>
|
2019-04-18 09:32:34 +00:00
|
|
|
</div>
|
|
|
|
}
|
2020-11-02 05:56:35 +00:00
|
|
|
</Fragment> :
|
2019-04-18 09:32:34 +00:00
|
|
|
<Fragment>
|
2020-11-02 05:56:35 +00:00
|
|
|
{this.state.isOperationShow &&
|
2019-04-18 09:32:34 +00:00
|
|
|
<div className="operations">
|
2021-09-29 07:23:02 +00:00
|
|
|
{(dirent.permission === 'rw' || dirent.permission === 'r' || (isCustomPermission && canDownload)) && (
|
|
|
|
<a href="#" className="op-icon sf2-icon-download" title={gettext('Download')} role="button" aria-label={gettext('Download')} onClick={this.onItemDownload}></a>
|
|
|
|
)}
|
|
|
|
{showShareBtn && (
|
|
|
|
<a href="#" className="op-icon sf2-icon-share" title={gettext('Share')} role="button" aria-label={gettext('Share')} onClick={this.onItemShare}></a>
|
|
|
|
)}
|
2023-08-01 07:27:19 +00:00
|
|
|
{(dirent.permission === 'rw' || dirent.permission === 'cloud-edit' || (isCustomPermission && canDelete)) && (
|
2021-09-29 07:23:02 +00:00
|
|
|
<a href="#" className="op-icon sf2-icon-delete" title={gettext('Delete')} role="button" aria-label={gettext('Delete')} onClick={this.onItemDelete}></a>
|
|
|
|
)}
|
|
|
|
<ItemDropdownMenu
|
|
|
|
item={this.props.dirent}
|
|
|
|
toggleClass={'sf2-icon-caret-down'}
|
|
|
|
isHandleContextMenuEvent={true}
|
|
|
|
getMenuList={this.props.getDirentItemMenuList}
|
|
|
|
onMenuItemClick={this.onMenuItemClick}
|
|
|
|
unfreezeItem={this.unfreezeItem}
|
|
|
|
freezeItem={this.props.freezeItem}
|
|
|
|
/>
|
2019-04-18 09:32:34 +00:00
|
|
|
</div>
|
|
|
|
}
|
|
|
|
</Fragment>
|
|
|
|
}
|
|
|
|
</Fragment>
|
2019-05-14 02:15:09 +00:00
|
|
|
);
|
2023-09-13 00:40:50 +00:00
|
|
|
};
|
2019-04-18 09:32:34 +00:00
|
|
|
|
2018-10-13 09:07:54 +00:00
|
|
|
render() {
|
2019-04-18 09:32:34 +00:00
|
|
|
let { path, dirent, activeDirent } = this.props;
|
2018-11-30 03:52:19 +00:00
|
|
|
let direntPath = Utils.joinPath(path, dirent.name);
|
2019-01-23 08:25:14 +00:00
|
|
|
let dirHref = '';
|
|
|
|
if (this.props.currentRepoInfo) {
|
|
|
|
dirHref = siteRoot + 'library/' + this.props.repoID + '/' + this.props.currentRepoInfo.repo_name + Utils.encodePath(direntPath);
|
|
|
|
}
|
2019-01-02 03:52:44 +00:00
|
|
|
let fileHref = siteRoot + 'lib/' + this.props.repoID + '/file' + Utils.encodePath(direntPath);
|
2023-07-24 02:47:12 +00:00
|
|
|
if (dirent.is_sdoc_revision && dirent.revision_id) {
|
|
|
|
fileHref = siteRoot + 'lib/' + this.props.repoID + '/revisions/' + dirent.revision_id + '/';
|
|
|
|
}
|
2019-07-03 09:46:24 +00:00
|
|
|
|
2018-12-17 10:43:18 +00:00
|
|
|
let tagTitle = '';
|
2018-12-18 01:02:16 +00:00
|
|
|
if (dirent.file_tags && dirent.file_tags.length > 0) {
|
2019-07-03 09:46:24 +00:00
|
|
|
tagTitle = dirent.file_tags.map(item => item.name).join(' ');
|
2018-12-17 10:43:18 +00:00
|
|
|
}
|
2019-01-08 05:53:01 +00:00
|
|
|
|
2019-01-29 07:22:02 +00:00
|
|
|
let iconUrl = Utils.getDirentIcon(dirent);
|
2019-01-08 05:53:01 +00:00
|
|
|
|
2019-03-28 05:32:22 +00:00
|
|
|
let trClass = this.state.highlight ? 'tr-highlight ' : '';
|
|
|
|
trClass += this.state.isDropTipshow ? 'tr-drop-effect' : '';
|
2019-04-13 02:45:11 +00:00
|
|
|
trClass += (activeDirent && activeDirent.name === dirent.name) ? 'tr-active' : '';
|
|
|
|
trClass += dirent.isSelected? 'tr-active' : '';
|
2019-03-28 05:32:22 +00:00
|
|
|
|
2019-08-30 10:10:48 +00:00
|
|
|
let lockedInfo = gettext('locked by {name}').replace('{name}', dirent.lock_owner_name);
|
|
|
|
const isDesktop = Utils.isDesktop();
|
2023-08-17 00:57:09 +00:00
|
|
|
const { canDrag } = this.state;
|
2019-08-30 10:10:48 +00:00
|
|
|
const desktopItem = (
|
2020-11-02 05:56:35 +00:00
|
|
|
<tr
|
|
|
|
className={trClass}
|
2023-08-17 00:57:09 +00:00
|
|
|
draggable={canDrag}
|
2021-09-29 07:23:02 +00:00
|
|
|
onFocus={this.onMouseEnter}
|
2020-11-02 05:56:35 +00:00
|
|
|
onMouseEnter={this.onMouseEnter}
|
|
|
|
onMouseOver={this.onMouseOver}
|
|
|
|
onMouseLeave={this.onMouseLeave}
|
|
|
|
onClick={this.onDirentClick}
|
|
|
|
onDragStart={this.onItemDragStart}
|
|
|
|
onDragEnter={this.onItemDragEnter}
|
|
|
|
onDragOver={this.onItemDragOver}
|
|
|
|
onDragLeave={this.onItemDragLeave}
|
2019-08-30 10:10:48 +00:00
|
|
|
onDrop={this.onItemDragDrop}
|
|
|
|
onMouseDown={this.onItemMouseDown}
|
|
|
|
onContextMenu={this.onItemContextMenu}
|
|
|
|
>
|
|
|
|
<td className={`pl10 ${this.state.isDragTipShow ? 'tr-drag-effect' : ''}`}>
|
|
|
|
<input type="checkbox" className="vam" onChange={this.onItemSelected} checked={dirent.isSelected}/>
|
|
|
|
</td>
|
|
|
|
<td className="pl10">
|
2021-09-29 07:23:02 +00:00
|
|
|
{dirent.starred !== undefined &&
|
|
|
|
<a href="#" role="button" aria-label={dirent.starred ? gettext('Unstar') : gettext('Star')} onClick={this.onItemStarred}>
|
|
|
|
<i className={`fa-star ${dirent.starred ? 'fas' : 'far star-empty'}`}></i>
|
|
|
|
</a>
|
|
|
|
}
|
2019-08-30 10:10:48 +00:00
|
|
|
</td>
|
|
|
|
<td className="pl10">
|
|
|
|
<div className="dir-icon">
|
2022-08-11 02:55:53 +00:00
|
|
|
{(this.canPreview && dirent.encoded_thumbnail_src) ?
|
2019-08-30 10:10:48 +00:00
|
|
|
<img ref='drag_icon' src={`${siteRoot}${dirent.encoded_thumbnail_src}`} className="thumbnail cursor-pointer" onClick={this.onItemClick} alt="" /> :
|
|
|
|
<img ref='drag_icon' src={iconUrl} width="24" alt='' />
|
|
|
|
}
|
|
|
|
{dirent.is_locked && <img className="locked" src={mediaUrl + 'img/file-locked-32.png'} alt={gettext('locked')} title={lockedInfo}/>}
|
|
|
|
<div ref="empty_content" style={{position: 'absolute', width: '1px', height: '1px'}}></div>
|
|
|
|
</div>
|
|
|
|
</td>
|
|
|
|
<td className="name">
|
2021-09-13 02:37:07 +00:00
|
|
|
{this.state.isRenameing && <Rename hasSuffix={dirent.type !== 'dir'} name={dirent.name} onRenameConfirm={this.onRenameConfirm} onRenameCancel={this.onRenameCancel} />}
|
|
|
|
{!this.state.isRenameing && (
|
|
|
|
<Fragment>
|
2023-09-13 00:40:50 +00:00
|
|
|
{(!dirent.isDir() && !this.canPreview) ?
|
2021-09-13 02:37:07 +00:00
|
|
|
<a className="sf-link" onClick={this.onItemClick}>{dirent.name}</a> :
|
|
|
|
<a href={dirent.type === 'dir' ? dirHref : fileHref} onClick={this.onItemClick}>{dirent.name}</a>
|
|
|
|
}
|
2023-06-20 13:18:07 +00:00
|
|
|
{(Utils.isSdocFile(dirent.name) && dirent.is_sdoc_draft) &&
|
2023-08-01 07:09:34 +00:00
|
|
|
<span className="dirent-sdoc-draft-identifier">{gettext('Draft')}</span>
|
2023-06-20 13:18:07 +00:00
|
|
|
}
|
2021-09-13 02:37:07 +00:00
|
|
|
</Fragment>
|
|
|
|
)}
|
2019-08-30 10:10:48 +00:00
|
|
|
</td>
|
2023-09-13 15:12:23 +00:00
|
|
|
<td className="tag-list-title" id={this.tagListTitleID}>
|
2019-08-30 10:10:48 +00:00
|
|
|
{(dirent.type !== 'dir' && dirent.file_tags && dirent.file_tags.length > 0) && (
|
|
|
|
<Fragment>
|
2023-09-13 15:12:23 +00:00
|
|
|
<div className="dirent-item tag-list tag-list-stacked">
|
2019-08-30 10:10:48 +00:00
|
|
|
{dirent.file_tags.map((fileTag, index) => {
|
|
|
|
let length = dirent.file_tags.length;
|
|
|
|
return (
|
|
|
|
<span className="file-tag" key={fileTag.id} style={{zIndex:length - index, backgroundColor:fileTag.color}}></span>
|
|
|
|
);
|
|
|
|
})}
|
|
|
|
</div>
|
2023-09-13 15:12:23 +00:00
|
|
|
<UncontrolledTooltip target={this.tagListTitleID} placement="bottom">
|
2019-08-30 10:10:48 +00:00
|
|
|
{tagTitle}
|
|
|
|
</UncontrolledTooltip>
|
|
|
|
</Fragment>
|
2020-11-02 05:56:35 +00:00
|
|
|
)}
|
2019-08-30 10:10:48 +00:00
|
|
|
</td>
|
|
|
|
<td className="operation">{this.renderItemOperation()}</td>
|
|
|
|
<td className="file-size">{dirent.size && dirent.size}</td>
|
2021-10-26 03:59:33 +00:00
|
|
|
<td className="last-update" title={moment.unix(dirent.mtime).format('llll')}>{dirent.mtime_relative}</td>
|
2019-08-30 10:10:48 +00:00
|
|
|
</tr>
|
2020-11-02 05:56:35 +00:00
|
|
|
);
|
2019-08-30 10:10:48 +00:00
|
|
|
const mobileItem = (
|
|
|
|
<tr>
|
2021-01-09 10:36:26 +00:00
|
|
|
<td onClick={this.onItemClick}>
|
2019-08-30 10:10:48 +00:00
|
|
|
<div className="dir-icon">
|
2022-08-11 02:55:53 +00:00
|
|
|
{(this.canPreview && dirent.encoded_thumbnail_src) ?
|
2021-01-09 10:36:26 +00:00
|
|
|
<img src={`${siteRoot}${dirent.encoded_thumbnail_src}`} className="thumbnail cursor-pointer" alt="" /> :
|
2019-08-30 10:10:48 +00:00
|
|
|
<img src={iconUrl} width="24" alt="" />
|
2018-11-27 06:47:19 +00:00
|
|
|
}
|
2019-08-30 10:10:48 +00:00
|
|
|
{dirent.is_locked && <img className="locked" src={mediaUrl + 'img/file-locked-32.png'} alt={gettext('locked')} title={lockedInfo}/>}
|
|
|
|
</div>
|
|
|
|
</td>
|
2021-01-09 10:36:26 +00:00
|
|
|
<td onClick={this.onItemClick}>
|
2021-09-13 02:37:07 +00:00
|
|
|
{this.state.isRenameing && <Rename hasSuffix={dirent.type !== 'dir'} name={dirent.name} onRenameConfirm={this.onRenameConfirm} onRenameCancel={this.onRenameCancel} /> }
|
|
|
|
{!this.state.isRenameing && (
|
|
|
|
<Fragment>
|
|
|
|
{(!dirent.isDir() && !this.canPreview) ?
|
|
|
|
<a className="sf-link">{dirent.name}</a> :
|
|
|
|
<a href={dirent.type === 'dir' ? dirHref : fileHref}>{dirent.name}</a>
|
|
|
|
}
|
|
|
|
</Fragment>
|
|
|
|
)}
|
2019-08-30 10:10:48 +00:00
|
|
|
<br />
|
|
|
|
{dirent.size && <span className="item-meta-info">{dirent.size}</span>}
|
|
|
|
<span className="item-meta-info">{dirent.mtime_relative}</span>
|
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
<Dropdown isOpen={this.state.isOpMenuOpen} toggle={this.toggleOpMenu}>
|
|
|
|
<DropdownToggle
|
|
|
|
tag="i"
|
|
|
|
className="sf-dropdown-toggle fa fa-ellipsis-v ml-0"
|
|
|
|
title={gettext('More Operations')}
|
|
|
|
data-toggle="dropdown"
|
|
|
|
aria-expanded={this.state.isOpMenuOpen}
|
|
|
|
/>
|
|
|
|
<div className={this.state.isOpMenuOpen ? '' : 'd-none'} onClick={this.toggleOpMenu}>
|
|
|
|
<div className="mobile-operation-menu-bg-layer"></div>
|
|
|
|
<div className="mobile-operation-menu">
|
|
|
|
{dirent.starred !== undefined &&
|
|
|
|
<DropdownItem className="mobile-menu-item" onClick={this.onItemStarred}>{dirent.starred ? gettext('Unstar') : gettext('Star')}</DropdownItem>}
|
|
|
|
{this.props.getDirentItemMenuList(dirent, true).map((item, index) => {
|
|
|
|
if (item != 'Divider' && item.key != 'Open via Client') {
|
2018-12-18 01:02:16 +00:00
|
|
|
return (
|
2019-08-30 10:10:48 +00:00
|
|
|
<DropdownItem className="mobile-menu-item" key={index} data-op={item.key} onClick={this.onMobileMenuItemClick}>{item.value}</DropdownItem>
|
2018-12-18 01:02:16 +00:00
|
|
|
);
|
2021-09-29 07:23:02 +00:00
|
|
|
} else {
|
|
|
|
return null;
|
2019-08-30 10:10:48 +00:00
|
|
|
}
|
|
|
|
})}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</Dropdown>
|
|
|
|
</td>
|
|
|
|
</tr>
|
2020-11-02 05:56:35 +00:00
|
|
|
);
|
2019-08-30 10:10:48 +00:00
|
|
|
|
|
|
|
return (
|
|
|
|
<Fragment>
|
2020-11-02 05:56:35 +00:00
|
|
|
{isDesktop ? desktopItem : mobileItem}
|
2018-11-27 06:47:19 +00:00
|
|
|
{this.state.isMoveDialogShow &&
|
|
|
|
<ModalPortal>
|
|
|
|
<MoveDirentDialog
|
|
|
|
path={this.props.path}
|
2018-11-28 04:41:49 +00:00
|
|
|
repoID={this.props.repoID}
|
2018-11-27 06:47:19 +00:00
|
|
|
dirent={this.props.dirent}
|
|
|
|
isMutipleOperation={this.state.isMutipleOperation}
|
|
|
|
onItemMove={this.props.onItemMove}
|
|
|
|
onCancelMove={this.onItemMoveToggle}
|
2019-03-11 03:14:49 +00:00
|
|
|
repoEncrypted={this.props.repoEncrypted}
|
2018-11-27 06:47:19 +00:00
|
|
|
/>
|
|
|
|
</ModalPortal>
|
|
|
|
}
|
|
|
|
{this.state.isCopyDialogShow &&
|
|
|
|
<ModalPortal>
|
|
|
|
<CopyDirentDialog
|
|
|
|
path={this.props.path}
|
2018-11-28 04:41:49 +00:00
|
|
|
repoID={this.props.repoID}
|
2018-11-27 06:47:19 +00:00
|
|
|
dirent={this.props.dirent}
|
|
|
|
isMutipleOperation={this.state.isMutipleOperation}
|
|
|
|
onItemCopy={this.props.onItemCopy}
|
|
|
|
onCancelCopy={this.onItemCopyToggle}
|
2019-03-11 03:14:49 +00:00
|
|
|
repoEncrypted={this.props.repoEncrypted}
|
2018-11-27 06:47:19 +00:00
|
|
|
/>
|
|
|
|
</ModalPortal>
|
|
|
|
}
|
2023-09-13 15:12:23 +00:00
|
|
|
<MediaQuery query="(min-width: 768px)">
|
|
|
|
{this.state.isEditFileTagShow &&
|
|
|
|
<EditFileTagPopover
|
|
|
|
repoID={this.props.repoID}
|
|
|
|
fileTagList={dirent.file_tags}
|
|
|
|
filePath={direntPath}
|
|
|
|
toggleCancel={this.onEditFileTagToggle}
|
|
|
|
onFileTagChanged={this.onFileTagChanged}
|
|
|
|
target={this.tagListTitleID}
|
|
|
|
isEditFileTagShow={this.state.isEditFileTagShow}
|
|
|
|
/>
|
|
|
|
}
|
|
|
|
</MediaQuery>
|
|
|
|
<MediaQuery query="(max-width: 767.8px)">
|
|
|
|
{this.state.isEditFileTagShow &&
|
|
|
|
<EditFileTagDialog
|
|
|
|
repoID={this.props.repoID}
|
|
|
|
fileTagList={dirent.file_tags}
|
|
|
|
filePath={direntPath}
|
|
|
|
toggleCancel={this.onEditFileTagToggle}
|
|
|
|
onFileTagChanged={this.onFileTagChanged}
|
|
|
|
/>
|
|
|
|
}
|
|
|
|
</MediaQuery>
|
2019-04-12 07:54:05 +00:00
|
|
|
{this.state.isZipDialogOpen &&
|
2018-11-27 06:47:19 +00:00
|
|
|
<ModalPortal>
|
2019-04-12 07:54:05 +00:00
|
|
|
<ZipDownloadDialog
|
|
|
|
repoID={this.props.repoID}
|
|
|
|
path={this.props.path}
|
|
|
|
target={this.props.dirent.name}
|
|
|
|
toggleDialog={this.closeZipDialog}
|
2018-11-27 06:47:19 +00:00
|
|
|
/>
|
|
|
|
</ModalPortal>
|
|
|
|
}
|
2018-12-06 03:28:16 +00:00
|
|
|
{this.state.isShareDialogShow &&
|
|
|
|
<ModalPortal>
|
2020-11-02 05:56:35 +00:00
|
|
|
<ShareDialog
|
2018-12-14 07:09:07 +00:00
|
|
|
itemType={dirent.type}
|
2018-12-06 03:28:16 +00:00
|
|
|
itemName={dirent.name}
|
2018-12-14 07:09:07 +00:00
|
|
|
itemPath={direntPath}
|
2019-01-29 02:06:26 +00:00
|
|
|
userPerm={dirent.permission}
|
2018-12-06 03:28:16 +00:00
|
|
|
repoID={this.props.repoID}
|
2020-07-21 03:16:33 +00:00
|
|
|
repoEncrypted={this.props.repoEncrypted}
|
2019-01-29 02:06:26 +00:00
|
|
|
enableDirPrivateShare={this.props.enableDirPrivateShare}
|
|
|
|
isGroupOwnedRepo={this.props.isGroupOwnedRepo}
|
2019-01-05 12:40:41 +00:00
|
|
|
toggleDialog={this.closeSharedDialog}
|
2018-12-06 03:28:16 +00:00
|
|
|
/>
|
|
|
|
</ModalPortal>
|
|
|
|
}
|
2019-05-15 00:01:48 +00:00
|
|
|
{this.state.isPermissionDialogOpen &&
|
|
|
|
<ModalPortal>
|
2020-11-02 05:56:35 +00:00
|
|
|
<LibSubFolderPermissionDialog
|
2019-05-15 00:01:48 +00:00
|
|
|
toggleDialog={this.onPermissionItem}
|
|
|
|
repoID={this.props.repoID}
|
|
|
|
folderPath={direntPath}
|
|
|
|
folderName={dirent.name}
|
2019-05-17 07:53:59 +00:00
|
|
|
isDepartmentRepo={this.props.isGroupOwnedRepo}
|
2019-05-15 00:01:48 +00:00
|
|
|
/>
|
|
|
|
</ModalPortal>
|
|
|
|
}
|
2018-11-27 06:47:19 +00:00
|
|
|
</Fragment>
|
2018-10-13 09:07:54 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DirentListItem.propTypes = propTypes;
|
|
|
|
|
|
|
|
export default DirentListItem;
|