mirror of
https://github.com/YMFE/yapi.git
synced 2025-02-17 13:49:43 +08:00
feat: 分组设置功能放入Tab中
This commit is contained in:
parent
5863738f77
commit
4552bf0fa6
@ -3,6 +3,7 @@ import GroupList from './GroupList/GroupList.js';
|
||||
import ProjectList from './ProjectList/ProjectList.js';
|
||||
import MemberList from './MemberList/MemberList.js';
|
||||
import GroupLog from './GroupLog/GroupLog.js';
|
||||
import GroupSetting from './GroupSetting/GroupSetting.js';
|
||||
import PropTypes from 'prop-types'
|
||||
import { connect } from 'react-redux'
|
||||
import { Route, Switch, Redirect } from 'react-router-dom';
|
||||
@ -54,6 +55,7 @@ export default class Group extends Component {
|
||||
<TabPane tab="项目列表" key="1"><ProjectList/></TabPane>
|
||||
{this.props.currGroup.type === 'public'?<TabPane tab="成员列表" key="2"><MemberList/></TabPane>:null}
|
||||
{["admin","owner","guest","dev"].indexOf(this.props.curUserRoleInGroup)>-1 || this.props.curUserRole === "admin"?<TabPane tab="分组动态" key="3"><GroupLog/></TabPane>:""}
|
||||
{(this.props.curUserRole === "admin" || this.props.curUserRoleInGroup === 'owner') && this.props.currGroup.type !== 'private' ? <TabPane tab="分组设置" key="4"><GroupSetting/></TabPane> : null}
|
||||
</Tabs>
|
||||
</Content>
|
||||
</Layout>
|
||||
|
@ -1,14 +1,12 @@
|
||||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { connect } from 'react-redux'
|
||||
import { Icon, Modal, Alert, Input, message, Menu, Row, Col, Dropdown, Popover } from 'antd'
|
||||
import { Icon, Modal, Input, message, Row, Menu, Col, Popover, Tooltip } from 'antd'
|
||||
import { autobind } from 'core-decorators';
|
||||
import axios from 'axios';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
const { TextArea } = Input;
|
||||
const Search = Input.Search;
|
||||
const TYPE_EDIT = 'edit';
|
||||
const confirm = Modal.confirm;
|
||||
import UsernameAutoComplete from '../../../components/UsernameAutoComplete/UsernameAutoComplete.js';
|
||||
import GuideBtns from '../../../components/GuideBtns/GuideBtns.js';
|
||||
import { fetchNewsData } from '../../../reducer/modules/news.js';
|
||||
@ -65,7 +63,6 @@ export default class GroupList extends Component {
|
||||
|
||||
state = {
|
||||
addGroupModalVisible: false,
|
||||
editGroupModalVisible: false,
|
||||
newGroupName: '',
|
||||
newGroupDesc: '',
|
||||
currGroupName: '',
|
||||
@ -100,34 +97,19 @@ export default class GroupList extends Component {
|
||||
}
|
||||
|
||||
@autobind
|
||||
showModal(type) {
|
||||
if (type === 'edit') {
|
||||
const { currGroup } = this.props;
|
||||
this.setState({
|
||||
currGroupName: currGroup.group_name,
|
||||
currGroupDesc: currGroup.group_desc,
|
||||
editGroupModalVisible: true
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
addGroupModalVisible: true
|
||||
});
|
||||
}
|
||||
showModal() {
|
||||
this.setState({
|
||||
addGroupModalVisible: true
|
||||
});
|
||||
}
|
||||
@autobind
|
||||
hideModal(type) {
|
||||
if (type === TYPE_EDIT) {
|
||||
this.setState({
|
||||
editGroupModalVisible: false
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
newGroupName: '',
|
||||
group_name: '',
|
||||
owner_uids: [],
|
||||
addGroupModalVisible: false
|
||||
});
|
||||
}
|
||||
hideModal() {
|
||||
this.setState({
|
||||
newGroupName: '',
|
||||
group_name: '',
|
||||
owner_uids: [],
|
||||
addGroupModalVisible: false
|
||||
});
|
||||
}
|
||||
@autobind
|
||||
async addGroup() {
|
||||
@ -159,9 +141,6 @@ export default class GroupList extends Component {
|
||||
if (res.data.errcode) {
|
||||
message.error(res.data.errmsg);
|
||||
} else {
|
||||
this.setState({
|
||||
editGroupModalVisible: false
|
||||
});
|
||||
await this.props.fetchGroupList();
|
||||
|
||||
this.setState({ groupList: this.props.groupList });
|
||||
@ -174,20 +153,12 @@ export default class GroupList extends Component {
|
||||
}
|
||||
}
|
||||
@autobind
|
||||
inputNewGroupName(e, type) {
|
||||
if (type === TYPE_EDIT) {
|
||||
this.setState({ currGroupName: e.target.value })
|
||||
} else {
|
||||
this.setState({ newGroupName: e.target.value });
|
||||
}
|
||||
inputNewGroupName(e) {
|
||||
this.setState({ newGroupName: e.target.value });
|
||||
}
|
||||
@autobind
|
||||
inputNewGroupDesc(e, type) {
|
||||
if (type === TYPE_EDIT) {
|
||||
this.setState({ currGroupDesc: e.target.value })
|
||||
} else {
|
||||
this.setState({ newGroupDesc: e.target.value });
|
||||
}
|
||||
inputNewGroupDesc(e) {
|
||||
this.setState({ newGroupDesc: e.target.value });
|
||||
}
|
||||
|
||||
@autobind
|
||||
@ -207,50 +178,6 @@ export default class GroupList extends Component {
|
||||
})
|
||||
}
|
||||
|
||||
showConfirm = () => {
|
||||
let that = this;
|
||||
confirm({
|
||||
title: "确认删除 " + that.props.currGroup.group_name + " 分组吗?",
|
||||
content: <div style={{ marginTop: '10px', fontSize: '13px', lineHeight: '25px' }}>
|
||||
<Alert message="警告:此操作非常危险,会删除该分组下面所有项目和接口,并且无法恢复!" type="warning" />
|
||||
<div style={{ marginTop: '16px' }}>
|
||||
<p><b>请输入分组名称确认此操作:</b></p>
|
||||
<Input id="group_name" />
|
||||
</div>
|
||||
</div>,
|
||||
onOk() {
|
||||
let groupName = document.getElementById('group_name').value;
|
||||
if (that.props.currGroup.group_name !== groupName) {
|
||||
message.error('分组名称有误')
|
||||
return new Promise((resolve, reject) => {
|
||||
reject('error')
|
||||
})
|
||||
} else {
|
||||
that.deleteGroup()
|
||||
}
|
||||
|
||||
},
|
||||
iconType: 'delete',
|
||||
onCancel() { }
|
||||
});
|
||||
}
|
||||
|
||||
@autobind
|
||||
async deleteGroup() {
|
||||
const self = this;
|
||||
const { currGroup } = self.props;
|
||||
const res = await axios.post('/api/group/del', { id: currGroup._id })
|
||||
if (res.data.errcode) {
|
||||
message.error(res.data.errmsg);
|
||||
} else {
|
||||
message.success('删除成功')
|
||||
await self.props.fetchGroupList()
|
||||
const currGroup = self.props.groupList[0] || { group_name: '', group_desc: '' };
|
||||
self.setState({ groupList: self.props.groupList });
|
||||
self.props.setCurrGroup(currGroup)
|
||||
}
|
||||
}
|
||||
|
||||
@autobind
|
||||
searchGroup(e, value) {
|
||||
const v = value || e.target.value;
|
||||
@ -262,40 +189,17 @@ export default class GroupList extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
// GroupSetting 组件设置的分组信息,通过redux同步到左侧分组菜单中
|
||||
if (this.props.groupList !== nextProps.groupList) {
|
||||
this.setState({
|
||||
groupList: nextProps.groupList
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { currGroup } = this.props;
|
||||
const delmark = <Menu.Item>
|
||||
<span onClick={() => this.showModal(TYPE_EDIT)}>编辑分组</span>
|
||||
</Menu.Item>
|
||||
const editmark = <Menu.Item>
|
||||
<span onClick={() => { this.showConfirm() }}>删除分组</span>
|
||||
</Menu.Item>
|
||||
const addmark = <Menu.Item>
|
||||
<span onClick={this.showModal}>添加分组</span>
|
||||
</Menu.Item>
|
||||
|
||||
let menu = <Menu>
|
||||
{
|
||||
this.props.curUserRole === "admin" && this.props.currGroup.type !== 'private' ? (editmark) : ''
|
||||
}
|
||||
{
|
||||
(this.props.curUserRole === "admin" || this.props.curUserRoleInGroup === 'owner') && this.props.currGroup.type !== 'private' ? (delmark) : ''
|
||||
}
|
||||
{
|
||||
this.props.curUserRole === 'admin' ? (addmark) : ''
|
||||
}
|
||||
</Menu>;
|
||||
menu = (this.props.curUserRoleInGroup === 'owner' && this.props.curUserRole !== 'admin') ? <a className="editSet"><Icon type="setting" onClick={() => this.showModal(TYPE_EDIT)} /></a> : <Dropdown overlay={menu}>
|
||||
<a className="ant-dropdown-link" href="#">
|
||||
<Icon type="setting" />
|
||||
</a>
|
||||
</Dropdown>;
|
||||
// console.log(this.props.currGroup.type,this.props.curUserRoleInGroup,this.props.curUserRole);
|
||||
// if(!(this.props.currGroup.type !=='private') && !(this.props.curUserRoleInGroup === 'owner' || this.props.curUserRole === 'admin')){
|
||||
// menu = null;
|
||||
// }
|
||||
|
||||
|
||||
return (
|
||||
<div className="m-group">
|
||||
{!this.props.study ? <div className="study-mask"></div> : null}
|
||||
@ -303,7 +207,10 @@ export default class GroupList extends Component {
|
||||
<div className="curr-group">
|
||||
<div className="curr-group-name">
|
||||
<span className="name">{currGroup.group_name}</span>
|
||||
{this.props.curUserRole === "admin" || this.props.curUserRoleInGroup === 'owner' ? (menu) : ''}
|
||||
{/* this.props.curUserRole === "admin" || this.props.curUserRoleInGroup === 'owner' ? (menu) : '' */}
|
||||
{ /* 只有超级管理员能添加分组 */
|
||||
this.props.curUserRole === 'admin' ? <Tooltip title="添加分组"><a className="editSet"><Icon className="btn" type="folder-add" onClick={this.showModal} /></a></Tooltip> : ''
|
||||
}
|
||||
</div>
|
||||
<div className="curr-group-desc">简介: {currGroup.group_desc}</div>
|
||||
</div>
|
||||
@ -370,27 +277,6 @@ export default class GroupList extends Component {
|
||||
</Row>
|
||||
</Modal> : ''
|
||||
}
|
||||
|
||||
<Modal
|
||||
title="编辑分组"
|
||||
visible={this.state.editGroupModalVisible}
|
||||
onOk={this.editGroup}
|
||||
onCancel={() => this.hideModal(TYPE_EDIT)}
|
||||
className="add-group-modal"
|
||||
>
|
||||
<Row gutter={6} className="modal-input">
|
||||
<Col span="5"><div className="label">分组名:</div></Col>
|
||||
<Col span="15">
|
||||
<Input placeholder="请输入分组名称" value={this.state.currGroupName} onChange={(e) => this.inputNewGroupName(e, TYPE_EDIT)}></Input>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row gutter={6} className="modal-input">
|
||||
<Col span="5"><div className="label">简介:</div></Col>
|
||||
<Col span="15">
|
||||
<TextArea rows={3} placeholder="请输入分组描述" value={this.state.currGroupDesc} onChange={(e) => this.inputNewGroupDesc(e, TYPE_EDIT)}></TextArea>
|
||||
</Col>
|
||||
</Row>
|
||||
</Modal>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
198
client/containers/Group/GroupSetting/GroupSetting.js
Normal file
198
client/containers/Group/GroupSetting/GroupSetting.js
Normal file
@ -0,0 +1,198 @@
|
||||
import React, { Component } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import { autobind } from 'core-decorators';
|
||||
import { Row, Col, Input, Button, message, Icon, Card, Alert, Modal } from 'antd';
|
||||
import { fetchNewsData } from '../../../reducer/modules/news.js';
|
||||
import { changeGroupMsg, fetchGroupList, setCurrGroup, fetchGroupMsg, updateGroupList, deleteGroup } from '../../../reducer/modules/group.js';
|
||||
const { TextArea } = Input;
|
||||
import _ from 'underscore';
|
||||
const confirm = Modal.confirm;
|
||||
|
||||
@connect(
|
||||
state => {
|
||||
return {
|
||||
groupList: state.group.groupList,
|
||||
currGroup: state.group.currGroup,
|
||||
curUserRole: state.user.role
|
||||
}
|
||||
},
|
||||
{
|
||||
changeGroupMsg,
|
||||
fetchGroupList,
|
||||
setCurrGroup,
|
||||
fetchGroupMsg,
|
||||
fetchNewsData,
|
||||
updateGroupList,
|
||||
deleteGroup
|
||||
}
|
||||
)
|
||||
class GroupLog extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
currGroupDesc: '',
|
||||
currGroupName: '',
|
||||
showDangerOptions: false
|
||||
}
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
currGroup: PropTypes.object,
|
||||
curUserRole: PropTypes.string,
|
||||
changeGroupMsg: PropTypes.func,
|
||||
fetchGroupList: PropTypes.func,
|
||||
setCurrGroup: PropTypes.func,
|
||||
fetchGroupMsg: PropTypes.func,
|
||||
fetchNewsData: PropTypes.func,
|
||||
updateGroupList: PropTypes.func,
|
||||
deleteGroup: PropTypes.func,
|
||||
groupList: PropTypes.array
|
||||
}
|
||||
|
||||
// 修改分组名称
|
||||
changeName = (e) => {
|
||||
this.setState({
|
||||
currGroupName: e.target.value
|
||||
})
|
||||
}
|
||||
// 修改分组描述
|
||||
changeDesc = (e) => {
|
||||
this.setState({
|
||||
currGroupDesc: e.target.value
|
||||
})
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.setState({
|
||||
currGroupName: this.props.currGroup.group_name,
|
||||
currGroupDesc: this.props.currGroup.group_desc
|
||||
})
|
||||
}
|
||||
|
||||
// 点击“查看危险操作”按钮
|
||||
toggleDangerOptions = () => {
|
||||
// console.log(this.state.showDangerOptions);
|
||||
this.setState({
|
||||
showDangerOptions: !this.state.showDangerOptions
|
||||
});
|
||||
}
|
||||
|
||||
// 编辑分组信息
|
||||
@autobind
|
||||
async editGroup() {
|
||||
const id = this.props.currGroup._id;
|
||||
const res = await this.props.changeGroupMsg({
|
||||
group_name: this.state.currGroupName,
|
||||
group_desc: this.state.currGroupDesc,
|
||||
id: this.props.currGroup._id
|
||||
});
|
||||
if (!res.payload.data.errcode) {
|
||||
message.success('修改成功!');
|
||||
await this.props.fetchGroupList(this.props.groupList);
|
||||
this.props.updateGroupList(this.props.groupList)
|
||||
const currGroup = _.find(this.props.groupList, (group) => { return + group._id === + id });
|
||||
|
||||
this.props.setCurrGroup(currGroup);
|
||||
this.props.fetchGroupMsg(this.props.currGroup._id);
|
||||
this.props.fetchNewsData(this.props.currGroup._id, "group", 1, 10)
|
||||
}
|
||||
}
|
||||
|
||||
// 删除分组
|
||||
@autobind
|
||||
async deleteGroup() {
|
||||
const that = this;
|
||||
const { currGroup } = that.props;
|
||||
const res = await this.props.deleteGroup({ id: currGroup._id });
|
||||
if (!res.payload.data.errcode) {
|
||||
message.success('删除成功')
|
||||
await that.props.fetchGroupList();
|
||||
const currGroup = that.props.groupList[0] || { group_name: '', group_desc: '' };
|
||||
that.setState({ groupList: that.props.groupList });
|
||||
that.props.setCurrGroup(currGroup)
|
||||
}
|
||||
}
|
||||
|
||||
// 删除分组的二次确认
|
||||
showConfirm = () => {
|
||||
const that = this;
|
||||
confirm({
|
||||
title: "确认删除 " + that.props.currGroup.group_name + " 分组吗?",
|
||||
content: <div style={{ marginTop: '10px', fontSize: '13px', lineHeight: '25px' }}>
|
||||
<Alert message="警告:此操作非常危险,会删除该分组下面所有项目和接口,并且无法恢复!" type="warning" />
|
||||
<div style={{ marginTop: '16px' }}>
|
||||
<p><b>请输入分组名称确认此操作:</b></p>
|
||||
<Input id="group_name" />
|
||||
</div>
|
||||
</div>,
|
||||
onOk() {
|
||||
const groupName = document.getElementById('group_name').value;
|
||||
if (that.props.currGroup.group_name !== groupName) {
|
||||
message.error('分组名称有误')
|
||||
return new Promise((resolve, reject) => {
|
||||
reject('error')
|
||||
})
|
||||
} else {
|
||||
that.deleteGroup()
|
||||
}
|
||||
|
||||
},
|
||||
iconType: 'delete',
|
||||
onCancel() { }
|
||||
});
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
// 切换分组时,更新分组信息并关闭删除分组操作
|
||||
if (this.props.currGroup._id !== nextProps.currGroup._id) {
|
||||
this.setState({
|
||||
showDangerOptions: false,
|
||||
currGroupName: nextProps.currGroup.group_name,
|
||||
currGroupDesc: nextProps.currGroup.group_desc
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
render () {
|
||||
return (
|
||||
<div className="m-panel card-panel-s">
|
||||
<div>
|
||||
<Row gutter={6} className="modal-input">
|
||||
<Col span="4"><div className="label">分组名:</div></Col>
|
||||
<Col span="15">
|
||||
<Input placeholder="请输入分组名称" value={this.state.currGroupName} onChange={this.changeName}></Input>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row gutter={6} className="modal-input">
|
||||
<Col span="4"><div className="label">简介:</div></Col>
|
||||
<Col span="15">
|
||||
<TextArea rows={3} placeholder="请输入分组描述" value={this.state.currGroupDesc} onChange={this.changeDesc}></TextArea>
|
||||
</Col>
|
||||
</Row>
|
||||
<Row gutter={6} className="modal-input">
|
||||
<Col span="15" offset="4"><Button type="primary" onClick={this.editGroup}>保存</Button></Col>
|
||||
</Row>
|
||||
</div>
|
||||
{/* 只有超级管理员能删除分组 */}
|
||||
{this.props.curUserRole === "admin" ?
|
||||
<div className="danger-container">
|
||||
<div className="title">
|
||||
<h2 className="content"><Icon type="exclamation-circle-o" /> 危险操作</h2>
|
||||
<Button onClick={this.toggleDangerOptions}>查 看<Icon type={this.state.showDangerOptions ? 'up' : 'down'} /></Button>
|
||||
</div>
|
||||
{this.state.showDangerOptions ? <Card noHovering={true} className="card-danger">
|
||||
<div className="card-danger-content">
|
||||
<h3>删除分组</h3>
|
||||
<p>分组一旦删除,将无法恢复数据,请慎重操作!</p>
|
||||
<p>只有超级管理员有权限删除分组。</p>
|
||||
</div>
|
||||
<Button type="danger" ghost className="card-danger-btn" onClick={this.showConfirm}>删除</Button>
|
||||
</Card> : null}
|
||||
</div> : null}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default GroupLog;
|
@ -8,11 +8,17 @@ const FETCH_GROUP_MSG = 'yapi/group/FETCH_GROUP_MSG';
|
||||
const ADD_GROUP_MEMBER = 'yapi/group/ADD_GROUP_MEMBER';
|
||||
const DEL_GROUP_MEMBER = 'yapi/group/DEL_GROUP_MEMBER';
|
||||
const CHANGE_GROUP_MEMBER = 'yapi/group/CHANGE_GROUP_MEMBER';
|
||||
const CHANGE_GROUP_MESSAGE = 'yapi/group/CHANGE_GROUP_MESSAGE';
|
||||
const UPDATE_GROUP_LIST = 'yapi/group/UPDATE_GROUP_LIST';
|
||||
const DEL_GROUP = 'yapi/group/DEL_GROUP';
|
||||
|
||||
// Reducer
|
||||
const initialState = {
|
||||
groupList: [],
|
||||
currGroup: { group_name: '' },
|
||||
currGroup: {
|
||||
group_name: '',
|
||||
group_desc: ''
|
||||
},
|
||||
member: [],
|
||||
role: ''
|
||||
};
|
||||
@ -25,6 +31,12 @@ export default (state = initialState, action) => {
|
||||
groupList: action.payload.data.data
|
||||
};
|
||||
}
|
||||
case UPDATE_GROUP_LIST: {
|
||||
return {
|
||||
...state,
|
||||
groupList: action.payload
|
||||
}
|
||||
}
|
||||
case SET_CURR_GROUP: {
|
||||
return {
|
||||
...state,
|
||||
@ -83,6 +95,30 @@ export function changeMemberRole(param) {
|
||||
}
|
||||
}
|
||||
|
||||
// 修改分组信息
|
||||
export function changeGroupMsg(param) {
|
||||
return {
|
||||
type: CHANGE_GROUP_MESSAGE,
|
||||
payload: axios.post('/api/group/up', param)
|
||||
}
|
||||
}
|
||||
|
||||
// 更新左侧的分组列表
|
||||
export function updateGroupList(param) {
|
||||
return {
|
||||
type: UPDATE_GROUP_LIST,
|
||||
payload: param
|
||||
}
|
||||
}
|
||||
|
||||
// 删除分组
|
||||
export function deleteGroup(param) {
|
||||
return {
|
||||
type: DEL_GROUP,
|
||||
payload: axios.post('/api/group/del', param)
|
||||
}
|
||||
}
|
||||
|
||||
// 获取分组成员列表
|
||||
export function fetchGroupMemberList(id) {
|
||||
return {
|
||||
|
Loading…
Reference in New Issue
Block a user