diff --git a/frontend/src/components/dialog/org-add-member-dialog.js b/frontend/src/components/dialog/org-add-member-dialog.js deleted file mode 100644 index 9d3d350faa..0000000000 --- a/frontend/src/components/dialog/org-add-member-dialog.js +++ /dev/null @@ -1,77 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { Button, Modal, ModalBody, ModalFooter, Alert } from 'reactstrap'; -import { gettext, orgID } from '../../utils/constants'; -import { orgAdminAPI } from '../../utils/org-admin-api'; -import { Utils } from '../../utils/utils'; -import toaster from '../toast'; -import UserSelect from '../user-select'; -import SeahubModalHeader from '@/components/common/seahub-modal-header'; - -const propTypes = { - toggle: PropTypes.func.isRequired, - groupID: PropTypes.string.isRequired, - onAddNewMembers: PropTypes.func.isRequired -}; - -class AddMemberDialog extends React.Component { - - constructor(props) { - super(props); - this.state = { - selectedOption: null, - errMessage: '', - }; - } - - handleSelectChange = (option) => { - this.setState({ selectedOption: option }); - }; - - handleSubmit = () => { - if (!this.state.selectedOption) return; - const email = this.state.selectedOption[0].email; - this.refs.orgSelect.clearSelect(); - this.setState({ errMessage: [] }); - orgAdminAPI.orgAdminAddGroupMember(orgID, this.props.groupID, email).then((res) => { - this.setState({ selectedOption: null }); - if (res.data.failed.length > 0) { - this.setState({ errMessage: res.data.failed[0].error_msg }); - } - if (res.data.success.length > 0) { - this.props.onAddNewMembers(res.data.success); - this.props.toggle(); - } - }).catch(error => { - let errMessage = Utils.getErrorMsg(error); - toaster.danger(errMessage); - }); - }; - - render() { - const { errMessage } = this.state; - return ( - - {gettext('Add Member')} - - - {errMessage && {errMessage}} - - - - - - - ); - } -} - -AddMemberDialog.propTypes = propTypes; - -export default AddMemberDialog; diff --git a/frontend/src/components/dialog/org-delete-member-dialog.js b/frontend/src/components/dialog/org-delete-member-dialog.js deleted file mode 100644 index 3a644046f4..0000000000 --- a/frontend/src/components/dialog/org-delete-member-dialog.js +++ /dev/null @@ -1,56 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { Button, Modal, ModalBody, ModalFooter } from 'reactstrap'; -import { gettext, orgID } from '../../utils/constants'; -import { orgAdminAPI } from '../../utils/org-admin-api'; -import { Utils } from '../../utils/utils'; -import toaster from '../toast'; -import SeahubModalHeader from '@/components/common/seahub-modal-header'; - -const propTypes = { - member: PropTypes.object.isRequired, - groupID: PropTypes.string, - toggle: PropTypes.func.isRequired, - onMemberChanged: PropTypes.func.isRequired -}; - -class DeleteMemberDialog extends React.Component { - - constructor(props) { - super(props); - } - - deleteMember = () => { - const userEmail = this.props.member.email; - orgAdminAPI.orgAdminDeleteGroupMember(orgID, this.props.groupID, userEmail).then((res) => { - if (res.data.success) { - this.props.onMemberChanged(); - this.props.toggle(); - } - }).catch(error => { - let errMessage = Utils.getErrorMsg(error); - toaster.danger(errMessage); - }); - }; - - render() { - let subtitle = gettext('Are you sure you want to delete {placeholder} ?'); - subtitle = subtitle.replace('{placeholder}', '' + Utils.HTMLescape(this.props.member.name) + ''); - return ( - - {gettext('Delete Member')} - -
-
- - - - -
- ); - } -} - -DeleteMemberDialog.propTypes = propTypes; - -export default DeleteMemberDialog; diff --git a/frontend/src/components/dialog/org-delete-repo-dialog.js b/frontend/src/components/dialog/org-delete-repo-dialog.js index 568bb64a69..a04487ebf9 100644 --- a/frontend/src/components/dialog/org-delete-repo-dialog.js +++ b/frontend/src/components/dialog/org-delete-repo-dialog.js @@ -18,7 +18,6 @@ class DeleteRepoDialog extends React.Component { orgAdminAPI.orgAdminDeleteDepartmentRepo(orgID, this.props.groupID, this.props.repo.repo_id).then((res) => { if (res.data.success) { this.props.onDeleteRepo(repo.repo_id); - this.props.toggle(); } }).catch(error => { let errMessage = Utils.getErrorMsg(error); @@ -47,7 +46,7 @@ class DeleteRepoDialog extends React.Component { const propTypes = { repo: PropTypes.object.isRequired, toggle: PropTypes.func.isRequired, - groupID: PropTypes.string, + groupID: PropTypes.number, onDeleteRepo: PropTypes.func.isRequired }; diff --git a/frontend/src/components/dialog/sysadmin-dialog/sysadmin-add-depart-member-v2-dialog.js b/frontend/src/components/dialog/sysadmin-dialog/sysadmin-add-depart-member-v2-dialog.js index a48c6c4fa0..0d01ffecef 100644 --- a/frontend/src/components/dialog/sysadmin-dialog/sysadmin-add-depart-member-v2-dialog.js +++ b/frontend/src/components/dialog/sysadmin-dialog/sysadmin-add-depart-member-v2-dialog.js @@ -1,6 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { Button, Modal, ModalBody, ModalFooter } from 'reactstrap'; +import toaster from '../../../components/toast'; import { gettext } from '../../../utils/constants'; import { systemAdminAPI } from '../../../utils/system-admin-api'; import { orgAdminAPI } from '../../../utils/org-admin-api'; @@ -20,7 +21,7 @@ export default class AddDepartMemberV2Dialog extends React.Component { super(props); this.state = { selectedOptions: [], - errMessage: '', + errMsgs: '', }; } @@ -39,7 +40,7 @@ export default class AddDepartMemberV2Dialog extends React.Component { req.then((res) => { this.setState({ selectedOptions: [] }); if (res.data.failed.length > 0) { - this.setState({ errMessage: res.data.failed[0].error_msg }); + this.setState({ errMsgs: res.data.failed.map(item => item.error_msg) }); } if (res.data.success.length > 0) { this.props.onMemberChanged(); @@ -47,21 +48,28 @@ export default class AddDepartMemberV2Dialog extends React.Component { } }).catch(error => { let errMessage = Utils.getErrorMsg(error); - this.setState({ errMessage }); + toaster.danger(errMessage); }); }; render() { + const { errMsgs } = this.state; return ( - {gettext('Add member')} + {gettext('Add members')} - {this.state.errMessage &&

{this.state.errMessage}

} + {errMsgs.length > 0 && ( +
    + {errMsgs.map((item, index) => { + return
  • {item}
  • ; + })} +
+ )}
diff --git a/frontend/src/pages/org-admin/departments-v2/departments-v2-members-item.js b/frontend/src/pages/org-admin/departments-v2/departments-v2-members-item.js deleted file mode 100644 index e468942fc2..0000000000 --- a/frontend/src/pages/org-admin/departments-v2/departments-v2-members-item.js +++ /dev/null @@ -1,120 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap'; -import RoleSelector from '../../../components/single-selector'; -import { gettext, siteRoot } from '../../../utils/constants'; - -const propTypes = { - isItemFreezed: PropTypes.bool, - member: PropTypes.object, - setMemberStaff: PropTypes.func, - deleteMember: PropTypes.func, - unfreezeItem: PropTypes.func, - freezeItem: PropTypes.func, - toggleItemFreezed: PropTypes.func, -}; - -class DepartmentsV2MembersItem extends React.Component { - - constructor(props) { - super(props); - this.state = { - dropdownOpenEmail: '', - isShowDropdownMenu: false, - isItemMenuShow: false, - }; - this.roleOptions = [ - { value: 'Admin', text: gettext('Admin'), isSelected: false }, - { value: 'Member', text: gettext('Member'), isSelected: false } - ]; - } - - onMouseEnter = () => { - if (!this.props.isItemFreezed) { - this.setState({ isShowDropdownMenu: true }); - } - }; - - onMouseLeave = () => { - if (!this.props.isItemFreezed) { - this.setState({ isShowDropdownMenu: false }); - } - }; - - setMemberStaff = (role) => { - this.props.setMemberStaff(this.props.member.email, role.value === 'Admin'); - }; - - deleteMember = (e) => { - e.stopPropagation(); - const { member } = this.props; - this.props.deleteMember(member.email); - }; - - toggleDropdownMenu = () => { - this.setState({ - isItemMenuShow: !this.state.isItemMenuShow - }, () => { - if (this.state.isItemMenuShow && typeof(this.props.freezeItem) === 'function') { - this.props.freezeItem(); - } else if (!this.state.isItemMenuShow && typeof(this.props.unfreezeItem) === 'function') { - this.props.unfreezeItem(); - } - }); - }; - - render() { - const { member, freezeItem, unfreezeItem } = this.props; - const { isShowDropdownMenu, isItemMenuShow } = this.state; - - this.roleOptions = this.roleOptions.map(item => { - item.isSelected = item.value == member.role; - return item; - }); - const currentSelectedOption = this.roleOptions.filter(item => item.isSelected)[0]; - - return ( - - - - {member.name} - - - { freeze ? freezeItem() : unfreezeItem(); }} - /> - - {member.contact_email} - - {isShowDropdownMenu && - - - - {gettext('Delete')} - - - } - - - ); - } -} - -DepartmentsV2MembersItem.propTypes = propTypes; - -export default DepartmentsV2MembersItem; diff --git a/frontend/src/pages/org-admin/departments-v2/department-node.js b/frontend/src/pages/org-admin/departments/department-node.js similarity index 100% rename from frontend/src/pages/org-admin/departments-v2/department-node.js rename to frontend/src/pages/org-admin/departments/department-node.js diff --git a/frontend/src/pages/org-admin/departments-v2/departments-v2-members-list.js b/frontend/src/pages/org-admin/departments/department.js similarity index 96% rename from frontend/src/pages/org-admin/departments-v2/departments-v2-members-list.js rename to frontend/src/pages/org-admin/departments/department.js index e33cce8551..69121562d1 100644 --- a/frontend/src/pages/org-admin/departments-v2/departments-v2-members-list.js +++ b/frontend/src/pages/org-admin/departments/department.js @@ -4,7 +4,7 @@ import { Table, Dropdown, DropdownToggle } from 'reactstrap'; import Loading from '../../../components/loading'; import EmptyTip from '../../../components/empty-tip'; import { gettext } from '../../../utils/constants'; -import DepartmentsV2MembersItem from './departments-v2-members-item'; +import MemberItem from './member-item'; import RepoItem from './repo-item'; import DepartmentNodeMenu from './departments-node-dropdown-menu'; @@ -21,7 +21,7 @@ const propTypes = { getRepos: PropTypes.func, }; -class DepartmentsV2MembersList extends React.Component { +class Department extends React.Component { constructor(props) { super(props); @@ -160,7 +160,7 @@ class DepartmentsV2MembersList extends React.Component { {isMembersListLoading && } {!isMembersListLoading && membersList.length > 0 &&
- +
@@ -173,7 +173,7 @@ class DepartmentsV2MembersList extends React.Component { {membersList.map((item, index) => { return ( - {rootNodes.map(rootNode => { return ( - { return comparator(a, b); @@ -282,7 +278,6 @@ class DepartmentsV2 extends React.Component { }; sortItems = (sortBy, sortOrder) => { - localStorage.setItem('departments-members-sort-items', { sort_by: sortBy, sort_order: sortOrder }); this.setState({ sortBy: sortBy, sortOrder: sortOrder, @@ -318,7 +313,7 @@ class DepartmentsV2 extends React.Component { {isTopDepartmentLoading && } {(!isTopDepartmentLoading && rootNodes.length > 0) && <> - - {isAddMembersDialogShow && - } {isRenameDepartmentDialogShow && - } {isDeleteDepartmentDialogShow && - } {isAddDepartmentDialogShow && - { + if (this.props.isItemFreezed) return; + this.setState({ highlighted: true }); + }; + + handleMouseLeave = () => { + if (this.props.isItemFreezed) return; + this.setState({ highlighted: false }); + }; + + setMemberStaff = (role) => { + this.props.setMemberStaff(this.props.member.email, role.value === 'Admin'); + }; + + deleteMember = () => { + const { member } = this.props; + this.props.deleteMember(member.email); + }; + + toggleDropdownMenu = () => { + this.setState({ + isItemMenuShow: !this.state.isItemMenuShow + }, () => { + if (this.state.isItemMenuShow && typeof(this.props.freezeItem) === 'function') { + this.props.freezeItem(); + } else if (!this.state.isItemMenuShow && typeof(this.props.unfreezeItem) === 'function') { + this.props.unfreezeItem(); + } + }); + }; + + toggleItemFreezed = (freezed) => { + if (freezed) { + this.props.freezeItem(); + } else { + this.props.unfreezeItem(); + this.setState({ highlighted: false }); + } + }; + + toggleDeleteMemberDialog = () => { + this.setState({ + isDeleteMemberDialogOpen: !this.state.isDeleteMemberDialogOpen + }); + }; + + render() { + const { member } = this.props; + const { highlighted, isItemMenuShow, isDeleteMemberDialogOpen } = this.state; + + this.roleOptions = this.roleOptions.map(item => { + item.isSelected = item.value == member.role; + return item; + }); + const currentSelectedOption = this.roleOptions.filter(item => item.isSelected)[0]; + + + return ( + <> + + + + + + + + {isDeleteMemberDialogOpen && ( + ' + Utils.HTMLescape(member.name) + '') + } + executeOperation={this.deleteMember} + confirmBtnText={gettext('Delete')} + toggleDialog={this.toggleDeleteMemberDialog} + /> + )} + + ); + } +} + +DepartmentsV2MembersItem.propTypes = propTypes; + +export default DepartmentsV2MembersItem; diff --git a/frontend/src/pages/org-admin/departments-v2/repo-item.js b/frontend/src/pages/org-admin/departments/repo-item.js similarity index 98% rename from frontend/src/pages/org-admin/departments-v2/repo-item.js rename to frontend/src/pages/org-admin/departments/repo-item.js index e5b803766b..3b556905bb 100644 --- a/frontend/src/pages/org-admin/departments-v2/repo-item.js +++ b/frontend/src/pages/org-admin/departments/repo-item.js @@ -64,7 +64,7 @@ class RepoItem extends React.Component { const RepoItemPropTypes = { repo: PropTypes.object.isRequired, - groupID: PropTypes.string.isRequired, + groupID: PropTypes.number.isRequired, onDeleteRepo: PropTypes.func.isRequired, }; diff --git a/frontend/src/pages/org-admin/departments-v2/departments-v2-tree-node.js b/frontend/src/pages/org-admin/departments/tree-node.js similarity index 100% rename from frontend/src/pages/org-admin/departments-v2/departments-v2-tree-node.js rename to frontend/src/pages/org-admin/departments/tree-node.js diff --git a/frontend/src/pages/org-admin/index.js b/frontend/src/pages/org-admin/index.js index 19e845b6e3..69d20efae4 100644 --- a/frontend/src/pages/org-admin/index.js +++ b/frontend/src/pages/org-admin/index.js @@ -29,7 +29,7 @@ import OrgTrashRepos from './libraries/org-repo-trash'; import OrgInfo from './org-info'; import OrgLinks from './org-links'; -import DepartmentsV2 from './departments-v2/departments-v2'; +import Departments from './departments/departments'; import OrgLogs from './org-logs'; import OrgLogsFileAudit from './org-logs-file-audit'; @@ -120,7 +120,7 @@ class Org extends React.Component { - + diff --git a/frontend/src/utils/org-admin-api.js b/frontend/src/utils/org-admin-api.js index 9e77c69cc5..170b934917 100644 --- a/frontend/src/utils/org-admin-api.js +++ b/frontend/src/utils/org-admin-api.js @@ -464,10 +464,12 @@ class OrgAdminAPI { return this.req.delete(url); } - orgAdminAddGroupMember(orgID, groupID, userEmail) { + orgAdminAddGroupMember(orgID, groupID, emails) { const url = this.server + '/api/v2.1/org/' + orgID + '/admin/groups/' + groupID + '/members/'; let form = new FormData(); - form.append('email', userEmail); + for (let i = 0; i < emails.length; i++) { + form.append('email', emails[i]); + } return this._sendPostRequest(url, form); }
+ {member.name} + + + {member.contact_email} + {highlighted && + + + + {gettext('Delete')} + + + } +