mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-19 18:29:23 +00:00
invite user
This commit is contained in:
113
frontend/src/components/dialog/group-invite-members-dialog.js
Normal file
113
frontend/src/components/dialog/group-invite-members-dialog.js
Normal file
@@ -0,0 +1,113 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Button, Modal, ModalBody } from 'reactstrap';
|
||||
import SeahubModalHeader from '@/components/common/seahub-modal-header';
|
||||
import copy from 'copy-to-clipboard';
|
||||
import toaster from '../toast';
|
||||
import { gettext } from '../../utils/constants';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import { Utils } from '../../utils/utils';
|
||||
|
||||
import '../../css/group-invite-members-dialog.css';
|
||||
|
||||
const propTypes = {
|
||||
groupID: PropTypes.string.isRequired,
|
||||
toggleGroupInviteDialog: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
class GroupInviteMembersDialog extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
inviteList: [],
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.listInviteLinks();
|
||||
}
|
||||
|
||||
listInviteLinks = () => {
|
||||
seafileAPI.getGroupInviteLinks(this.props.groupID).then((res) => {
|
||||
this.setState({ inviteList: res.data.group_invite_link_list });
|
||||
}).catch(error => {
|
||||
this.onError(error);
|
||||
});
|
||||
};
|
||||
|
||||
addInviteLink = () => {
|
||||
seafileAPI.addGroupInviteLinks(this.props.groupID).then(() => {
|
||||
this.listInviteLinks();
|
||||
}).catch(error => {
|
||||
this.onError(error);
|
||||
});
|
||||
};
|
||||
|
||||
deleteLink = (token) => {
|
||||
seafileAPI.deleteGroupInviteLinks(this.props.groupID, token).then(() => {
|
||||
this.listInviteLinks();
|
||||
}).catch(error => {
|
||||
this.onError(error);
|
||||
});
|
||||
};
|
||||
|
||||
onError = (error) => {
|
||||
let errMsg = Utils.getErrorMsg(error, true);
|
||||
if (!error.response || error.response.status !== 403) {
|
||||
toaster.danger(errMsg);
|
||||
}
|
||||
};
|
||||
|
||||
copyLink = () => {
|
||||
const inviteLinkItem = this.state.inviteList[0];
|
||||
copy(inviteLinkItem.link);
|
||||
const message = gettext('Invitation link has been copied to clipboard');
|
||||
toaster.success((message), {
|
||||
duration: 2
|
||||
});
|
||||
};
|
||||
|
||||
toggle = () => {
|
||||
this.props.toggleGroupInviteDialog();
|
||||
};
|
||||
|
||||
render() {
|
||||
const { inviteList } = this.state;
|
||||
const link = inviteList[0];
|
||||
return (
|
||||
<Modal isOpen={true} toggle={this.toggle} className="group-invite-members">
|
||||
<SeahubModalHeader toggle={this.toggle}>{gettext('Invite members')}</SeahubModalHeader>
|
||||
<ModalBody>
|
||||
{link ?
|
||||
<>
|
||||
<div>
|
||||
<strong>{gettext('Group invitation link')}</strong>
|
||||
</div>
|
||||
<div className="invite-link-item">
|
||||
<div className="form-item text-truncate">{link.link}</div>
|
||||
<div className="invite-link-copy">
|
||||
<Button color="primary" onClick={this.copyLink} className="invite-link-copy-btn text-truncate">{gettext('Copy')}</Button>
|
||||
</div>
|
||||
<Button color="secondary" onClick={this.deleteLink.bind(this, link.token)} className="delete-link-btn ml-2">
|
||||
<i className="sf2-icon-delete"></i>
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
:
|
||||
<>
|
||||
<div className="no-link-tip mb-4">
|
||||
{gettext('No group invitation link yet. Group invitation link let registered users to join the group by clicking a link.')}
|
||||
</div>
|
||||
<Button color="primary" onClick={this.addInviteLink} className="my-4">{gettext('Generate')}</Button>
|
||||
</>
|
||||
}
|
||||
</ModalBody>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
GroupInviteMembersDialog.propTypes = propTypes;
|
||||
|
||||
export default GroupInviteMembersDialog;
|
40
frontend/src/css/group-invite-members-dialog.css
Normal file
40
frontend/src/css/group-invite-members-dialog.css
Normal file
@@ -0,0 +1,40 @@
|
||||
.group-invite-members th,
|
||||
.group-invite-members td {
|
||||
vertical-align: middle;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.group-invite-members .no-link-tip {
|
||||
line-height: 24px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.invite-link-item {
|
||||
display: flex;
|
||||
margin: 1rem 0 2.5rem;
|
||||
}
|
||||
|
||||
.invite-link-item .form-item {
|
||||
width: calc(100% - 120px);
|
||||
padding-left: 10px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
border: 1px solid #ccc;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.invite-link-item .invite-link-copy {
|
||||
width: 72px;
|
||||
}
|
||||
|
||||
.invite-link-item .invite-link-copy-btn {
|
||||
width: 72px;
|
||||
height: 40px;
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
.invite-link-item .delete-link-btn {
|
||||
color: #999;
|
||||
width: 40px;
|
||||
}
|
@@ -2,7 +2,7 @@ import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import cookie from 'react-cookies';
|
||||
import classnames from 'classnames';
|
||||
import { gettext, username, canAddRepo } from '../../utils/constants';
|
||||
import { gettext, username, canAddRepo, isMultiTenancy } from '../../utils/constants';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import Loading from '../../components/loading';
|
||||
@@ -21,6 +21,7 @@ import DepartmentDetailDialog from '../../components/dialog/department-detail-di
|
||||
import LeaveGroupDialog from '../../components/dialog/leave-group-dialog';
|
||||
import SharedRepoListView from '../../components/shared-repo-list-view/shared-repo-list-view';
|
||||
import SortOptionsDialog from '../../components/dialog/sort-options';
|
||||
import GroupInviteMembersDialog from '../../components/dialog/group-invite-members-dialog';
|
||||
import SingleDropdownToolbar from '../../components/toolbar/single-dropdown-toolbar';
|
||||
import ViewModes from '../../components/view-modes';
|
||||
import ReposSortMenu from '../../components/sort-menu';
|
||||
@@ -65,6 +66,7 @@ class GroupView extends React.Component {
|
||||
showTransferGroupDialog: false,
|
||||
showImportMembersDialog: false,
|
||||
showManageMembersDialog: false,
|
||||
showInviteMembersDialog: false,
|
||||
isLeaveGroupDialogOpen: false,
|
||||
isMembersDialogOpen: false
|
||||
};
|
||||
@@ -287,6 +289,13 @@ class GroupView extends React.Component {
|
||||
});
|
||||
};
|
||||
|
||||
toggleInviteMembersDialog = () => {
|
||||
this.setState({
|
||||
showInviteMembersDialog: !this.state.showInviteMembersDialog,
|
||||
showGroupDropdown: false,
|
||||
});
|
||||
};
|
||||
|
||||
importMembersInBatch = (file) => {
|
||||
toaster.notify(gettext('It may take some time, please wait.'));
|
||||
seafileAPI.importGroupMembersViaFile(this.state.currentGroup.id, file).then((res) => {
|
||||
@@ -365,6 +374,7 @@ class GroupView extends React.Component {
|
||||
|
||||
getOpList = () => {
|
||||
const { currentGroup, isDepartmentGroup, isStaff, isOwner } = this.state;
|
||||
// const isGroup = this.state.currentGroup.owner !== 'system admin';
|
||||
const opList = [];
|
||||
if ((!isDepartmentGroup && canAddRepo) ||
|
||||
(isDepartmentGroup && isStaff)) {
|
||||
@@ -389,6 +399,10 @@ class GroupView extends React.Component {
|
||||
if (!isOwner && !isDepartmentGroup) {
|
||||
opList.push({ 'text': gettext('Leave group'), 'onClick': this.toggleLeaveGroupDialog });
|
||||
}
|
||||
|
||||
if (isOwner && this.state.currentGroup.owner !== 'system admin' && !isMultiTenancy) {
|
||||
opList.push({ 'text': gettext('Invite Members'), 'onClick': this.toggleInviteMembersDialog });
|
||||
}
|
||||
}
|
||||
|
||||
return opList;
|
||||
@@ -589,6 +603,12 @@ class GroupView extends React.Component {
|
||||
onGroupChanged={this.props.onGroupChanged}
|
||||
/>
|
||||
}
|
||||
{this.state.showInviteMembersDialog &&
|
||||
<GroupInviteMembersDialog
|
||||
groupID={this.props.groupID}
|
||||
onGroupChanged={this.props.onGroupChanged}
|
||||
toggleGroupInviteDialog={this.toggleInviteMembersDialog}/>
|
||||
}
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
@@ -112,6 +112,7 @@ export const enablePDFThumbnail = window.app.pageOptions.enablePDFThumbnail;
|
||||
export const enableOnlyoffice = window.app.pageOptions.enableOnlyoffice || false;
|
||||
export const onlyofficeConverterExtensions = window.app.pageOptions.onlyofficeConverterExtensions || [];
|
||||
|
||||
export const isMultiTenancy = window.app.pageOptions.isMultiTenacy;
|
||||
export const enableFileTags = window.app.pageOptions.enableFileTags || false;
|
||||
|
||||
export const enableShowAbout = window.app.pageOptions.enableShowAbout || false;
|
||||
|
@@ -303,6 +303,22 @@ class SeafileAPI {
|
||||
return this.req.delete(url, { data: params });
|
||||
}
|
||||
|
||||
deleteGroupInviteLinks(groupID, token) {
|
||||
const url = this.server + '/api/v2.1/groups/' + groupID + '/invite-links/' + token + '/';
|
||||
return this.req.delete(url);
|
||||
}
|
||||
|
||||
addGroupInviteLinks(groupID) {
|
||||
const url = this.server + '/api/v2.1/groups/' + groupID + '/invite-links/';
|
||||
let formData = new FormData();
|
||||
return this._sendPostRequest(url, formData);
|
||||
}
|
||||
|
||||
getGroupInviteLinks(groupID) {
|
||||
const url = this.server + '/api/v2.1/groups/' + groupID + '/invite-links/';
|
||||
return this.req.get(url);
|
||||
}
|
||||
|
||||
// ---- share operation
|
||||
|
||||
listShareLinks({ repoID, path, page, perPage }) {
|
||||
|
Reference in New Issue
Block a user