diff --git a/frontend/src/pages/org-admin/index.js b/frontend/src/pages/org-admin/index.js index 83711b75a6..af3d949776 100644 --- a/frontend/src/pages/org-admin/index.js +++ b/frontend/src/pages/org-admin/index.js @@ -10,6 +10,7 @@ import OrgUserProfile from './org-user-profile'; import OrgUserRepos from './org-user-repos'; import OrgUserSharedRepos from './org-user-shared-repos'; import OrgGroups from './org-groups'; +import OrgGroupsSearchGroups from './org-groups-search-groups'; import OrgGroupInfo from './org-group-info'; import OrgGroupRepos from './org-group-repos'; import OrgGroupMembers from './org-group-members'; @@ -75,6 +76,7 @@ class Org extends React.Component { + diff --git a/frontend/src/pages/org-admin/org-groups-search-groups.js b/frontend/src/pages/org-admin/org-groups-search-groups.js new file mode 100644 index 0000000000..a7e6cd9b7c --- /dev/null +++ b/frontend/src/pages/org-admin/org-groups-search-groups.js @@ -0,0 +1,279 @@ +import React, { Component, Fragment } from 'react'; +import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap'; +import { Button, Form, FormGroup, Input, Col } from 'reactstrap'; +import { Utils } from '../../utils/utils'; +import { seafileAPI } from '../../utils/seafile-api'; +import { gettext, orgID, siteRoot } from '../../utils/constants'; +import toaster from '../../components/toast'; +import OrgGroupInfo from '../../models/org-group'; + +class GroupItem extends React.Component { + + constructor(props) { + super(props); + this.state = { + highlight: false, + showMenu: false, + isItemMenuShow: false + }; + } + + onMouseEnter = () => { + if (!this.props.isItemFreezed) { + this.setState({ + showMenu: true, + highlight: true, + }); + } + } + + onMouseLeave = () => { + if (!this.props.isItemFreezed) { + this.setState({ + showMenu: false, + highlight: false + }); + } + } + + onDropdownToggleClick = (e) => { + e.preventDefault(); + this.toggleOperationMenu(e); + } + + toggleOperationMenu = (e) => { + e.stopPropagation(); + this.setState( + {isItemMenuShow: !this.state.isItemMenuShow }, () => { + if (this.state.isItemMenuShow) { + this.props.onFreezedItem(); + } else { + this.setState({ + highlight: false, + showMenu: false, + }); + this.props.onUnfreezedItem(); + } + } + ); + } + + toggleDelete = () => { + this.props.deleteGroupItem(this.props.group); + } + + renderGroupHref = (group) => { + let groupInfoHref; + if (group.creatorName == 'system admin') { + groupInfoHref = siteRoot + 'org/departmentadmin/groups/' + group.id + '/'; + } else { + groupInfoHref = siteRoot + 'org/groupadmin/' + group.id + '/'; + } + + return groupInfoHref; + } + + renderGroupCreator = (group) => { + let userInfoHref = siteRoot + 'org/useradmin/info/' + group.creatorEmail + '/'; + if (group.creatorName == 'system admin') { + return ( + -- + ); + } else { + return( + + {group.creatorName} + + ); + } + } + + render() { + let { group } = this.props; + let isOperationMenuShow = (group.creatorName != 'system admin') && this.state.showMenu; + return ( + + + {group.groupName} + + {this.renderGroupCreator(group)} + {group.ctime} + + {isOperationMenuShow && + + + + {gettext('Delete')} + + + } + + + ); + } +} + + +class OrgGroupsSearchGroupsResult extends React.Component { + + constructor(props) { + super(props); + this.state = { + isItemFreezed: false + }; + } + + onFreezedItem = () => { + this.setState({isItemFreezed: true}); + } + + onUnfreezedItem = () => { + this.setState({isItemFreezed: false}); + } + + render() { + let { orgGroups } = this.props; + return ( +
+ + + + + + + + + + + {orgGroups.map(item => { + return ( + + ); + })} + +
{gettext('Name')}{gettext('Creator')}{gettext('Created At')}{gettext('Operations')}
+
+ ); + } +} + +class OrgGroupsSearchGroups extends Component { + + constructor(props) { + super(props); + this.state = { + query: '', + orgGroups: [], + isSubmitBtnActive: false, + loading: true, + errorMsg: '', + }; + } + + componentDidMount () { + let params = (new URL(document.location)).searchParams; + this.setState({ + query: params.get('query') || '', + }, () => {this.getItems();}); + } + + getItems = () => { + seafileAPI.orgAdminSearchGroup(orgID, this.state.query.trim()).then(res => { + let groupList = res.data.group_list.map(item => { + return new OrgGroupInfo(item); + }); + this.setState({ + orgGroups: groupList, + loading: false, + }); + }).catch((error) => { + this.setState({ + loading: false, + errorMsg: Utils.getErrorMsg(error, true) // true: show login tip if 403 + }); + }); + } + + deleteGroupItem = (group) => { + seafileAPI.orgAdminDeleteOrgGroup(orgID, group.id).then(res => { + this.setState({ + orgGroups: this.state.orgGroups.filter(item => item.id != group.id) + }); + let msg = gettext('Successfully deleted {name}'); + msg = msg.replace('{name}', group.groupName); + toaster.success(msg); + }).catch(error => { + let errMessage = Utils.getErrorMsg(error); + toaster.danger(errMessage); + }); + } + + handleInputChange = (e) => { + this.setState({ + query: e.target.value + }, this.checkSubmitBtnActive); + } + + checkSubmitBtnActive = () => { + const { query } = this.state; + this.setState({ + isSubmitBtnActive: query.trim() + }); + } + + render() { + const { query, isSubmitBtnActive } = this.state; + + return ( + +
+
+
+

{gettext('Groups')}

+
+
+
+

{gettext('Search Groups')}

+
+ + + + + + + + + + +
+
+
+

{gettext('Result')}

+ +
+
+
+
+
+ ); + } +} + +export default OrgGroupsSearchGroups; diff --git a/frontend/src/pages/org-admin/org-groups.js b/frontend/src/pages/org-admin/org-groups.js index 82f635e053..a07d871c59 100644 --- a/frontend/src/pages/org-admin/org-groups.js +++ b/frontend/src/pages/org-admin/org-groups.js @@ -1,4 +1,5 @@ import React, { Component, Fragment } from 'react'; +import { navigate } from '@reach/router'; import PropTypes from 'prop-types'; import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap'; import { siteRoot, gettext, orgID } from '../../utils/constants'; @@ -8,6 +9,55 @@ import toaster from '../../components/toast'; import OrgGroupInfo from '../../models/org-group'; import MainPanelTopbar from './main-panel-topbar'; +class Search extends React.Component { + + constructor(props) { + super(props); + this.state = { + value: '' + }; + } + + handleInputChange = (e) => { + this.setState({ + value: e.target.value + }); + } + + handleKeyPress = (e) => { + if (e.key == 'Enter') { + e.preventDefault(); + this.handleSubmit(); + } + } + + handleSubmit = () => { + const value = this.state.value.trim(); + if (!value) { + return false; + } + this.props.submit(value); + } + + render() { + return ( +
+ + +
+ ); + } +} + class OrgGroups extends Component { constructor(props) { @@ -77,11 +127,22 @@ class OrgGroups extends Component { }); } + searchItems = (keyword) => { + navigate(`${siteRoot}org/groupadmin/search-groups/?query=${encodeURIComponent(keyword)}`); + } + + getSearch = () => { + return ; + } + render() { let groups = this.state.orgGroups; return ( - +
diff --git a/frontend/src/pages/org-admin/org-users-search-users.js b/frontend/src/pages/org-admin/org-users-search-users.js index 03c860345d..85a7370038 100644 --- a/frontend/src/pages/org-admin/org-users-search-users.js +++ b/frontend/src/pages/org-admin/org-users-search-users.js @@ -82,7 +82,7 @@ class OrgUsersSearchUsers extends Component { } getItems = () => { - seafileAPI.orgAdminSearchUser(1, this.state.query.trim()).then(res => { + seafileAPI.orgAdminSearchUser(orgID, this.state.query.trim()).then(res => { let userList = res.data.user_list.map(item => { return new OrgUserInfo(item); });