mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-20 02:48:51 +00:00
group member pagination (#4704)
* group member pagination * update * update * update Co-authored-by: lian <lian@seafile.com>
This commit is contained in:
@@ -2,6 +2,7 @@ import React, { Fragment } from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { Link } from '@reach/router';
|
import { Link } from '@reach/router';
|
||||||
|
import Paginator from '../../../components/paginator';
|
||||||
import { seafileAPI } from '../../../utils/seafile-api';
|
import { seafileAPI } from '../../../utils/seafile-api';
|
||||||
import { Utils } from '../../../utils/utils.js';
|
import { Utils } from '../../../utils/utils.js';
|
||||||
import toaster from '../../../components/toast';
|
import toaster from '../../../components/toast';
|
||||||
@@ -35,6 +36,11 @@ class DepartmentDetail extends React.Component {
|
|||||||
isItemFreezed: false,
|
isItemFreezed: false,
|
||||||
ancestorGroups: [],
|
ancestorGroups: [],
|
||||||
members: [],
|
members: [],
|
||||||
|
membersErrorMsg: '',
|
||||||
|
membersPageInfo: {
|
||||||
|
},
|
||||||
|
membersPage: 1,
|
||||||
|
membersPerPage: 25,
|
||||||
deletedMember: {},
|
deletedMember: {},
|
||||||
isShowAddMemberDialog: false,
|
isShowAddMemberDialog: false,
|
||||||
showDeleteMemberDialog: false,
|
showDeleteMemberDialog: false,
|
||||||
@@ -54,13 +60,15 @@ class DepartmentDetail extends React.Component {
|
|||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const groupID = this.props.groupID;
|
const groupID = this.props.groupID;
|
||||||
this.listGroupRepo(groupID);
|
this.listGroupRepo(groupID);
|
||||||
this.listMembers(groupID);
|
this.getDepartmentInfo(groupID);
|
||||||
|
this.listMembers(groupID, this.state.membersPage, this.state.membersPerPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
if (this.props.groupID !== nextProps.groupID) {
|
if (this.props.groupID !== nextProps.groupID) {
|
||||||
this.listGroupRepo(nextProps.groupID);
|
this.listGroupRepo(nextProps.groupID);
|
||||||
this.listMembers(nextProps.groupID);
|
this.getDepartmentInfo(nextProps.groupID);
|
||||||
|
this.listMembers(nextProps.groupID, this.state.membersPage, this.state.membersPerPage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,10 +81,9 @@ class DepartmentDetail extends React.Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
listMembers = (groupID) => {
|
getDepartmentInfo = (groupID) => {
|
||||||
seafileAPI.sysAdminGetDepartmentInfo(groupID, true).then(res => {
|
seafileAPI.sysAdminGetDepartmentInfo(groupID, true).then(res => {
|
||||||
this.setState({
|
this.setState({
|
||||||
members: res.data.members,
|
|
||||||
groups: res.data.groups,
|
groups: res.data.groups,
|
||||||
ancestorGroups: res.data.ancestor_groups,
|
ancestorGroups: res.data.ancestor_groups,
|
||||||
groupName: res.data.name,
|
groupName: res.data.name,
|
||||||
@@ -87,6 +94,34 @@ class DepartmentDetail extends React.Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
listMembers = (groupID, page, perPage) => {
|
||||||
|
seafileAPI.sysAdminListGroupMembers(groupID, page, perPage).then((res) => {
|
||||||
|
this.setState({
|
||||||
|
members: res.data.members,
|
||||||
|
membersPageInfo: res.data.page_info
|
||||||
|
});
|
||||||
|
}).catch(error => {
|
||||||
|
let errMessage = Utils.getErrorMsg(error);
|
||||||
|
this.setState({membersErrorMsg: errMessage});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getPreviousPageList = () => {
|
||||||
|
this.listMembers(this.props.groupID, this.state.membersPageInfo.current_page - 1, this.state.membersPerPage);
|
||||||
|
}
|
||||||
|
|
||||||
|
getNextPageList = () => {
|
||||||
|
this.listMembers(this.props.groupID, this.state.membersPageInfo.current_page + 1, this.state.membersPerPage);
|
||||||
|
}
|
||||||
|
|
||||||
|
resetPerPage = (perPage) => {
|
||||||
|
this.setState({
|
||||||
|
membersPerPage: perPage
|
||||||
|
}, () => {
|
||||||
|
this.listMembers(this.props.groupID, 1, perPage);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
listSubDepartGroups = (groupID) => {
|
listSubDepartGroups = (groupID) => {
|
||||||
seafileAPI.sysAdminGetDepartmentInfo(groupID, true).then(res => {
|
seafileAPI.sysAdminGetDepartmentInfo(groupID, true).then(res => {
|
||||||
this.setState({ groups: res.data.groups });
|
this.setState({ groups: res.data.groups });
|
||||||
@@ -114,7 +149,7 @@ class DepartmentDetail extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMemberChanged = () => {
|
onMemberChanged = () => {
|
||||||
this.listMembers(this.props.groupID);
|
this.listMembers(this.props.groupID, this.state.membersPageInfo.current_page, this.state.membersPerPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleItemFreezed = (isFreezed) => {
|
toggleItemFreezed = (isFreezed) => {
|
||||||
@@ -157,7 +192,7 @@ class DepartmentDetail extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { members, repos, groups } = this.state;
|
const { members, membersErrorMsg, repos, groups } = this.state;
|
||||||
const groupID = this.props.groupID;
|
const groupID = this.props.groupID;
|
||||||
const topBtn = 'btn btn-secondary operation-item';
|
const topBtn = 'btn btn-secondary operation-item';
|
||||||
const topbarChildren = (
|
const topbarChildren = (
|
||||||
@@ -259,8 +294,10 @@ class DepartmentDetail extends React.Component {
|
|||||||
<div className="fleft"><h3 className="sf-heading">{gettext('Members')}</h3></div>
|
<div className="fleft"><h3 className="sf-heading">{gettext('Members')}</h3></div>
|
||||||
</div>
|
</div>
|
||||||
<div className="cur-view-content">
|
<div className="cur-view-content">
|
||||||
{(members && members.length === 1 && members[0].role === 'Owner') ?
|
{membersErrorMsg ? <p className="error text-center">{membersErrorMsg}</p> :
|
||||||
|
members.length == 0 ?
|
||||||
<p className="no-member">{gettext('No members')}</p> :
|
<p className="no-member">{gettext('No members')}</p> :
|
||||||
|
<Fragment>
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -287,6 +324,17 @@ class DepartmentDetail extends React.Component {
|
|||||||
})}
|
})}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
{this.state.membersPageInfo &&
|
||||||
|
<Paginator
|
||||||
|
gotoPreviousPage={this.getPreviousPageList}
|
||||||
|
gotoNextPage={this.getNextPageList}
|
||||||
|
currentPage={this.state.membersPageInfo.current_page}
|
||||||
|
hasNextPage={this.state.membersPageInfo.has_next_page}
|
||||||
|
curPerPage={this.state.membersPerPage}
|
||||||
|
resetPerPage={this.resetPerPage}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
</Fragment>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -6,6 +6,7 @@ import { siteRoot, gettext } from '../../../utils/constants';
|
|||||||
import toaster from '../../../components/toast';
|
import toaster from '../../../components/toast';
|
||||||
import EmptyTip from '../../../components/empty-tip';
|
import EmptyTip from '../../../components/empty-tip';
|
||||||
import Loading from '../../../components/loading';
|
import Loading from '../../../components/loading';
|
||||||
|
import Paginator from '../../../components/paginator';
|
||||||
import CommonOperationConfirmationDialog from '../../../components/dialog/common-operation-confirmation-dialog';
|
import CommonOperationConfirmationDialog from '../../../components/dialog/common-operation-confirmation-dialog';
|
||||||
import SysAdminGroupAddMemberDialog from '../../../components/dialog/sysadmin-dialog/sysadmin-group-add-member-dialog';
|
import SysAdminGroupAddMemberDialog from '../../../components/dialog/sysadmin-dialog/sysadmin-group-add-member-dialog';
|
||||||
import SysAdminGroupRoleEditor from '../../../components/select-editor/sysadmin-group-role-editor';
|
import SysAdminGroupRoleEditor from '../../../components/select-editor/sysadmin-group-role-editor';
|
||||||
@@ -19,8 +20,16 @@ class Content extends Component {
|
|||||||
super(props);
|
super(props);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getPreviousPageList = () => {
|
||||||
|
this.props.getListByPage(this.props.pageInfo.current_page - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
getNextPageList = () => {
|
||||||
|
this.props.getListByPage(this.props.pageInfo.current_page + 1);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { loading, errorMsg, items } = this.props;
|
const { loading, errorMsg, items, pageInfo, curPerPage } = this.props;
|
||||||
if (loading) {
|
if (loading) {
|
||||||
return <Loading />;
|
return <Loading />;
|
||||||
} else if (errorMsg) {
|
} else if (errorMsg) {
|
||||||
@@ -53,6 +62,16 @@ class Content extends Component {
|
|||||||
})}
|
})}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
{pageInfo &&
|
||||||
|
<Paginator
|
||||||
|
gotoPreviousPage={this.getPreviousPageList}
|
||||||
|
gotoNextPage={this.getNextPageList}
|
||||||
|
currentPage={pageInfo.current_page}
|
||||||
|
hasNextPage={pageInfo.has_next_page}
|
||||||
|
curPerPage={curPerPage}
|
||||||
|
resetPerPage={this.props.resetPerPage}
|
||||||
|
/>
|
||||||
|
}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
return items.length ? table : emptyTip;
|
return items.length ? table : emptyTip;
|
||||||
@@ -148,16 +167,33 @@ class GroupMembers extends Component {
|
|||||||
errorMsg: '',
|
errorMsg: '',
|
||||||
groupName: '',
|
groupName: '',
|
||||||
memberList: [],
|
memberList: [],
|
||||||
|
pageInfo: {},
|
||||||
|
currentPage: 1,
|
||||||
|
perPage: 25,
|
||||||
isAddMemberDialogOpen: false
|
isAddMemberDialogOpen: false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
seafileAPI.sysAdminListGroupMembers(this.props.groupID).then((res) => {
|
|
||||||
|
let urlParams = (new URL(window.location)).searchParams;
|
||||||
|
const { currentPage, perPage } = this.state;
|
||||||
|
this.setState({
|
||||||
|
currentPage: parseInt(urlParams.get('page') || currentPage),
|
||||||
|
perPage: parseInt(urlParams.get('per_page') || perPage)
|
||||||
|
}, () => {
|
||||||
|
this.getListByPage(this.state.currentPage);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getListByPage = (page) => {
|
||||||
|
const { perPage } = this.state;
|
||||||
|
seafileAPI.sysAdminListGroupMembers(this.props.groupID, page, perPage).then((res) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false,
|
loading: false,
|
||||||
memberList: res.data.members,
|
memberList: res.data.members,
|
||||||
groupName: res.data.group_name
|
groupName: res.data.group_name,
|
||||||
|
pageInfo: res.data.page_info
|
||||||
});
|
});
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
@@ -167,6 +203,14 @@ class GroupMembers extends Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resetPerPage = (perPage) => {
|
||||||
|
this.setState({
|
||||||
|
perPage: perPage
|
||||||
|
}, () => {
|
||||||
|
this.getListByPage(1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
toggleAddMemgerDialog = () => {
|
toggleAddMemgerDialog = () => {
|
||||||
this.setState({isAddMemberDialogOpen: !this.state.isAddMemberDialogOpen});
|
this.setState({isAddMemberDialogOpen: !this.state.isAddMemberDialogOpen});
|
||||||
}
|
}
|
||||||
@@ -250,6 +294,10 @@ class GroupMembers extends Component {
|
|||||||
items={this.state.memberList}
|
items={this.state.memberList}
|
||||||
removeMember={this.removeMember}
|
removeMember={this.removeMember}
|
||||||
updateMemberRole={this.updateMemberRole}
|
updateMemberRole={this.updateMemberRole}
|
||||||
|
pageInfo={this.state.pageInfo}
|
||||||
|
curPerPage={this.state.perPage}
|
||||||
|
getListByPage={this.getListByPage}
|
||||||
|
resetPerPage={this.resetPerPage}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -184,20 +184,7 @@ class AdminAddressBookGroup(APIView):
|
|||||||
for group in groups:
|
for group in groups:
|
||||||
ret_groups.append(address_book_group_to_dict(group))
|
ret_groups.append(address_book_group_to_dict(group))
|
||||||
|
|
||||||
try:
|
|
||||||
members = ccnet_api.get_group_members(group_id)
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(e)
|
|
||||||
error_msg = 'Internal Server Error'
|
|
||||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
|
||||||
|
|
||||||
for m in members:
|
|
||||||
member_info = self._get_address_book_group_memeber_info(request,
|
|
||||||
m, avatar_size)
|
|
||||||
ret_members.append(member_info)
|
|
||||||
|
|
||||||
ret_dict['groups'] = ret_groups
|
ret_dict['groups'] = ret_groups
|
||||||
ret_dict['members'] = ret_members
|
|
||||||
|
|
||||||
if return_ancestors:
|
if return_ancestors:
|
||||||
# get ancestor groups and remove last group which is self
|
# get ancestor groups and remove last group which is self
|
||||||
|
@@ -45,18 +45,33 @@ class AdminGroupMembers(APIView):
|
|||||||
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
return api_error(status.HTTP_404_NOT_FOUND, error_msg)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
avatar_size = int(request.GET.get('avatar_size',
|
avatar_size = int(request.GET.get('avatar_size', AVATAR_DEFAULT_SIZE))
|
||||||
AVATAR_DEFAULT_SIZE))
|
|
||||||
except ValueError:
|
except ValueError:
|
||||||
avatar_size = AVATAR_DEFAULT_SIZE
|
avatar_size = AVATAR_DEFAULT_SIZE
|
||||||
|
|
||||||
try:
|
try:
|
||||||
members = ccnet_api.get_group_members(group_id)
|
page = int(request.GET.get('page', '1'))
|
||||||
|
per_page = int(request.GET.get('per_page', '100'))
|
||||||
|
except ValueError:
|
||||||
|
page = 1
|
||||||
|
per_page = 100
|
||||||
|
|
||||||
|
start = (page - 1) * per_page
|
||||||
|
limit = per_page + 1
|
||||||
|
|
||||||
|
try:
|
||||||
|
members = ccnet_api.get_group_members(group_id, start, limit)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
error_msg = 'Internal Server Error'
|
error_msg = 'Internal Server Error'
|
||||||
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
return api_error(status.HTTP_500_INTERNAL_SERVER_ERROR, error_msg)
|
||||||
|
|
||||||
|
if len(members) > per_page:
|
||||||
|
members = members[:per_page]
|
||||||
|
has_next_page = True
|
||||||
|
else:
|
||||||
|
has_next_page = False
|
||||||
|
|
||||||
group_members_info = []
|
group_members_info = []
|
||||||
for m in members:
|
for m in members:
|
||||||
member_info = get_group_member_info(request, group_id, m.user_name, avatar_size)
|
member_info = get_group_member_info(request, group_id, m.user_name, avatar_size)
|
||||||
@@ -65,9 +80,12 @@ class AdminGroupMembers(APIView):
|
|||||||
group_members = {
|
group_members = {
|
||||||
'group_id': group_id,
|
'group_id': group_id,
|
||||||
'group_name': group.group_name,
|
'group_name': group.group_name,
|
||||||
'members': group_members_info
|
'members': group_members_info,
|
||||||
|
'page_info': {
|
||||||
|
'has_next_page': has_next_page,
|
||||||
|
'current_page': page
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Response(group_members)
|
return Response(group_members)
|
||||||
|
|
||||||
def post(self, request, group_id):
|
def post(self, request, group_id):
|
||||||
|
@@ -45,13 +45,23 @@ class GroupMembers(APIView):
|
|||||||
except ValueError:
|
except ValueError:
|
||||||
avatar_size = AVATAR_DEFAULT_SIZE
|
avatar_size = AVATAR_DEFAULT_SIZE
|
||||||
|
|
||||||
|
try:
|
||||||
|
page = int(request.GET.get('page', '1'))
|
||||||
|
per_page = int(request.GET.get('per_page', '100'))
|
||||||
|
except ValueError:
|
||||||
|
page = 1
|
||||||
|
per_page = 100
|
||||||
|
|
||||||
|
start = (page - 1) * per_page
|
||||||
|
limit = per_page
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# only group member can get info of all group members
|
# only group member can get info of all group members
|
||||||
if not is_group_member(group_id, request.user.username):
|
if not is_group_member(group_id, request.user.username):
|
||||||
error_msg = 'Permission denied.'
|
error_msg = 'Permission denied.'
|
||||||
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
return api_error(status.HTTP_403_FORBIDDEN, error_msg)
|
||||||
|
|
||||||
members = ccnet_api.get_group_members(group_id)
|
members = ccnet_api.get_group_members(group_id, start, limit)
|
||||||
|
|
||||||
except SearpcError as e:
|
except SearpcError as e:
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
|
Reference in New Issue
Block a user