diff --git a/frontend/src/pages/sys-admin/departments/department-detail.js b/frontend/src/pages/sys-admin/departments/department-detail.js index 4d4dddccf4..87d1fe9f5d 100644 --- a/frontend/src/pages/sys-admin/departments/department-detail.js +++ b/frontend/src/pages/sys-admin/departments/department-detail.js @@ -2,6 +2,7 @@ import React, { Fragment } from 'react'; import PropTypes from 'prop-types'; import moment from 'moment'; import { Link } from '@reach/router'; +import Paginator from '../../../components/paginator'; import { seafileAPI } from '../../../utils/seafile-api'; import { Utils } from '../../../utils/utils.js'; import toaster from '../../../components/toast'; @@ -35,6 +36,11 @@ class DepartmentDetail extends React.Component { isItemFreezed: false, ancestorGroups: [], members: [], + membersErrorMsg: '', + membersPageInfo: { + }, + membersPage: 1, + membersPerPage: 25, deletedMember: {}, isShowAddMemberDialog: false, showDeleteMemberDialog: false, @@ -54,13 +60,15 @@ class DepartmentDetail extends React.Component { componentDidMount() { const groupID = this.props.groupID; this.listGroupRepo(groupID); - this.listMembers(groupID); + this.getDepartmentInfo(groupID); + this.listMembers(groupID, this.state.membersPage, this.state.membersPerPage); } componentWillReceiveProps(nextProps) { if (this.props.groupID !== 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 => { this.setState({ - members: res.data.members, groups: res.data.groups, ancestorGroups: res.data.ancestor_groups, 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) => { seafileAPI.sysAdminGetDepartmentInfo(groupID, true).then(res => { this.setState({ groups: res.data.groups }); @@ -114,7 +149,7 @@ class DepartmentDetail extends React.Component { } onMemberChanged = () => { - this.listMembers(this.props.groupID); + this.listMembers(this.props.groupID, this.state.membersPageInfo.current_page, this.state.membersPerPage); } toggleItemFreezed = (isFreezed) => { @@ -142,7 +177,7 @@ class DepartmentDetail extends React.Component { } showDeleteDepartDialog = (subGroup) => { - this.setState({ + this.setState({ showDeleteDepartDialog: true, subGroupID: subGroup.id, subGroupName: subGroup.name @@ -157,7 +192,7 @@ class DepartmentDetail extends React.Component { } render() { - const { members, repos, groups } = this.state; + const { members, membersErrorMsg, repos, groups } = this.state; const groupID = this.props.groupID; const topBtn = 'btn btn-secondary operation-item'; const topbarChildren = ( @@ -207,7 +242,7 @@ class DepartmentDetail extends React.Component {

- {groupID ? + {groupID ? {gettext('Departments')} : {gettext('Departments')} } @@ -253,14 +288,16 @@ class DepartmentDetail extends React.Component { }

- +

{gettext('Members')}

- {(members && members.length === 1 && members[0].role === 'Owner') ? + {membersErrorMsg ?

{membersErrorMsg}

: + members.length == 0 ?

{gettext('No members')}

: + @@ -287,6 +324,17 @@ class DepartmentDetail extends React.Component { })}
+ {this.state.membersPageInfo && + + } +
}
diff --git a/frontend/src/pages/sys-admin/groups/group-members.js b/frontend/src/pages/sys-admin/groups/group-members.js index a82c2e43aa..88eecb8d1c 100644 --- a/frontend/src/pages/sys-admin/groups/group-members.js +++ b/frontend/src/pages/sys-admin/groups/group-members.js @@ -6,6 +6,7 @@ import { siteRoot, gettext } from '../../../utils/constants'; import toaster from '../../../components/toast'; import EmptyTip from '../../../components/empty-tip'; import Loading from '../../../components/loading'; +import Paginator from '../../../components/paginator'; import CommonOperationConfirmationDialog from '../../../components/dialog/common-operation-confirmation-dialog'; import SysAdminGroupAddMemberDialog from '../../../components/dialog/sysadmin-dialog/sysadmin-group-add-member-dialog'; import SysAdminGroupRoleEditor from '../../../components/select-editor/sysadmin-group-role-editor'; @@ -19,8 +20,16 @@ class Content extends Component { super(props); } + getPreviousPageList = () => { + this.props.getListByPage(this.props.pageInfo.current_page - 1); + } + + getNextPageList = () => { + this.props.getListByPage(this.props.pageInfo.current_page + 1); + } + render() { - const { loading, errorMsg, items } = this.props; + const { loading, errorMsg, items, pageInfo, curPerPage } = this.props; if (loading) { return ; } else if (errorMsg) { @@ -53,9 +62,19 @@ class Content extends Component { })} + {pageInfo && + + } ); - return items.length ? table : emptyTip; + return items.length ? table : emptyTip; } } } @@ -110,7 +129,7 @@ class Item extends Component { {item.role == 'Owner' ? gettext('Owner') : - {isDeleteDialogOpen && - { + + 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({ loading: false, memberList: res.data.members, - groupName: res.data.group_name + groupName: res.data.group_name, + pageInfo: res.data.page_info }); }).catch((error) => { this.setState({ @@ -167,6 +203,14 @@ class GroupMembers extends Component { }); } + resetPerPage = (perPage) => { + this.setState({ + perPage: perPage + }, () => { + this.getListByPage(1); + }); + } + toggleAddMemgerDialog = () => { this.setState({isAddMemberDialogOpen: !this.state.isAddMemberDialogOpen}); } @@ -238,7 +282,7 @@ class GroupMembers extends Component {
-
diff --git a/seahub/api2/endpoints/admin/address_book/groups.py b/seahub/api2/endpoints/admin/address_book/groups.py index 4b2083f9d2..f678f91dae 100644 --- a/seahub/api2/endpoints/admin/address_book/groups.py +++ b/seahub/api2/endpoints/admin/address_book/groups.py @@ -184,20 +184,7 @@ class AdminAddressBookGroup(APIView): for group in groups: 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['members'] = ret_members if return_ancestors: # get ancestor groups and remove last group which is self diff --git a/seahub/api2/endpoints/admin/group_members.py b/seahub/api2/endpoints/admin/group_members.py index 79135dfe91..8887a9aa57 100644 --- a/seahub/api2/endpoints/admin/group_members.py +++ b/seahub/api2/endpoints/admin/group_members.py @@ -45,18 +45,33 @@ class AdminGroupMembers(APIView): return api_error(status.HTTP_404_NOT_FOUND, error_msg) try: - avatar_size = int(request.GET.get('avatar_size', - AVATAR_DEFAULT_SIZE)) + avatar_size = int(request.GET.get('avatar_size', AVATAR_DEFAULT_SIZE)) except ValueError: avatar_size = AVATAR_DEFAULT_SIZE 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: logger.error(e) error_msg = 'Internal Server Error' 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 = [] for m in members: member_info = get_group_member_info(request, group_id, m.user_name, avatar_size) @@ -65,9 +80,12 @@ class AdminGroupMembers(APIView): group_members = { 'group_id': group_id, '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) def post(self, request, group_id): diff --git a/seahub/api2/endpoints/group_members.py b/seahub/api2/endpoints/group_members.py index 7be9b80236..8f364001c5 100644 --- a/seahub/api2/endpoints/group_members.py +++ b/seahub/api2/endpoints/group_members.py @@ -45,13 +45,23 @@ class GroupMembers(APIView): except ValueError: 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: # only group member can get info of all group members if not is_group_member(group_id, request.user.username): error_msg = 'Permission denied.' 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: logger.error(e)