import React from 'react'; import ReactDom from 'react-dom'; import PropTypes from 'prop-types'; import { navigate } from '@gatsbyjs/reach-router'; import moment from 'moment'; import { Utils } from './utils/utils'; import { gettext, siteRoot, mediaUrl, logoPath, logoWidth, logoHeight, siteTitle } from './utils/constants'; import { seafileAPI } from './utils/seafile-api'; import Loading from './components/loading'; import ModalPortal from './components/modal-portal'; import toaster from './components/toast'; import CommonToolbar from './components/toolbar/common-toolbar'; import CleanTrash from './components/dialog/clean-trash'; import './css/toolbar.css'; import './css/search.css'; import './css/repo-folder-trash.css'; const { repoID, repoFolderName, path, enableUserCleanTrash, isRepoAdmin } = window.app.pageOptions; class RepoFolderTrash extends React.Component { constructor(props) { super(props); this.state = { isLoading: true, errorMsg: '', items: [], scanStat: null, more: false, isCleanTrashDialogOpen: false, }; } componentDidMount() { this.getItems(); } getItems = (scanStat) => { seafileAPI.getRepoFolderTrash(repoID, path, scanStat).then((res) => { const { data, more, scan_stat } = res.data; if (!data.length && more) { this.getItems(scan_stat); } else { this.setState({ isLoading: false, items: this.state.items.concat(data), more: more, scanStat: scan_stat }); } }).catch((error) => { this.setState({ isLoading: false, errorMsg: Utils.getErrorMsg(error, true) // true: show login tip if 403 }); }); }; getMore = () => { this.setState({ isLoading: true }); this.getItems(this.state.scanStat); }; onSearchedClick = (selectedItem) => { if (selectedItem.is_dir === true) { let url = siteRoot + 'library/' + selectedItem.repo_id + '/' + selectedItem.repo_name + selectedItem.path; navigate(url, { repalce: true }); } else { let url = siteRoot + 'lib/' + selectedItem.repo_id + '/file' + Utils.encodePath(selectedItem.path); let newWindow = window.open('about:blank'); newWindow.location.href = url; } }; goBack = (e) => { e.preventDefault(); window.history.back(); }; cleanTrash = () => { this.toggleCleanTrashDialog(); }; toggleCleanTrashDialog = () => { this.setState({ isCleanTrashDialogOpen: !this.state.isCleanTrashDialogOpen }); }; refreshTrash = () => { this.setState({ isLoading: true, errorMsg: '', items: [], scanStat: null, more: false, showFolder: false }); this.getItems(); }; renderFolder = (commitID, baseDir, folderPath) => { this.setState({ showFolder: true, commitID: commitID, baseDir: baseDir, folderPath: folderPath, folderItems: [], isLoading: true }); seafileAPI.listCommitDir(repoID, commitID, `${baseDir.substr(0, baseDir.length - 1)}${folderPath}`).then((res) => { this.setState({ isLoading: false, folderItems: res.data.dirent_list }); }).catch((error) => { if (error.response) { if (error.response.status == 403) { this.setState({ isLoading: false, errorMsg: gettext('Permission denied') }); } else { this.setState({ isLoading: false, errorMsg: gettext('Error') }); } } else { this.setState({ isLoading: false, errorMsg: gettext('Please check the network.') }); } }); }; clickRoot = (e) => { e.preventDefault(); this.refreshTrash(); }; clickFolderPath = (folderPath, e) => { e.preventDefault(); const { commitID, baseDir } = this.state; this.renderFolder(commitID, baseDir, folderPath); }; renderFolderPath = () => { const pathList = this.state.folderPath.split('/'); return ( {repoFolderName} / {pathList.map((item, index) => { if (index > 0 && index != pathList.length - 1) { return ( {pathList[index]} / ); } return null; } )} {pathList[pathList.length - 1]} ); }; render() { const { isCleanTrashDialogOpen, showFolder } = this.state; let title = gettext('{placeholder} Trash'); title = title.replace('{placeholder}', '' + Utils.HTMLescape(repoFolderName) + ''); return (
logo

{gettext('Current path: ')}{showFolder ? this.renderFolderPath() : {repoFolderName}}

{(path === '/' && enableUserCleanTrash && !showFolder && isRepoAdmin) && }
{isCleanTrashDialogOpen && }
); } } class Content extends React.Component { constructor(props) { super(props); this.theadData = [ { width: '5%', text: '' }, { width: '20%', text: gettext('Name') }, { width: '40%', text: gettext('Original path') }, { width: '12%', text: gettext('Delete Time') }, { width: '13%', text: gettext('Size') }, { width: '10%', text: '' } ]; } render() { const { isLoading, errorMsg, items, more, showFolder, commitID, baseDir, folderPath, folderItems } = this.props.data; return ( {this.theadData.map((item, index) => { return ; })} {showFolder ? folderItems.map((item, index) => { return ; }) : items.map((item, index) => { return ; })}
{item.text}
{isLoading && } {errorMsg &&

{errorMsg}

} {(more && !isLoading && !showFolder) && ( )}
); } } Content.propTypes = { data: PropTypes.object.isRequired, getMore: PropTypes.func.isRequired, renderFolder: PropTypes.func.isRequired, }; class Item extends React.Component { constructor(props) { super(props); this.state = { restored: false, isIconShown: false }; } handleMouseOver = () => { this.setState({ isIconShown: true }); }; handleMouseOut = () => { this.setState({ isIconShown: false }); }; restoreItem = (e) => { e.preventDefault(); const item = this.props.item; const { commit_id, parent_dir, obj_name } = item; const path = parent_dir + obj_name; const request = item.is_dir ? seafileAPI.restoreFolder(repoID, commit_id, path) : seafileAPI.restoreFile(repoID, commit_id, path); request.then((res) => { this.setState({ restored: true }); toaster.success(gettext('Successfully restored 1 item.')); }).catch((error) => { let errorMsg = ''; if (error.response) { errorMsg = error.response.data.error_msg || gettext('Error'); } else { errorMsg = gettext('Please check the network.'); } toaster.danger(errorMsg); }); }; renderFolder = (e) => { e.preventDefault(); const item = this.props.item; this.props.renderFolder(item.commit_id, item.parent_dir, Utils.joinPath('/', item.obj_name)); }; render() { const item = this.props.item; const { restored, isIconShown } = this.state; if (restored) { return null; } return item.is_dir ? ( {gettext('Folder')} {item.obj_name} {item.parent_dir} {moment(item.deleted_time).format('YYYY-MM-DD')} {gettext('Restore')} ) : ( {gettext('File')} {item.obj_name} {item.parent_dir} {moment(item.deleted_time).format('YYYY-MM-DD')} {Utils.bytesToSize(item.size)} {gettext('Restore')} ); } } Item.propTypes = { item: PropTypes.object.isRequired, renderFolder: PropTypes.func.isRequired, }; class FolderItem extends React.Component { constructor(props) { super(props); this.state = { isIconShown: false }; } handleMouseOver = () => { this.setState({ isIconShown: true }); }; handleMouseOut = () => { this.setState({ isIconShown: false }); }; renderFolder = (e) => { e.preventDefault(); const item = this.props.item; const { commitID, baseDir, folderPath } = this.props; this.props.renderFolder(commitID, baseDir, Utils.joinPath(folderPath, item.name)); }; render() { const item = this.props.item; const { commitID, baseDir, folderPath } = this.props; return item.type == 'dir' ? ( {gettext('Folder')} {item.name} {item.parent_dir} ) : ( {gettext('File')} {item.name} {item.parent_dir} {Utils.bytesToSize(item.size)} ); } } FolderItem.propTypes = { item: PropTypes.object.isRequired, commitID: PropTypes.string.isRequired, baseDir: PropTypes.string.isRequired, folderPath: PropTypes.string.isRequired, renderFolder: PropTypes.func.isRequired, }; ReactDom.render(, document.getElementById('wrapper'));