1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-20 02:48:51 +00:00
This commit is contained in:
Michael An
2019-05-06 16:15:11 +08:00
parent 4f426988a1
commit 19f41c2b06
2 changed files with 188 additions and 88 deletions

View File

@@ -1,47 +1,65 @@
import React, { Fragment } from 'react'; import React, { Fragment } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import moment from 'moment';
import { Link } from '@reach/router'; import { Link } from '@reach/router';
import { seafileAPI } from '../../utils/seafile-api'; import { seafileAPI } from '../../utils/seafile-api';
import { Utils } from '../../utils/utils.js'; import { Utils } from '../../utils/utils.js';
import { serviceURL, siteRoot, gettext, orgID } from '../../utils/constants'; import MainPanelTopbar from './main-panel-topbar';
import OrgDepartmentsList from './org-departments-list';
import ModalPortal from '../../components/modal-portal'; import ModalPortal from '../../components/modal-portal';
import RoleEditor from '../../components/select-editor/role-editor';
import AddDepartDialog from '../../components/dialog/org-add-department-dialog'; import AddDepartDialog from '../../components/dialog/org-add-department-dialog';
import AddMemberDialog from '../../components/dialog/org-add-member-dialog'; import AddMemberDialog from '../../components/dialog/org-add-member-dialog';
import DeleteMemberDialog from '../../components/dialog/org-delete-member-dialog'; import DeleteMemberDialog from '../../components/dialog/org-delete-member-dialog';
import AddRepoDialog from '../../components/dialog/org-add-repo-dialog'; import AddRepoDialog from '../../components/dialog/org-add-repo-dialog';
import DeleteRepoDialog from '../../components/dialog/org-delete-repo-dialog'; import DeleteRepoDialog from '../../components/dialog/org-delete-repo-dialog';
import RoleEditor from '../../components/select-editor/role-editor'; import DeleteDepartDialog from '../../components/dialog/org-delete-department-dialog';
import MainPanelTopbar from './main-panel-topbar'; import SetGroupQuotaDialog from '../../components/dialog/org-set-group-quota-dialog';
import { serviceURL, siteRoot, gettext, orgID, lang } from '../../utils/constants';
import '../../css/org-department-item.css'; import '../../css/org-department-item.css';
moment.locale(lang);
class OrgDepartmentItem extends React.Component { class OrgDepartmentItem extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
members: [],
repos: [],
groups: [],
ancestorGroups: [],
deletedMember: {},
deletedRepo: {},
showDeleteMemberDialog: false,
showDeleteRepoDialog: false,
isShowAddRepoDialog: false,
isShowAddMemberDialog: false,
isShowAddDepartDialog: false,
isItemFreezed: false,
isSubdepartChanged: false,
groupName: '', groupName: '',
isItemFreezed: false,
ancestorGroups: [],
members: [],
deletedMember: {},
isShowAddMemberDialog: false,
showDeleteMemberDialog: false,
repos: [],
deletedRepo: {},
isShowAddRepoDialog: false,
showDeleteRepoDialog: false,
groups: [],
subGroupID: '',
subGroupName: '',
isShowAddDepartDialog: false,
showDeleteDepartDialog: false,
showSetGroupQuotaDialog: false,
}; };
} }
componentDidMount() {
const groupID = this.props.groupID;
this.listOrgGroupRepo(groupID);
this.listOrgMembers(groupID);
}
componentWillReceiveProps(nextProps) {
if (this.props.groupID !== nextProps.groupID) {
this.listOrgGroupRepo(nextProps.groupID);
this.listOrgMembers(nextProps.groupID);
}
}
listOrgGroupRepo = (groupID) => { listOrgGroupRepo = (groupID) => {
seafileAPI.orgAdminListDepartGroupRepos(orgID, groupID).then(res => { seafileAPI.orgAdminListDepartGroupRepos(orgID, groupID).then(res => {
this.setState({ this.setState({ repos: res.data.libraries });
repos: res.data.libraries
});
}); });
} }
@@ -56,21 +74,25 @@ class OrgDepartmentItem extends React.Component {
}); });
} }
showDeleteMemberDialog = (member) => { listSubDepartGroups = (groupID) => {
this.setState({ showDeleteMemberDialog: true, deletedMember: member }); seafileAPI.orgAdminListGroupInfo(orgID, groupID, true).then(res => {
} this.setState({ groups: res.data.groups });
});
showDeleteRepoDialog = (repo) => {
this.setState({ showDeleteRepoDialog: true, deletedRepo: repo });
} }
toggleCancel = () => { toggleCancel = () => {
this.setState({ this.setState({
showDeleteMemberDialog: false, showDeleteMemberDialog: false,
showDeleteRepoDialog: false, showDeleteRepoDialog: false,
showDeleteDepartDialog: false,
showSetGroupQuotaDialog: false,
}); });
} }
onSubDepartChanged = () => {
this.listSubDepartGroups(this.props.groupID);
}
onRepoChanged = () => { onRepoChanged = () => {
this.listOrgGroupRepo(this.props.groupID); this.listOrgGroupRepo(this.props.groupID);
} }
@@ -83,6 +105,14 @@ class OrgDepartmentItem extends React.Component {
this.setState({ isItemFreezed: isFreezed }); this.setState({ isItemFreezed: isFreezed });
} }
showDeleteMemberDialog = (member) => {
this.setState({ showDeleteMemberDialog: true, deletedMember: member });
}
showDeleteRepoDialog = (repo) => {
this.setState({ showDeleteRepoDialog: true, deletedRepo: repo });
}
toggleAddRepoDialog = () => { toggleAddRepoDialog = () => {
this.setState({ isShowAddRepoDialog: !this.state.isShowAddRepoDialog }); this.setState({ isShowAddRepoDialog: !this.state.isShowAddRepoDialog });
} }
@@ -95,25 +125,23 @@ class OrgDepartmentItem extends React.Component {
this.setState({ isShowAddDepartDialog: !this.state.isShowAddDepartDialog}); this.setState({ isShowAddDepartDialog: !this.state.isShowAddDepartDialog});
} }
onDepartChanged = () => { showDeleteDepartDialog = (subGroup) => {
this.setState({ isSubdepartChanged: !this.state.isSubdepartChanged }); this.setState({
showDeleteDepartDialog: true,
subGroupID: subGroup.id,
subGroupName: subGroup.name
});
} }
componentWillMount() { showSetGroupQuotaDialog = (subGroupID) => {
const groupID = this.props.groupID; this.setState({
this.listOrgGroupRepo(groupID); showSetGroupQuotaDialog: true,
this.listOrgMembers(groupID); subGroupID: subGroupID
} });
componentWillReceiveProps(nextProps) {
if (this.props.groupID !== nextProps.groupID) {
this.listOrgGroupRepo(nextProps.groupID);
this.listOrgMembers(nextProps.groupID);
}
} }
render() { render() {
const { members, repos } = this.state; const { members, repos, groups } = this.state;
const groupID = this.props.groupID; const groupID = this.props.groupID;
const topBtn = 'btn btn-secondary operation-item'; const topBtn = 'btn btn-secondary operation-item';
const topbarChildren = ( const topbarChildren = (
@@ -148,7 +176,7 @@ class OrgDepartmentItem extends React.Component {
{this.state.isShowAddDepartDialog && ( {this.state.isShowAddDepartDialog && (
<ModalPortal> <ModalPortal>
<AddDepartDialog <AddDepartDialog
onDepartChanged={this.onDepartChanged} onDepartChanged={this.onSubDepartChanged}
parentGroupID={groupID} parentGroupID={groupID}
toggle={this.toggleAddDepartDialog} toggle={this.toggleAddDepartDialog}
/> />
@@ -179,14 +207,42 @@ class OrgDepartmentItem extends React.Component {
</div> </div>
<div className="cur-view-subcontainer org-groups"> <div className="cur-view-subcontainer org-groups">
<OrgDepartmentsList groupID={groupID} isSubdepartChanged={this.state.isSubdepartChanged}/> <div className="cur-view-path">
<div className="fleft"><h3 className="sf-heading">{gettext('Sub-departments')}</h3></div>
</div>
<div className="cur-view-content">
{groups && groups.length > 0 ?
<table>
<thead>
<tr>
<th width="40%">{gettext('Name')}</th>
<th width="25%">{gettext('Created At')}</th>
<th width="20%">{gettext('Quota')}</th>
<th width="15%"></th>
</tr>
</thead>
<tbody>
{groups.map((group, index) => {
return(
<React.Fragment key={group.id}>
<GroupItem
group={group}
showDeleteDepartDialog={this.showDeleteDepartDialog}
showSetGroupQuotaDialog={this.showSetGroupQuotaDialog}
/>
</React.Fragment>
);
})}
</tbody>
</table>
: <p className="no-group">{gettext('No sub-departments')}</p>
}
</div>
</div> </div>
<div className="cur-view-subcontainer org-members"> <div className="cur-view-subcontainer org-members">
<div className="cur-view-path"> <div className="cur-view-path">
<div className="fleft"> <div className="fleft"><h3 className="sf-heading">{gettext('Members')}</h3></div>
<h3 className="sf-heading">{gettext('Members')}</h3>
</div>
</div> </div>
<div className="cur-view-content"> <div className="cur-view-content">
{(members && members.length === 1 && members[0].role === 'Owner') ? {(members && members.length === 1 && members[0].role === 'Owner') ?
@@ -273,6 +329,25 @@ class OrgDepartmentItem extends React.Component {
/> />
</ModalPortal> </ModalPortal>
)} )}
{this.state.showDeleteDepartDialog && (
<ModalPortal>
<DeleteDepartDialog
toggle={this.toggleCancel}
groupID={this.state.subGroupID}
groupName={this.state.subGroupName}
onDepartChanged={this.onSubDepartChanged}
/>
</ModalPortal>
)}
{this.state.showSetGroupQuotaDialog && (
<ModalPortal>
<SetGroupQuotaDialog
toggle={this.toggleCancel}
groupID={this.state.subGroupID}
onDepartChanged={this.onSubDepartChanged}
/>
</ModalPortal>
)}
</React.Fragment> </React.Fragment>
</div> </div>
</Fragment> </Fragment>
@@ -354,7 +429,6 @@ const MemberItemPropTypes = {
MemberItem.propTypes = MemberItemPropTypes; MemberItem.propTypes = MemberItemPropTypes;
class RepoItem extends React.Component { class RepoItem extends React.Component {
constructor(props) { constructor(props) {
@@ -396,4 +470,50 @@ const RepoItemPropTypes = {
RepoItem.propTypes = RepoItemPropTypes; RepoItem.propTypes = RepoItemPropTypes;
class GroupItem extends React.Component {
constructor(props) {
super(props);
this.state = {
highlight: false,
};
}
onMouseEnter = () => {
this.setState({ highlight: true });
}
onMouseLeave = () => {
this.setState({ highlight: false });
}
render() {
const group = this.props.group;
const highlight = this.state.highlight;
const newHref = siteRoot+ 'org/departmentadmin/groups/' + group.id + '/';
return (
<tr className={highlight ? 'tr-highlight' : ''} onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave}>
<td><Link to={newHref}>{group.name}</Link></td>
<td>{moment(group.created_at).fromNow()}</td>
<td onClick={this.props.showSetGroupQuotaDialog.bind(this, group.id)}>
{Utils.bytesToSize(group.quota)}{' '}
<span title="Edit Quota" className={`fa fa-pencil-alt attr-action-icon ${highlight ? '' : 'vh'}`}></span>
</td>
<td className="cursor-pointer text-center" onClick={this.props.showDeleteDepartDialog.bind(this, group)}>
<span className={`sf2-icon-delete action-icon ${highlight ? '' : 'vh'}`} title="Delete"></span>
</td>
</tr>
);
}
}
const GroupItemPropTypes = {
group: PropTypes.object.isRequired,
showSetGroupQuotaDialog: PropTypes.func.isRequired,
showDeleteDepartDialog: PropTypes.func.isRequired,
isSubdepartChanged: PropTypes.bool,
};
GroupItem.propTypes = GroupItemPropTypes;
export default OrgDepartmentItem; export default OrgDepartmentItem;

View File

@@ -2,14 +2,14 @@ import React, { Fragment } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import moment from 'moment'; import moment from 'moment';
import { Link } from '@reach/router'; import { Link } from '@reach/router';
import { seafileAPI } from '../../utils/seafile-api';
import { siteRoot, gettext, orgID, lang } from '../../utils/constants';
import { Utils } from '../../utils/utils.js'; import { Utils } from '../../utils/utils.js';
import { seafileAPI } from '../../utils/seafile-api';
import MainPanelTopbar from './main-panel-topbar';
import ModalPortal from '../../components/modal-portal'; import ModalPortal from '../../components/modal-portal';
import AddDepartDialog from '../../components/dialog/org-add-department-dialog'; import AddDepartDialog from '../../components/dialog/org-add-department-dialog';
import DeleteDepartDialog from '../../components/dialog/org-delete-department-dialog'; import DeleteDepartDialog from '../../components/dialog/org-delete-department-dialog';
import SetGroupQuotaDialog from '../../components/dialog/org-set-group-quota-dialog'; import SetGroupQuotaDialog from '../../components/dialog/org-set-group-quota-dialog';
import MainPanelTopbar from './main-panel-topbar'; import { siteRoot, gettext, orgID, lang } from '../../utils/constants';
import '../../css/org-department-item.css'; import '../../css/org-department-item.css';
moment.locale(lang); moment.locale(lang);
@@ -27,17 +27,15 @@ class OrgDepartmentsList extends React.Component {
isShowAddDepartDialog: false, isShowAddDepartDialog: false,
}; };
} }
componentDidMount() {
this.listDepartGroups();
}
listDepartGroups = (groupID) => { listDepartGroups = () => {
if (groupID) { seafileAPI.orgAdminListDepartGroups(orgID).then(res => {
seafileAPI.orgAdminListGroupInfo(orgID, groupID, true).then(res => { this.setState({ groups: res.data.data });
this.setState({ groups: res.data.groups }); });
});
} else {
seafileAPI.orgAdminListDepartGroups(orgID).then(res => {
this.setState({ groups: res.data.data });
});
}
} }
showDeleteDepartDialog = (group) => { showDeleteDepartDialog = (group) => {
@@ -48,6 +46,10 @@ class OrgDepartmentsList extends React.Component {
this.setState({ showSetGroupQuotaDialog: true, groupID: groupID }); this.setState({ showSetGroupQuotaDialog: true, groupID: groupID });
} }
toggleAddDepartDialog = () => {
this.setState({ isShowAddDepartDialog: !this.state.isShowAddDepartDialog});
}
toggleCancel = () => { toggleCancel = () => {
this.setState({ this.setState({
showDeleteDepartDialog: false, showDeleteDepartDialog: false,
@@ -56,35 +58,15 @@ class OrgDepartmentsList extends React.Component {
} }
onDepartChanged = () => { onDepartChanged = () => {
this.listDepartGroups(this.props.groupID); this.listDepartGroups();
}
toggleAddDepartDialog = () => {
this.setState({ isShowAddDepartDialog: !this.state.isShowAddDepartDialog});
}
componentDidMount() {
this.listDepartGroups(this.props.groupID);
}
componentWillReceiveProps(nextProps) {
if (this.props.groupID !== nextProps.groupID || this.props.isSubdepartChanged !== nextProps.isSubdepartChanged) {
this.listDepartGroups(nextProps.groupID);
}
} }
render() { render() {
const groups = this.state.groups; const groups = this.state.groups;
let isSub = this.props.groupID ? true : false;
let header = isSub ? gettext('Sub-departments') : gettext('Departments');
let noGroup = isSub ? gettext('No sub-departments') : gettext('No departments');
const topbarChildren = ( const topbarChildren = (
<Fragment> <Fragment>
{!this.props.groupID && <button className='btn btn-secondary operation-item' title={gettext('New Department')} onClick={this.toggleAddDepartDialog}>{gettext('New Department')}
<button className='btn btn-secondary operation-item' title={gettext('New Department')} onClick={this.toggleAddDepartDialog}>{gettext('New Department')} </button>
</button>
}
{this.state.isShowAddDepartDialog && ( {this.state.isShowAddDepartDialog && (
<ModalPortal> <ModalPortal>
<AddDepartDialog <AddDepartDialog
@@ -97,15 +79,14 @@ class OrgDepartmentsList extends React.Component {
)} )}
</Fragment> </Fragment>
); );
return ( return (
<Fragment> <Fragment>
{!isSub && <MainPanelTopbar children={topbarChildren} />} <MainPanelTopbar children={topbarChildren}/>
<div className="main-panel-center flex-row h-100"> <div className="main-panel-center flex-row h-100">
<div className="cur-view-container o-auto"> <div className="cur-view-container o-auto">
<div className="cur-view-path"> <div className="cur-view-path">
<div className="fleft"> <div className="fleft">
<h3 className="sf-heading">{header}</h3> <h3 className="sf-heading">{gettext('Departments')}</h3>
</div> </div>
</div> </div>
<div className="cur-view-content"> <div className="cur-view-content">
@@ -133,8 +114,8 @@ class OrgDepartmentsList extends React.Component {
})} })}
</tbody> </tbody>
</table> </table>
: :
<p className="no-group">{noGroup}</p> <p className="no-group">{gettext('No departments')}</p>
} }
</div> </div>
<React.Fragment> <React.Fragment>
@@ -206,7 +187,6 @@ const GroupItemPropTypes = {
group: PropTypes.object.isRequired, group: PropTypes.object.isRequired,
showSetGroupQuotaDialog: PropTypes.func.isRequired, showSetGroupQuotaDialog: PropTypes.func.isRequired,
showDeleteDepartDialog: PropTypes.func.isRequired, showDeleteDepartDialog: PropTypes.func.isRequired,
isSubdepartChanged: PropTypes.bool,
}; };
GroupItem.propTypes = GroupItemPropTypes; GroupItem.propTypes = GroupItemPropTypes;