1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-23 12:27:48 +00:00
Files
seahub/frontend/src/pages/sys-admin/departments/department.js
Michael An 31e0b24e07 12.0 department set quota (#7736)
* 01 system admin department set quota

* 02 org admin department set quota
2025-04-15 13:46:17 +08:00

274 lines
9.2 KiB
JavaScript

import React from 'react';
import PropTypes from 'prop-types';
import { Dropdown, DropdownToggle } from 'reactstrap';
import { gettext } from '../../../utils/constants';
import Paginator from '../../../components/paginator';
import Loading from '../../../components/loading';
import EmptyTip from '../../../components/empty-tip';
import ModalPortal from '../../../components/modal-portal';
import DeleteRepoDialog from '../../../components/dialog/sysadmin-dialog/sysadmin-delete-repo-dialog';
import DepartmentNodeMenu from './departments-node-dropdown-menu';
import MemberItem from './member-item';
import RepoItem from './repo-item';
const propTypes = {
rootNodes: PropTypes.array,
checkedDepartmentId: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
membersList: PropTypes.array,
isMembersListLoading: PropTypes.bool,
setMemberStaff: PropTypes.func,
sortItems: PropTypes.func,
sortOrder: PropTypes.string,
sortBy: PropTypes.string,
deleteMember: PropTypes.func,
getRepos: PropTypes.func,
getPreviousPageList: PropTypes.func,
getNextPageList: PropTypes.func,
resetPerPage: PropTypes.func,
currentPageInfo: PropTypes.object,
perPage: PropTypes.number,
};
class Department extends React.Component {
constructor(props) {
super(props);
this.state = {
isItemFreezed: false,
activeNav: 'members',
repos: [],
deletedRepo: {},
showDeleteRepoDialog: false,
dropdownOpen: false,
};
}
componentDidMount() {
this.getRepos(this.props.checkedDepartmentId);
}
UNSAFE_componentWillReceiveProps(nextProps) {
if (this.props.checkedDepartmentId !== nextProps.checkedDepartmentId || this.props.isAddNewRepo !== nextProps.isAddNewRepo) {
this.getRepos(nextProps.checkedDepartmentId);
}
}
showDeleteRepoDialog = (repo) => {
this.setState({
showDeleteRepoDialog: true,
deletedRepo: repo,
});
};
toggleCancel = () => {
this.setState({
showDeleteRepoDialog: false,
deletedRepo: {},
});
};
onRepoChanged = () => {
this.getRepos(this.props.checkedDepartmentId);
};
freezeItem = () => {
this.setState({ isItemFreezed: true });
};
unfreezeItem = () => {
this.setState({ isItemFreezed: false });
};
getCurrentDepartment = () => {
const { rootNodes, checkedDepartmentId } = this.props;
if (!rootNodes) return {};
let currentDepartment = {};
let arr = [...rootNodes];
while (!currentDepartment.id && arr.length > 0) {
let curr = arr.shift();
if (curr.id === checkedDepartmentId) {
currentDepartment = curr;
} else if (curr.children && curr.children.length > 0) {
arr.push(...curr.children);
}
}
return currentDepartment;
};
sortByName = (e) => {
e.preventDefault();
const sortBy = 'name';
let { sortOrder } = this.props;
sortOrder = sortOrder === 'asc' ? 'desc' : 'asc';
this.props.sortItems(sortBy, sortOrder);
};
sortByRole = (e) => {
e.preventDefault();
const sortBy = 'role';
let { sortOrder } = this.props;
sortOrder = sortOrder === 'asc' ? 'desc' : 'asc';
this.props.sortItems(sortBy, sortOrder);
};
changeActiveNav = (activeNav) => {
this.setState({ activeNav });
};
getRepos = (id) => {
this.props.getRepos(id, (repos) => {
this.setState({ repos });
});
};
dropdownToggle = (e) => {
e.stopPropagation();
this.setState({ dropdownOpen: !this.state.dropdownOpen });
};
render() {
const { activeNav, repos } = this.state;
const { membersList, isMembersListLoading, sortBy, sortOrder } = this.props;
const sortByName = sortBy === 'name';
const sortByRole = sortBy === 'role';
const sortIcon = <span className={`sort-dirent sf3-font sf3-font-down ${sortOrder === 'asc' ? 'rotate-180' : ''}`}></span>;
const currentDepartment = this.getCurrentDepartment();
return (
<div className="department-content-main d-flex flex-column">
<div className="cur-view-path justify-content-start">
<h4 className="sf-heading">{currentDepartment.name}</h4>
<Dropdown
isOpen={this.state.dropdownOpen}
toggle={(e) => this.dropdownToggle(e)}
direction="down"
className="department-dropdown-menu"
>
<DropdownToggle
tag='span'
role="button"
className='sf3-font-down sf3-font ml-1 sf-dropdown-toggle'
title={gettext('More operations')}
aria-label={gettext('More operations')}
data-toggle="dropdown"
/>
<DepartmentNodeMenu
node={currentDepartment}
toggleAddDepartment={this.props.toggleAddDepartment}
toggleSetQuotaDialog={this.props.toggleSetQuotaDialog}
toggleAddLibrary={this.props.toggleAddLibrary}
toggleAddMembers={this.props.toggleAddMembers}
toggleRename={this.props.toggleRename}
toggleDelete={this.props.toggleDelete}
/>
</Dropdown>
</div>
<div className="cur-view-path tab-nav-container">
<ul className="nav">
<li className="nav-item">
<span className={`nav-link ${activeNav === 'members' ? 'active' : ''}`} onClick={() => this.changeActiveNav('members')}>{gettext('Members')}</span>
</li>
<li className="nav-item">
<span className={`nav-link ${activeNav === 'repos' ? 'active' : ''}`} onClick={() => this.changeActiveNav('repos')}>{gettext('Libraries')}</span>
</li>
</ul>
</div>
{activeNav === 'members' && (
<div className='cur-view-content'>
{isMembersListLoading
? <Loading />
: membersList.length == 0
? <EmptyTip text={gettext('No members')} />
: (
<div className="w-xs-250">
<table>
<thead>
<tr>
<th width="10%"></th>
<th width="25%" onClick={this.sortByName}>{gettext('Name')}{' '}{sortByName && sortIcon}</th>
<th width="25%" onClick={this.sortByRole}>{gettext('Role')}{' '}{sortByRole && sortIcon}</th>
<th width="30%">{gettext('Contact email')}</th>
<th width="10%">{/* Operations */}</th>
</tr>
</thead>
<tbody>
{membersList.map((item, index) => {
return (
<MemberItem
key={index}
member={item}
deleteMember={this.props.deleteMember}
setMemberStaff={this.props.setMemberStaff}
unfreezeItem={this.unfreezeItem}
freezeItem={this.freezeItem}
isItemFreezed={this.state.isItemFreezed}
/>
);
})}
</tbody>
</table>
{this.props.currentPageInfo &&
<Paginator
gotoPreviousPage={this.props.getPreviousPageList}
gotoNextPage={this.props.getNextPageList}
currentPage={this.props.currentPageInfo.current_page}
hasNextPage={this.props.currentPageInfo.has_next_page}
curPerPage={this.props.perPage}
resetPerPage={this.props.resetPerPage}
noURLUpdate={true}
/>
}
</div>
)}
</div>
)}
{activeNav === 'repos' && (
<div className="cur-view-content">
{repos.length == 0
? <EmptyTip text={gettext('No libraries')} />
: (
<>
<table>
<thead>
<tr>
<th width="5%"></th>
<th width="50%">{gettext('Name')}</th>
<th width="30%">{gettext('Size')}</th>
<th width="15%"></th>
</tr>
</thead>
<tbody>
{repos.map((repo, index) => {
return (
<RepoItem key={index} repo={repo} showDeleteRepoDialog={this.showDeleteRepoDialog} />
);
})}
</tbody>
</table>
{this.state.showDeleteRepoDialog && (
<ModalPortal>
<DeleteRepoDialog
toggle={this.toggleCancel}
onRepoChanged={this.onRepoChanged}
repo={this.state.deletedRepo}
groupID={this.props.checkedDepartmentId}
/>
</ModalPortal>
)}
</>
)
}
</div>
)}
</div>
);
}
}
Department.propTypes = propTypes;
export default Department;