1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-07-23 19:27:33 +00:00
seahub/frontend/src/components/dirent-list-view/dirent-list-view.js

289 lines
9.4 KiB
JavaScript
Raw Normal View History

import React, { Fragment } from 'react';
2018-10-13 09:07:54 +00:00
import PropTypes from 'prop-types';
import { siteRoot, gettext, thumbnailSizeForOriginal } from '../../utils/constants';
import { Utils } from '../../utils/utils';
import Loading from '../loading';
2018-10-13 09:07:54 +00:00
import DirentListItem from './dirent-list-item';
import ModalPortal from '../modal-portal';
import CreateFile from '../../components/dialog/create-file-dialog';
import Lightbox from 'react-image-lightbox';
import 'react-image-lightbox/style.css';
import '../../css/tip-for-new-md.css';
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,
repoEncrypted: PropTypes.bool.isRequired,
2018-11-28 04:41:49 +00:00
isRepoOwner: PropTypes.bool,
2018-12-18 09:21:01 +00:00
currentRepoInfo: PropTypes.object,
2018-11-28 04:41:49 +00:00
isAllItemSelected: PropTypes.bool.isRequired,
isDirentListLoading: PropTypes.bool.isRequired,
2018-10-13 09:07:54 +00:00
direntList: PropTypes.array.isRequired,
sortBy: PropTypes.string.isRequired,
sortOrder: PropTypes.string.isRequired,
sortItems: PropTypes.func.isRequired,
onAddFile: PropTypes.func.isRequired,
2018-10-13 09:07:54 +00:00
onItemDelete: PropTypes.func.isRequired,
2018-11-23 12:19:42 +00:00
onAllItemSelected: PropTypes.func.isRequired,
onItemSelected: PropTypes.func.isRequired,
onItemRename: PropTypes.func.isRequired,
2018-10-13 09:07:54 +00:00
onItemClick: PropTypes.func.isRequired,
onItemMove: PropTypes.func.isRequired,
onItemCopy: PropTypes.func.isRequired,
onDirentClick: PropTypes.func.isRequired,
onItemDetails: PropTypes.func.isRequired,
2018-11-22 03:26:00 +00:00
updateDirent: PropTypes.func.isRequired,
2018-10-13 09:07:54 +00:00
};
class DirentListView extends React.Component {
constructor(props) {
super(props);
this.state = {
isItemFreezed: false,
isImagePopupOpen: false,
imageItems: [],
imageIndex: 0,
isCreateFileDialogShow: false,
fileType: ''
2018-10-13 09:07:54 +00:00
};
}
onFreezedItem = () => {
2018-10-13 09:07:54 +00:00
this.setState({isItemFreezed: true});
}
2018-11-22 03:26:00 +00:00
onUnfreezedItem = () => {
2018-10-13 09:07:54 +00:00
this.setState({isItemFreezed: false});
}
2018-11-23 12:19:42 +00:00
onItemRenameToggle = () => {
this.onFreezedItem();
2018-10-13 09:07:54 +00:00
}
2018-11-29 09:55:14 +00:00
onItemDetails = (dirent) => {
this.props.onItemDetails(dirent);
}
onCreateFileToggle = () => {
this.setState({
isCreateFileDialogShow: !this.state.isCreateFileDialogShow,
fileType: ''
});
}
onCreateMarkdownToggle = () => {
this.setState({
isCreateFileDialogShow: !this.state.isCreateFileDialogShow,
fileType: '.md'
});
}
onAddFile = (filePath, isDraft) => {
this.setState({isCreateFileDialogShow: false});
this.props.onAddFile(filePath, isDraft);
}
sortByName = (e) => {
e.preventDefault();
const sortBy = 'name';
const sortOrder = this.props.sortOrder == 'asc' ? 'desc' : 'asc';
this.props.sortItems(sortBy, sortOrder);
}
sortByTime = (e) => {
e.preventDefault();
const sortBy = 'time';
const sortOrder = this.props.sortOrder == 'asc' ? 'desc' : 'asc';
this.props.sortItems(sortBy, sortOrder);
}
// for image popup
prepareImageItems = () => {
let items = this.props.direntList.filter((item) => {
return Utils.imageCheck(item.name);
});
const useThumbnail = !this.props.repoEncrypted;
let prepareItem = (item) => {
const name = item.name;
const fileExt = name.substr(name.lastIndexOf('.') + 1).toLowerCase();
const isGIF = fileExt == 'gif';
const path = Utils.encodePath(Utils.joinPath(this.props.path, name));
const repoID = this.props.repoID;
let src;
if (useThumbnail && !isGIF) {
src = `${siteRoot}thumbnail/${repoID}/${thumbnailSizeForOriginal}${path}`;
} else {
src = `${siteRoot}repo/${repoID}/raw${path}`;
}
return {
'name': name,
'url': `${siteRoot}lib/${repoID}/file${path}`,
'src': src
};
}
return items.map((item) => { return prepareItem(item); });
}
showImagePopup = (dirent) => {
let items = this.props.direntList.filter((item) => {
return Utils.imageCheck(item.name);
});
this.setState({
isImagePopupOpen: true,
imageItems: this.prepareImageItems(),
imageIndex: items.indexOf(dirent)
});
}
moveToPrevImage = () => {
const imageItemsLength = this.state.imageItems.length;
this.setState((prevState) => ({
imageIndex: (prevState.imageIndex + imageItemsLength - 1) % imageItemsLength
}));
}
moveToNextImage = () => {
const imageItemsLength = this.state.imageItems.length;
this.setState((prevState) => ({
imageIndex: (prevState.imageIndex + 1) % imageItemsLength
}));
}
closeImagePopup = () => {
this.setState({
isImagePopupOpen: false
});
}
2018-10-13 09:07:54 +00:00
render() {
const { direntList, sortBy, sortOrder } = this.props;
if (this.props.isDirentListLoading) {
return (<Loading />);
}
if (this.props.path == '/' && !direntList.length) {
return (
<Fragment>
<div className="tip-for-new-md d-flex">
<button className="big-new-md-button" onClick={this.onCreateMarkdownToggle}><span className="sf2-icon-plus add-md-icon"></span><br />{gettext('Markdown Document')}</button>
<p>{gettext('You can create online document using Markdown format easily. When creating a document, you can mark it as draft. After finishing the draft, you can ask others to review it. They can view the document history in the review page and leave comments on the document.')}</p>
</div>
{this.state.isCreateFileDialogShow && (
<ModalPortal>
<CreateFile
parentPath={this.props.path}
fileType={this.state.fileType}
onAddFile={this.onAddFile}
addFileCancel={this.onCreateFileToggle}
/>
</ModalPortal>
)}
</Fragment>
);
}
// sort
const sortByName = sortBy == 'name';
const sortByTime = sortBy == 'time';
const sortIcon = sortOrder == 'asc' ? <span className="fas fa-caret-up"></span> : <span className="fas fa-caret-down"></span>;
// for image popup
const imageItems = this.state.imageItems;
const imageIndex = this.state.imageIndex;
const imageItemsLength = imageItems.length;
const imageCaption = imageItemsLength && (
<Fragment>
<span>{gettext("%curr% of %total%").replace('%curr%', imageIndex + 1).replace('%total%', imageItemsLength)}</span>
<br />
<a href={imageItems[imageIndex].url} target="_blank">{gettext("Open in New Tab")}</a>
</Fragment>
);
2018-10-13 09:07:54 +00:00
return (
<Fragment>
2018-11-23 12:19:42 +00:00
<table>
<thead>
<tr>
2018-12-28 03:12:24 +00:00
<th width="3%" className="text-center">
2018-11-23 12:19:42 +00:00
<input type="checkbox" className="vam" onChange={this.props.onAllItemSelected} checked={this.props.isAllItemSelected}/>
</th>
2018-12-17 08:52:04 +00:00
<th width="3%">{/*icon */}</th>
<th width="5%">{/*star */}</th>
<th width="39%"><a className="d-block table-sort-op" href="#" onClick={this.sortByName}>{gettext('Name')} {sortByName && sortIcon}</a></th>
2018-12-17 08:52:04 +00:00
<th width="6%">{/*tag */}</th>
<th width="20%">{/*operation */}</th>
2018-11-23 12:19:42 +00:00
<th width="11%">{gettext('Size')}</th>
<th width="13%"><a className="d-block table-sort-op" href="#" onClick={this.sortByTime}>{gettext('Last Update')} {sortByTime && sortIcon}</a></th>
2018-11-23 12:19:42 +00:00
</tr>
</thead>
<tbody>
{
direntList.length !== 0 && direntList.map((dirent, index) => {
return (
<DirentListItem
key={index}
dirent={dirent}
path={this.props.path}
2018-11-28 04:41:49 +00:00
repoID={this.props.repoID}
2018-12-18 09:21:01 +00:00
currentRepoInfo={this.props.currentRepoInfo}
2018-11-23 12:19:42 +00:00
isRepoOwner={this.props.isRepoOwner}
onItemClick={this.props.onItemClick}
onItemRenameToggle={this.onItemRenameToggle}
onItemSelected={this.props.onItemSelected}
onItemDelete={this.props.onItemDelete}
onItemRename={this.props.onItemRename}
onItemMove={this.props.onItemMove}
onItemCopy={this.props.onItemCopy}
2018-11-23 12:19:42 +00:00
updateDirent={this.props.updateDirent}
isItemFreezed={this.state.isItemFreezed}
onFreezedItem={this.onFreezedItem}
onUnfreezedItem={this.onUnfreezedItem}
onDirentClick={this.props.onDirentClick}
2018-11-23 12:19:42 +00:00
onItemDetails={this.onItemDetails}
showImagePopup={this.showImagePopup}
2018-11-23 12:19:42 +00:00
/>
);
})
}
</tbody>
</table>
{this.state.isImagePopupOpen && (
<Lightbox
mainSrc={imageItems[imageIndex].src}
imageTitle={imageItems[imageIndex].name}
imageCaption={imageCaption}
nextSrc={imageItems[(imageIndex + 1) % imageItemsLength].src}
prevSrc={imageItems[(imageIndex + imageItemsLength - 1) % imageItemsLength].src}
onCloseRequest={this.closeImagePopup}
onMovePrevRequest={this.moveToPrevImage}
onMoveNextRequest={this.moveToNextImage}
2019-01-19 04:15:26 +00:00
imagePadding={70}
imageLoadErrorMessage={gettext('The image could not be loaded.')}
prevLabel={gettext("Previous (Left arrow key)")}
nextLabel={gettext("Next (Right arrow key)")}
closeLabel={gettext("Close (Esc)")}
zoomInLabel={gettext('Zoom in')}
zoomOutLabel={gettext('Zoom out')}
/>
)}
</Fragment>
2018-10-13 09:07:54 +00:00
);
}
}
DirentListView.propTypes = propTypes;
export default DirentListView;