import React from 'react'; import ReactDom from 'react-dom'; import PropTypes from 'prop-types'; import { navigate } from '@gatsbyjs/reach-router'; 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 ConfirmRestoreRepo from './components/dialog/confirm-restore-repo'; import './css/toolbar.css'; import './css/search.css'; import './css/repo-snapshot.css'; const { repoID, repoName, canRestoreRepo, commitID, commitTime, commitDesc, commitRelativeTime, showAuthor, authorAvatarURL, authorName, authorNickName } = window.app.pageOptions; class RepoSnapshot extends React.Component { constructor(props) { super(props); this.state = { isLoading: true, errorMsg: '', folderPath: '/', folderItems: [], isConfirmDialogOpen: false }; } componentDidMount() { this.renderFolder(this.state.folderPath); } toggleDialog = () => { this.setState({ isConfirmDialogOpen: !this.state.isConfirmDialogOpen }); }; onSearchedClick = (selectedItem) => { if (selectedItem.is_dir === true) { let url = siteRoot + 'library/' + selectedItem.repo_id + '/' + selectedItem.repo_name + selectedItem.path; navigate(url, { replace: 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(); }; renderFolder = (folderPath) => { this.setState({ folderPath: folderPath, folderItems: [], isLoading: true }); seafileAPI.listCommitDir(repoID, commitID, folderPath).then((res) => { this.setState({ isLoading: false, folderItems: res.data.dirent_list }); }).catch((error) => { this.setState({ isLoading: false, errorMsg: Utils.getErrorMsg(error, true) // true: show login tip if 403 }); }); }; clickFolderPath = (folderPath, e) => { e.preventDefault(); this.renderFolder(folderPath); }; renderPath = () => { const path = this.state.folderPath; const pathList = path.split('/'); if (path == '/') { return {repoName}; } return ( {repoName} / {pathList.map((item, index) => { if (index > 0 && index != pathList.length - 1) { return ( {pathList[index]} / ); } return null; } )} {pathList[pathList.length - 1]} ); }; restoreRepo = () => { seafileAPI.revertRepo(repoID, commitID).then((res) => { this.toggleDialog(); toaster.success(gettext('Successfully restored the library.')); }).catch((error) => { let errorMsg = Utils.getErrorMsg(error); this.toggleDialog(); toaster.danger(errorMsg); }); }; render() { const { isConfirmDialogOpen, folderPath } = this.state; let title = gettext('{placeholder} Snapshot'); title = title.replace('{placeholder}', '' + Utils.HTMLescape(repoName) + ''); return (
logo

({commitTime})

{folderPath == '/' && (

{commitDesc}

{showAuthor ? ( {authorNickName} ) : {gettext('Unknown')}}

)}

{gettext('Current path: ')}{this.renderPath()}

{(folderPath == '/' && canRestoreRepo) && }
{isConfirmDialogOpen && }
); } } class Content extends React.Component { constructor(props) { super(props); this.theadData = [ { width: '5%', text: '' }, { width: '55%', text: gettext('Name') }, { width: '20%', text: gettext('Size') }, { width: '20%', text: '' } ]; } render() { const { isLoading, errorMsg, folderPath, folderItems } = this.props.data; if (isLoading) { return ; } if (errorMsg) { return

{errorMsg}

; } return ( {this.theadData.map((item, index) => { return ; })} {folderItems.map((item, index) => { return ; }) }
{item.text}
); } } Content.propTypes = { data: 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 }); }; restoreItem = (e) => { e.preventDefault(); const item = this.props.item; const path = Utils.joinPath(this.props.folderPath, item.name); const request = item.type == 'dir' ? seafileAPI.revertFolder(repoID, path, commitID) : seafileAPI.revertFile(repoID, path, commitID); request.then((res) => { toaster.success(gettext('Restored 1 item')); }).catch((error) => { let errorMsg = Utils.getErrorMsg(error); toaster.danger(errorMsg); }); }; renderFolder = (e) => { e.preventDefault(); const item = this.props.item; const { folderPath } = this.props; this.props.renderFolder(Utils.joinPath(folderPath, item.name)); }; render() { const item = this.props.item; const { isIconShown } = this.state; const { folderPath } = this.props; return item.type == 'dir' ? ( {gettext('Folder')} {item.name} ) : ( {gettext('File')} {item.name} {Utils.bytesToSize(item.size)} ); } } FolderItem.propTypes = { item: PropTypes.object.isRequired, folderPath: PropTypes.string.isRequired, renderFolder: PropTypes.func.isRequired, }; ReactDom.render(, document.getElementById('wrapper'));