diff --git a/frontend/src/components/dialog/change-group-dialog.js b/frontend/src/components/dialog/change-group-dialog.js
new file mode 100644
index 0000000000..b30fc541ef
--- /dev/null
+++ b/frontend/src/components/dialog/change-group-dialog.js
@@ -0,0 +1,49 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { Button, Modal, ModalHeader, ModalFooter, ModalBody } from 'reactstrap';
+import { Utils } from '../../utils/utils';
+import { gettext } from '../../utils/constants';
+
+const propTypes = {
+ groupName: PropTypes.string.isRequired,
+ changeGroup2Department: PropTypes.func.isRequired,
+ toggleDialog: PropTypes.func.isRequired
+};
+
+class ChangeGroupDialog extends React.Component {
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ selectedOption: null
+ };
+ }
+
+ submit = () => {
+ this.props.changeGroup2Department();
+ this.props.toggleDialog();
+ };
+
+ render() {
+ const groupName = '' + Utils.HTMLescape(this.props.groupName) + '';
+ const msg = gettext('Are you sure to change Group {placeholder} to Department ?').replace('{placeholder}', groupName);
+ return (
+
+
+ {gettext('Change group to departmen')}
+
+
+
+
+
+
+
+
+
+ );
+ }
+}
+
+ChangeGroupDialog.propTypes = propTypes;
+
+export default ChangeGroupDialog;
diff --git a/frontend/src/pages/org-admin/org-groups.js b/frontend/src/pages/org-admin/org-groups.js
index 02ad3f79e5..8970b4bae4 100644
--- a/frontend/src/pages/org-admin/org-groups.js
+++ b/frontend/src/pages/org-admin/org-groups.js
@@ -8,6 +8,8 @@ import { Utils } from '../../utils/utils';
import toaster from '../../components/toast';
import OrgGroupInfo from '../../models/org-group';
import MainPanelTopbar from './main-panel-topbar';
+import ChangeGroupDialog from '../../components/dialog/change-group-dialog';
+import { orgAdminAPI } from '../../utils/org-admin-api';
class Search extends React.Component {
@@ -132,6 +134,24 @@ class OrgGroups extends Component {
});
};
+ changeGroupItem = (group) => {
+ orgAdminAPI.orgAdminGroup2Department(orgID, group.id).then(res => {
+ let newGroupList = this.state.orgGroups.map(item => {
+ if (item.id == group.id) {
+ item = new OrgGroupInfo(res.data);
+ }
+ return item;
+ });
+ this.setState({
+ orgGroups: newGroupList
+ });
+ toaster.success(gettext('Successfully Change the group.'));
+ }).catch(error => {
+ let errMessage = Utils.getErrorMsg(error);
+ toaster.danger(errMessage);
+ });
+ };
+
searchItems = (keyword) => {
navigate(`${siteRoot}org/groupadmin/search-groups/?query=${encodeURIComponent(keyword)}`);
};
@@ -173,6 +193,7 @@ class OrgGroups extends Component {
onFreezedItem={this.onFreezedItem}
onUnfreezedItem={this.onUnfreezedItem}
deleteGroupItem={this.deleteGroupItem}
+ changeGroupItem={this.changeGroupItem}
/>
);
})}
@@ -197,6 +218,7 @@ const GroupItemPropTypes = {
onFreezedItem: PropTypes.func.isRequired,
onUnfreezedItem: PropTypes.func.isRequired,
deleteGroupItem: PropTypes.func.isRequired,
+ changeGroupItem: PropTypes.func.isRequired,
};
class GroupItem extends React.Component {
@@ -206,7 +228,8 @@ class GroupItem extends React.Component {
this.state = {
highlight: false,
showMenu: false,
- isItemMenuShow: false
+ isItemMenuShow: false,
+ isChangeDialogOpen: false,
};
}
@@ -253,6 +276,16 @@ class GroupItem extends React.Component {
toggleDelete = () => {
this.props.deleteGroupItem(this.props.group);
};
+ toggleChange = () => {
+ this.props.changeGroupItem(this.props.group);
+ };
+
+ toggleChangeDialog = (e) => {
+ if (e) {
+ e.preventDefault();
+ }
+ this.setState({ isChangeDialogOpen: !this.state.isChangeDialogOpen });
+ };
renderGroupHref = (group) => {
let groupInfoHref;
@@ -304,11 +337,19 @@ class GroupItem extends React.Component {
/>
{gettext('Delete')}
+ {gettext('Change to department')}
}
+ {this.state.isChangeDialogOpen &&
+
+ }
+
);
}
diff --git a/frontend/src/pages/sys-admin/groups/groups-content.js b/frontend/src/pages/sys-admin/groups/groups-content.js
index aea759fc24..b12d8cebba 100644
--- a/frontend/src/pages/sys-admin/groups/groups-content.js
+++ b/frontend/src/pages/sys-admin/groups/groups-content.js
@@ -10,6 +10,7 @@ import Paginator from '../../../components/paginator';
import OpMenu from '../../../components/dialog/op-menu';
import CommonOperationConfirmationDialog from '../../../components/dialog/common-operation-confirmation-dialog';
import SysAdminTransferGroupDialog from '../../../components/dialog/sysadmin-dialog/sysadmin-group-transfer-dialog';
+import ChangeGroupDialog from '../../../components/dialog/change-group-dialog';
import UserLink from '../user-link';
class Content extends Component {
@@ -70,6 +71,7 @@ class Content extends Component {
onUnfreezedItem={this.onUnfreezedItem}
deleteGroup={this.props.deleteGroup}
transferGroup={this.props.transferGroup}
+ changeGroup2Department={this.props.changeGroup2Department}
/>);
})}
@@ -102,6 +104,7 @@ Content.propTypes = {
getListByPage: PropTypes.func.isRequired,
deleteGroup: PropTypes.func.isRequired,
transferGroup: PropTypes.func.isRequired,
+ changeGroup2Department: PropTypes.func.isRequired,
};
class Item extends Component {
@@ -112,7 +115,8 @@ class Item extends Component {
isOpIconShown: false,
highlight: false,
isDeleteDialogOpen: false,
- isTransferDialogOpen: false
+ isTransferDialogOpen: false,
+ isChangeDialogOpen: false
};
}
@@ -150,6 +154,9 @@ class Item extends Component {
case 'Transfer':
this.toggleTransferDialog();
break;
+ case 'Change':
+ this.toggleChangeDialog();
+ break;
default:
break;
}
@@ -169,6 +176,12 @@ class Item extends Component {
this.setState({ isTransferDialogOpen: !this.state.isTransferDialogOpen });
};
+ toggleChangeDialog = (e) => {
+ if (e) {
+ e.preventDefault();
+ }
+ this.setState({ isChangeDialogOpen: !this.state.isChangeDialogOpen });
+ };
deleteGroup = () => {
this.props.deleteGroup(this.props.item.id);
};
@@ -177,6 +190,10 @@ class Item extends Component {
this.props.transferGroup(this.props.item.id, receiver);
};
+ changeGroup = () => {
+ this.props.changeGroup2Department(this.props.item.id);
+ };
+
translateOperations = (item) => {
let translateResult = '';
switch (item) {
@@ -186,6 +203,9 @@ class Item extends Component {
case 'Transfer':
translateResult = gettext('Transfer');
break;
+ case 'Change':
+ translateResult = gettext('Change to department');
+ break;
}
return translateResult;
@@ -193,7 +213,7 @@ class Item extends Component {
render() {
const { item } = this.props;
- const { isOpIconShown, isDeleteDialogOpen, isTransferDialogOpen } = this.state;
+ const { isOpIconShown, isDeleteDialogOpen, isTransferDialogOpen, isChangeDialogOpen } = this.state;
let groupName = '' + Utils.HTMLescape(item.name) + '';
let deleteDialogMsg = gettext('Are you sure you want to delete {placeholder} ?').replace('{placeholder}', groupName);
@@ -218,7 +238,7 @@ class Item extends Component {
{(isOpIconShown && item.owner != 'system admin') &&
}
+ {isChangeDialogOpen &&
+
+ }
);
}
diff --git a/frontend/src/pages/sys-admin/groups/groups.js b/frontend/src/pages/sys-admin/groups/groups.js
index b874b24b3e..7bae385cc1 100644
--- a/frontend/src/pages/sys-admin/groups/groups.js
+++ b/frontend/src/pages/sys-admin/groups/groups.js
@@ -9,6 +9,7 @@ import SysAdminCreateGroupDialog from '../../../components/dialog/sysadmin-dialo
import MainPanelTopbar from '../main-panel-topbar';
import Search from '../search';
import Content from './groups-content';
+import { systemAdminAPI } from '../../../utils/system-admin-api';
class Groups extends Component {
@@ -109,6 +110,24 @@ class Groups extends Component {
});
};
+ changeGroup2Department = (groupID) => {
+ systemAdminAPI.adminGroup2Department(groupID).then((res) => {
+ let newGroupList = this.state.groupList.map(item => {
+ if (item.id == groupID) {
+ item = res.data;
+ }
+ return item;
+ });
+ this.setState({
+ groupList: newGroupList
+ });
+ toaster.success(gettext('Successfully Change the group.'));
+ }).catch((error) => {
+ let errMessage = Utils.getErrorMsg(error);
+ toaster.danger(errMessage);
+ });
+ };
+
getSearch = () => {
return /admin/search-group/', OrgAdminSearchGroup.as_view(), name='api-v2.1-org-admin-search-group'),
path('/admin/groups//', OrgAdminGroup.as_view(), name='api-admin-group'),
path('/admin/groups//libraries/', AdminGroupLibraries.as_view(), name='api-admin-group-libraries'),
+ path('/admin/groups//group-to-department/', OrgAdminGroupToDeptView.as_view(), name='api-admin-group-to-department'),
re_path(r'^(?P\d+)/admin/groups/(?P\d+)/libraries/(?P[-0-9a-f]{36})/$', AdminGroupLibrary.as_view(), name='api-admin-group-library'),
path('/admin/groups//group-owned-libraries/', AdminGroupOwnedLibraries.as_view(), name='api-admin-group-owned-libraries'),
diff --git a/seahub/urls.py b/seahub/urls.py
index 0244164040..0ab9813970 100644
--- a/seahub/urls.py
+++ b/seahub/urls.py
@@ -151,7 +151,8 @@ from seahub.api2.endpoints.admin.system_library import AdminSystemLibrary, \
AdminSystemLibraryUploadLink
from seahub.api2.endpoints.admin.default_library import AdminDefaultLibrary
from seahub.api2.endpoints.admin.trash_libraries import AdminTrashLibraries, AdminTrashLibrary
-from seahub.api2.endpoints.admin.groups import AdminGroups, AdminGroup, AdminSearchGroup, AdminDepartments
+from seahub.api2.endpoints.admin.groups import AdminGroups, AdminGroup, AdminSearchGroup, \
+ AdminDepartments, AdminGroupToDeptView
from seahub.api2.endpoints.admin.group_libraries import AdminGroupLibraries, AdminGroupLibrary
from seahub.api2.endpoints.admin.group_members import AdminGroupMembers, AdminGroupMember
from seahub.api2.endpoints.admin.shares import AdminShares
@@ -655,7 +656,8 @@ urlpatterns = [
re_path(r'^api/v2.1/admin/groups/(?P\d+)/members/(?P[^/]+)/$', AdminGroupMember.as_view(), name='api-v2.1-admin-group-member'),
re_path(r'^api/v2.1/admin/groups/(?P\d+)/group-owned-libraries/$', AdminGroupOwnedLibraries.as_view(), name='api-v2.1-admin-group-owned-libraries'),
re_path(r'^api/v2.1/admin/groups/(?P\d+)/group-owned-libraries/(?P[-0-9a-f]{36})/$', AdminGroupOwnedLibrary.as_view(), name='api-v2.1-admin-owned-group-library'),
-
+ re_path(r'^api/v2.1/admin/groups/(?P\d+)/group-to-department/', AdminGroupToDeptView.as_view(), name='api-v2.1-admin-group-to-department'),
+
## admin::departments
re_path(r'api/v2.1/admin/departments/$', AdminDepartments.as_view(), name='api-v2.1-admin-departments'),
diff --git a/seahub/utils/ccnet_db.py b/seahub/utils/ccnet_db.py
index 36124e67f9..a42c0d4538 100644
--- a/seahub/utils/ccnet_db.py
+++ b/seahub/utils/ccnet_db.py
@@ -162,7 +162,6 @@ class CcnetDB:
users.append(users_obj)
return users, total_count
-
def get_group_ids_admins_map(self, group_ids):
group_admins = {}
@@ -183,3 +182,21 @@ class CcnetDB:
else:
group_admins[group_id] = [user]
return group_admins
+
+ def change_groups_into_departments(self, group_id):
+ sql = f"""
+ UPDATE `{self.db_name}`.`Group` g
+ SET
+ g.creator_name = 'system admin',
+ g.parent_group_id = -1
+ WHERE
+ g.group_id = {group_id}
+ """
+ structure_sql = f"""
+ INSERT INTO `{self.db_name}`.`GroupStructure` (group_id, path)
+ VALUES ('{group_id}', '{group_id}')
+ """
+
+ with connection.cursor() as cursor:
+ cursor.execute(sql)
+ cursor.execute(structure_sql)
|