组织 all over

This commit is contained in:
caishi 2021-02-03 15:53:15 +08:00
parent 9380c0172c
commit 3b208ba751
17 changed files with 379 additions and 434 deletions

View File

@ -0,0 +1,93 @@
import React, { useEffect, useState } from 'react';
import { AutoComplete , Button , Icon } from 'antd';
import axios from 'axios';
import { getImageUrl } from 'educoder';
const { Option } = AutoComplete;
function AddMember({getID}){
const [ id , setID ] = useState(undefined);
const [ source , setSource ] = useState(undefined);
const [ searchKey , setSearchKey ] = useState(undefined);
useEffect(()=>{
getUserList();
},[searchKey])
function getUserList(e){
const url = `/users/list.json`;
axios.get(url, {
params: {
search: searchKey,
},
}).then((result) => {
if (result) {
sourceOptions(result.data.users);
}
})
.catch((error) => {
console.log(error);
});
};
function sourceOptions(userDataSource){
const s = userDataSource && userDataSource.map((item, key) => {
return (
<Option
key={key}
value={`${item.login}`}
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>
);
});
setSource(s);
}
function changeInputUser(e){
setSearchKey(e);
};
//
function selectInputUser(e, option){
setID(e);
setSearchKey(option.props.searchValue);
};
function addCollaborator(){
getID && getID(id);
}
return(
<div className="addPanel">
<AutoComplete
dataSource={source}
value={searchKey}
style={{ width: 300 }}
onChange={changeInputUser}
onSelect={selectInputUser}
placeholder="搜索需要添加的用户..."
/>
<Button
type="primary"
ghost
onClick={addCollaborator}
className="ml15"
>
<Icon type="plus" size="16"></Icon>
添加成员
</Button>
</div>
)
}
export default AddMember;

View File

@ -32,26 +32,6 @@ const I = styled.i`{
color:#60B25E;
margin-right:2px;
}`
const FocusBtn = styled.a`{
display:inline-block;
height:30px;
line-height:26px;
padding:0px 12px;
background-color:#fafafa;
border:1px solid #eee;
border-radius:2px;
color:#888!important;
}`
const Ifocused = styled.i`{
font-size:16px!important;
color:#FFA802;
margin-right:4px;
}`
const Ifocus = styled.i`{
font-size:16px!important;
color:#BBBBBB;
margin-right:4px;
}`
const Div = styled.div`{
margin-bottom: 18px;
padding:20px 16px;
@ -59,7 +39,7 @@ const Div = styled.div`{
align-items: center;
border:1px solid #eee;
}`
export default (({ img, name, time, focusStatus, is_current_user, login }) => {
export default (({ img, name, time, focusStatus, is_current_user, login , successFunc }) => {
return (
<Div>
<Img src={getImageUrl(`images/${img}`)} />
@ -68,9 +48,9 @@ export default (({ img, name, time, focusStatus, is_current_user, login }) => {
<Time><I className="iconfont icon-shijian"></I>加入时间:{time}</Time>
{
is_current_user ?
<Button type="default">当前用户</Button>
:
<FocusButton is_watch={focusStatus} id={login} />
<Button type="default">当前用户</Button>
:
<FocusButton is_watch={focusStatus} id={login} successFunc={successFunc}/>
}
</div>
</Div>

View File

@ -0,0 +1,26 @@
import React, { useState } from 'react';
import styled from 'styled-components';
import Modals from './Modals';
const ALink = styled.a`{
border:1px solid #F73030;
color:#F73030!important;
height:30px;
line-height:30px;
padding:0px 15px;
border-radius:5px;
}`
function LeaveTeam({teamID , onOk }){
const [ visible , setVisible ] = useState(false);
return(
<React.Fragment>
<ALink onClick={()=>setVisible(true)}>离开团队</ALink>
<Modals visible={visible} okText={"确定"} cancelText={"取消"} onCancel={()=>setVisible(false)} onOk={()=>onOk(teamID)}>
<p className="font-16 edu-txt-center">确定要离开当前团队吗</p>
</Modals>
</React.Fragment>
)
}
export default LeaveTeam;

View File

@ -0,0 +1,21 @@
import React from 'react';
import { Modal } from 'antd';
function Modals({visible , okText , cancelText , onOk , onCancel , children}){
return(
<Modal
visible={visible}
okText={okText}
onCancel={onCancel}
onOk={onOk}
cancelText={cancelText}
title={"提示"}
closable={false}
centered
>
{children}
</Modal>
)
}
export default Modals;

View File

@ -2,7 +2,7 @@ import React from 'react';
import Cards from '../../Component/MemberCards';
import Nodata from '../../Nodata';
export default (({ data , current_user }) => {
export default (({ data , current_user , successFunc }) => {
return (
data && data.length > 0 ?
<div className="MemberBoxThree">
@ -16,6 +16,7 @@ export default (({ data , current_user }) => {
focusStatus={item.user.watched}
is_current_user={current_user && item.user.login === current_user.login}
login={item.user.login}
successFunc={successFunc}
/>
)
})

View File

@ -18,8 +18,7 @@ const Div = styled.div`{
}
}`
const Imgs = styled.img`{
width:30px;
height:30px;
width:60px;
margin-right:12px;
border-radius:50%;
}`

View File

@ -130,7 +130,7 @@ export default ((props) => {
<WhiteBack>
<Tabs nav={['团队成员', '团队项目']} index={nav} onChange={setNav}>
{
nav === "0" ? <Memberlist data={members} current_user={props.current_user}/> : <Grouplist projects={projects}/>
nav === "0" ? <Memberlist data={members} current_user={props.current_user} successFunc={()=>getMember( OIdentifier, groupId, page )}/> : <Grouplist projects={projects}/>
}
</Tabs>
{

View File

@ -1,10 +1,11 @@
import React, { useState, useEffect } from 'react';
import { WhiteBack, Blueline, AlignCenter, FlexAJ } from '../../../Component/layout';
import { WhiteBack , FlexAJ } from '../../../Component/layout';
import { Menu, Table, Pagination, Icon, Tooltip, Popconfirm, Dropdown, Spin } from 'antd';
import Sort from '../../../Component/Sort';
import Title from '../../../Component/Title';
import Search from '../../../Component/Search';
import SearchUser from '../../../Component/SearchUser';
import AddMember from '../../../Component/AddMember';
import styled from 'styled-components';
import { getImageUrl } from 'educoder';
import axios from 'axios';
@ -14,18 +15,15 @@ const Img = styled.img`{
height:30px;
border-radius:50%;
}`
const limit = 15
export default ((props) => {
const [login, setAddUserLogin] = useState(undefined);
const [page, setPage] = useState(1);
const [limit, setLimit] = useState(15);
const [total, setTotal] = useState(0);
const [data, setMembers] = useState(undefined);
const [isSpin, setIsSpin] = useState(false);
const [identify, setIdentify] = useState(undefined);
const [search, setQuery] = useState(undefined);
const { OIdentifier, groupId } = props.match.params;
const { current_user } = props;
useEffect(() => {
getMember()
@ -34,69 +32,26 @@ export default ((props) => {
function getMember() {
setIsSpin(true)
const url = `/organizations/${OIdentifier}/teams/${groupId}/team_users.json`;
axios
.get(url, {
params: {
page,
search,
identify,
limit
},
})
.then((result) => {
if (result && result.data) {
setMembers(result.data.team_users)
setTotal(result.data.total_count)
}
}).catch((error) => { });
axios.get(url, {
params: {
page,
search,
identify,
limit
},
})
.then((result) => {
if (result && result.data) {
setMembers(result.data.team_users)
setTotal(result.data.total_count)
}
}).catch((error) => { });
setIsSpin(false)
};
// Login
function getUser(login) {
setAddUserLogin(login)
}
function addUser() {
setIsSpin(true)
const url = `/organizations/${OIdentifier}/teams/${groupId}/team_users.json`;
if (login) {
axios.post(url, {
username: login
})
.then((result) => {
if (result && result.data) {
setPage(1)
setQuery(undefined)
setIdentify(undefined)
this.getMember();
}
})
.catch((error) => { });
}
setIsSpin(false)
}
//
function onSearch(value) {
setQuery(value)
}
//
function onSelectMenu(e) {
let select_role = e.key
setPage(1)
setQuery(undefined)
setIdentify(select_role === "all" ? undefined : select_role)
}
//
function ChangePage(page) {
setPage(page);
}
//
function removeUser(username) {
setIsSpin(true)
setIsSpin(true);
const url = `/organizations/${OIdentifier}/teams/${groupId}/team_users/${username}.json`;
if (username) {
axios.delete(url)
@ -105,7 +60,7 @@ export default ((props) => {
setPage(1)
setQuery(undefined)
setIdentify(undefined)
this.getMember();
getMember();
}
})
.catch((error) => { });
@ -113,112 +68,6 @@ export default ((props) => {
setIsSpin(false)
}
const MENU_LIST = [
{
id: "Manager",
name: "管理员",
desc: "拥有仓库设置功能、代码库读、写操作"
},
{
id: "Developer",
name: "开发者",
desc: "只拥有代码库读、写操作"
},
{
id: "Reporter",
name: "报告者",
desc: "只拥有代码库读操作"
},
];
const menu = (
<Menu onSelect={onSelectMenu}>
<Menu.Item key="all">全部</Menu.Item>
{MENU_LIST.map((item, key) => {
return (
<Menu.Item
key={item.id}
value={item.id}
>
{item.name}
</Menu.Item>
);
})}
</Menu>
)
const roleTitle = (
<div><span className="mr3">角色</span>
<Tooltip placement='bottom' title=
{
<div>
{MENU_LIST.map((item, key) => {
return (
<div className="mb3">{item.name}{item.desc}</div>
);
})}
</div>
}
>
<Icon type="question-circle"></Icon>
</Tooltip>
</div>
);
function get_color(role) {
if (role === "manager") {
return "text-green";
} else if (role === "developer") {
return "text-primary";
} else {
return "text-yellow";
}
};
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>
);
//
function changeOperaiton(e, id) {
console.log(e)
};
const member_roles = (item) => {
const operation = MENU_LIST.filter((i) => i.id === item.identify);
return (
<span>
{operation && operation[0] ?
<span>
{current_user && current_user.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>
: ""
}
</span>
);
};
const columns = [
{
title: '头像',
@ -251,12 +100,6 @@ export default ((props) => {
)
}
},
{
title: roleTitle,
dataIndex: 'role',
width: "20%",
render: (value, item) => member_roles(item.user),
},
{
title: '操作',
dataIndex: 'operation',
@ -268,29 +111,46 @@ export default ((props) => {
okText="确认"
cancelText="取消"
>
<a className="color-grey-8" href="#">移除成员</a>
<a className="color-grey-8">移除成员</a>
</Popconfirm>
}
}
]
function getID(id){
addUser(id);
}
function addUser(l) {
setIsSpin(true);
const url = `/organizations/${OIdentifier}/teams/${groupId}/team_users.json`;
if (l) {
axios.post(url, {
username: l
}).then((result) => {
if (result && result.data) {
setPage(1)
setQuery(undefined)
setIdentify(undefined)
getMember();
}
})
.catch((error) => { });
}
setIsSpin(false)
}
return (
<Spin spinning={isSpin}>
<WhiteBack style={{minHeight:"400px"}}>
<Title>
<span>团队成员管理</span>
<AlignCenter>
<SearchUser getUser={getUser} />
<Blueline className="ml30" onClick={addUser}>+&nbsp;添加用户</Blueline>
</AlignCenter>
<AddMember getID={getID}/>
</Title>
<FlexAJ className="padding20-30">
<div style={{ width: "580px" }}>
<Search placeholder="输入用户名或邮箱、团队名搜索" value={search} onSearch={onSearch} />
<Search placeholder="输入用户名或邮箱、团队名搜索" value={search} onSearch={(value)=>setQuery(value)} />
</div>
<Sort menu={menu}>
<a className="color-blue">角色筛选<i className="iconfont icon-sanjiaoxing-down ml3 font-14"></i></a>
</Sort>
</FlexAJ>
<div className="pl30 pr30 pb30">
<Table
@ -303,7 +163,7 @@ export default ((props) => {
{
total > limit ?
<div className="edu-txt-center mt30 mb20">
<Pagination simple defaultCurrent={page} total={total} pageSize={limit} onChange={ChangePage}></Pagination>
<Pagination simple defaultCurrent={page} total={total} pageSize={limit} onChange={(page)=>setPage(page)}></Pagination>
</div>
: ""
}

View File

@ -3,58 +3,37 @@ import axios from 'axios';
import { AutoComplete, Pagination, List, Popconfirm, Dropdown, Spin } from 'antd';
import { WhiteBack, Blueline, FlexAJ, GroupProjectBackgroup, Greenline, Redline } from '../../../Component/layout';
import Title from '../../../Component/Title';
const faker_projects = [
{
id: 2,
project: {
owner_name: "ceshi_org_1",
name: "jajaj0",
identifier: "ssjsksjsk"
}
},
{
id: 3,
project: {
owner_name: "sylor_test",
name: "sylor_test",
identifier: "sylor_test"
}
}
]
const { Option } = AutoComplete;
const limit = 15;
// 使faker
function GroupProjectSetting(props) {
const [isSpin, setIsSpin] = useState(false);
const [projects, setProjects] = useState(undefined);
const [page, setPage] = useState(1);
const [limit, setLimit] = useState(15);
const [total, setTotal] = useState(0);
const [search, setQuery] = useState(undefined);
const [repo_name, setRepoName] = useState(undefined);
const [ search , setSearch ] = useState("");
const [ optionsSource , setOptionsSource ] = useState(undefined);
const { OIdentifier, groupId } = props.match.params;
useEffect(() => {
get_project()
}, [page, search])
}, [page])
function get_project() {
setIsSpin(true)
setIsSpin(true);
const url = `/organizations/${OIdentifier}/teams/${groupId}/team_projects.json`;
axios
.get(url, {
params: {
page,
search,
limit
},
})
.then((result) => {
if (result && result.data && result.data.team_projects.length > 0) {
setProjects(result.data.team_projects)
setTotal(result.data.total_count)
} else {
setProjects(faker_projects)
}
}).catch((error) => { });
axios.get(url, {
params: {page,limit},
})
.then((result) => {
if (result && result.data) {
setProjects(result.data.team_projects)
setTotal(result.data.total_count)
}
}).catch((error) => { });
setIsSpin(false)
}
@ -70,7 +49,6 @@ function GroupProjectSetting(props) {
.then((result) => {
if (result && result.data.status > -1) {
setPage(1)
setQuery(undefined)
get_project()
}
}).catch((error) => { });
@ -87,35 +65,80 @@ function GroupProjectSetting(props) {
//
function addSingleProject(){
setIsSpin(true)
const url = `/organizations/${OIdentifier}/teams/${groupId}/team_projects.json`;
axios.post(url, {repo_name: repo_name})
if(repo_name){
setIsSpin(true);
const url = `/organizations/${OIdentifier}/teams/${groupId}/team_projects.json`;
axios.post(url, {repo_name})
.then((result) => {
if (result && result.data.id) {
setPage(1)
setQuery(undefined)
get_project()
}
}).catch((error) => { });
setIsSpin(false)
setIsSpin(false)
}).catch((error) => {setIsSpin(false)});
}else{
props.showNotification("请选择要添加的项目!");
}
}
//
useEffect(()=>{
const url = `/organizations/${OIdentifier}/projects/search.json`;
axios.get(url,{
params:{
search
}
}).then(result=>{
if(result && result.data){
setOptions(result.data.projects);
}
}).catch(error=>{})
},[search])
function setOptions(data){
const s = data && data.map((item, key) => {
return (
<Option
key={key}
value={`${item.id}`}
searchValue={`${item.name}`}
>
{item.name}
</Option>
);
});
setOptionsSource(s);
}
function changeInput(value){
let s = value || "";
setSearch(s);
}
function selectInput(value,e){
setRepoName(value);
}
return (
<Spin spinning={isSpin}>
<WhiteBack className="mb30">
<Title>
<span>团队项目管理</span>
<FlexAJ style={{width:"100%"}}>
<span>团队项目管理</span>
<div>
<AutoComplete
style={{ width: 300 }}
placeholder="搜索项目..."
onChange={changeInput}
onSelect={selectInput}
allowClear
>
{optionsSource}
</AutoComplete>
<Blueline className="ml30" onClick={()=>addSingleProject()}>+&nbsp;添加项目</Blueline>
</div>
</FlexAJ>
</Title>
<FlexAJ className="padding20-30">
{/* <FlexAJ className="padding20-30">
<GroupProjectBackgroup>
<FlexAJ>
<div>
<AutoComplete
style={{ width: 300 }}
placeholder="搜索项目..."
/>
<Blueline className="ml30" onClick={()=>addSingleProject()}>+&nbsp;添加项目</Blueline>
</div>
<div>
<Popconfirm
title="确认添加所有成员的项目吗?"
@ -134,11 +157,11 @@ function GroupProjectSetting(props) {
>
<Redline bold className="ml30">移除所有</Redline>
</Popconfirm>
</div>
</div>
</FlexAJ>
</GroupProjectBackgroup>
</FlexAJ>
<div className="padding20-30"style={{paddingTop:"0px"}}>
</FlexAJ>*/}
<div className="padding20-30"style={{paddingTop:"0px",minHeight:"400px"}}>
<List
itemLayout="horizontal"
dataSource={projects}
@ -151,7 +174,7 @@ function GroupProjectSetting(props) {
okText="确认"
cancelText="取消"
>
<a className="color-red" href="#">移除</a>
<a className="color-red">移除</a>
</Popconfirm>
}
>
@ -162,13 +185,12 @@ function GroupProjectSetting(props) {
)}
/>
</div>
{
total > limit ?
<div className="edu-txt-center mt30 mb20">
<Pagination simple defaultCurrent={page} total={total} pageSize={limit} onChange={ChangePage}></Pagination>
</div>
: ""
<div className="edu-txt-center mt30 mb20">
<Pagination simple defaultCurrent={page} total={total} pageSize={limit} onChange={ChangePage}></Pagination>
</div>
: ""
}
</WhiteBack>
</Spin>

View File

@ -49,7 +49,7 @@ function RightBox({ OIdentifier , history }) {
function getMember(iden){
const url = `/organizations/${iden}/organization_users.json`;
axios.get(url).then(result=>{
axios.get(url,{params:{limit:5}}).then(result=>{
if(result && result.data){
setMemberData(result.data);
}
@ -57,7 +57,7 @@ function RightBox({ OIdentifier , history }) {
}
function getGroup(iden){
const url = `/organizations/${iden}/teams.json`;
axios.get(url).then(result=>{
axios.get(url,{params:{limit:5}}).then(result=>{
if(result && result.data){
setGroupData(result.data);
}

View File

@ -5,6 +5,8 @@ import Title from '../../Component/Title';
import styled from 'styled-components';
import UploadImage from '../Component/UploadImage';
import axios from 'axios';
import Modals from '../Component/Modals';
import { getImageUrl } from 'educoder';
const TextArea = Input.TextArea;
@ -22,6 +24,7 @@ export default Form.create()(
const [ imageFlag , setImageFlag ] = useState(false);
const [ password , setPassword ] = useState(undefined);
const [ passwordFlag , setPasswordFlag ] = useState(false);
const [ visible , setVisible ] = useState(false);
const { getFieldDecorator , validateFields , setFieldsValue } = form;
useEffect(()=>{
@ -74,20 +77,24 @@ export default Form.create()(
function deleteOrganize(){
if(!password){
setPasswordFlag(true);
return
}else{
setPasswordFlag(false);
const url = `/organizations/${organizeDetail.id}.json`;
axios.delete(url,{
params:{ password }
}).then(result=>{
if(result && result.data){
//
history.push(`/users/${current_user && current_user.login}/organizes`);
}
})
setVisible(true);
}
}
function onOk(password){
const url = `/organizations/${organizeDetail.id}.json`;
axios.delete(url,{
params:{ password }
}).then(result=>{
if(result && result.data){
//
history.push(`/users/${current_user && current_user.login}/organizes`);
}
})
setVisible(false);
}
return(
<div>
<WhiteBack>
@ -159,6 +166,9 @@ export default Form.create()(
{ passwordFlag && <span className="color-red ml10">请输入密码</span>}
</div>
<a className="warningDelete" onClick={deleteOrganize}>删除组织</a>
<Modals visible={visible} okText={"确定"} cancelText={"取消"} onCancel={()=>setVisible(false)} onOk={()=>onOk(password)}>
<p className="font-16 edu-txt-center">确定要删除当前组织吗</p>
</Modals>
</FlexAJ>
</div>
</div>

View File

@ -1,9 +1,11 @@
import React , { useEffect , useState } from 'react';
import { WhiteBack , Banner , Blueline } from '../../Component/layout';
import styled from 'styled-components';
import Axios from 'axios';
import { Pagination , Popconfirm } from 'antd';
import axios from 'axios';
import { Pagination } from 'antd';
import { getImageUrl } from 'educoder';
import LeaveTeam from '../Component/LeaveTeam';
import { Link } from 'react-router-dom';
const SpanName = styled.span`{
font-size:16px;
@ -13,15 +15,6 @@ const SpanFoot = styled.span`{
margin-right:5px;
color:#333
}`
const ALink = styled.a`{
border:1px solid #F73030;
color:#F73030!important;
height:32px;
line-height:30px;
display:block;
padding:0px 15px;
border-radius:2px;
}`
const ImgContent = styled.img`{
height:44px;
width:44px;
@ -33,19 +26,18 @@ function TeamSettingGroup({organizeDetail,history}){
const [ list ,setList ] = useState(undefined);
const [ page ,setPage ] = useState(1);
const [ total ,setTotal ] = useState(0);
const [ search ,setSearch ] = useState(undefined);
useEffect(()=>{
if(organizeDetail){
getData();
}
},[organizeDetail,page,search]);
},[organizeDetail,page]);
function getData(){
const url = `/organizations/${organizeDetail.id}/teams.json`;
Axios.get(url,{
axios.get(url,{
params:{
page,limit,search
page,limit
}
}).then(result=>{
if(result && result.data){
@ -58,7 +50,7 @@ function TeamSettingGroup({organizeDetail,history}){
//
function removeMember(teamid){
const url = `/organizations/${organizeDetail.id}/teams/${teamid}/team_users/quit.json`;
Axios.delete(url).then(result=>{
axios.delete(url).then(result=>{
if(result && result.data){
getData();
}
@ -81,10 +73,10 @@ function TeamSettingGroup({organizeDetail,history}){
return(
<div>
<p className="g-head">
<SpanName>{item.name}</SpanName>
<Link to={`/organize/${organizeDetail && organizeDetail.name}/group/${item.id}`}><SpanName>{item.name}</SpanName></Link>
<span className="df">
{ item.is_member &&
<Popconfirm title="确定离开团队?" okText="是" cancelText="否" onConfirm={()=>removeMember(item.id)}><ALink>离开团队</ALink></Popconfirm>
<LeaveTeam teamID={item.id} onOk={removeMember}/>
}
{ item.is_admin && <Blueline className="ml15" onClick={()=>toGroupSetting(item.id)}>团队设置</Blueline> }
</span>

View File

@ -51,95 +51,60 @@ export default (({organizeDetail})=>{
}).catch(error=>{})
}
// ID便
function getUser(login){
serChoiceId(login);
}
//
function ChangePage(page){
setPage(page);
}
const menu=(
<Menu>
<Menu.Item key="all">全部</Menu.Item>
<Menu.Item key="Manager">管理员</Menu.Item>
<Menu.Item key="Developer">开发者</Menu.Item>
<Menu.Item key="Reporter">报告者</Menu.Item>
</Menu>
)
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',
dataIndex: 'user',
width:"5%",
render:(value,item)=>{
render:(value)=>{
return(
item.user && <Img src={getImageUrl('images/'+item.user.image_url)}></Img>
value && <Img src={getImageUrl('images/'+value.image_url)}></Img>
)
}
},
{
title: '用户名',
dataIndex: 'name',
dataIndex: 'user',
width:"15%",
render:(value,item)=>{
return(
item.user && item.user.name
)
return value && value.name
}
},
{
title: '邮箱',
dataIndex: 'mail',
dataIndex: 'user',
width:"25%",
align:"left",
render:(value,item)=>{
return(
item.user && item.user.mail
)
render:(value)=>{
return value && value.mail
}
},
{
title: '所属团队',
dataIndex: 'team',
dataIndex: 'team_names',
width:"20%",
render:(value,item)=>{
return item.team_names && item.team_names.length > 0 && item.team_names[0]
render:(value)=>{
let array = value && value.length > 0 && value.map((i,k)=>{
return (i+",")
})
console.log(array && array[0]);
return array && array[0].substring(0,array[0].length-1);
}
},
// {
// title: roleTitle,
// dataIndex: 'role',
// width:"20%",
// render:(value,item)=>{
// return(
// item.role
// )
// }
// },
{
title: '操作',
dataIndex: 'operation',
width:"15%",
render:(value,item)=>{
return (organizeDetail && organizeDetail.is_admin ? "" :
<Popconfirm title="是否将此成员移出组织?" okText={"是"} cancelText={"否"} onConfirm={()=>deleteMember(item.login)}><a className="color-grey-8">移除成员</a></Popconfirm>
let c_isAdmin = organizeDetail && organizeDetail.is_admin;
let last = (data && data.length === 1) && (item.team_names && item.team_names.length === 1 && item.team_names[0]==="Owners");
return (
c_isAdmin && !last && <Popconfirm title="是否将此成员移出组织?" okText={"是"} cancelText={"否"} onConfirm={()=>deleteMember(item.user && item.user.login)}><a className="color-grey-8">移除成员</a></Popconfirm>
)
}
}
@ -149,7 +114,7 @@ export default (({organizeDetail})=>{
const url = `/organizations/${organizeDetail && organizeDetail.id}/organization_users/${login}.json`;
axios.delete(url).then(result=>{
if(result && result.data){
getData();
}
}).catch(error=>{})
}

View File

@ -79,7 +79,7 @@ function Detail(props){
<Cards
src={`/organize/${detail.name}`}
title={detail.name}
desc={detail.description}
desc={!buttonflag && detail.description}
img={detail.avatar_url}
rightBtn={
<React.Fragment>

View File

@ -6,6 +6,7 @@ import { getImageUrl } from 'educoder';
import Nodata from '../Nodata';
import { Pagination } from 'antd';
import { Link } from 'react-router-dom';
import LeaveTeam from './Component/LeaveTeam';
const SpanFoot = styled.span`{
margin-right:5px;
@ -66,10 +67,10 @@ function TeamGroup({organizeDetail,current_user}){
{
list.map((item,key)=>{
return(
<div>
<div key={key}>
<p className="g-head">
<Link to={`/organize/${organizeDetail.name}/group/${item.id}`} className="color-grey-3 font-16">{item.name}</Link>
{item.is_member && <ALink onClick={()=>outTeam(item.id)}>离开团队</ALink>}
{item.is_member && <LeaveTeam teamID={item.id} onOk={outTeam}/>}
</p>
<div className="g-body">
{

View File

@ -1,23 +1,27 @@
import React ,{ useEffect , useState } from 'react';
import { Banner } from '../Component/layout';
import { Banner , WhiteBack } from '../Component/layout';
import Cards from '../Component/MemberCards';
import axios from 'axios';
import Nodata from '../Nodata';
import { Pagination } from 'antd';
const limit = 15;
function TeamMember({organizeDetail,current_user}){
const [ page , setPage ] = useState(1);
const [ total , setTotal ] = useState(0);
const [ list , setList ] = useState(undefined);
useEffect(()=>{
if(organizeDetail){
getData();
}
},[organizeDetail]);
},[organizeDetail,page]);
function getData(){
const url = `/organizations/${organizeDetail.id}/organization_users.json`;
axios.get(url).then(result=>{
axios.get(url,{
page,limit
}).then(result=>{
if(result && result.data){
setList(result.data.organization_users);
setTotal(result.data.total_count);
@ -26,14 +30,13 @@ function TeamMember({organizeDetail,current_user}){
}
return(
<div>
<WhiteBack style={{marginBottom:"30px"}}>
<Banner>组织成员</Banner>
{
list && list.length > 0 ?
<div className="memberBox">
{
list.map((item,key)=>{
console.log(current_user);
return(
item.user && <Cards
img={item.user.image_url}
@ -41,6 +44,8 @@ function TeamMember({organizeDetail,current_user}){
time={item.created_at}
focusStatus={item.user.watched}
is_current_user={current_user && current_user.login === item.user.login}
login={item.user && item.user.login}
successFunc={getData}
/>
)
})
@ -48,6 +53,12 @@ function TeamMember({organizeDetail,current_user}){
</div>
:<Nodata _html="暂无数据"/>
}
</div>
{
total >limit &&
<div className="mt20 pb20 edu-txt-center">
<Pagination simple current={page} pageSize={limit} total={total} onChange={(page)=>setPage(page)}/>
</div>
}
</WhiteBack>
)
}export default TeamMember
}export default TeamMember;

View File

@ -1,80 +1,44 @@
import React, { Component } from "react";
import React , {useState} from "react";
import axios from "axios";
import { Button } from "antd";
import "./list.css";
class FocusButton extends Component {
constructor(props) {
super(props);
this.state = {
is_watch: false,
id: "",
isSpin: false,
fontClass: "font-12",
starText: "关注",
is_block: false
};
}
componentDidMount = () => {
this.set_watch();
};
set_watch = () => {
this.setState({
is_watch: this.props.is_watch,
id: this.props.id,
isSpin: false,
fontClass: this.props.fontClass ? this.props.fontClass : "font-12",
starText: this.props.starText ? this.props.starText : "关注",
is_block: this.props.is_block === undefined ? false : this.props.is_block
});
};
function FocusButton({is_watch , fontClass, starText, is_block , id , successFunc}){
const [ isSpin , setIsSpin ] = useState(false);
// 关注和取消关注
focusFunc = (flag) => {
const { id } = this.state;
this.setState({ isSpin: true });
function focusFunc(flag){
setIsSpin(true);
axios({
method: flag ? "delete" : "post",
url: `/watchers/${flag ? "unfollow" : "follow"}.json`,
params: {
target_type: "user",
id: id,
id,
},
}).then((result) => {
if (result && result.data.status === 0) {
successFunc && successFunc();
}
setIsSpin(false);
})
.then((result) => {
if (result && result.data.status === 0) {
this.setState({
is_watch: result.data.watched,
isSpin: false,
});
}
})
.catch((error) => {
this.setState({ isSpin: false })
});
.catch((error) => {setIsSpin(false);});
};
render() {
const { is_watch, isSpin, fontClass, starText, is_block } = this.state;
return (
<Button type={is_watch ? "default" : "primary"} ghost={!is_watch} block={is_block} loading={isSpin} onClick={() => this.focusFunc(is_watch)}>
{is_watch ? (
return (
<Button type={is_watch ? "default" : "primary"} ghost={!is_watch} block={is_block} loading={isSpin} onClick={() => focusFunc(is_watch)}>
{is_watch ? (
<span className="">
<i className="iconfont icon-shixing font-15 text-yellow mr-4"></i>
<span className={fontClass || "font-12"}>已关注</span>
</span>
) : (
<span className="">
<i className="iconfont icon-shixing font-15 text-yellow mr-4"></i>
<span className={fontClass}>已关注</span>
<i className="iconfont icon-kongxing font-15"></i>
<span className={fontClass}>{starText || "关注"}</span>
</span>
) : (
<span className="">
<i className="iconfont icon-kongxing font-15"></i>
<span className={fontClass}>{starText}</span>
</span>
)}
</Button>
);
}
)}
</Button>
);
}
export default FocusButton;