forgeplus-react/src/forge/Main/Detail.js

625 lines
23 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { Component } from 'react';
import { Spin, Tooltip } from 'antd';
import { Link, Route, Switch } from 'react-router-dom';
import { Content } from '../Component/layout';
import '../css/index.scss'
import './list.css';
import Loadable from 'react-loadable';
import Loading from '../../Loading';
import axios from 'axios';
import img_1 from '../Images/1.png';
import img_2 from '../Images/2.png';
import img_3 from '../Images/3.png';
import img_6 from '../Images/6.png';
import img_7 from '../Images/7.png';
import img_parise from '../Images/parise.png';
import img_focus from '../Images/focus.png';
import img_parised from '../Images/parised.png';
import img_focused from '../Images/focused.png';
import img_fork from '../Images/fork.png';
import img_milepost from '../Images/milepost.png';
const Setting = Loadable({
loader: () => import('../Settings/Index'),
loading: Loading,
})
const TagList = Loadable({
loader: () => import('../Order/Tags'),
loading: Loading,
})
const OrderNew = Loadable({
loader: () => import('../Order/New'),
loading: Loading,
})
const OrderDetail = Loadable({
loader: () => import('../Order/Detail'),
loading: Loading,
})
const OrderIndex = Loadable({
loader: () => import('../Order/order'),
loading: Loading,
})
const CoderRootIndex = Loadable({
loader: () => import('./CoderRootIndex'),
loading: Loading,
})
const OrderMilepost = Loadable({
loader: () => import('../Order/Milepost'),
loading: Loading,
})
const OrdernewMilepost = Loadable({
loader: () => import('../Order/newMilepost'),
loading: Loading,
})
const OrderupdateMilepost = Loadable({
loader: () => import('../Order/UpdateMilepost'),
loading: Loading,
})
const OrderupdateDetail = Loadable({
loader: () => import('../Order/UpdateDetail'),
loading: Loading,
})
const OrdercopyDetail = Loadable({
loader: () => import('../Order/CopyDetail'),
loading: Loading,
})
//合并请求
const MergeIndexDetail = Loadable({
loader: () => import('../Merge/merge'),
loading: Loading,
})
const CreateMerge = Loadable({
loader: () => import('../Merge/NewMerge'),
loading: Loading,
})
const MessageCount = Loadable({
loader: () => import('../Merge/MessageCount'),
loading: Loading,
})
const UpdateMerge = Loadable({
loader: () => import('../Merge/UpdateMerge'),
loading: Loading,
})
const MilepostDetail = Loadable({
loader: () => import('../Order/MilepostDetail'),
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({
loader: () => import('../Activity/Activity'),
loading: Loading,
})
const DevIndex = Loadable({
loader: () => import('../DevOps/Index'),
loading: Loading,
})
/**
* permissionManager:管理员Reporter报告人员(只有读取权限)Developer开发人员除不能设置仓库信息外
*/
class Detail extends Component {
constructor(props) {
super(props);
this.state = {
projectDetail: undefined,
isManager: false,
isReporter: false,
isDeveloper: false,
project_id: undefined,
watchers_count: undefined,
praises_count: undefined,
forked_count: undefined,
watched: false,
praised: false,
http_url: undefined,
author: undefined,
branchs: undefined,
branchList: undefined,
project: null,
firstSync:false,
secondSync:false,
}
}
componentDidMount = () => {
this.getProject();
}
componentDidUpdate = (prevState) => {
if ((prevState.match.params.projectsId !== this.props.match.params.projectsId)) {
this.getProject();
}
}
getProject = (num) => {
const { projectsId } = this.props.match.params;
const url = `/projects/${projectsId}/simple.json`;
axios.get(url).then((result) => {
if (result && result.data) {
this.setState({
project: result.data
})
if (result.data.type !== 0 && result.data.mirror_status === 1) {
console.log("--------start channel --------");
// 是镜像项目,且未完成迁移
this.canvasChannel();
if(num){
this.setState({
secondSync:true,
firsrtSync:false
})
}else{
this.setState({
firstSync:true,
secondSync:false
})
}
}else{
this.getDetail();
this.setState({
firsrtSync:false,
secondSync:false
})
}
}
})
}
canvasChannel = () => {
const name = window.location.hostname === "localhost" ? "testforgeplus.trustie.net" : window.location.hostname;
const actioncable = require("actioncable");
var project = this.state.project;
var cable = actioncable.createConsumer(`wss://${name}/cable`);
this.canvasChannel1 = cable.subscriptions.create({
channel: `MirrorProjectChannel`,
id: project && project.identifier
}, {
connected: () => {
console.log("###### channel connected! ######");
},
disconnected: () => { },
received: data => {
console.log(`###### ---received data--- ######`);
console.log(data);
if (data) {
this.getDetail();
cable.subscriptions.consumer.disconnect();
}
}
})
}
getDetail = () => {
const { projectsId } = this.props.match.params;
const url = `/repositories/${projectsId}.json`;
axios.get(url).then((result) => {
if (result) {
this.setState({
projectDetail: result.data,
project_id: result.data.project_id,
isManager: result.data.permission && result.data.permission === "Manager",
isReporter: result.data.permission && result.data.permission === "Reporter",
isDeveloper: result.data.permission && result.data.permission === "Developer",
http_url: result.data.clone_url,
author: result.data.author,
praised: result.data.praised,
watched: result.data.watched,
watchers_count: result.data.watchers_count,
praises_count: result.data.praises_count,
forked_count: result.data.forked_count,
})
}
}).catch((error) => { })
}
// 关注和取消关注
focusFunc = (flag) => {
const { project_id } = this.state;
axios({
method: flag ? 'delete' : 'post',
url: `/watchers/${flag ? 'unfollow' : 'follow'}.json`,
params: {
target_type: "project",
id: project_id
}
})
.then(result => {
if (result && result.data.status === 0) {
this.setWatchersCount(result.data.watchers_count, result.data.watched);
}
})
.catch(error => {
console.log(error);
});
}
// 点赞和取消点赞
pariseFunc = (flag) => {
const { project_id } = this.state;
axios({
method: flag ? 'delete' : 'post',
url: `/projects/${project_id}/praise_tread/${flag ? 'unlike' : 'like'}.json`
})
.then(result => {
if (result && result.data.status === 0) {
this.setPraisesCount(result.data.praises_count, result.data.praised)
}
})
.catch(error => {
console.log(error);
});
}
setWatchersCount = (count, is_watched) => {
this.setState({
watched: is_watched,
watchers_count: count
})
}
setPraisesCount = (count, is_praised) => {
this.setState({
praised: is_praised,
praises_count: count
})
}
// fork项目
forkFunc = () => {
const { project_id } = this.state;
const url = `/projects/${project_id}/forks.json`;
axios.post(url).then(result => {
if (result && result.data.status === 0) {
this.props.history.push(`/projects/${result.data.id}/coders`);
this.props.showNotification(result.data.message);
}
}).catch(error => {
console.log(error);
})
}
// 同步镜像
synchronismMirror = () => {
const { repo_id } = this.state.projectDetail;
const url = `/repositories/${repo_id}/sync_mirror.json`;
axios.post(url).then(result => {
if (result && result.data && result.data.status === 0) {
this.getProject(2);
} else {
this.props.showNotification("镜像同步失败!");
}
}).catch(error => {
console.log(error);
})
}
render() {
const { projectDetail, watchers_count, praises_count, forked_count, firstSync , secondSync , isManager, watched, praised, project } = this.state;
const url = this.props.history.location.pathname;
const urlArr = url.split("/");
const urlFlag = (urlArr.length === 3);
const { projectsId } = this.props.match.params;
const { state } = this.props.history.location;
const { current_user } = this.props;
const checkLogin = current_user && current_user.login;
const text = (
projectDetail && projectDetail.forked_from_project_id && projectDetail.fork_info ?
<React.Fragment>
<span>forked from </span>
<Link to={`/users/${projectDetail.fork_info.fork_project_user_login}`} className="show-user-link color-grey-ccc">{projectDetail.fork_info.fork_project_user_name}</Link>
<span> / </span>
<Link to={`/projects/${projectDetail.forked_from_project_id}/coders`} className="color-grey-ccc">{projectDetail.fork_info.fork_form_name}</Link>
</React.Fragment> : ""
);
const common = {
getDetail: this.getDetail
}
return (
<div>
<div className="detailHeader-wrapper">
<div className="normal">
<div className="f-wrap-between pb15" style={{ position: "relative" }}>
<p className="font-22 color-white df flex-1 lineH2 mt15" style={{ alignItems: "center" }}>
{project && project.author &&
<Link to={`/users/${project.author.login}`} className="show-user-link color-white">
{project.author.name}
</Link>
}
<span className="ml5 mr5">/</span>
<span className="hide-1 flex-1 df">
<Link to={`/projects/${projectsId}/coders`} className="color-white font-22">{project && project.name}</Link>
{
projectDetail && projectDetail.forked_from_project_id && projectDetail.fork_info ?
<Tooltip placement={'right'} title={text}>
<Link to={`/projects/${projectDetail.forked_from_project_id}/coders`}
className="ml10" >
<i className="iconfont icon-fork font-18 fl mt6" style={{ color: "#8D90E3" }}></i>
</Link>
</Tooltip> : ""
}
{
projectDetail && projectDetail.type && projectDetail.type !== 0 ?
projectDetail.type === 2 ?
<Tooltip title={"镜像自: " + projectDetail.mirror_url} className="ml5" placement={'right'}>
<i className="iconfont icon-banbenku font-18 mt6" style={{ color: "#8D90E3" }}/>
</Tooltip>:
<Tooltip title={"镜像自: " + projectDetail.mirror_url} className="ml5" placement={'right'}>
<i className="iconfont icon-jingxiang font-18 color-green mt6" />
</Tooltip>
:""
}
</span>
</p>
{
firstSync ? "":
<span className="df mt25">
{
projectDetail && projectDetail.type && projectDetail.type === 2 ?
<a className="synchronism ml30" onClick={this.synchronismMirror}>同步镜像</a> : ""
}
<span className="detail_tag_btn">
<a className="detail_tag_btn_name" onClick={() => this.focusFunc(watched)}>
<img src={watched ? img_focused : img_focus} alt="" width="14px" />
{watched ? '取消关注' : '关注'}
</a>
<Link className="detail_tag_btn_count" to={{ pathname: `/projects/${projectsId}/watch_users`, state }}>
{watchers_count}
</Link>
</span>
<span className="detail_tag_btn">
<a className="detail_tag_btn_name" onClick={() => this.pariseFunc(praised)}>
<img src={praised ? img_parised : img_parise} width="13px" alt="" />
{praised ? '取消点赞' : '点赞'}
</a>
<Link className="detail_tag_btn_count" to={{ pathname: `/projects/${projectsId}/praise_users`, state }}>
{praises_count}
</Link>
</span>
<span className="detail_tag_btn">
<a className="detail_tag_btn_name" onClick={this.forkFunc}>
<img src={img_fork} alt="" width="10px" />Fork</a>
<Link className="detail_tag_btn_count" to={{ pathname: `/projects/${projectsId}/fork_users`, state }}>
{forked_count}
</Link>
</span>
</span>
}
</div>
{
firstSync ? "" :
<div className="f-wrap-between pb20">
<ul className="headerMenu-wrapper">
<li className={(url.indexOf("coders") > -1 || urlFlag) ? "active" : ""}>
<Link to={{ pathname: `/projects/${projectsId}/coders`, state }}>
<img alt="" src={img_1} width="18" />代码库
</Link>
</li>
<li className={(url.indexOf("/orders") > -1 && !(url.indexOf("Milepost") > 0 || url.indexOf("meilpost") > 0 || url.indexOf("tags") > 0)) ? "active" : ""}>
<Link to={{ pathname: `/projects/${projectsId}/orders`, state }}>
<img alt="" src={img_2} width="12" />任务
{projectDetail && projectDetail.issues_count ? <span>{projectDetail.issues_count}</span> : ""}
</Link>
</li>
{
projectDetail && parseInt(projectDetail.type) !== 2 &&
<li className={url.indexOf("merge") > -1 ? "active" : ""}>
<Link to={{ pathname: `/projects/${projectsId}/merge`, state }}>
<img alt="" src={img_3} width="13" />合并请求
{projectDetail && projectDetail.pull_requests_count ? <span>{projectDetail.pull_requests_count}</span> : ""}
</Link>
</li>
}
<li className={url.indexOf("/ops") > -1 ? "active" : ""}>
<Link to={{ pathname: `/projects/${projectsId}/ops`, state }}>
<i className="iconfont icon-gongzuoliu font-13 mr8"></i>
{/* {projectDetail && projectDetail.pull_requests_count ? <span>{projectDetail.pull_requests_count}</span> : ""} */}
</Link>
</li>
<li className={(url.indexOf("/Milepost") > -1 || url.indexOf("meilpost") > -1) ? "active" : ""}>
<Link to={{ pathname: `/projects/${projectsId}/orders/Milepost`, state }}>
<img alt="" src={img_milepost} width="16" />里程碑
{projectDetail && projectDetail.version_count && <span>{projectDetail.version_count}</span>}
</Link>
</li>
<li className={url.indexOf("/trends") > -1 ? "active" : ""}>
<Link to={{ pathname: `/projects/${projectsId}/trends`, state }}>
<img alt="" src={img_6} width="16" />动态
</Link>
</li>
{
isManager &&
<li className={url.indexOf("/setting") > 0 ? "active" : ""}><Link to={`/projects/${projectsId}/setting`}><img alt="" src={img_7} width="19" />仓库设置</Link></li>
}
</ul>
</div>
}
</div>
</div>
{
firstSync ?
<Content className="spincontent">
<Spin className="spinstyle" tip={project && `正在从 ${project.mirror_url} 迁移`} size="large">
</Spin>
</Content>
:
<Spin spinning={secondSync} className="spinstyle" tip="正在同步镜像" size="large">
<Switch {...this.props}>
{/* 工作流 */}
<Route path="/projects/:projectsId/ops"
render={
() => (<DevIndex {...this.props} {...this.state} {...common} />)
}
></Route>
{/* 标签列表 */}
<Route path="/projects/:projectsId/orders/tags"
render={
(props) => (<TagList {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 仓库设置 */}
<Route path="/projects/:projectsId/setting"
render={
(props) => (<Setting {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 任务详情 */}
<Route path="/projects/:projectsId/orders/:orderId/detail"
render={
(props) => (<OrderDetail {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 里程碑 */}
<Route path="/projects/:projectsId/orders/Milepost"
render={
(props) => (<OrderMilepost {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 新建里程碑 */}
<Route path="/projects/:projectsId/orders/meilpost"
render={
(props) => (<OrdernewMilepost {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/*里程碑详情*/}
<Route path="/projects/:projectsId/orders/:meilid/MilepostDetail"
render={
(props) => (<MilepostDetail {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/*修改里程碑*/}
<Route path="/projects/:projectsId/orders/:meilid/meilpost"
render={
(props) => (<OrderupdateMilepost {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 里程碑页面新建任务 */}
<Route path="/projects/:projectsId/orders/:milepostId/new"
render={
(props) => (<OrderNew {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 新建任务 */}
<Route path="/projects/:projectsId/orders/new"
render={
(props) => (<OrderNew {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 修改详情 */}
<Route path="/projects/:projectsId/orders/:orderId/updatedetail"
render={
(props) => (<OrderupdateDetail {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 复制详情 */}
<Route path="/projects/:projectsId/orders/:orderId/copyetail"
render={
(props) => (<OrdercopyDetail {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 动态 */}
<Route path="/projects/:projectsId/trends"
render={
(props) => (<TrendsIndex {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 代码Index */}
<Route path="/projects/:projectsId/orders"
render={
(props) => (<OrderIndex {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/projects/:projectsId/merge/new"
render={
(props) => (<CreateMerge {...this.props} {...props} {...this.state} {...common} is_fork={true} />)
}
></Route>
<Route path="/projects/:projectsId/merge/:mergeId/UpdateMerge"
render={
(props) => (<UpdateMerge {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/projects/:projectsId/merge/:mergeId/Messagecount"
render={
(props) => (<MessageCount {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/projects/:projectsId/merge/:mergeId/MergeSubmit"
render={
(props) => (<MessageCount {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/projects/:projectsId/merge"
render={
(props) => (<MergeIndexDetail {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/projects/:projectsId/coders/filesurl"
render={
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/projects/:projectsId/coders"
render={
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/projects/:projectsId/watch_users"
render={
(props) => (<WatchUsers {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/projects/:projectsId/praise_users"
render={
(props) => (<PraiseUsers {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/projects/:projectsId/fork_users"
render={
(props) => (<ForkUsers {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/projects/:projectsId"
render={
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
</Switch>
</Spin>
}
</div>
)
}
}
export default Detail;