add project watch/praise/fork users list

This commit is contained in:
sylor_huang@126.com 2020-05-18 16:46:51 +08:00
parent fc33fd0a2f
commit b5dca5a1aa
9 changed files with 581 additions and 5 deletions

View File

@ -117,6 +117,18 @@ const MilepostDetail = Loadable({
loader: () => import('../Order/MilepostDetail'), loader: () => import('../Order/MilepostDetail'),
loading: Loading, loading: Loading,
}) })
const WatchUsers = Loadable({
loader: () => import('../UsersList/watch_users'),
loading: Loading,
})
const PraiseUsers = Loadable({
loader: () => import('../UsersList/praise_users'),
loading: Loading,
})
const ForkUsers = Loadable({
loader: () => import('../UsersList/fork_users'),
loading: Loading,
})
const TrendsIndex = Loadable({ const TrendsIndex = Loadable({
@ -200,9 +212,14 @@ class Detail extends Component{
// 关注和取消关注 // 关注和取消关注
focusFunc =(flag)=>{ focusFunc =(flag)=>{
const { project_id } = this.state; const { project_id } = this.state;
axios({ axios({
method: flag? 'delete' : 'post', method: flag? 'delete' : 'post',
url: `/projects/${project_id}/watchers/${flag? 'unfollow' : 'follow'}.json` url: `/watchers/${flag? 'unfollow' : 'follow'}.json`,
params: {
target_type: "project",
id: project_id
}
}) })
.then(result => { .then(result => {
if(result && result.data.status === 0){ if(result && result.data.status === 0){
@ -363,19 +380,28 @@ class Detail extends Component{
<img src={watched ? img_focused : img_focus} alt="" width="14px"/> <img src={watched ? img_focused : img_focus} alt="" width="14px"/>
{watched ? '取消关注':'关注'} {watched ? '取消关注':'关注'}
</a> </a>
<span className="detail_tag_btn_count">{watchers_count}</span> <Link className="detail_tag_btn_count" to={{pathname:`/projects/${projectsId}/watch_users`, state}}>
{watchers_count}
</Link>
{/* <span className="detail_tag_btn_count">{watchers_count}</span> */}
</span> </span>
<span className="detail_tag_btn"> <span className="detail_tag_btn">
<a className="detail_tag_btn_name" onClick={()=>this.pariseFunc(praised)}> <a className="detail_tag_btn_name" onClick={()=>this.pariseFunc(praised)}>
<img src={praised ? img_parised : img_parise} width="13px" alt=""/> <img src={praised ? img_parised : img_parise} width="13px" alt=""/>
{praised ? '取消点赞':'点赞'} {praised ? '取消点赞':'点赞'}
</a> </a>
<span className="detail_tag_btn_count">{praises_count}</span> <Link className="detail_tag_btn_count" to={{pathname:`/projects/${projectsId}/praise_users`,state}}>
{praises_count}
</Link>
{/* <span className="detail_tag_btn_count">{praises_count}</span> */}
</span> </span>
<span className="detail_tag_btn"> <span className="detail_tag_btn">
<a className="detail_tag_btn_name" onClick={this.forkFunc}> <a className="detail_tag_btn_name" onClick={this.forkFunc}>
<img src={img_fork} alt="" width="10px"/>Fork</a> <img src={img_fork} alt="" width="10px"/>Fork</a>
<span className="detail_tag_btn_count">{forked_count}</span> <Link className="detail_tag_btn_count" to={{pathname:`/projects/${projectsId}/fork_users`,state}}>
{forked_count}
</Link>
{/* <span className="detail_tag_btn_count">{forked_count}</span> */}
</span> </span>
</span> </span>
</div> </div>
@ -539,6 +565,21 @@ class Detail extends Component{
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state}/>) (props) => (<CoderRootIndex {...this.props} {...props} {...this.state}/>)
} }
></Route> ></Route>
<Route path="/projects/:projectsId/watch_users"
render={
(props) => (<WatchUsers {...this.props} {...props} {...this.state}/>)
}
></Route>
<Route path="/projects/:projectsId/praise_users"
render={
(props) => (<PraiseUsers {...this.props} {...props} {...this.state}/>)
}
></Route>
<Route path="/projects/:projectsId/fork_users"
render={
(props) => (<ForkUsers {...this.props} {...props} {...this.state}/>)
}
></Route>
<Route path="/projects/:projectsId" <Route path="/projects/:projectsId"
render={ render={
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state}/>) (props) => (<CoderRootIndex {...this.props} {...props} {...this.state}/>)

View File

@ -308,10 +308,14 @@
} }
.detail_tag_btn_count{ .detail_tag_btn_count{
padding:0px 10px; padding:0px 10px;
color: #fff; color: #fff !important;
background: #1C91FF; background: #1C91FF;
border-radius: 0px 4px 4px 0px; border-radius: 0px 4px 4px 0px;
} }
.detail_tag_btn_count:hover{
color: #1C91FF !important;
background: #fff;
}
/* 详情-代码 */ /* 详情-代码 */
.branch-wrapper{ .branch-wrapper{
border:1px solid #eee; border:1px solid #eee;

View File

@ -0,0 +1,147 @@
import React, { Component } from "react";
import { Link } from "react-router-dom";
import axios from "axios";
import { getImageUrl } from "educoder";
import { Spin, Pagination } from "antd";
import "./list.css";
import NoneData from "../Nodata";
import FocusButton from "./focus_button";
class CommonUsers extends Component {
constructor(props) {
super(props);
this.state = {
user_type: this.props.user_type,
type_title: this.props.type_title,
project_id: this.props.project_id,
users: null,
count: 0,
limit: 20,
page: 1,
isSpin: false,
};
}
componentDidMount = () => {
this.getUsersList();
};
getUsersList = (page, limit) => {
this.setState({
isSpin: true,
});
const { user_type, project_id } = this.state;
const url = `/projects/${project_id}/${user_type}.json`;
axios
.get(url, {
params: {
page,
limit,
},
})
.then((result) => {
if (result) {
this.setState({
count: result.data.count,
users: result.data.users,
isSpin: false,
});
}
})
.catch((error) => {
console.log(error);
});
};
// 翻页
ChangePage = (page) => {
this.setState({
page,
isSpin: true,
});
const { limit } = this.state;
this.getUsersList(page, limit);
};
render() {
const { users, count, page, limit, isSpin, type_title } = this.state;
const Paginations = (
<React.Fragment>
{count > limit ? (
<div className="mt50 mb30 edu-txt-center">
<Pagination
simple
defaultCurrent={page}
total={count}
pageSize={limit}
onChange={this.ChangePage}
></Pagination>
</div>
) : (
""
)}
</React.Fragment>
);
const renderList = () => {
if (users && users.length > 0) {
return users.map((item, key) => {
return (
<div className="w-25 pull-left" key={key}>
<div className="pbt25 grid-item mlr10 border-b-line">
<div>
<Link
to={`/users/${item.login}/projects`}
className="show-user-link"
>
<img
className="avatar-60"
src={getImageUrl(`images/${item.image_url}`)}
alt=""
/>
</Link>
</div>
<div className="ml12">
<div>
<Link
to={`/users/${item.login}/projects`}
className="font-16 text-primary hide-1 task-hide max-w-200"
>
{item.name}
</Link>
</div>
<div className="font-12 text-gray grid-item pb5">
<i className="iconfont icon-shijian user-join-time"></i>
<span className="ml4">加入时间{item.format_time}</span>
</div>
<FocusButton is_watch={item.is_watch} id={item.login} />
</div>
</div>
</div>
);
});
}
};
return (
<div className="background-g pbt15">
<div className="main background-f">
<div className="plr-20 user-list-items">
<div className="font-18 pb-10 border-b-line">{type_title}</div>
<Spin spinning={isSpin}>
<div className="w-100 inline-block">
{count === 0 ? (
<NoneData _html="暂时还没有相关数据哦!" />
) : (
renderList()
)}
</div>
</Spin>
{Paginations}
</div>
</div>
</div>
);
}
}
export default CommonUsers;

View File

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

View File

@ -0,0 +1,144 @@
import React, { Component } from "react";
import { Link } from "react-router-dom";
import axios from "axios";
import { getImageUrl } from "educoder";
import { Spin, Pagination } from "antd";
import "./list.css";
import NoneData from "../Nodata";
// import FocusButton from "./focus_button";
class ForkUsers extends Component {
constructor(props) {
super(props);
this.state = {
users: null,
count: 0,
limit: 20,
page: 1,
isSpin: false,
};
}
componentDidMount = () => {
this.getUsersList();
};
getUsersList = (page, limit) => {
this.setState({
isSpin: true,
});
const { projectsId } = this.props.match.params;
const url = `/projects/${projectsId}/fork_users.json`;
axios
.get(url, {
params: {
page,
limit,
},
})
.then((result) => {
if (result) {
this.setState({
count: result.data.count,
users: result.data.users,
isSpin: false,
});
}
})
.catch((error) => {
console.log(error);
});
};
// 翻页
ChangePage = (page) => {
this.setState({
page,
isSpin: true,
});
const { limit } = this.state;
this.getUsersList(page, limit);
};
render() {
const { users, count, page, limit, isSpin } = this.state;
const Paginations = (
<React.Fragment>
{count > limit ? (
<div className="mt50 mb30 edu-txt-center">
<Pagination
simple
defaultCurrent={page}
total={count}
pageSize={limit}
onChange={this.ChangePage}
></Pagination>
</div>
) : (
""
)}
</React.Fragment>
);
const renderList = () => {
if (users && users.length > 0) {
return users.map((item, key) => {
return (
<div className="w-25 pull-left" key={key}>
<div className="pbt25 grid-item mlr10 border-b-line">
<div>
<Link
to={`/users/${item.login}/projects`}
className="show-user-link"
>
<img
className="avatar-60"
src={getImageUrl(`images/${item.image_url}`)}
alt=""
/>
</Link>
</div>
<div className="ml12">
<div>
<Link
to={`/users/${item.login}/projects`}
className="font-16 text-primary hide-1 task-hide max-w-200"
>
{item.name}
</Link>
</div>
<div className="font-12 text-gray grid-item pb5">
<i className="iconfont icon-shijian user-join-time"></i>
<span className="ml4">fork时间{item.format_time}</span>
</div>
{/* <FocusButton is_watch={item.is_watch} id={item.login} /> */}
</div>
</div>
</div>
);
});
}
};
return (
<div className="background-g pbt15">
<div className="main background-f">
<div className="plr-20 user-list-items">
<div className="font-18 pb-10 border-b-line">Fork列表</div>
<Spin spinning={isSpin}>
<div className="w-100 inline-block">
{count === 0 ? (
<NoneData _html="暂时还没有相关数据哦!" />
) : (
renderList()
)}
</div>
</Spin>
{Paginations}
</div>
</div>
</div>
);
}
}
export default ForkUsers;

View File

@ -0,0 +1,100 @@
.background-f {
background: #fff;
}
.background-g {
background: rgb(234, 235, 236);
}
.pt-15 {
padding-top: 15px;
}
.mr-4{margin-right: 4px;}
.pb-10 {
padding-bottom: 10px;
}
.plr-20 {
padding: 0 20px;
}
.font-18 {
font-size: 18px;
font-weight: 600;
}
.font-12 {
font-size: 12px;
}
.font-15 {
font-size: 15px;
}
.border-b-line {
border-bottom: 1px solid #eee;
}
.list-item {
width: 100%;
}
.w-100 {
width: 100%;
}
.w-25 {
width: 25%;
}
.p-10 {
padding: 10px;
}
.pd-105 {
padding: 15px 10px;
}
.grid-item {
display: grid !important;
align-items: center;
grid-template-columns: max-content 1fr;
}
.avatar-60 {
height: 60px;
width: 60px;
border-radius: 50%;
}
.text-primary {
color: #5091ff !important;
}
.text-primary:hover {
color: #2878ff !important;
}
.text-yellow{
color: #FFA802 !important
}
.text-gray {
color: #888888;
}
.ml12 {
margin-left: 12px;
}
.user-join-time {
font-size: 14px !important;
color: #60b25e;
}
.btn-cir-grey {
background: rgba(250, 250, 250, 1);
color: #888888;
font-weight: normal;
border: 1px solid rgba(238, 238, 238, 1);
border-radius: 2px;
cursor: pointer;
}
.wd-75 {
width: 75px;
}
.pbt15 {
padding: 15px 0;
}
.pbt25 {
padding: 25px 0;
}
.mlr10 {
margin: 0 15px;
}
.user-list-items {
height: 100%;
width: 100%;
display: inline-block;
}
.max-w-200{max-width: 200px;}
.inline-block{display: inline-block;}

View File

@ -0,0 +1,32 @@
import React, { Component } from "react";
import CommonUsers from "./common_users"
class PraiseUsers extends Component {
constructor(props) {
super(props);
this.state = {
projectId: null
};
}
componentDidMount = () => {
this.get_projectId();
};
get_projectId = () => {
this.setState({
projectId: this.props.match.params.projectsId
})
};
render() {
const { projectId } = this.state;
return (
<div>
{projectId && <CommonUsers user_type="praise_users" type_title="点赞列表" project_id={projectId} />}
</div>
);
}
}
export default PraiseUsers;

View File

@ -0,0 +1,32 @@
import React, { Component } from "react";
import CommonUsers from "./common_users"
class WatchUsers extends Component {
constructor(props) {
super(props);
this.state = {
projectId: null
};
}
componentDidMount = () => {
this.get_projectId();
};
get_projectId = () => {
this.setState({
projectId: this.props.match.params.projectsId
})
};
render() {
const { projectId } = this.state;
return (
<div>
{projectId && <CommonUsers user_type="watch_users" type_title="关注列表" project_id={projectId} />}
</div>
);
}
}
export default WatchUsers;

View File

@ -921,6 +921,9 @@ class NewHeader extends Component {
</img> </img>
</a> </a>
<ul className="edu-menu-list" style={{ top: '46px', 'textAlign': 'center' }}> <ul className="edu-menu-list" style={{ top: '46px', 'textAlign': 'center' }}>
<li className="bor-bottom-greyE">
<a href="javascript:void(0)" className="fs12 hide-1 task-hide edu-txt-w80">{user.username}</a>
</li>
{ {
mygetHelmetapi2 && mygetHelmetapi2.new_course && mygetHelmetapi2.new_course.edit_account && mygetHelmetapi2 && mygetHelmetapi2.new_course && mygetHelmetapi2.new_course.edit_account &&
<li><a href={`${mygetHelmetapi2.new_course.edit_account}`} target="_blank">修改资料</a></li> <li><a href={`${mygetHelmetapi2.new_course.edit_account}`} target="_blank">修改资料</a></li>