mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-01 07:01:12 +00:00
Group manage member (#4805)
* [group manage members] added 'scroll to load more members' * [group manage members] fixup for 'add/delete/modify member'
This commit is contained in:
@@ -1,12 +1,14 @@
|
||||
import React from 'react';
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { gettext } from '../../utils/constants';
|
||||
import { Button, Modal, ModalHeader, ModalBody, ModalFooter, Table } from 'reactstrap';
|
||||
import { seafileAPI } from '../../utils/seafile-api.js';
|
||||
import RoleEditor from '../select-editor/role-editor';
|
||||
import UserSelect from '../user-select.js';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import { gettext } from '../../utils/constants';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import RoleEditor from '../select-editor/role-editor';
|
||||
import UserSelect from '../user-select';
|
||||
import toaster from '../toast';
|
||||
import Loading from '../loading';
|
||||
|
||||
import '../../css/manage-members-dialog.css';
|
||||
|
||||
const propTypes = {
|
||||
@@ -21,13 +23,45 @@ class ManageMembersDialog extends React.Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isLoading: true, // first loading
|
||||
isLoadingMore: false,
|
||||
groupMembers: [],
|
||||
page: 1,
|
||||
perPage: 100,
|
||||
hasNextPage: false,
|
||||
selectedOption: null,
|
||||
errMessage: [],
|
||||
isItemFreezed: false,
|
||||
isItemFreezed: false
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.listGroupMembers(this.state.page);
|
||||
}
|
||||
|
||||
listGroupMembers = (page) => {
|
||||
const { groupID } = this.props;
|
||||
const { perPage, groupMembers } = this.state;
|
||||
seafileAPI.listGroupMembers(groupID, page, perPage).then((res) => {
|
||||
const members = res.data;
|
||||
this.setState({
|
||||
isLoading: false,
|
||||
isLoadingMore: false,
|
||||
page: page,
|
||||
hasNextPage: members.length < perPage ? false : true,
|
||||
groupMembers: groupMembers.concat(members)
|
||||
});
|
||||
}).catch(error => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
this.setState({
|
||||
isLoading: false,
|
||||
isLoadingMore: false,
|
||||
hasNextPage: false
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
onSelectChange = (option) => {
|
||||
this.setState({
|
||||
selectedOption: option,
|
||||
@@ -41,8 +75,9 @@ class ManageMembersDialog extends React.Component {
|
||||
emails.push(this.state.selectedOption[i].email);
|
||||
}
|
||||
seafileAPI.addGroupMembers(this.props.groupID, emails).then((res) => {
|
||||
this.onGroupMembersChange();
|
||||
const newMembers = res.data.success;
|
||||
this.setState({
|
||||
groupMembers: [].concat(newMembers, this.state.groupMembers),
|
||||
selectedOption: null,
|
||||
});
|
||||
this.refs.userSelect.clearSelect();
|
||||
@@ -57,21 +92,6 @@ class ManageMembersDialog extends React.Component {
|
||||
});
|
||||
}
|
||||
|
||||
listGroupMembers = () => {
|
||||
seafileAPI.listGroupMembers(this.props.groupID).then((res) => {
|
||||
this.setState({
|
||||
groupMembers: res.data
|
||||
});
|
||||
}).catch(error => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
});
|
||||
}
|
||||
|
||||
onGroupMembersChange = () => {
|
||||
this.listGroupMembers();
|
||||
}
|
||||
|
||||
toggleItemFreezed = (isFreezed) => {
|
||||
this.setState({
|
||||
isItemFreezed: isFreezed
|
||||
@@ -82,11 +102,43 @@ class ManageMembersDialog extends React.Component {
|
||||
this.props.toggleManageMembersDialog();
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.listGroupMembers();
|
||||
handleScroll = (event) => {
|
||||
// isLoadingMore: to avoid repeated request
|
||||
const { page, hasNextPage, isLoadingMore } = this.state;
|
||||
if (hasNextPage && !isLoadingMore) {
|
||||
const clientHeight = event.target.clientHeight;
|
||||
const scrollHeight = event.target.scrollHeight;
|
||||
const scrollTop = event.target.scrollTop;
|
||||
const isBottom = (clientHeight + scrollTop + 1 >= scrollHeight);
|
||||
if (isBottom) { // scroll to the bottom
|
||||
this.setState({isLoadingMore: true}, () => {
|
||||
this.listGroupMembers(page + 1);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
changeMember = (targetMember) => {
|
||||
this.setState({
|
||||
groupMembers: this.state.groupMembers.map((item) => {
|
||||
if (item.email == targetMember.email) {
|
||||
item = targetMember;
|
||||
}
|
||||
return item;
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
deleteMember = (targetMember) => {
|
||||
const groupMembers = this.state.groupMembers;
|
||||
groupMembers.splice(groupMembers.indexOf(targetMember), 1);
|
||||
this.setState({
|
||||
groupMembers: groupMembers
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { isLoading, hasNextPage } = this.state;
|
||||
return (
|
||||
<Modal isOpen={true} toggle={this.toggle}>
|
||||
<ModalHeader toggle={this.toggle}>{gettext('Manage group members')}</ModalHeader>
|
||||
@@ -113,36 +165,41 @@ class ManageMembersDialog extends React.Component {
|
||||
);
|
||||
})
|
||||
}
|
||||
<div className="manage-members">
|
||||
<Table size="sm" className="manage-members-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="15%"></th>
|
||||
<th width="45%">{gettext('Name')}</th>
|
||||
<th width="30%">{gettext('Role')}</th>
|
||||
<th width="10%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{
|
||||
this.state.groupMembers.length > 0 &&
|
||||
this.state.groupMembers.map((item, index = 0) => {
|
||||
<div className="manage-members" onScroll={this.handleScroll}>
|
||||
{isLoading ? <Loading /> : (
|
||||
<Fragment>
|
||||
<Table size="sm" className="manage-members-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="15%"></th>
|
||||
<th width="45%">{gettext('Name')}</th>
|
||||
<th width="30%">{gettext('Role')}</th>
|
||||
<th width="10%"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{
|
||||
this.state.groupMembers.length > 0 &&
|
||||
this.state.groupMembers.map((item, index) => {
|
||||
return (
|
||||
<React.Fragment key={index}>
|
||||
<Member
|
||||
key={index}
|
||||
item={item}
|
||||
onGroupMembersChange={this.onGroupMembersChange}
|
||||
changeMember={this.changeMember}
|
||||
deleteMember={this.deleteMember}
|
||||
groupID={this.props.groupID}
|
||||
isOwner={this.props.isOwner}
|
||||
isItemFreezed={this.state.isItemFreezed}
|
||||
toggleItemFreezed={this.toggleItemFreezed}
|
||||
/>
|
||||
</React.Fragment>
|
||||
);
|
||||
})
|
||||
}
|
||||
</tbody>
|
||||
</Table>
|
||||
}
|
||||
</tbody>
|
||||
</Table>
|
||||
{hasNextPage && <Loading />}
|
||||
</Fragment>
|
||||
)}
|
||||
</div>
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
@@ -157,7 +214,8 @@ ManageMembersDialog.propTypes = propTypes;
|
||||
|
||||
const MemberPropTypes = {
|
||||
item: PropTypes.object.isRequired,
|
||||
onGroupMembersChange: PropTypes.func.isRequired,
|
||||
changeMember: PropTypes.func.isRequired,
|
||||
deleteMember: PropTypes.func.isRequired,
|
||||
groupID: PropTypes.string.isRequired,
|
||||
isOwner: PropTypes.bool.isRequired,
|
||||
};
|
||||
@@ -175,16 +233,18 @@ class Member extends React.PureComponent {
|
||||
onChangeUserRole = (role) => {
|
||||
let isAdmin = role === 'Admin' ? 'True' : 'False';
|
||||
seafileAPI.setGroupAdmin(this.props.groupID, this.props.item.email, isAdmin).then((res) => {
|
||||
this.props.onGroupMembersChange();
|
||||
});
|
||||
this.setState({
|
||||
highlight: false,
|
||||
this.props.changeMember(res.data);
|
||||
}).catch(error => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
});
|
||||
}
|
||||
|
||||
deleteMember = (name) => {
|
||||
seafileAPI.deleteGroupMember(this.props.groupID, name).then((res) => {
|
||||
this.props.onGroupMembersChange();
|
||||
deleteMember = () => {
|
||||
const { item } = this.props;
|
||||
seafileAPI.deleteGroupMember(this.props.groupID, item.email).then((res) => {
|
||||
this.props.deleteMember(item);
|
||||
toaster.success(gettext('Successfully deleted {name}.').replace('{name}', item.name));
|
||||
}).catch(error => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
@@ -243,8 +303,7 @@ class Member extends React.PureComponent {
|
||||
{(deleteAuthority && !this.props.isItemFreezed) &&
|
||||
<i
|
||||
className="fa fa-times delete-group-member-icon"
|
||||
name={item.email}
|
||||
onClick={this.deleteMember.bind(this, item.email)}>
|
||||
onClick={this.deleteMember}>
|
||||
</i>
|
||||
}
|
||||
</td>
|
||||
|
Reference in New Issue
Block a user