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 (
+
+
+
+
+ {gettext('Name')} |
+ {gettext('Creator')} |
+ {gettext('Created At')} |
+ {gettext('Operations')} |
+
+
+
+ {orgGroups.map(item => {
+ return (
+
+ );
+ })}
+
+
+
+ );
+ }
+}
+
+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);
});