import React, { Component, Fragment } from 'react'; import PropTypes from 'prop-types'; import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap'; import { Utils } from '../../../utils/utils'; import { seafileAPI } from '../../../utils/seafile-api'; import { gettext, siteRoot, mediaUrl, orgID } from '../../../utils/constants'; import toaster from '../../../components/toast/index'; import EmptyTip from '../../../components/empty-tip'; import Loading from '../../../components/loading'; import Paginator from '../../../components/paginator'; import ModalPortal from '../../../components/modal-portal'; import TransferDialog from '../../../components/dialog/transfer-dialog'; import { navigate } from '@gatsbyjs/reach-router'; import OrgAdminRepo from '../../../models/org-admin-repo'; import MainPanelTopbar from '../main-panel-topbar'; import ReposNav from './org-repo-nav'; class Content extends Component { constructor(props) { super(props); this.state = { isItemFreezed: false }; } onFreezedItem = () => { this.setState({ isItemFreezed: true }); }; onUnfreezedItem = () => { this.setState({ isItemFreezed: false }); }; getPreviousPageList = () => { this.props.getListByPage(this.props.pageInfo.current_page - 1); }; getNextPageList = () => { this.props.getListByPage(this.props.pageInfo.current_page + 1); }; sortByFileCount = (e) => { e.preventDefault(); this.props.sortItems('file_count'); }; sortBySize = (e) => { e.preventDefault(); this.props.sortItems('size'); }; render() { // offer 'sort' only for 'all repos' const { loading, errorMsg, items, pageInfo, curPerPage, sortBy } = this.props; if (loading) { return ; } else if (errorMsg) { return

{errorMsg}

; } else { const emptyTip = ( ); const initialSortIcon = ; const sortIcon = ; const table = ( {items.map((item, index) => { return (); })}
{/* icon*/} {gettext('Name')} {sortBy != undefined ? {gettext('Files')} {sortBy == 'file_count' ? sortIcon : initialSortIcon}{' / '} {gettext('Size')} {sortBy == 'size' ? sortIcon : initialSortIcon} : gettext('Files') / gettext('Size') } ID {gettext('Owner')} {/* Operations*/}
{pageInfo && }
); return items.length ? table : emptyTip; } } } Content.propTypes = { loading: PropTypes.bool.isRequired, errorMsg: PropTypes.string.isRequired, items: PropTypes.array.isRequired, deleteItem: PropTypes.func, onDeleteRepo: PropTypes.func.isRequired, onRestoreRepo: PropTypes.func, getListByPage: PropTypes.func.isRequired, resetPerPage: PropTypes.func, pageInfo: PropTypes.object, curPerPage: PropTypes.number, sortItems: PropTypes.func, sortBy: PropTypes.string, transferRepoItem: PropTypes.func.isRequired, }; const propTypes = { repo: PropTypes.object.isRequired, isItemFreezed: PropTypes.bool, onFreezedItem: PropTypes.func.isRequired, onUnfreezedItem: PropTypes.func.isRequired, onDeleteRepo: PropTypes.func.isRequired, transferRepoItem: PropTypes.func.isRequired, }; class RepoItem extends React.Component { constructor(props) { super(props); this.state = { highlight: false, showMenu: false, isItemMenuShow: false, isTransferDialogShow: false, }; } onMouseEnter = () => { if (!this.props.isItemFreezed) { this.setState({ showMenu: true, highlight: true, }); } }; onMouseLeave = () => { if (!this.props.isItemFreezed) { this.setState({ showMenu: false, highlight: false }); } }; onDropdownToggleClick = (e) => { e.preventDefault(); this.toggleOperationMenu(e); }; toggleOperationMenu = (e) => { e.stopPropagation(); this.setState( { isItemMenuShow: !this.state.isItemMenuShow }, () => { if (this.state.isItemMenuShow) { this.props.onFreezedItem(); } else { this.setState({ highlight: false, showMenu: false, }); this.props.onUnfreezedItem(); } } ); }; toggleDelete = () => { this.props.onDeleteRepo(this.props.repo); }; renderLibIcon = (repo) => { let href; let iconTitle; if (repo.encrypted) { href = mediaUrl + 'img/lib/48/lib-encrypted.png'; iconTitle = gettext('Encrypted library'); } else { href = mediaUrl + 'img/lib/48/lib.png'; iconTitle = gettext('Read-Write library'); } return {iconTitle}; }; renderRepoOwnerHref = (repo) => { let href; if (repo.isDepartmentRepo) { href = siteRoot + 'org/groupadmin/' + repo.groupID + '/'; } else { href = siteRoot + 'org/useradmin/info/' + repo.ownerEmail + '/'; } return href; }; toggleTransfer = () => { this.setState({ isTransferDialogShow: !this.state.isTransferDialogShow }); }; onTransferRepo = (user) => { let repo = this.props.repo; let email = null; if (Array.isArray(user)) { email = user[0].email; } else { email = user.email; } seafileAPI.orgAdminTransferOrgRepo(orgID, repo.repoID, email).then(res => { this.props.transferRepoItem(repo.repoID, user); let msg = gettext('Successfully transferred the library.'); toaster.success(msg); }).catch(error => { let errMessage = Utils.getErrorMsg(error); toaster.danger(errMessage); }); this.toggleTransfer(); }; render() { let { repo } = this.props; let isOperationMenuShow = this.state.showMenu; return ( {this.renderLibIcon(repo)} {repo.repoName} {`${repo.file_count} / ${Utils.bytesToSize(repo.size)}`} {repo.repoID} {repo.ownerName} {isOperationMenuShow && {gettext('Delete')} {gettext('Transfer')} } {this.state.isTransferDialogShow && ( )} ); } } RepoItem.propTypes = propTypes; class OrgAllRepos extends Component { constructor(props) { super(props); this.state = { loading: true, errorMsg: '', repos: [], pageInfo: {}, perPage: 100, sortBy: '', }; } componentDidMount() { let urlParams = (new URL(window.location)).searchParams; const { currentPage = 1, perPage, sortBy } = this.state; this.setState({ sortBy: urlParams.get('order_by') || sortBy, perPage: parseInt(urlParams.get('per_page') || perPage), currentPage: parseInt(urlParams.get('page') || currentPage) }, () => { this.getReposByPage(this.state.currentPage); }); } getReposByPage = (page) => { let { perPage } = this.state; seafileAPI.orgAdminListOrgRepos(orgID, page, perPage, this.state.sortBy).then((res) => { let orgRepos = res.data.repo_list.map(item => { return new OrgAdminRepo(item); }); let page_info = {}; if (res.data.page_info === undefined) { let page = res.data.page; let has_next_page = res.data.page_next; page_info = { 'current_page': page, 'has_next_page': has_next_page }; } else { page_info = res.data.page_info; } this.setState({ loading: false, repos: orgRepos, pageInfo: page_info }); }).catch((error) => { this.setState({ loading: false, errorMsg: Utils.getErrorMsg(error, true) // true: show login tip if 403 }); }); }; sortItems = (sortBy) => { this.setState({ currentPage: 1, sortBy: sortBy }, () => { let url = new URL(location.href); let searchParams = new URLSearchParams(url.search); const { currentPage, sortBy } = this.state; searchParams.set('page', currentPage); searchParams.set('order_by', sortBy); url.search = searchParams.toString(); navigate(url.toString()); this.getReposByPage(currentPage); }); }; resetPerPage = (perPage) => { this.setState({ perPage: perPage }, () => { this.getReposByPage(1); }); }; deleteRepoItem = (repo) => { seafileAPI.orgAdminDeleteOrgRepo(orgID, repo.repoID).then(res => { this.setState({ repos: this.state.repos.filter(item => item.repoID !== repo.repoID) }); let msg = gettext('Successfully deleted {name}'); msg = msg.replace('{name}', repo.repoName); toaster.success(msg); }).catch(error => { let errMessage = Utils.getErrorMsg(error); toaster.danger(errMessage); }); }; transferRepoItem = (repoID, user) => { this.setState({ repos: this.state.repos.map(item => { if (item.repoID == repoID) { item.ownerEmail = user.email; item.ownerName = user.value; } return item; }) }); }; render() { return (
); } } export default OrgAllRepos;