import React, { Component, Fragment } from 'react'; import PropTypes from 'prop-types'; import { seafileAPI } from '../../../utils/seafile-api'; import { gettext } from '../../../utils/constants'; import { Utils } from '../../../utils/utils'; import EmptyTip from '../../../components/empty-tip'; import { Button } from 'reactstrap'; import { navigate } from '@gatsbyjs/reach-router'; import moment from 'moment'; import Loading from '../../../components/loading'; import Paginator from '../../../components/paginator'; import LogsExportExcelDialog from '../../../components/dialog/sysadmin-dialog/sysadmin-logs-export-excel-dialog'; import ModalPortal from '../../../components/modal-portal'; import LogsNav from './logs-nav'; import FilterMenu from './file-access-item-menu'; import ToggleFilter from './file-access-toggle-filter'; import MainPanelTopbar from '../main-panel-topbar'; import UserLink from '../user-link'; class Content extends Component { constructor(props) { super(props); this.state = { isItemFreezed: false }; } getPreviousPage = () => { this.props.getLogsByPage(this.props.currentPage - 1); }; getNextPage = () => { this.props.getLogsByPage(this.props.currentPage + 1); }; toggleFilterByUser = () => { this.props.filterByUser(null); }; toggleFilterByRepo = () => { this.props.filterByRepo(null); }; toggleFreezeItem = (freezed) => { this.setState({ isItemFreezed: freezed }); }; render() { const { loading, errorMsg, items, userFilteredBy, repoFilteredBy, perPage, currentPage, hasNextPage } = this.props; if (loading) { return ; } else if (errorMsg) { return

{errorMsg}

; } else { const emptyTip = ( ); const table = (
{userFilteredBy && ( )} {repoFilteredBy && ( )}
{items && {items.map((item, index) => { return (); })} }
{gettext('Name')} {gettext('Type')} {gettext('IP')}{' / '}{gettext('Device')} {gettext('Date')} {gettext('Library')} {gettext('File')}{' / '}{gettext('Folder')}
); return items.length ? table : emptyTip; } } } Content.propTypes = { loading: PropTypes.bool, errorMsg: PropTypes.string, items: PropTypes.array, getLogsByPage: PropTypes.func, resetPerPage: PropTypes.func, currentPage: PropTypes.number, perPage: PropTypes.number, pageInfo: PropTypes.object, hasNextPage: PropTypes.bool, toggleFreezeItem: PropTypes.func, userFilteredBy: PropTypes.string, repoFilteredBy: PropTypes.string, filterByUser: PropTypes.func, filterByRepo: PropTypes.func, }; class Item extends Component { constructor(props) { super(props); this.state = { isHighlighted: false, isOpIconShown: false }; } handleMouseEnter = () => { if (!this.props.isFreezed) { this.setState({ isHighlighted: true, isOpIconShown: true }); } }; handleMouseLeave = () => { if (!this.props.isFreezed) { this.setState({ isHighlighted: false, isOpIconShown: false }); } }; filterByUser = () => { const { item } = this.props; this.props.filterByUser(item.email); }; filterByRepo = () => { const { item } = this.props; this.props.filterByRepo(item.repo_id); }; toggleFreezeItem = (freezed) => { this.props.toggleFreezeItem(freezed); if (!freezed) { this.setState({ isHighlighted: false, isOpIconShown: false }); } }; render() { const { isHighlighted, isOpIconShown } = this.state; const { item, userFilteredBy, repoFilteredBy } = this.props; return ( {isOpIconShown && !userFilteredBy && ( )} {item.event_type} {item.ip}{' / '}{item.device || '--'} {moment(item.time).fromNow()} {item.repo_name ? item.repo_name : gettext('Deleted')} {isOpIconShown && item.repo_name && !repoFilteredBy && ( )} {item.file_or_dir_name} ); } } Item.propTypes = { item: PropTypes.object, isFreezed: PropTypes.bool, toggleFreezeItem: PropTypes.func, userFilteredBy: PropTypes.string, repoFilteredBy: PropTypes.string, filterByUser: PropTypes.func, filterByRepo: PropTypes.func, }; class FileAccessLogs extends Component { constructor(props) { super(props); this.state = { loading: true, errorMsg: '', logList: [], perPage: 100, currentPage: 1, hasNextPage: false, isExportExcelDialogOpen: false, }; this.initPage = 1; } toggleExportExcelDialog = () => { this.setState({ isExportExcelDialogOpen: !this.state.isExportExcelDialogOpen }); }; componentDidMount() { let urlParams = (new URL(window.location)).searchParams; const { currentPage, perPage } = this.state; this.setState({ perPage: parseInt(urlParams.get('per_page') || perPage), currentPage: parseInt(urlParams.get('page') || currentPage), userFilteredBy: urlParams.get('email'), repoFilteredBy: urlParams.get('repo_id') }, () => { this.getLogsByPage(this.state.currentPage); }); } getLogsByPage = (page) => { const { perPage, userFilteredBy, repoFilteredBy } = this.state; seafileAPI.sysAdminListFileAccessLogs(page, perPage, userFilteredBy, repoFilteredBy).then((res) => { this.setState({ logList: res.data.file_access_log_list, loading: false, currentPage: page, hasNextPage: res.data.has_next_page, }); }).catch((error) => { this.setState({ loading: false, errorMsg: Utils.getErrorMsg(error, true) // true: show login tip if 403 }); }); }; resetPerPage = (newPerPage) => { this.setState({ perPage: newPerPage, }, () => this.getLogsByPage(this.initPage)); }; updateURL = (obj) => { let url = new URL(location.href); let searchParams = new URLSearchParams(url.search); for (let key in obj) { obj[key] == null ? searchParams.delete(key) : searchParams.set(key, obj[key]); } url.search = searchParams.toString(); navigate(url.toString()); }; filterByUser = (email) => { this.setState({ userFilteredBy: email }, () => { this.getLogsByPage(this.initPage); this.updateURL({ 'email': email }); }); }; filterByRepo = (repoID) => { this.setState({ repoFilteredBy: repoID }, () => { this.getLogsByPage(this.initPage); this.updateURL({ 'repo_id': repoID }); }); }; render() { const { logList, userFilteredBy, repoFilteredBy, currentPage, perPage, hasNextPage, isExportExcelDialogOpen } = this.state; return (
{isExportExcelDialogOpen && }
); } } export default FileAccessLogs;