forked from Gitlink/forgeplus-react
489 lines
12 KiB
JavaScript
489 lines
12 KiB
JavaScript
import React, { Component } from "react";
|
||
import { Link } from "react-router-dom";
|
||
import {
|
||
Input,
|
||
AutoComplete,
|
||
Dropdown,
|
||
Menu,
|
||
Icon,
|
||
Spin,
|
||
Pagination,
|
||
Button,
|
||
Table,
|
||
Tooltip
|
||
} from "antd";
|
||
import NoneData from "../Nodata";
|
||
import axios from "axios";
|
||
import { getImageUrl } from "educoder";
|
||
const { Search } = Input;
|
||
|
||
const { Option } = AutoComplete;
|
||
const MENU_LIST = [
|
||
{
|
||
id: "Manager",
|
||
name: "管理员",
|
||
},
|
||
{
|
||
id: "Developer",
|
||
name: "开发者",
|
||
},
|
||
{
|
||
id: "Reporter",
|
||
name: "报告者",
|
||
},
|
||
];
|
||
const LIMIT = 15;
|
||
class Collaborator extends Component {
|
||
constructor(props) {
|
||
super(props);
|
||
this.state = {
|
||
listData: undefined,
|
||
user: undefined,
|
||
user_id: undefined,
|
||
userDataSource: undefined,
|
||
page: 1,
|
||
total_count: undefined,
|
||
isSpin: true,
|
||
searchKey: undefined,
|
||
search: undefined,
|
||
role: undefined,
|
||
otherSpin: false,
|
||
searchSpin: false,
|
||
roleName: undefined,
|
||
};
|
||
}
|
||
|
||
componentDidMount = () => {
|
||
if (this.props.project_id) {
|
||
this.getMember();
|
||
}
|
||
};
|
||
|
||
componentDidUpdate = (prevState) => {
|
||
if (
|
||
this.props.project_id &&
|
||
this.props.project_id !== prevState.project_id
|
||
) {
|
||
this.getMember();
|
||
}
|
||
};
|
||
|
||
// 获取项目协作者
|
||
getMember = () => {
|
||
const { page, search, role } = this.state;
|
||
console.log("search", search);
|
||
console.log("role", role);
|
||
const url = `/projects/${this.props.project_id}/members.json`;
|
||
axios
|
||
.get(url, {
|
||
params: {
|
||
page,
|
||
search: search,
|
||
role: role,
|
||
limit: LIMIT,
|
||
},
|
||
})
|
||
.then((result) => {
|
||
if (result) {
|
||
this.setState({
|
||
listData: result.data.members,
|
||
isSpin: false,
|
||
otherSpin: false,
|
||
searchSpin: false,
|
||
total_count: result.data.total_count,
|
||
});
|
||
}
|
||
})
|
||
.catch((error) => {
|
||
this.setState({
|
||
isSpin: false,
|
||
otherSpin: false,
|
||
searchSpin: false,
|
||
});
|
||
console.log(error);
|
||
});
|
||
};
|
||
// 输入用户
|
||
changeInputUser = (e) => {
|
||
this.setState({
|
||
searchKey: e,
|
||
});
|
||
this.getUserList(e);
|
||
};
|
||
searchMember = (e) => {
|
||
this.state.search = e;
|
||
this.setState({
|
||
searchSpin: true,
|
||
});
|
||
this.getMember();
|
||
};
|
||
orderMember = (id, name) => {
|
||
this.setState({
|
||
isSpin: true
|
||
})
|
||
this.state.role = id;
|
||
this.state.roleName = name;
|
||
this.getMember();
|
||
};
|
||
// 选择用户
|
||
selectInputUser = (e, option) => {
|
||
this.setState({
|
||
user_id: e,
|
||
searchKey: option.props.searchValue,
|
||
});
|
||
this.getUserList(option.props.searchValue);
|
||
};
|
||
getUserList = (e) => {
|
||
const url = `/users/list.json`;
|
||
axios
|
||
.get(url, {
|
||
params: {
|
||
search: e,
|
||
},
|
||
})
|
||
.then((result) => {
|
||
if (result) {
|
||
this.setState({
|
||
userDataSource: result.data.users,
|
||
});
|
||
}
|
||
})
|
||
.catch((error) => {
|
||
console.log(error);
|
||
});
|
||
};
|
||
|
||
// 增加协作者
|
||
addCollaborator = () => {
|
||
// const { project_id } = this.props;
|
||
this.setState({
|
||
otherSpin: true,
|
||
});
|
||
const { user_id } = this.state;
|
||
const url = `/projects/${this.props.project_id}/members.json`;
|
||
axios
|
||
.post(url, {
|
||
user_id,
|
||
})
|
||
.then((result) => {
|
||
if (result) {
|
||
this.setState({
|
||
isSpin: true,
|
||
otherSpin: false,
|
||
});
|
||
this.getMember();
|
||
}
|
||
})
|
||
.catch((error) => {
|
||
console.log(error);
|
||
});
|
||
};
|
||
|
||
// 修改权限
|
||
changeOperaiton = (e, id) => {
|
||
// const { project_id, page } = this.state;
|
||
this.setState({
|
||
isSpin: true,
|
||
});
|
||
const url = `/projects/${this.props.project_id}/members/change_role.json`;
|
||
axios
|
||
.put(url, {
|
||
user_id: id,
|
||
role: e.key,
|
||
})
|
||
.then((result) => {
|
||
if (result) {
|
||
this.setState({
|
||
isSpin: true,
|
||
});
|
||
this.props.showNotification("权限修改成功!");
|
||
this.getMember();
|
||
}
|
||
})
|
||
.catch((error) => {
|
||
console.log(error);
|
||
});
|
||
};
|
||
|
||
// 删除协作者
|
||
deleteUser = (id) => {
|
||
const { page } = this.state;
|
||
this.props.confirm({
|
||
content: "确认将此成员从项目中移除?",
|
||
onOk: () => {
|
||
const { project_id } = this.props;
|
||
const url = `/projects/${project_id}/members/remove.json`;
|
||
axios
|
||
.delete(url, {
|
||
data: {
|
||
user_id: id,
|
||
},
|
||
})
|
||
.then((result) => {
|
||
if (result) {
|
||
this.setState({
|
||
isSpin: true,
|
||
});
|
||
this.props.showNotification("成员删除成功!");
|
||
this.getMember();
|
||
}
|
||
})
|
||
.catch((error) => {
|
||
console.log(error);
|
||
});
|
||
},
|
||
});
|
||
};
|
||
changePage = (page) => {
|
||
this.state.page = page;
|
||
this.setState({
|
||
isSpin: true,
|
||
});
|
||
this.getMember();
|
||
};
|
||
|
||
render() {
|
||
const {
|
||
userDataSource,
|
||
listData,
|
||
isSpin,
|
||
page,
|
||
total_count,
|
||
searchKey,
|
||
otherSpin,
|
||
searchSpin,
|
||
roleName,
|
||
} = this.state;
|
||
// 获取当前项目的拥有者
|
||
const { author } = this.props;
|
||
const get_color = (role) => {
|
||
if (role === "Manager") {
|
||
return "text-green";
|
||
} else if (role === "Developer") {
|
||
return "text-primary";
|
||
} else {
|
||
return "text-yellow";
|
||
}
|
||
};
|
||
const member_roles = (item) => {
|
||
const operation = MENU_LIST.filter((i) => i.id === item.role);
|
||
return (
|
||
<span>
|
||
{author && author.login === item.login ? (
|
||
<label className={get_color(item.role)}>
|
||
{operation && operation[0].name}
|
||
</label>
|
||
) : (
|
||
<Dropdown overlay={setRoles(`${item.id}`)} placement={"bottomCenter"}>
|
||
<span className={get_color(item.role)}>
|
||
{operation && operation[0].name}
|
||
<Icon type="caret-down" className="ml2" size="13" />
|
||
</span>
|
||
</Dropdown>
|
||
)}
|
||
</span>
|
||
);
|
||
};
|
||
const roleTitle = (
|
||
<div><span className="mr3">角色</span>
|
||
<Tooltip placement='bottom' title={<div>
|
||
<div className="mb3">管理员:拥有仓库设置功能、代码库读、写操作</div>
|
||
<div className="mb3">开发人员:只拥有代码库读、写操作</div>
|
||
<div className="mb3">报告者:只拥有代码库读操作</div>
|
||
</div>
|
||
}>
|
||
<Icon type="question-circle"></Icon>
|
||
</Tooltip>
|
||
</div>
|
||
);
|
||
const columns = [
|
||
{
|
||
title: "头像",
|
||
dataIndex: "image_url",
|
||
render: (text, item) => (
|
||
<span className="f-wrap-alignCenter">
|
||
<Link
|
||
to={`/users/${item.login}/projects`}
|
||
className="show-user-link"
|
||
>
|
||
<img
|
||
src={getImageUrl(`images/${text}`)}
|
||
alt=""
|
||
width="32px"
|
||
height="32px"
|
||
className="mr3 radius"
|
||
/>
|
||
</Link>
|
||
</span>
|
||
),
|
||
},
|
||
{
|
||
title: "用户名",
|
||
dataIndex: "name",
|
||
render: (text, item) => (
|
||
<Link to={`/users/${item.login}/projects`} className="show-user-link">
|
||
{text}
|
||
</Link>
|
||
),
|
||
},
|
||
{
|
||
title: "邮箱",
|
||
dataIndex: "email",
|
||
render: (text) => <span>{text}</span>,
|
||
},
|
||
{
|
||
title: roleTitle,
|
||
dataIndex: "role_name",
|
||
render: (text, item) => member_roles(item),
|
||
},
|
||
{
|
||
title: "操作",
|
||
dataIndex: "action",
|
||
render: (text, item) => (
|
||
<span style={{ justifyContent: "center" }}>
|
||
{author && author.login !== item.login && (
|
||
<a
|
||
className="text-delete"
|
||
onClick={() => this.deleteUser(item.id)}
|
||
>
|
||
删除
|
||
</a>
|
||
)}
|
||
</span>
|
||
),
|
||
},
|
||
];
|
||
const roles = (id) => (
|
||
<Menu>
|
||
<Menu.Item
|
||
key={0}
|
||
value={undefined}
|
||
onClick={(e) => this.orderMember(undefined, "角色筛选")}
|
||
>
|
||
全部
|
||
</Menu.Item>
|
||
{MENU_LIST.map((item, key) => {
|
||
return (
|
||
<Menu.Item
|
||
key={item.id}
|
||
value={item.id}
|
||
onClick={(e) => this.orderMember(item.id, item.name)}
|
||
>
|
||
{item.name}
|
||
</Menu.Item>
|
||
);
|
||
})}
|
||
</Menu>
|
||
);
|
||
const setRoles = (id) => (
|
||
<Menu>
|
||
{MENU_LIST.map((item, key) => {
|
||
return (
|
||
<Menu.Item
|
||
key={item.id}
|
||
value={item.id}
|
||
onClick={(e) => this.changeOperaiton(e,id)}
|
||
>
|
||
{item.name}
|
||
</Menu.Item>
|
||
);
|
||
})}
|
||
</Menu>
|
||
);
|
||
|
||
const source =
|
||
userDataSource &&
|
||
userDataSource.map((item, key) => {
|
||
return (
|
||
<Option
|
||
key={key}
|
||
value={`${item.user_id}`}
|
||
searchValue={`${item.username}`}
|
||
>
|
||
<img
|
||
className="user_img radius"
|
||
width="28"
|
||
height="28"
|
||
src={getImageUrl(`images/${item && item.image_url}`)}
|
||
alt=""
|
||
/>
|
||
<span className="ml10" style={{ "vertical-align": "middle" }}>
|
||
{item.username}
|
||
<span className="color-grey ml10">({item.login})</span>
|
||
</span>
|
||
</Option>
|
||
);
|
||
});
|
||
return (
|
||
<div>
|
||
<div className="flex-a-center baseForm bbr">
|
||
<span className="font-18 fwb text-black">协作者管理</span>
|
||
<div className="addPanel">
|
||
<AutoComplete
|
||
dataSource={source}
|
||
value={searchKey}
|
||
style={{ width: 300 }}
|
||
onChange={this.changeInputUser}
|
||
onSelect={this.selectInputUser}
|
||
placeholder="搜索需要添加的用户..."
|
||
/>
|
||
<Button
|
||
type="primary"
|
||
ghost
|
||
onClick={this.addCollaborator}
|
||
className="ml15"
|
||
loading={otherSpin}
|
||
>
|
||
<Icon type="plus" size="16"></Icon>
|
||
添加成员
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
<div className="grid-item-left baseForm">
|
||
<Search
|
||
placeholder="搜索项目成员..."
|
||
enterButton="搜索"
|
||
loading={searchSpin}
|
||
onSearch={(value) => this.searchMember(value)}
|
||
/>
|
||
<Dropdown overlay={roles} placement={"bottomCenter"}>
|
||
<a className="ml180 text-primary">
|
||
{roleName ? roleName : "角色筛选"}
|
||
<Icon type="caret-down" size="16"></Icon>
|
||
</a>
|
||
</Dropdown>
|
||
</div>
|
||
|
||
<Spin spinning={isSpin}>
|
||
<div className="collaboratorList baseForm">
|
||
{listData ? (
|
||
<Table
|
||
pagination={false}
|
||
columns={columns}
|
||
dataSource={listData}
|
||
rowKey={(record) => record.id}
|
||
></Table>
|
||
) : (
|
||
<NoneData _html="暂时还没有相关数据哦!" />
|
||
)}
|
||
</div>
|
||
</Spin>
|
||
{total_count && total_count > LIMIT ? (
|
||
<div className="edu-txt-center mt20 mb20">
|
||
<Pagination
|
||
showQuickJumper
|
||
pageSize={LIMIT}
|
||
current={page}
|
||
total={total_count}
|
||
onChange={this.changePage}
|
||
></Pagination>
|
||
</div>
|
||
) : (
|
||
""
|
||
)}
|
||
</div>
|
||
);
|
||
}
|
||
}
|
||
export default Collaborator;
|