diff --git a/frontend/src/models/org-group.js b/frontend/src/models/org-group.js new file mode 100644 index 0000000000..ab55144f69 --- /dev/null +++ b/frontend/src/models/org-group.js @@ -0,0 +1,18 @@ +import { Utils } from '../utils/utils'; +import { lang } from '../utils/constants'; +import moment from 'moment'; + +moment.locale(lang); + +class OrgGroupInfo { + constructor(object) { + this.id = object.id; + this.groupName = object.group_name; + this.creatorName = object.creator_name; + this.creatorEmail = object.creator_email; + this.creatorContactEmail = object.creator_contact_email; + this.ctime = moment(object.ctime).format('YYYY-MM-DD HH:mm:ss'); + } +} + +export default OrgGroupInfo; diff --git a/frontend/src/pages/org-admin/index.js b/frontend/src/pages/org-admin/index.js index 490196c204..ef33df45af 100644 --- a/frontend/src/pages/org-admin/index.js +++ b/frontend/src/pages/org-admin/index.js @@ -8,6 +8,7 @@ import MainPanel from './main-panel'; import OrgUsers from './org-users'; import OrgUsersList from './org-users-list'; import OrgAdminList from './org-admin-list'; +import OrgGroups from './org-groups'; import '../../assets/css/fa-solid.css'; import '../../assets/css/fa-regular.css'; @@ -56,7 +57,7 @@ class Org extends React.Component { let { isSidePanelClosed, currentTab, isShowAddOrgUserDialog, isShowAddOrgAdminDialog } = this.state; return (
- + + +
diff --git a/frontend/src/pages/org-admin/org-groups.js b/frontend/src/pages/org-admin/org-groups.js new file mode 100644 index 0000000000..cabb6e8ded --- /dev/null +++ b/frontend/src/pages/org-admin/org-groups.js @@ -0,0 +1,231 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap'; + +import OrgGroupInfo from '../../models/org-group'; +import Toast from '../../components/toast'; + +import { seafileAPI } from '../../utils/seafile-api'; +import { siteRoot, gettext, orgID } from '../../utils/constants'; + +class OrgGroups extends Component { + + constructor(props) { + super(props); + this.state = { + page: 1, + pageNext: 2, + orgGroups: [], + isItemFreezed: false + } + } + + componentDidMount() { + let page = this.state.page; + this.initData(page); + } + + initData = (page) => { + seafileAPI.listOrgGroups(orgID, page).then(res => { + let orgGroups = res.data.groups.map(item => { + return new OrgGroupInfo(item); + }); + + this.setState({ + orgGroups: orgGroups, + pageNext: res.data.page_next, + page: res.data.page, + }); + }); + } + + + onChangePageNum = (e, num) => { + e.preventDefault(); + let page = this.state.page; + + if (num == 1) { + page = page + 1; + } else { + page = page - 1; + } + this.initData(page); + } + + onFreezedItem = () => { + this.setState({isItemFreezed: true}); + } + + onUnfreezedItem = () => { + this.setState({isItemFreezed: false}); + } + + deleteGroupItem = (group) => { + seafileAPI.deleteOrgGroup(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); + Toast.success(msg); + }) + } + + render() { + let groups = this.state.orgGroups; + return ( +
+
+
+

{gettext('All Groups')}

+
+
+ + + + + + + + + + + {groups.map(item => { + return ( + + )})} + +
{gettext('Name')}{gettext('Creator')}{gettext('Created At')}{gettext('Operations')}
+
+ {this.state.page != 1 && this.onChangePageNum(e, -1)}>{gettext("Previous")}} + {this.state.pageNext && this.onChangePageNum(e, 1)}>{gettext("Next")}} +
+
+
+
+ ); + } +} + +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/admin/#address-book/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')} + + + } + + + ); + } + +} + +export default OrgGroups; diff --git a/frontend/src/pages/org-admin/side-panel.js b/frontend/src/pages/org-admin/side-panel.js index 1a989d985d..41a9a9f12e 100644 --- a/frontend/src/pages/org-admin/side-panel.js +++ b/frontend/src/pages/org-admin/side-panel.js @@ -7,10 +7,20 @@ import { gettext, siteRoot } from '../../utils/constants'; const propTypes = { isSidePanelClosed: PropTypes.bool.isRequired, onCloseSidePanel: PropTypes.func.isRequired, + currentTab: PropTypes.string.isRequired, + tabItemClick: PropTypes.func.isRequired }; class SidePanel extends React.Component { + getActiveClass = (tab) => { + return this.props.currentTab == tab ? 'active' : ''; + } + + tabItemClick = (tab) => { + this.props.tabItemClick(tab); + } + render() { return (
@@ -35,23 +45,23 @@ class SidePanel extends React.Component {
  • - + this.tabItemClick('users')} > {gettext('Users')}
  • +
  • + this.tabItemClick('groupadmin')}> + + {gettext('Groups')} + +
  • {gettext('Departments')}
  • -
  • - - - {gettext('Groups')} - -