mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-28 16:17:02 +00:00
Optimize fileter log (#7669)
* filter log v1 * optimize log user selector * optimize ui and filter repo * optimize ui of file update and permission * admin filter completed * optimize selector component * optimize lint * optimize code * optimize filter * update * add filter group audit * update parameters * Update log-user-selector.js * Update log-filter.css * update var name * update func name --------- Co-authored-by: 孙永强 <11704063+s-yongqiang@user.noreply.gitee.com> Co-authored-by: r350178982 <32759763+r350178982@users.noreply.github.com>
This commit is contained in:
74
frontend/src/css/log-filter.css
Normal file
74
frontend/src/css/log-filter.css
Normal file
@@ -0,0 +1,74 @@
|
||||
.activity-details {
|
||||
text-decoration: underline;
|
||||
cursor: pointer;
|
||||
}
|
||||
.activity-details:hover {
|
||||
color: #212529;
|
||||
}
|
||||
.mobile-activity-time {
|
||||
display: inline-block;
|
||||
margin-bottom: .2em;
|
||||
}
|
||||
|
||||
.cur-activity-modifiers {
|
||||
margin-left: -0.5rem;
|
||||
}
|
||||
|
||||
.cur-activity-modifiers:hover {
|
||||
background: #f5f5f5;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.cur-activity-modifiers .toggle-icon {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.activity-modifier-selector-container {
|
||||
width: 320px;
|
||||
background: #fff;
|
||||
border: 1px solid #e8e8e8;
|
||||
margin-top: 2px;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.activity-selected-modifiers {
|
||||
min-height: 2rem;
|
||||
background: #f6f6f6;
|
||||
border-bottom: 1px solid #dde2ea;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.activity-selected-modifier {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
margin-right: 10px;
|
||||
padding: 0 8px 0 2px;
|
||||
border-radius: 10px;
|
||||
background: #eaeaea;
|
||||
}
|
||||
|
||||
.unselect-activity-user {
|
||||
color: #909090;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.unselect-activity-user:hover {
|
||||
color: #5a5a5a;
|
||||
}
|
||||
|
||||
.activity-user-list {
|
||||
min-height: 4rem;
|
||||
max-height: 200px;
|
||||
}
|
||||
|
||||
.activity-user-item {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.activity-user-item:hover {
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.activity-user-name {
|
||||
font-size: 14px;
|
||||
}
|
@@ -235,7 +235,7 @@ class FilesActivities extends Component {
|
||||
const { onlyMine } = this.props;
|
||||
const { targetUsers, availableUsers } = this.state;
|
||||
return (
|
||||
<div className="main-panel-center">
|
||||
<div className="mt-4">
|
||||
<div className="cur-view-container" id="activities">
|
||||
<div className="cur-view-path">
|
||||
<ul className="nav">
|
||||
|
154
frontend/src/pages/dashboard/log-repo-selector.js
Normal file
154
frontend/src/pages/dashboard/log-repo-selector.js
Normal file
@@ -0,0 +1,154 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Input } from 'reactstrap';
|
||||
import { gettext } from '../../utils/constants';
|
||||
import '../../css/log-filter.css';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import toaster from '../../components/toast';
|
||||
|
||||
const propTypes = {
|
||||
items: PropTypes.array.isRequired,
|
||||
selectedItems: PropTypes.array.isRequired,
|
||||
onSelect: PropTypes.func.isRequired,
|
||||
isOpen: PropTypes.bool.isRequired,
|
||||
onToggle: PropTypes.func.isRequired,
|
||||
searchReposFunc: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class LogRepoSelector extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
query: '',
|
||||
isLoading: false,
|
||||
searchResults: []
|
||||
};
|
||||
this.dropdownRef = React.createRef();
|
||||
this.finalValue = '';
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
document.addEventListener('click', this.handleClickOutside);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
document.removeEventListener('click', this.handleClickOutside);
|
||||
}
|
||||
|
||||
handleClickOutside = (e) => {
|
||||
if (this.props.isOpen && !this.repoSelector.contains(e.target)) {
|
||||
this.props.onToggle();
|
||||
}
|
||||
};
|
||||
|
||||
onToggleClick = (e) => {
|
||||
e.stopPropagation();
|
||||
this.props.onToggle();
|
||||
};
|
||||
|
||||
onQueryChange = (e) => {
|
||||
const value = e.target.value;
|
||||
this.setState({ query: value });
|
||||
this.searchRepos(value);
|
||||
};
|
||||
|
||||
searchRepos = (value) => {
|
||||
this.finalValue = value;
|
||||
if (value.length > 0) {
|
||||
this.setState({ isLoading: true });
|
||||
setTimeout(() => {
|
||||
if (this.finalValue === value) {
|
||||
this.props.searchReposFunc(value).then((res) => {
|
||||
const repos = res.data.repo_list || res.data.repos || [];
|
||||
this.setState({
|
||||
searchResults: repos,
|
||||
isLoading: false
|
||||
});
|
||||
}).catch(error => {
|
||||
this.setState({ isLoading: false });
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
});
|
||||
}
|
||||
}, 500);
|
||||
} else {
|
||||
this.setState({ searchResults: [] });
|
||||
}
|
||||
};
|
||||
|
||||
toggleSelectItem = (e, item) => {
|
||||
e.stopPropagation();
|
||||
this.props.onSelect(item, false);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { query, isLoading, searchResults } = this.state;
|
||||
const { selectedItems, isOpen } = this.props;
|
||||
const displayItems = query.trim() ? searchResults : this.props.items;
|
||||
|
||||
return (
|
||||
<div className="position-relative d-inline-block" ref={this.dropdownRef}>
|
||||
<span className="cur-activity-modifiers d-inline-block p-2 rounded" onClick={this.onToggleClick}>
|
||||
{selectedItems.length > 0 ? (
|
||||
<>
|
||||
<span>{gettext('Libraries:')}</span>
|
||||
<span className="d-inline-block ml-1">{selectedItems.map(item => item.name).join(', ')}</span>
|
||||
</>
|
||||
) : gettext('Libraries')}
|
||||
<i className="sf3-font sf3-font-down ml-2 toggle-icon"></i>
|
||||
</span>
|
||||
{isOpen && (
|
||||
<div className="position-absolute activity-modifier-selector-container rounded shadow" ref={ref => this.repoSelector = ref}>
|
||||
<ul className="activity-selected-modifiers px-3 py-1 list-unstyled">
|
||||
{selectedItems.map((item, index) => (
|
||||
<li key={index} className="activity-selected-modifier">
|
||||
<i className="fas fa-folder"></i>
|
||||
<span className="activity-user-name ml-2">{item.name}</span>
|
||||
<i className="sf2-icon-close unselect-activity-user ml-2" onClick={(e) => {this.toggleSelectItem(e, item);}}></i>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<div className="px-3 pt-3">
|
||||
<Input
|
||||
type="text"
|
||||
placeholder={gettext('Find libraries')}
|
||||
value={query}
|
||||
onChange={this.onQueryChange}
|
||||
/>
|
||||
</div>
|
||||
<ul className="activity-user-list list-unstyled p-3 o-auto">
|
||||
{isLoading ? (
|
||||
<li className="text-center">{gettext('Loading...')}</li>
|
||||
) : displayItems.length === 0 ? (
|
||||
<li className="text-center">
|
||||
{query ? gettext('Library not found') : gettext('Enter characters to start searching')}
|
||||
</li>
|
||||
) : (
|
||||
displayItems.map((item, index) => {
|
||||
const isSelected = selectedItems.some(selected => selected.id === item.id);
|
||||
return (
|
||||
<li key={index}
|
||||
className="activity-user-item h-6 p-1 rounded d-flex justify-content-between align-items-center"
|
||||
onClick={(e) => {this.toggleSelectItem(e, item);}}
|
||||
>
|
||||
<div>
|
||||
<i className="fas fa-folder"></i>
|
||||
<span className="activity-user-name ml-2">{item.name}</span>
|
||||
</div>
|
||||
{isSelected && <i className="sf2-icon-tick text-gray font-weight-bold"></i>}
|
||||
</li>
|
||||
);
|
||||
})
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
LogRepoSelector.propTypes = propTypes;
|
||||
|
||||
export default LogRepoSelector;
|
190
frontend/src/pages/dashboard/log-user-selector.js
Normal file
190
frontend/src/pages/dashboard/log-user-selector.js
Normal file
@@ -0,0 +1,190 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Input } from 'reactstrap';
|
||||
import { gettext } from '../../utils/constants';
|
||||
import '../../css/log-filter.css';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import toaster from '../../components/toast';
|
||||
|
||||
const propTypes = {
|
||||
componentName: PropTypes.string.isRequired,
|
||||
items: PropTypes.array.isRequired,
|
||||
selectedItems: PropTypes.array.isRequired,
|
||||
onSelect: PropTypes.func.isRequired,
|
||||
isOpen: PropTypes.bool.isRequired,
|
||||
onToggle: PropTypes.func.isRequired,
|
||||
searchUsersFunc: PropTypes.func,
|
||||
searchGroupsFunc: PropTypes.func
|
||||
};
|
||||
|
||||
class LogUserSelector extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
query: '',
|
||||
searchResults: [],
|
||||
isLoading: false
|
||||
};
|
||||
this.dropdownRef = React.createRef();
|
||||
this.finalValue = '';
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
document.addEventListener('click', this.handleClickOutside);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
document.removeEventListener('click', this.handleClickOutside);
|
||||
}
|
||||
|
||||
handleClickOutside = (e) => {
|
||||
if (this.props.isOpen && !this.userSelector.contains(e.target)) {
|
||||
this.props.onToggle();
|
||||
}
|
||||
};
|
||||
|
||||
onToggleClick = (e) => {
|
||||
e.stopPropagation();
|
||||
this.props.onToggle();
|
||||
};
|
||||
|
||||
onQueryChange = (e) => {
|
||||
const value = e.target.value;
|
||||
this.setState({ query: value });
|
||||
this.handleSearchUser(value);
|
||||
};
|
||||
|
||||
handleSearchUser = (value) => {
|
||||
if (!value.trim()) {
|
||||
this.setState({
|
||||
searchResults: []
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
isLoading: true
|
||||
});
|
||||
|
||||
this.finalValue = value;
|
||||
|
||||
setTimeout(() => {
|
||||
if (this.finalValue === value) {
|
||||
if (this.props.searchUsersFunc) {
|
||||
this.props.searchUsersFunc(value).then((res) => {
|
||||
const users = res.data.user_list || res.data.users || [];
|
||||
this.setState({
|
||||
searchResults: users,
|
||||
isLoading: false
|
||||
}, () => {
|
||||
if (this.props.searchGroupsFunc) {
|
||||
this.props.searchGroupsFunc(value).then((res) => {
|
||||
const groups = res.data.group_list || res.data.groups || [];
|
||||
this.setState({
|
||||
searchResults: [...users, ...groups]
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}).catch((error) => {
|
||||
this.setState({
|
||||
isLoading: false
|
||||
});
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
});
|
||||
}
|
||||
if (this.props.searchGroupsFunc && !this.props.searchUsersFunc) {
|
||||
this.props.searchGroupsFunc(value).then((res) => {
|
||||
const groups = res.data.group_list || res.data.groups || [];
|
||||
this.setState({
|
||||
searchResults: groups,
|
||||
isLoading: false
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}, 500);
|
||||
};
|
||||
|
||||
toggleSelectItem = (e, item) => {
|
||||
e.stopPropagation();
|
||||
this.props.onSelect(item, false);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { query, isLoading, searchResults } = this.state;
|
||||
const { selectedItems, isOpen } = this.props;
|
||||
const displayItems = query.trim() ? searchResults : this.props.items;
|
||||
|
||||
return (
|
||||
<div className="position-relative d-inline-block ml-2" ref={this.dropdownRef}>
|
||||
<span className="cur-activity-modifiers d-inline-block p-2 rounded" onClick={this.onToggleClick}>
|
||||
{selectedItems.length > 0 ? (
|
||||
<>
|
||||
<span>{gettext(this.props.componentName + ':')}</span>
|
||||
<span className="d-inline-block ml-1">{selectedItems.map(item => item.name).join(', ')}</span>
|
||||
</>
|
||||
) : gettext(this.props.componentName)}
|
||||
<i className="sf3-font sf3-font-down ml-2 toggle-icon"></i>
|
||||
</span>
|
||||
{isOpen && (
|
||||
<div className="position-absolute activity-modifier-selector-container rounded shadow" ref={ref => this.userSelector = ref}>
|
||||
<ul className="activity-selected-modifiers px-3 py-1 list-unstyled">
|
||||
{selectedItems.map((item, index) => {
|
||||
return (
|
||||
<li key={index} className="activity-selected-modifier">
|
||||
<img src={item.avatar_url} className="avatar w-5 h-5" alt="" />
|
||||
<span className="activity-user-name ml-2">{item.name}</span>
|
||||
<i className="sf2-icon-close unselect-activity-user ml-2" onClick={(e) => {this.toggleSelectItem(e, item);}}></i>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
<div className="px-3 pt-3">
|
||||
<Input
|
||||
type="text"
|
||||
placeholder={gettext('Find users')}
|
||||
value={query}
|
||||
onChange={this.onQueryChange}
|
||||
/>
|
||||
</div>
|
||||
<ul className="activity-user-list list-unstyled p-3 o-auto">
|
||||
{isLoading ? (
|
||||
<li className="text-center">{gettext('Loading...')}</li>
|
||||
) : displayItems.length === 0 ? (
|
||||
<li className="text-center">
|
||||
{query ? gettext('User not found') : gettext('Enter characters to start searching')}
|
||||
</li>
|
||||
) : (
|
||||
displayItems.map((item, index) => {
|
||||
const isSelected = selectedItems.some(selected =>
|
||||
(item.email && selected.email === item.email) ||
|
||||
(item.id && selected.id === item.id)
|
||||
);
|
||||
return (
|
||||
<li key={index}
|
||||
className="activity-user-item h-6 p-1 rounded d-flex justify-content-between align-items-center"
|
||||
onClick={(e) => {this.toggleSelectItem(e, item);}}
|
||||
>
|
||||
<div>
|
||||
<img src={item.avatar_url} className="avatar w-5 h-5" alt="" />
|
||||
<span className="activity-user-name ml-2">{item.name}</span>
|
||||
</div>
|
||||
{isSelected && <i className="sf2-icon-tick text-gray font-weight-bold"></i>}
|
||||
</li>
|
||||
);
|
||||
})
|
||||
)}
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
LogUserSelector.propTypes = propTypes;
|
||||
|
||||
export default LogUserSelector;
|
@@ -13,10 +13,10 @@ 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';
|
||||
import LogUserSelector from '../../dashboard/log-user-selector';
|
||||
import LogRepoSelector from '../../dashboard/log-repo-selector';
|
||||
|
||||
dayjs.extend(relativeTime);
|
||||
|
||||
@@ -37,14 +37,6 @@ class Content extends Component {
|
||||
this.props.getLogsByPage(this.props.currentPage + 1);
|
||||
};
|
||||
|
||||
toggleFilterByUser = () => {
|
||||
this.props.filterByUser(null);
|
||||
};
|
||||
|
||||
toggleFilterByRepo = () => {
|
||||
this.props.filterByRepo(null);
|
||||
};
|
||||
|
||||
toggleFreezeItem = (freezed) => {
|
||||
this.setState({
|
||||
isItemFreezed: freezed
|
||||
@@ -54,7 +46,6 @@ class Content extends Component {
|
||||
render() {
|
||||
const {
|
||||
loading, errorMsg, items,
|
||||
userFilteredBy, repoFilteredBy,
|
||||
perPage, currentPage, hasNextPage
|
||||
} = this.props;
|
||||
if (loading) {
|
||||
@@ -68,20 +59,6 @@ class Content extends Component {
|
||||
);
|
||||
const table = (
|
||||
<Fragment>
|
||||
<div>
|
||||
{userFilteredBy && (
|
||||
<ToggleFilter
|
||||
filterBy={items[0].name}
|
||||
toggleFilter={this.toggleFilterByUser}
|
||||
/>
|
||||
)}
|
||||
{repoFilteredBy && (
|
||||
<ToggleFilter
|
||||
filterBy={items[0].repo_name}
|
||||
toggleFilter={this.toggleFilterByRepo}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -101,10 +78,6 @@ class Content extends Component {
|
||||
item={item}
|
||||
isFreezed={this.state.isItemFreezed}
|
||||
toggleFreezeItem={this.toggleFreezeItem}
|
||||
userFilteredBy={userFilteredBy}
|
||||
repoFilteredBy={repoFilteredBy}
|
||||
filterByUser={this.props.filterByUser}
|
||||
filterByRepo={this.props.filterByRepo}
|
||||
/>);
|
||||
})}
|
||||
</tbody>
|
||||
@@ -135,11 +108,7 @@ Content.propTypes = {
|
||||
perPage: PropTypes.number,
|
||||
pageInfo: PropTypes.object,
|
||||
hasNextPage: PropTypes.bool,
|
||||
toggleFreezeItem: PropTypes.func,
|
||||
userFilteredBy: PropTypes.string,
|
||||
repoFilteredBy: PropTypes.string,
|
||||
filterByUser: PropTypes.func,
|
||||
filterByRepo: PropTypes.func,
|
||||
toggleFreezeItem: PropTypes.func
|
||||
};
|
||||
|
||||
|
||||
@@ -149,7 +118,6 @@ class Item extends Component {
|
||||
super(props);
|
||||
this.state = {
|
||||
isHighlighted: false,
|
||||
isOpIconShown: false
|
||||
};
|
||||
}
|
||||
|
||||
@@ -157,7 +125,6 @@ class Item extends Component {
|
||||
if (!this.props.isFreezed) {
|
||||
this.setState({
|
||||
isHighlighted: true,
|
||||
isOpIconShown: true
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -166,58 +133,32 @@ class Item extends Component {
|
||||
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;
|
||||
const { isHighlighted } = this.state;
|
||||
const { item } = this.props;
|
||||
return (
|
||||
<tr className={isHighlighted ? 'tr-highlight' : ''} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>
|
||||
<td>
|
||||
<UserLink email={item.email} name={item.name} />
|
||||
{isOpIconShown && !userFilteredBy && (
|
||||
<FilterMenu
|
||||
filterBy={item.name}
|
||||
filterItems={this.filterByUser}
|
||||
toggleFreezeItem={this.toggleFreezeItem}
|
||||
/>
|
||||
)}
|
||||
</td>
|
||||
<td>{item.event_type}</td>
|
||||
<td>{item.ip}{' / '}{item.device || '--'}</td>
|
||||
<td>{dayjs(item.time).fromNow()}</td>
|
||||
<td>
|
||||
{item.repo_name ? item.repo_name : gettext('Deleted')}
|
||||
{isOpIconShown && item.repo_name && !repoFilteredBy && (
|
||||
<FilterMenu
|
||||
filterBy={item.repo_name}
|
||||
filterItems={this.filterByRepo}
|
||||
toggleFreezeItem={this.toggleFreezeItem}
|
||||
/>
|
||||
)}
|
||||
</td>
|
||||
<td>{item.file_or_dir_name}</td>
|
||||
</tr>
|
||||
@@ -230,10 +171,6 @@ 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 {
|
||||
@@ -248,6 +185,11 @@ class FileAccessLogs extends Component {
|
||||
currentPage: 1,
|
||||
hasNextPage: false,
|
||||
isExportExcelDialogOpen: false,
|
||||
availableUsers: [],
|
||||
selectedUsers: [],
|
||||
availableRepos: [],
|
||||
selectedRepos: [],
|
||||
openSelector: null,
|
||||
};
|
||||
this.initPage = 1;
|
||||
}
|
||||
@@ -262,16 +204,16 @@ class FileAccessLogs extends Component {
|
||||
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;
|
||||
systemAdminAPI.sysAdminListFileAccessLogs(page, perPage, userFilteredBy, repoFilteredBy).then((res) => {
|
||||
const { perPage, selectedUsers, selectedRepos } = this.state;
|
||||
let emails = selectedUsers.map(user => user.email);
|
||||
let repos = selectedRepos.map(repo => repo.id);
|
||||
systemAdminAPI.sysAdminListFileAccessLogs(page, perPage, { 'email': emails, 'repo': repos }).then((res) => {
|
||||
this.setState({
|
||||
logList: res.data.file_access_log_list,
|
||||
loading: false,
|
||||
@@ -304,30 +246,87 @@ class FileAccessLogs extends Component {
|
||||
navigate(url.toString());
|
||||
};
|
||||
|
||||
filterByUser = (email) => {
|
||||
handleUserFilter = (user, shouldFetchData = true) => {
|
||||
const { selectedUsers } = this.state;
|
||||
let newSelectedUsers;
|
||||
|
||||
if (user === null) {
|
||||
newSelectedUsers = selectedUsers;
|
||||
} else {
|
||||
const isSelected = selectedUsers.find(item => item.email === user.email);
|
||||
if (isSelected) {
|
||||
newSelectedUsers = selectedUsers.filter(item => item.email !== user.email);
|
||||
} else {
|
||||
newSelectedUsers = [...selectedUsers, user];
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({
|
||||
userFilteredBy: email
|
||||
selectedUsers: newSelectedUsers,
|
||||
currentPage: 1
|
||||
}, () => {
|
||||
this.getLogsByPage(this.initPage);
|
||||
this.updateURL({ 'email': email });
|
||||
if (shouldFetchData) {
|
||||
this.getLogsByPage(1);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
filterByRepo = (repoID) => {
|
||||
handleRepoFilter = (repo, shouldFetchData = true) => {
|
||||
const { selectedRepos } = this.state;
|
||||
let newSelectedRepos;
|
||||
|
||||
if (repo === null) {
|
||||
newSelectedRepos = [];
|
||||
} else {
|
||||
const isSelected = selectedRepos.find(item => item.id === repo.id);
|
||||
if (isSelected) {
|
||||
newSelectedRepos = selectedRepos.filter(item => item.id !== repo.id);
|
||||
} else {
|
||||
newSelectedRepos = [...selectedRepos, repo];
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({
|
||||
repoFilteredBy: repoID
|
||||
selectedRepos: newSelectedRepos,
|
||||
currentPage: 1
|
||||
}, () => {
|
||||
this.getLogsByPage(this.initPage);
|
||||
this.updateURL({ 'repo_id': repoID });
|
||||
if (shouldFetchData) {
|
||||
this.getLogsByPage(1);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
handleSelectorToggle = (selectorType) => {
|
||||
const { openSelector } = this.state;
|
||||
const wasOpen = openSelector === selectorType;
|
||||
|
||||
this.setState({
|
||||
openSelector: wasOpen ? null : selectorType
|
||||
}, () => {
|
||||
if (wasOpen) {
|
||||
this.getLogsByPage(1);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
searchUsers = (value) => {
|
||||
return systemAdminAPI.sysAdminSearchUsers(value);
|
||||
};
|
||||
|
||||
searchRepos = (value) => {
|
||||
return systemAdminAPI.sysAdminSearchRepos(value);
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
logList,
|
||||
userFilteredBy, repoFilteredBy,
|
||||
currentPage, perPage, hasNextPage,
|
||||
isExportExcelDialogOpen
|
||||
isExportExcelDialogOpen,
|
||||
availableUsers,
|
||||
selectedUsers,
|
||||
availableRepos,
|
||||
selectedRepos,
|
||||
openSelector
|
||||
} = this.state;
|
||||
return (
|
||||
<Fragment>
|
||||
@@ -338,20 +337,38 @@ class FileAccessLogs extends Component {
|
||||
<div className="cur-view-container">
|
||||
<LogsNav currentItem="fileAccessLogs" />
|
||||
<div className="cur-view-content">
|
||||
<Content
|
||||
loading={this.state.loading}
|
||||
errorMsg={this.state.errorMsg}
|
||||
items={logList}
|
||||
userFilteredBy={userFilteredBy}
|
||||
repoFilteredBy={repoFilteredBy}
|
||||
filterByUser={this.filterByUser}
|
||||
filterByRepo={this.filterByRepo}
|
||||
currentPage={currentPage}
|
||||
perPage={perPage}
|
||||
hasNextPage={hasNextPage}
|
||||
getLogsByPage={this.getLogsByPage}
|
||||
resetPerPage={this.resetPerPage}
|
||||
/>
|
||||
<Fragment>
|
||||
<div className="d-flex align-items-center mb-2">
|
||||
<LogUserSelector
|
||||
componentName="Users"
|
||||
items={availableUsers}
|
||||
selectedItems={selectedUsers}
|
||||
onSelect={this.handleUserFilter}
|
||||
isOpen={openSelector === 'user'}
|
||||
onToggle={() => this.handleSelectorToggle('user')}
|
||||
searchUsersFunc={this.searchUsers}
|
||||
/>
|
||||
<div className="mx-3"></div>
|
||||
<LogRepoSelector
|
||||
items={availableRepos}
|
||||
selectedItems={selectedRepos}
|
||||
onSelect={this.handleRepoFilter}
|
||||
isOpen={openSelector === 'repo'}
|
||||
onToggle={() => this.handleSelectorToggle('repo')}
|
||||
searchReposFunc={this.searchRepos}
|
||||
/>
|
||||
</div>
|
||||
<Content
|
||||
loading={this.state.loading}
|
||||
errorMsg={this.state.errorMsg}
|
||||
items={logList}
|
||||
currentPage={currentPage}
|
||||
perPage={perPage}
|
||||
hasNextPage={hasNextPage}
|
||||
getLogsByPage={this.getLogsByPage}
|
||||
resetPerPage={this.resetPerPage}
|
||||
/>
|
||||
</Fragment>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
||||
import { Link } from '@gatsbyjs/reach-router';
|
||||
import dayjs from 'dayjs';
|
||||
import relativeTime from 'dayjs/plugin/relativeTime';
|
||||
import { seafileAPI } from '../../../utils/seafile-api';
|
||||
import { systemAdminAPI } from '../../../utils/system-admin-api';
|
||||
import { gettext, siteRoot } from '../../../utils/constants';
|
||||
import { Utils } from '../../../utils/utils';
|
||||
import EmptyTip from '../../../components/empty-tip';
|
||||
@@ -12,6 +12,8 @@ import Paginator from '../../../components/paginator';
|
||||
import MainPanelTopbar from '../main-panel-topbar';
|
||||
import UserLink from '../user-link';
|
||||
import LogsNav from './logs-nav';
|
||||
import LogUserSelector from '../../dashboard/log-user-selector';
|
||||
import LogRepoSelector from '../../dashboard/log-repo-selector';
|
||||
|
||||
dayjs.extend(relativeTime);
|
||||
|
||||
@@ -162,6 +164,14 @@ class FIleTransferLogs extends Component {
|
||||
perPage: 100,
|
||||
currentPage: 1,
|
||||
hasNextPage: false,
|
||||
availableUsers: [],
|
||||
selectedFromUsers: [],
|
||||
selectedToUsers: [],
|
||||
selectedToGroups: [],
|
||||
selectedOperators: [],
|
||||
openSelector: null,
|
||||
availableRepos: [],
|
||||
selectedRepos: [],
|
||||
};
|
||||
this.initPage = 1;
|
||||
}
|
||||
@@ -178,8 +188,28 @@ class FIleTransferLogs extends Component {
|
||||
}
|
||||
|
||||
getLogsByPage = (page) => {
|
||||
let { perPage } = this.state;
|
||||
seafileAPI.sysAdminListFileTransferLogs(page, perPage).then((res) => {
|
||||
let {
|
||||
perPage,
|
||||
selectedFromUsers,
|
||||
selectedToUsers,
|
||||
selectedToGroups,
|
||||
selectedOperators,
|
||||
selectedRepos
|
||||
} = this.state;
|
||||
|
||||
const options = {
|
||||
'from_email': selectedFromUsers.filter(item => item.email).map(user => user.email),
|
||||
'from_group': selectedFromUsers.filter(item => !item.email).map(group => group.id),
|
||||
'to_email': selectedToUsers.map(user => user.email),
|
||||
'to_group': selectedToGroups.map(group => group.to_group_id || group.id),
|
||||
'operator_email': selectedOperators.map(user => user.email),
|
||||
'repo': selectedRepos.map(repo => repo.id)
|
||||
};
|
||||
systemAdminAPI.sysAdminListFileTransferLogs(
|
||||
page,
|
||||
perPage,
|
||||
options
|
||||
).then((res) => {
|
||||
this.setState({
|
||||
logList: res.data.repo_transfer_log_list,
|
||||
loading: false,
|
||||
@@ -189,7 +219,8 @@ class FIleTransferLogs extends Component {
|
||||
}).catch((error) => {
|
||||
this.setState({
|
||||
loading: false,
|
||||
errorMsg: Utils.getErrorMsg(error, true) // true: show login tip if 403
|
||||
currentPage: page,
|
||||
errorMsg: Utils.getErrorMsg(error, true)
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -200,8 +231,196 @@ class FIleTransferLogs extends Component {
|
||||
}, () => this.getLogsByPage(this.initPage));
|
||||
};
|
||||
|
||||
handleFromUserFilter = (item, shouldFetchData = true) => {
|
||||
const { selectedFromUsers } = this.state;
|
||||
let newSelectedUsers;
|
||||
|
||||
if (item === null) {
|
||||
newSelectedUsers = selectedFromUsers;
|
||||
} else {
|
||||
if (item.email) {
|
||||
const isSelected = selectedFromUsers.find(user => user.email === item.email);
|
||||
if (isSelected) {
|
||||
newSelectedUsers = selectedFromUsers.filter(user => user.email !== item.email);
|
||||
} else {
|
||||
newSelectedUsers = [...selectedFromUsers, item];
|
||||
}
|
||||
} else {
|
||||
const groupId = item.id;
|
||||
const isSelected = selectedFromUsers.find(group => group.id === groupId);
|
||||
if (isSelected) {
|
||||
newSelectedUsers = selectedFromUsers.filter(group => group.id !== groupId);
|
||||
} else {
|
||||
const groupItem = {
|
||||
id: groupId,
|
||||
name: item.name,
|
||||
from_group_id: groupId,
|
||||
from_group_name: item.name
|
||||
};
|
||||
newSelectedUsers = [...selectedFromUsers, groupItem];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({
|
||||
selectedFromUsers: newSelectedUsers,
|
||||
currentPage: 1
|
||||
}, () => {
|
||||
if (shouldFetchData) {
|
||||
this.getLogsByPage(1);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
handleToUserFilter = (item, shouldFetchData = true) => {
|
||||
const { selectedToUsers, selectedToGroups } = this.state;
|
||||
let newSelectedUsers = selectedToUsers;
|
||||
let newSelectedGroups = selectedToGroups;
|
||||
|
||||
if (item === null) {
|
||||
newSelectedUsers = selectedToUsers;
|
||||
newSelectedGroups = selectedToGroups;
|
||||
} else {
|
||||
if (item.email) {
|
||||
const isSelected = selectedToUsers.find(user => user.email === item.email);
|
||||
if (isSelected) {
|
||||
newSelectedUsers = selectedToUsers.filter(user => user.email !== item.email);
|
||||
} else {
|
||||
newSelectedUsers = [...selectedToUsers, item];
|
||||
}
|
||||
} else {
|
||||
const groupId = item.to_group_id || item.id;
|
||||
const groupName = item.to_group_name || item.name;
|
||||
|
||||
const isSelected = selectedToGroups.find(group => {
|
||||
const selectedGroupId = group.to_group_id || group.id;
|
||||
return selectedGroupId === groupId;
|
||||
});
|
||||
|
||||
if (isSelected) {
|
||||
newSelectedGroups = selectedToGroups.filter(group => {
|
||||
const selectedGroupId = group.to_group_id || group.id;
|
||||
return selectedGroupId !== groupId;
|
||||
});
|
||||
} else {
|
||||
const groupItem = {
|
||||
id: groupId,
|
||||
name: groupName,
|
||||
to_group_id: groupId,
|
||||
to_group_name: groupName
|
||||
};
|
||||
newSelectedGroups = [...selectedToGroups, groupItem];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({
|
||||
selectedToUsers: newSelectedUsers,
|
||||
selectedToGroups: newSelectedGroups,
|
||||
currentPage: 1
|
||||
}, () => {
|
||||
if (shouldFetchData) {
|
||||
this.getLogsByPage(1);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
handleOperatorFilter = (user, shouldFetchData = true) => {
|
||||
const { selectedOperators } = this.state;
|
||||
let newSelectedUsers;
|
||||
|
||||
if (user === null) {
|
||||
newSelectedUsers = selectedOperators;
|
||||
} else {
|
||||
const isSelected = selectedOperators.find(item => item.email === user.email);
|
||||
if (isSelected) {
|
||||
newSelectedUsers = selectedOperators.filter(item => item.email !== user.email);
|
||||
} else {
|
||||
newSelectedUsers = [...selectedOperators, user];
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({
|
||||
selectedOperators: newSelectedUsers,
|
||||
currentPage: 1
|
||||
}, () => {
|
||||
if (shouldFetchData) {
|
||||
this.getLogsByPage(1);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
handleSelectorToggle = (selectorType) => {
|
||||
const { openSelector } = this.state;
|
||||
const wasOpen = openSelector === selectorType;
|
||||
|
||||
this.setState({
|
||||
openSelector: wasOpen ? null : selectorType
|
||||
}, () => {
|
||||
if (wasOpen) {
|
||||
this.getLogsByPage(1);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
handleRepoFilter = (repo, shouldFetchData = true) => {
|
||||
const { selectedRepos } = this.state;
|
||||
let newSelectedRepos;
|
||||
|
||||
if (repo === null) {
|
||||
newSelectedRepos = [];
|
||||
} else {
|
||||
const isSelected = selectedRepos.find(item => item.id === repo.id);
|
||||
if (isSelected) {
|
||||
newSelectedRepos = selectedRepos.filter(item => item.id !== repo.id);
|
||||
} else {
|
||||
newSelectedRepos = [...selectedRepos, repo];
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({
|
||||
selectedRepos: newSelectedRepos,
|
||||
currentPage: 1
|
||||
}, () => {
|
||||
if (shouldFetchData) {
|
||||
this.getLogsByPage(1);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
searchUsers = (value) => {
|
||||
return systemAdminAPI.sysAdminSearchUsers(value);
|
||||
};
|
||||
|
||||
searchGroups = (value) => {
|
||||
return systemAdminAPI.sysAdminSearchGroups(value);
|
||||
};
|
||||
|
||||
searchRepos = (value) => {
|
||||
return systemAdminAPI.sysAdminSearchRepos(value);
|
||||
};
|
||||
|
||||
render() {
|
||||
let { logList, currentPage, perPage, hasNextPage } = this.state;
|
||||
let {
|
||||
logList, currentPage, perPage, hasNextPage,
|
||||
availableUsers, selectedFromUsers,
|
||||
selectedToUsers, selectedToGroups,
|
||||
selectedOperators,
|
||||
availableRepos, selectedRepos,
|
||||
openSelector
|
||||
} = this.state;
|
||||
|
||||
const selectedToItems = [
|
||||
...selectedToUsers,
|
||||
...selectedToGroups.map(group => ({
|
||||
id: group.to_group_id || group.id,
|
||||
name: group.to_group_name || group.name,
|
||||
to_group_id: group.to_group_id || group.id,
|
||||
to_group_name: group.to_group_name || group.name
|
||||
}))
|
||||
];
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<MainPanelTopbar {...this.props} />
|
||||
@@ -209,16 +428,58 @@ class FIleTransferLogs extends Component {
|
||||
<div className="cur-view-container">
|
||||
<LogsNav currentItem="fileTransfer" />
|
||||
<div className="cur-view-content">
|
||||
<Content
|
||||
loading={this.state.loading}
|
||||
errorMsg={this.state.errorMsg}
|
||||
items={logList}
|
||||
currentPage={currentPage}
|
||||
perPage={perPage}
|
||||
hasNextPage={hasNextPage}
|
||||
getLogsByPage={this.getLogsByPage}
|
||||
resetPerPage={this.resetPerPage}
|
||||
/>
|
||||
<Fragment>
|
||||
<div className="d-flex align-items-center mb-2">
|
||||
<LogUserSelector
|
||||
componentName="Transfer From"
|
||||
items={availableUsers}
|
||||
selectedItems={selectedFromUsers}
|
||||
onSelect={this.handleFromUserFilter}
|
||||
isOpen={openSelector === 'fromUser'}
|
||||
onToggle={() => this.handleSelectorToggle('fromUser')}
|
||||
searchUsersFunc={this.searchUsers}
|
||||
searchGroupsFunc={this.searchGroups}
|
||||
/>
|
||||
<LogUserSelector
|
||||
componentName="Transfer To"
|
||||
items={availableUsers}
|
||||
selectedItems={selectedToItems}
|
||||
onSelect={this.handleToUserFilter}
|
||||
isOpen={openSelector === 'toUser'}
|
||||
onToggle={() => this.handleSelectorToggle('toUser')}
|
||||
searchUsersFunc={this.searchUsers}
|
||||
searchGroupsFunc={this.searchGroups}
|
||||
/>
|
||||
<LogUserSelector
|
||||
componentName="Operator"
|
||||
items={availableUsers}
|
||||
selectedItems={selectedOperators}
|
||||
onSelect={this.handleOperatorFilter}
|
||||
isOpen={openSelector === 'operator'}
|
||||
onToggle={() => this.handleSelectorToggle('operator')}
|
||||
searchUsersFunc={this.searchUsers}
|
||||
/>
|
||||
<div className="mx-3"></div>
|
||||
<LogRepoSelector
|
||||
items={availableRepos}
|
||||
selectedItems={selectedRepos}
|
||||
onSelect={this.handleRepoFilter}
|
||||
isOpen={openSelector === 'repo'}
|
||||
onToggle={() => this.handleSelectorToggle('repo')}
|
||||
searchReposFunc={this.searchRepos}
|
||||
/>
|
||||
</div>
|
||||
<Content
|
||||
loading={this.state.loading}
|
||||
errorMsg={this.state.errorMsg}
|
||||
items={logList}
|
||||
currentPage={currentPage}
|
||||
perPage={perPage}
|
||||
hasNextPage={hasNextPage}
|
||||
getLogsByPage={this.getLogsByPage}
|
||||
resetPerPage={this.resetPerPage}
|
||||
/>
|
||||
</Fragment>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -15,6 +15,8 @@ import UserLink from '../user-link';
|
||||
import ModalPortal from '../../../components/modal-portal';
|
||||
import CommitDetails from '../../../components/dialog/commit-details';
|
||||
import LogsExportExcelDialog from '../../../components/dialog/sysadmin-dialog/sysadmin-logs-export-excel-dialog';
|
||||
import LogUserSelector from '../../dashboard/log-user-selector';
|
||||
import LogRepoSelector from '../../dashboard/log-repo-selector';
|
||||
|
||||
dayjs.extend(relativeTime);
|
||||
|
||||
@@ -173,6 +175,11 @@ class FileUpdateLogs extends Component {
|
||||
currentPage: 1,
|
||||
hasNextPage: false,
|
||||
isExportExcelDialogOpen: false,
|
||||
availableUsers: [],
|
||||
selectedUsers: [],
|
||||
availableRepos: [],
|
||||
selectedRepos: [],
|
||||
openSelector: null,
|
||||
};
|
||||
this.initPage = 1;
|
||||
}
|
||||
@@ -193,8 +200,10 @@ class FileUpdateLogs extends Component {
|
||||
}
|
||||
|
||||
getLogsByPage = (page) => {
|
||||
let { perPage } = this.state;
|
||||
systemAdminAPI.sysAdminListFileUpdateLogs(page, perPage).then((res) => {
|
||||
let { perPage, selectedUsers, selectedRepos } = this.state;
|
||||
let emails = selectedUsers.map(user => user.email);
|
||||
let repos = selectedRepos.map(repo => repo.id);
|
||||
systemAdminAPI.sysAdminListFileUpdateLogs(page, perPage, { 'email': emails, 'repo': repos }).then((res) => {
|
||||
this.setState({
|
||||
logList: res.data.file_update_log_list,
|
||||
loading: false,
|
||||
@@ -215,8 +224,80 @@ class FileUpdateLogs extends Component {
|
||||
}, () => this.getLogsByPage(this.initPage));
|
||||
};
|
||||
|
||||
|
||||
handleUserFilter = (user, shouldFetchData = true) => {
|
||||
const { selectedUsers } = this.state;
|
||||
let newSelectedUsers;
|
||||
|
||||
if (user === null) {
|
||||
newSelectedUsers = selectedUsers;
|
||||
} else {
|
||||
const isSelected = selectedUsers.find(item => item.email === user.email);
|
||||
if (isSelected) {
|
||||
newSelectedUsers = selectedUsers.filter(item => item.email !== user.email);
|
||||
} else {
|
||||
newSelectedUsers = [...selectedUsers, user];
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({
|
||||
selectedUsers: newSelectedUsers,
|
||||
currentPage: 1
|
||||
}, () => {
|
||||
if (shouldFetchData) {
|
||||
this.getLogsByPage(1);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
handleSelectorToggle = (selectorType) => {
|
||||
const { openSelector } = this.state;
|
||||
const wasOpen = openSelector === selectorType;
|
||||
|
||||
this.setState({
|
||||
openSelector: wasOpen ? null : selectorType
|
||||
}, () => {
|
||||
if (wasOpen) {
|
||||
this.getLogsByPage(1);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
handleRepoFilter = (repo, shouldFetchData = true) => {
|
||||
const { selectedRepos } = this.state;
|
||||
let newSelectedRepos;
|
||||
|
||||
if (repo === null) {
|
||||
newSelectedRepos = selectedRepos;
|
||||
} else {
|
||||
const isSelected = selectedRepos.find(item => item.id === repo.id);
|
||||
if (isSelected) {
|
||||
newSelectedRepos = selectedRepos.filter(item => item.id !== repo.id);
|
||||
} else {
|
||||
newSelectedRepos = [...selectedRepos, repo];
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({
|
||||
selectedRepos: newSelectedRepos,
|
||||
currentPage: 1
|
||||
}, () => {
|
||||
if (shouldFetchData) {
|
||||
this.getLogsByPage(1);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
searchUsers = (value) => {
|
||||
return systemAdminAPI.sysAdminSearchUsers(value);
|
||||
};
|
||||
|
||||
searchRepos = (value) => {
|
||||
return systemAdminAPI.sysAdminSearchRepos(value);
|
||||
};
|
||||
|
||||
render() {
|
||||
let { logList, currentPage, perPage, hasNextPage, isExportExcelDialogOpen } = this.state;
|
||||
let { logList, currentPage, perPage, hasNextPage, isExportExcelDialogOpen, availableUsers, selectedUsers, availableRepos, selectedRepos } = this.state;
|
||||
return (
|
||||
<Fragment>
|
||||
<MainPanelTopbar {...this.props}>
|
||||
@@ -226,16 +307,38 @@ class FileUpdateLogs extends Component {
|
||||
<div className="cur-view-container">
|
||||
<LogsNav currentItem="fileUpdateLogs" />
|
||||
<div className="cur-view-content">
|
||||
<Content
|
||||
loading={this.state.loading}
|
||||
errorMsg={this.state.errorMsg}
|
||||
items={logList}
|
||||
currentPage={currentPage}
|
||||
perPage={perPage}
|
||||
hasNextPage={hasNextPage}
|
||||
getLogsByPage={this.getLogsByPage}
|
||||
resetPerPage={this.resetPerPage}
|
||||
/>
|
||||
<Fragment>
|
||||
<div className="d-flex align-items-center mb-2">
|
||||
<LogUserSelector
|
||||
componentName="Users"
|
||||
items={availableUsers}
|
||||
selectedItems={selectedUsers}
|
||||
onSelect={this.handleUserFilter}
|
||||
isOpen={this.state.openSelector === 'user'}
|
||||
onToggle={() => this.handleSelectorToggle('user')}
|
||||
searchUsersFunc={this.searchUsers}
|
||||
/>
|
||||
<div className="mx-3"></div>
|
||||
<LogRepoSelector
|
||||
items={availableRepos}
|
||||
selectedItems={selectedRepos}
|
||||
onSelect={this.handleRepoFilter}
|
||||
isOpen={this.state.openSelector === 'repo'}
|
||||
onToggle={() => this.handleSelectorToggle('repo')}
|
||||
searchReposFunc={this.searchRepos}
|
||||
/>
|
||||
</div>
|
||||
<Content
|
||||
loading={this.state.loading}
|
||||
errorMsg={this.state.errorMsg}
|
||||
items={logList}
|
||||
currentPage={currentPage}
|
||||
perPage={perPage}
|
||||
hasNextPage={hasNextPage}
|
||||
getLogsByPage={this.getLogsByPage}
|
||||
resetPerPage={this.resetPerPage}
|
||||
/>
|
||||
</Fragment>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -3,15 +3,16 @@ import PropTypes from 'prop-types';
|
||||
import { Link } from '@gatsbyjs/reach-router';
|
||||
import dayjs from 'dayjs';
|
||||
import relativeTime from 'dayjs/plugin/relativeTime';
|
||||
import { seafileAPI } from '../../../utils/seafile-api';
|
||||
import { gettext, siteRoot } from '../../../utils/constants';
|
||||
import { Utils } from '../../../utils/utils';
|
||||
import { systemAdminAPI } from '../../../utils/system-admin-api';
|
||||
import EmptyTip from '../../../components/empty-tip';
|
||||
import Loading from '../../../components/loading';
|
||||
import Paginator from '../../../components/paginator';
|
||||
import MainPanelTopbar from '../main-panel-topbar';
|
||||
import UserLink from '../user-link';
|
||||
import LogsNav from './logs-nav';
|
||||
import LogUserSelector from '../../dashboard/log-user-selector';
|
||||
|
||||
dayjs.extend(relativeTime);
|
||||
|
||||
@@ -154,6 +155,11 @@ class GroupMemberAuditLogs extends Component {
|
||||
perPage: 100,
|
||||
currentPage: 1,
|
||||
hasNextPage: false,
|
||||
availableUsers: [],
|
||||
selectedUsers: [],
|
||||
selectedOperators: [],
|
||||
selectedGroups: [],
|
||||
openSelector: null,
|
||||
};
|
||||
this.initPage = 1;
|
||||
}
|
||||
@@ -170,8 +176,15 @@ class GroupMemberAuditLogs extends Component {
|
||||
}
|
||||
|
||||
getLogsByPage = (page) => {
|
||||
let { perPage } = this.state;
|
||||
seafileAPI.sysAdminListGroupInviteLogs(page, perPage).then((res) => {
|
||||
let { perPage, selectedUsers, selectedOperators, selectedGroups } = this.state;
|
||||
|
||||
const emails = {
|
||||
'user_email': selectedUsers.map(user => user.email),
|
||||
'operator_email': selectedOperators.map(user => user.email),
|
||||
'group_id': selectedGroups.map(group => group.id)
|
||||
};
|
||||
|
||||
systemAdminAPI.sysAdminListGroupInviteLogs(page, perPage, emails).then((res) => {
|
||||
this.setState({
|
||||
logList: res.data.group_invite_log_list,
|
||||
loading: false,
|
||||
@@ -186,6 +199,102 @@ class GroupMemberAuditLogs extends Component {
|
||||
});
|
||||
};
|
||||
|
||||
handleUserFilter = (user, shouldFetchData = true) => {
|
||||
const { selectedUsers } = this.state;
|
||||
let newSelectedUsers;
|
||||
|
||||
if (user === null) {
|
||||
newSelectedUsers = selectedUsers;
|
||||
} else {
|
||||
const isSelected = selectedUsers.find(item => item.email === user.email);
|
||||
if (isSelected) {
|
||||
newSelectedUsers = selectedUsers.filter(item => item.email !== user.email);
|
||||
} else {
|
||||
newSelectedUsers = [...selectedUsers, user];
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({
|
||||
selectedUsers: newSelectedUsers,
|
||||
currentPage: 1
|
||||
}, () => {
|
||||
if (shouldFetchData) {
|
||||
this.getLogsByPage(1);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
handleOperatorFilter = (user, shouldFetchData = true) => {
|
||||
const { selectedOperators } = this.state;
|
||||
let newSelectedUsers;
|
||||
|
||||
if (user === null) {
|
||||
newSelectedUsers = selectedOperators;
|
||||
} else {
|
||||
const isSelected = selectedOperators.find(item => item.email === user.email);
|
||||
if (isSelected) {
|
||||
newSelectedUsers = selectedOperators.filter(item => item.email !== user.email);
|
||||
} else {
|
||||
newSelectedUsers = [...selectedOperators, user];
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({
|
||||
selectedOperators: newSelectedUsers,
|
||||
currentPage: 1
|
||||
}, () => {
|
||||
if (shouldFetchData) {
|
||||
this.getLogsByPage(1);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
handleGroupFilter = (group, shouldFetchData = true) => {
|
||||
const { selectedGroups } = this.state;
|
||||
let newSelectedGroups;
|
||||
|
||||
if (group === null) {
|
||||
newSelectedGroups = selectedGroups;
|
||||
} else {
|
||||
const isSelected = selectedGroups.find(item => item.id === group.id);
|
||||
if (isSelected) {
|
||||
newSelectedGroups = selectedGroups.filter(item => item.id !== group.id);
|
||||
} else {
|
||||
newSelectedGroups = [...selectedGroups, group];
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({
|
||||
selectedGroups: newSelectedGroups,
|
||||
currentPage: 1
|
||||
}, () => {
|
||||
if (shouldFetchData) {
|
||||
this.getLogsByPage(1);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
handleSelectorToggle = (selectorType) => {
|
||||
const { openSelector } = this.state;
|
||||
const wasOpen = openSelector === selectorType;
|
||||
|
||||
this.setState({
|
||||
openSelector: wasOpen ? null : selectorType
|
||||
}, () => {
|
||||
if (wasOpen) {
|
||||
this.getLogsByPage(1);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
searchUsers = (value) => {
|
||||
return systemAdminAPI.sysAdminSearchUsers(value);
|
||||
};
|
||||
|
||||
searchGroups = (value) => {
|
||||
return systemAdminAPI.sysAdminSearchGroups(value);
|
||||
};
|
||||
|
||||
resetPerPage = (newPerPage) => {
|
||||
this.setState({
|
||||
perPage: newPerPage,
|
||||
@@ -193,7 +302,12 @@ class GroupMemberAuditLogs extends Component {
|
||||
};
|
||||
|
||||
render() {
|
||||
let { logList, currentPage, perPage, hasNextPage } = this.state;
|
||||
let {
|
||||
logList, currentPage, perPage, hasNextPage,
|
||||
availableUsers, selectedUsers, selectedOperators, selectedGroups,
|
||||
openSelector
|
||||
} = this.state;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<MainPanelTopbar {...this.props} />
|
||||
@@ -201,16 +315,47 @@ class GroupMemberAuditLogs extends Component {
|
||||
<div className="cur-view-container">
|
||||
<LogsNav currentItem="groupMember" />
|
||||
<div className="cur-view-content">
|
||||
<Content
|
||||
loading={this.state.loading}
|
||||
errorMsg={this.state.errorMsg}
|
||||
items={logList}
|
||||
currentPage={currentPage}
|
||||
perPage={perPage}
|
||||
hasNextPage={hasNextPage}
|
||||
getLogsByPage={this.getLogsByPage}
|
||||
resetPerPage={this.resetPerPage}
|
||||
/>
|
||||
<Fragment>
|
||||
<div className="d-flex align-items-center mb-2">
|
||||
<LogUserSelector
|
||||
componentName="Member"
|
||||
items={availableUsers}
|
||||
selectedItems={selectedUsers}
|
||||
onSelect={this.handleUserFilter}
|
||||
isOpen={openSelector === 'user'}
|
||||
onToggle={() => this.handleSelectorToggle('user')}
|
||||
searchUsersFunc={this.searchUsers}
|
||||
/>
|
||||
<LogUserSelector
|
||||
componentName="Group"
|
||||
items={availableUsers}
|
||||
selectedItems={selectedGroups}
|
||||
onSelect={this.handleGroupFilter}
|
||||
isOpen={openSelector === 'group'}
|
||||
onToggle={() => this.handleSelectorToggle('group')}
|
||||
searchGroupsFunc={this.searchGroups}
|
||||
/>
|
||||
<LogUserSelector
|
||||
componentName="Operator"
|
||||
items={availableUsers}
|
||||
selectedItems={selectedOperators}
|
||||
onSelect={this.handleOperatorFilter}
|
||||
isOpen={openSelector === 'operator'}
|
||||
onToggle={() => this.handleSelectorToggle('operator')}
|
||||
searchUsersFunc={this.searchUsers}
|
||||
/>
|
||||
</div>
|
||||
<Content
|
||||
loading={this.state.loading}
|
||||
errorMsg={this.state.errorMsg}
|
||||
items={logList}
|
||||
currentPage={currentPage}
|
||||
perPage={perPage}
|
||||
hasNextPage={hasNextPage}
|
||||
getLogsByPage={this.getLogsByPage}
|
||||
resetPerPage={this.resetPerPage}
|
||||
/>
|
||||
</Fragment>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -14,6 +14,7 @@ import MainPanelTopbar from '../main-panel-topbar';
|
||||
import UserLink from '../user-link';
|
||||
import LogsExportExcelDialog from '../../../components/dialog/sysadmin-dialog/sysadmin-logs-export-excel-dialog';
|
||||
import ModalPortal from '../../../components/modal-portal';
|
||||
import LogUserSelector from '../../dashboard/log-user-selector';
|
||||
|
||||
dayjs.extend(relativeTime);
|
||||
|
||||
@@ -138,6 +139,9 @@ class LoginLogs extends Component {
|
||||
currentPage: 1,
|
||||
hasNextPage: false,
|
||||
isExportExcelDialogOpen: false,
|
||||
availableUsers: [],
|
||||
selectedUsers: [],
|
||||
isUserSelectorOpen: false,
|
||||
};
|
||||
this.initPage = 1;
|
||||
}
|
||||
@@ -158,8 +162,10 @@ class LoginLogs extends Component {
|
||||
}
|
||||
|
||||
getLogsByPage = (page) => {
|
||||
let { perPage } = this.state;
|
||||
systemAdminAPI.sysAdminListLoginLogs(page, perPage).then((res) => {
|
||||
let { perPage, selectedUsers } = this.state;
|
||||
let emails = selectedUsers.map(user => user.email);
|
||||
|
||||
systemAdminAPI.sysAdminListLoginLogs(page, perPage, { 'email': emails }).then((res) => {
|
||||
this.setState({
|
||||
logList: res.data.login_log_list,
|
||||
loading: false,
|
||||
@@ -180,8 +186,44 @@ class LoginLogs extends Component {
|
||||
}, () => this.getLogsByPage(this.initPage));
|
||||
};
|
||||
|
||||
handleUserFilter = (user) => {
|
||||
const { selectedUsers } = this.state;
|
||||
let newSelectedUsers;
|
||||
|
||||
if (user === null) {
|
||||
newSelectedUsers = selectedUsers;
|
||||
} else {
|
||||
const isSelected = selectedUsers.find(item => item.email === user.email);
|
||||
if (isSelected) {
|
||||
newSelectedUsers = selectedUsers.filter(item => item.email !== user.email);
|
||||
} else {
|
||||
newSelectedUsers = [...selectedUsers, user];
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({
|
||||
selectedUsers: newSelectedUsers,
|
||||
currentPage: 1
|
||||
});
|
||||
};
|
||||
|
||||
toggleUserSelector = () => {
|
||||
const { isUserSelectorOpen } = this.state;
|
||||
this.setState({
|
||||
isUserSelectorOpen: !isUserSelectorOpen
|
||||
}, () => {
|
||||
if (!this.state.isUserSelectorOpen) {
|
||||
this.getLogsByPage(1);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
searchUsers = (value) => {
|
||||
return systemAdminAPI.sysAdminSearchUsers(value);
|
||||
};
|
||||
|
||||
render() {
|
||||
let { logList, currentPage, perPage, hasNextPage, isExportExcelDialogOpen } = this.state;
|
||||
let { logList, currentPage, perPage, hasNextPage, isExportExcelDialogOpen, availableUsers, selectedUsers } = this.state;
|
||||
return (
|
||||
<Fragment>
|
||||
<MainPanelTopbar {...this.props}>
|
||||
@@ -191,16 +233,27 @@ class LoginLogs extends Component {
|
||||
<div className="cur-view-container">
|
||||
<LogsNav currentItem="loginLogs" />
|
||||
<div className="cur-view-content">
|
||||
<Content
|
||||
loading={this.state.loading}
|
||||
errorMsg={this.state.errorMsg}
|
||||
items={logList}
|
||||
currentPage={currentPage}
|
||||
perPage={perPage}
|
||||
hasNextPage={hasNextPage}
|
||||
getLogsByPage={this.getLogsByPage}
|
||||
resetPerPage={this.resetPerPage}
|
||||
/>
|
||||
<Fragment>
|
||||
<LogUserSelector
|
||||
componentName="Users"
|
||||
items={availableUsers}
|
||||
selectedItems={selectedUsers}
|
||||
onSelect={this.handleUserFilter}
|
||||
isOpen={this.state.isUserSelectorOpen}
|
||||
onToggle={this.toggleUserSelector}
|
||||
searchUsersFunc={this.searchUsers}
|
||||
/>
|
||||
<Content
|
||||
loading={this.state.loading}
|
||||
errorMsg={this.state.errorMsg}
|
||||
items={logList}
|
||||
currentPage={currentPage}
|
||||
perPage={perPage}
|
||||
hasNextPage={hasNextPage}
|
||||
getLogsByPage={this.getLogsByPage}
|
||||
resetPerPage={this.resetPerPage}
|
||||
/>
|
||||
</Fragment>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -15,6 +15,8 @@ import Paginator from '../../../components/paginator';
|
||||
import MainPanelTopbar from '../main-panel-topbar';
|
||||
import UserLink from '../user-link';
|
||||
import LogsNav from './logs-nav';
|
||||
import LogUserSelector from '../../dashboard/log-user-selector';
|
||||
import LogRepoSelector from '../../dashboard/log-repo-selector';
|
||||
|
||||
dayjs.extend(relativeTime);
|
||||
|
||||
@@ -151,6 +153,13 @@ class SharePermissionLogs extends Component {
|
||||
currentPage: 1,
|
||||
hasNextPage: false,
|
||||
isExportExcelDialogOpen: false,
|
||||
availableUsers: [],
|
||||
selectedFromUsers: [],
|
||||
selectedToUsers: [],
|
||||
selectedToGroups: [],
|
||||
availableRepos: [],
|
||||
selectedRepos: [],
|
||||
openSelector: null,
|
||||
};
|
||||
this.initPage = 1;
|
||||
}
|
||||
@@ -171,8 +180,25 @@ class SharePermissionLogs extends Component {
|
||||
}
|
||||
|
||||
getLogsByPage = (page) => {
|
||||
let { perPage } = this.state;
|
||||
systemAdminAPI.sysAdminListSharePermissionLogs(page, perPage).then((res) => {
|
||||
let {
|
||||
perPage,
|
||||
selectedFromUsers,
|
||||
selectedToUsers,
|
||||
selectedToGroups,
|
||||
selectedRepos
|
||||
} = this.state;
|
||||
|
||||
const options = {
|
||||
'from_email': selectedFromUsers.map(user => user.email),
|
||||
'to_email': selectedToUsers.map(user => user.email),
|
||||
'to_group': selectedToGroups.map(group => group.id),
|
||||
'repo': selectedRepos.map(repo => repo.id)
|
||||
};
|
||||
systemAdminAPI.sysAdminListSharePermissionLogs(
|
||||
page,
|
||||
perPage,
|
||||
options
|
||||
).then((res) => {
|
||||
this.setState({
|
||||
logList: res.data.share_permission_log_list,
|
||||
loading: false,
|
||||
@@ -182,7 +208,7 @@ class SharePermissionLogs extends Component {
|
||||
}).catch((error) => {
|
||||
this.setState({
|
||||
loading: false,
|
||||
errorMsg: Utils.getErrorMsg(error, true) // true: show login tip if 403
|
||||
errorMsg: Utils.getErrorMsg(error, true)
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -193,8 +219,124 @@ class SharePermissionLogs extends Component {
|
||||
}, () => this.getLogsByPage(this.initPage));
|
||||
};
|
||||
|
||||
handleFromUserFilter = (user, shouldFetchData = true) => {
|
||||
const { selectedFromUsers } = this.state;
|
||||
let newSelectedUsers;
|
||||
|
||||
if (user === null) {
|
||||
newSelectedUsers = selectedFromUsers;
|
||||
} else {
|
||||
const isSelected = selectedFromUsers.find(item => item.email === user.email);
|
||||
if (isSelected) {
|
||||
newSelectedUsers = selectedFromUsers.filter(item => item.email !== user.email);
|
||||
} else {
|
||||
newSelectedUsers = [...selectedFromUsers, user];
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({
|
||||
selectedFromUsers: newSelectedUsers,
|
||||
currentPage: 1
|
||||
}, () => {
|
||||
if (shouldFetchData) {
|
||||
this.getLogsByPage(1);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
handleToUserFilter = (item, shouldFetchData = true) => {
|
||||
const { selectedToUsers, selectedToGroups } = this.state;
|
||||
let newSelectedUsers = selectedToUsers;
|
||||
let newSelectedGroups = selectedToGroups;
|
||||
|
||||
if (item === null) {
|
||||
newSelectedUsers = selectedToUsers;
|
||||
newSelectedGroups = selectedToGroups;
|
||||
} else {
|
||||
if (item.email) {
|
||||
const isSelected = selectedToUsers.find(user => user.email === item.email);
|
||||
if (isSelected) {
|
||||
newSelectedUsers = selectedToUsers.filter(user => user.email !== item.email);
|
||||
} else {
|
||||
newSelectedUsers = [...selectedToUsers, item];
|
||||
}
|
||||
} else {
|
||||
const isSelected = selectedToGroups.find(group => group.id === item.id);
|
||||
if (isSelected) {
|
||||
newSelectedGroups = selectedToGroups.filter(group => group.id !== item.id);
|
||||
} else {
|
||||
newSelectedGroups = [...selectedToGroups, item];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({
|
||||
selectedToUsers: newSelectedUsers,
|
||||
selectedToGroups: newSelectedGroups,
|
||||
currentPage: 1
|
||||
}, () => {
|
||||
if (shouldFetchData) {
|
||||
this.getLogsByPage(1);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
handleSelectorToggle = (selectorType) => {
|
||||
const { openSelector } = this.state;
|
||||
const wasOpen = openSelector === selectorType;
|
||||
|
||||
this.setState({
|
||||
openSelector: wasOpen ? null : selectorType
|
||||
}, () => {
|
||||
if (wasOpen) {
|
||||
this.getLogsByPage(1);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
handleRepoFilter = (repo, shouldFetchData = true) => {
|
||||
const { selectedRepos } = this.state;
|
||||
let newSelectedRepos;
|
||||
|
||||
if (repo === null) {
|
||||
newSelectedRepos = selectedRepos;
|
||||
} else {
|
||||
const isSelected = selectedRepos.find(item => item.id === repo.id);
|
||||
if (isSelected) {
|
||||
newSelectedRepos = selectedRepos.filter(item => item.id !== repo.id);
|
||||
} else {
|
||||
newSelectedRepos = [...selectedRepos, repo];
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({
|
||||
selectedRepos: newSelectedRepos,
|
||||
currentPage: 1
|
||||
}, () => {
|
||||
if (shouldFetchData) {
|
||||
this.getLogsByPage(1);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
searchUsers = (value) => {
|
||||
return systemAdminAPI.sysAdminSearchUsers(value);
|
||||
};
|
||||
|
||||
searchRepos = (value) => {
|
||||
return systemAdminAPI.sysAdminSearchRepos(value);
|
||||
};
|
||||
|
||||
searchGroups = (value) => {
|
||||
return systemAdminAPI.sysAdminSearchGroups(value);
|
||||
};
|
||||
|
||||
render() {
|
||||
let { logList, currentPage, perPage, hasNextPage, isExportExcelDialogOpen } = this.state;
|
||||
let {
|
||||
logList, currentPage, perPage, hasNextPage, isExportExcelDialogOpen,
|
||||
availableUsers, selectedFromUsers, selectedToUsers,
|
||||
selectedToGroups, availableRepos, selectedRepos, openSelector
|
||||
} = this.state;
|
||||
return (
|
||||
<Fragment>
|
||||
<MainPanelTopbar {...this.props}>
|
||||
@@ -204,16 +346,48 @@ class SharePermissionLogs extends Component {
|
||||
<div className="cur-view-container">
|
||||
<LogsNav currentItem="sharePermissionLogs" />
|
||||
<div className="cur-view-content">
|
||||
<Content
|
||||
loading={this.state.loading}
|
||||
errorMsg={this.state.errorMsg}
|
||||
items={logList}
|
||||
currentPage={currentPage}
|
||||
perPage={perPage}
|
||||
hasNextPage={hasNextPage}
|
||||
getLogsByPage={this.getLogsByPage}
|
||||
resetPerPage={this.resetPerPage}
|
||||
/>
|
||||
<Fragment>
|
||||
<div className="d-flex align-items-center mb-2">
|
||||
<LogUserSelector
|
||||
componentName="Share From"
|
||||
items={availableUsers}
|
||||
selectedItems={selectedFromUsers}
|
||||
onSelect={this.handleFromUserFilter}
|
||||
isOpen={openSelector === 'fromUser'}
|
||||
onToggle={() => this.handleSelectorToggle('fromUser')}
|
||||
searchUsersFunc={this.searchUsers}
|
||||
/>
|
||||
<LogUserSelector
|
||||
componentName="Share To"
|
||||
items={availableUsers}
|
||||
selectedItems={[...selectedToUsers, ...selectedToGroups]}
|
||||
onSelect={this.handleToUserFilter}
|
||||
isOpen={openSelector === 'toUser'}
|
||||
onToggle={() => this.handleSelectorToggle('toUser')}
|
||||
searchUsersFunc={this.searchUsers}
|
||||
searchGroupsFunc={this.searchGroups}
|
||||
/>
|
||||
<div className="mx-3"></div>
|
||||
<LogRepoSelector
|
||||
items={availableRepos}
|
||||
selectedItems={selectedRepos}
|
||||
onSelect={this.handleRepoFilter}
|
||||
isOpen={openSelector === 'repo'}
|
||||
onToggle={() => this.handleSelectorToggle('repo')}
|
||||
searchReposFunc={this.searchRepos}
|
||||
/>
|
||||
</div>
|
||||
<Content
|
||||
loading={this.state.loading}
|
||||
errorMsg={this.state.errorMsg}
|
||||
items={logList}
|
||||
currentPage={currentPage}
|
||||
perPage={perPage}
|
||||
hasNextPage={hasNextPage}
|
||||
getLogsByPage={this.getLogsByPage}
|
||||
resetPerPage={this.resetPerPage}
|
||||
/>
|
||||
</Fragment>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -2207,24 +2207,6 @@ class SeafileAPI {
|
||||
return this._sendPostRequest(url, formData);
|
||||
}
|
||||
|
||||
sysAdminListFileTransferLogs(page, perPage) {
|
||||
const url = this.server + '/api/v2.1/admin/logs/repo-transfer-logs/';
|
||||
let params = {
|
||||
page: page,
|
||||
per_page: perPage
|
||||
};
|
||||
return this.req.get(url, { params: params });
|
||||
}
|
||||
|
||||
sysAdminListGroupInviteLogs(page, perPage) {
|
||||
const url = this.server + '/api/v2.1/admin/logs/group-member-audit/';
|
||||
let params = {
|
||||
page: page,
|
||||
per_page: perPage
|
||||
};
|
||||
return this.req.get(url, { params: params });
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
let seafileAPI = new SeafileAPI();
|
||||
|
@@ -680,46 +680,166 @@ class SystemAdminAPI {
|
||||
return this.req.get(url);
|
||||
}
|
||||
|
||||
sysAdminListLoginLogs(page, perPage) {
|
||||
sysAdminListLoginLogs(page, perPage, options = {}) {
|
||||
const url = this.server + '/api/v2.1/admin/logs/login-logs/';
|
||||
let params = {
|
||||
page: page,
|
||||
per_page: perPage
|
||||
per_page: perPage,
|
||||
...options
|
||||
};
|
||||
return this.req.get(url, { params: params });
|
||||
return this.req.get(url, {
|
||||
params: params,
|
||||
paramsSerializer: {
|
||||
serialize: function (params) {
|
||||
let list = [];
|
||||
for (let key in params) {
|
||||
if (Array.isArray(params[key])) {
|
||||
for (let i = 0, len = params[key].length; i < len; i++) {
|
||||
list.push(key + '=' + encodeURIComponent(params[key][i]));
|
||||
}
|
||||
} else {
|
||||
list.push(key + '=' + encodeURIComponent(params[key]));
|
||||
}
|
||||
}
|
||||
return list.join('&');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
sysAdminListFileAccessLogs(page, perPage, email, repoID) {
|
||||
sysAdminListFileAccessLogs(page, perPage, options = {}) {
|
||||
const url = this.server + '/api/v2.1/admin/logs/file-access-logs/';
|
||||
let params = {
|
||||
page: page,
|
||||
per_page: perPage
|
||||
per_page: perPage,
|
||||
...options
|
||||
};
|
||||
if (email != undefined) {
|
||||
params.email = email;
|
||||
}
|
||||
if (repoID != undefined) {
|
||||
params.repo_id = repoID;
|
||||
}
|
||||
return this.req.get(url, { params: params });
|
||||
return this.req.get(url, {
|
||||
params: params,
|
||||
paramsSerializer: {
|
||||
serialize: function (params) {
|
||||
let list = [];
|
||||
for (let key in params) {
|
||||
if (Array.isArray(params[key])) {
|
||||
for (let i = 0, len = params[key].length; i < len; i++) {
|
||||
list.push(key + '=' + encodeURIComponent(params[key][i]));
|
||||
}
|
||||
} else {
|
||||
list.push(key + '=' + encodeURIComponent(params[key]));
|
||||
}
|
||||
}
|
||||
return list.join('&');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
sysAdminListFileUpdateLogs(page, perPage) {
|
||||
sysAdminListFileUpdateLogs(page, perPage, options = {}) {
|
||||
const url = this.server + '/api/v2.1/admin/logs/file-update-logs/';
|
||||
let params = {
|
||||
page: page,
|
||||
per_page: perPage
|
||||
per_page: perPage,
|
||||
...options
|
||||
};
|
||||
return this.req.get(url, { params: params });
|
||||
return this.req.get(url, {
|
||||
params: params,
|
||||
paramsSerializer: {
|
||||
serialize: function (params) {
|
||||
let list = [];
|
||||
for (let key in params) {
|
||||
if (Array.isArray(params[key])) {
|
||||
for (let i = 0, len = params[key].length; i < len; i++) {
|
||||
list.push(key + '=' + encodeURIComponent(params[key][i]));
|
||||
}
|
||||
} else {
|
||||
list.push(key + '=' + encodeURIComponent(params[key]));
|
||||
}
|
||||
}
|
||||
return list.join('&');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
sysAdminListSharePermissionLogs(page, perPage) {
|
||||
sysAdminListSharePermissionLogs(page, perPage, options = {}) {
|
||||
const url = this.server + '/api/v2.1/admin/logs/share-permission-logs/';
|
||||
let params = {
|
||||
page: page,
|
||||
per_page: perPage
|
||||
per_page: perPage,
|
||||
...options
|
||||
};
|
||||
return this.req.get(url, { params: params });
|
||||
return this.req.get(url, {
|
||||
params: params,
|
||||
paramsSerializer: {
|
||||
serialize: function (params) {
|
||||
let list = [];
|
||||
for (let key in params) {
|
||||
if (Array.isArray(params[key])) {
|
||||
for (let i = 0, len = params[key].length; i < len; i++) {
|
||||
list.push(key + '=' + encodeURIComponent(params[key][i]));
|
||||
}
|
||||
} else {
|
||||
list.push(key + '=' + encodeURIComponent(params[key]));
|
||||
}
|
||||
}
|
||||
return list.join('&');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
sysAdminListFileTransferLogs(page, perPage, options = {}) {
|
||||
const url = this.server + '/api/v2.1/admin/logs/repo-transfer-logs/';
|
||||
let params = {
|
||||
page: page,
|
||||
per_page: perPage,
|
||||
...options
|
||||
};
|
||||
return this.req.get(url, {
|
||||
params: params,
|
||||
paramsSerializer: {
|
||||
serialize: function (params) {
|
||||
let list = [];
|
||||
for (let key in params) {
|
||||
if (Array.isArray(params[key])) {
|
||||
for (let i = 0, len = params[key].length; i < len; i++) {
|
||||
list.push(key + '=' + encodeURIComponent(params[key][i]));
|
||||
}
|
||||
} else {
|
||||
list.push(key + '=' + encodeURIComponent(params[key]));
|
||||
}
|
||||
}
|
||||
return list.join('&');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
sysAdminListGroupInviteLogs(page, perPage, options = {}) {
|
||||
const url = this.server + '/api/v2.1/admin/logs/group-member-audit/';
|
||||
let params = {
|
||||
page: page,
|
||||
per_page: perPage,
|
||||
...options
|
||||
};
|
||||
return this.req.get(url, {
|
||||
params: params,
|
||||
paramsSerializer: {
|
||||
serialize: function (params) {
|
||||
let list = [];
|
||||
for (let key in params) {
|
||||
if (Array.isArray(params[key])) {
|
||||
for (let i = 0, len = params[key].length; i < len; i++) {
|
||||
list.push(key + '=' + encodeURIComponent(params[key][i]));
|
||||
}
|
||||
} else {
|
||||
list.push(key + '=' + encodeURIComponent(params[key]));
|
||||
}
|
||||
}
|
||||
return list.join('&');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
sysAdminExportLogsExcel(start, end, logType) {
|
||||
|
Reference in New Issue
Block a user