forked from Gitlink/forgeplus-react
Merge pull request 'merge old version' (#260) from feature_noti_v2 into feature_notification_v2
This commit is contained in:
commit
ed3bf55f90
|
@ -1949,9 +1949,7 @@ a.decoration {
|
|||
}
|
||||
|
||||
.mr20 {
|
||||
margin-right: 10px;
|
||||
margin-left: 10px;
|
||||
float: left;
|
||||
margin-right: 20px;
|
||||
}
|
||||
|
||||
.mr25 {
|
||||
|
@ -1959,7 +1957,7 @@ a.decoration {
|
|||
}
|
||||
|
||||
.mr30 {
|
||||
margin-right: 10px;
|
||||
margin-right: 30px;
|
||||
}
|
||||
|
||||
.mr35 {
|
||||
|
@ -2458,7 +2456,7 @@ a.hoverLine:hover{
|
|||
|
||||
|
||||
.color-grey-9 {
|
||||
color: #333333 !important;
|
||||
color: #999 !important;
|
||||
}
|
||||
|
||||
a:hover{
|
||||
|
|
10
src/App.js
10
src/App.js
|
@ -97,10 +97,10 @@ const ProjectIndex = Loadable({
|
|||
loading: Loading,
|
||||
});
|
||||
|
||||
const CreateMerge = Loadable({
|
||||
loader: () => import('./forge/Merge/NewMerge'),
|
||||
loading: Loading,
|
||||
})
|
||||
// const CreateMerge = Loadable({
|
||||
// loader: () => import('./forge/Merge/NewMerge'),
|
||||
// loading: Loading,
|
||||
// })
|
||||
|
||||
// 此处仅维护前端可能的一级路由,不用进行项目或者组织判断的字段。
|
||||
const keyWord = ["explore", "settings", "setting", "mulan", "wiki", "issues", "setting", "trending", "code", "projects", "pulls", "mine", "login", "register", "email", "export", "nopage", "404", "403", "500", "501", "search", "organize"];
|
||||
|
@ -279,7 +279,7 @@ class App extends Component {
|
|||
} />
|
||||
|
||||
{/* 项目PR */}
|
||||
<Route path="/:owner/:projectsId/pulls/new"
|
||||
<Route path="/:owner/:projectsId/compare"
|
||||
render={
|
||||
(props) => (<ProjectDetail {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
|
|
|
@ -10,6 +10,10 @@ import ActivityItem from './ActivityItem';
|
|||
import axios from 'axios';
|
||||
const LIMIT = 15;
|
||||
const ARRAY = [
|
||||
{
|
||||
id:"",
|
||||
name:'全部'
|
||||
},
|
||||
{
|
||||
id:1,
|
||||
name:'1天'
|
||||
|
@ -32,10 +36,15 @@ class Activity extends Component{
|
|||
constructor(props){
|
||||
super(props);
|
||||
this.state={
|
||||
time:'30',
|
||||
time:undefined,
|
||||
type:undefined,
|
||||
state:undefined,
|
||||
page:1,
|
||||
pr_count:undefined,
|
||||
new_pr_count:undefined,
|
||||
close_issues_count:undefined,
|
||||
open_issues_count:undefined,
|
||||
pr_all_count:undefined,issues_count:undefined,
|
||||
|
||||
data:undefined,
|
||||
project_trends:undefined,
|
||||
|
@ -63,8 +72,15 @@ class Activity extends Component{
|
|||
this.setState({
|
||||
data:result.data,
|
||||
project_trends:result.data.project_trends,
|
||||
isSpin:false
|
||||
isSpin:false,
|
||||
pr_count:result.data.pr_count,
|
||||
new_pr_count:result.data.new_pr_count,
|
||||
close_issues_count:result.data.close_issues_count,
|
||||
open_issues_count:result.data.open_issues_count,
|
||||
pr_all_count:result.data.pr_all_count,
|
||||
issues_count:result.data.issues_count,
|
||||
})
|
||||
window.scrollTo(0,0);
|
||||
}
|
||||
}).catch(error=>{
|
||||
console.log(error);
|
||||
|
@ -74,19 +90,19 @@ class Activity extends Component{
|
|||
// 切换周期
|
||||
changeTime=(e)=>{
|
||||
this.setState({
|
||||
time:e.key,
|
||||
time:e.key ==="item_0"?undefined:e.key,
|
||||
isSpin:true
|
||||
})
|
||||
const { type,status,page } = this.state;
|
||||
this.getInfo(e.key,type,status,page);
|
||||
this.getInfo(e.key ==="item_0"?undefined:e.key,type,status,page);
|
||||
}
|
||||
//筛选
|
||||
changeTrends=(type,status)=>{
|
||||
this.setState({
|
||||
type,status
|
||||
type,status,page:1
|
||||
})
|
||||
const {time,page}=this.state;
|
||||
this.getInfo(time,type,status,page);
|
||||
const {time}=this.state;
|
||||
this.getInfo(time,type,status,1);
|
||||
}
|
||||
// 分页
|
||||
ChangePage=(page)=>{
|
||||
|
@ -108,12 +124,14 @@ class Activity extends Component{
|
|||
</Menu>
|
||||
)
|
||||
render(){
|
||||
const { time , data , page , project_trends , isSpin } = this.state;
|
||||
const { time , data , page , project_trends , isSpin , pr_count , new_pr_count , close_issues_count , open_issues_count , pr_all_count ,issues_count } = this.state;
|
||||
let name = time ? ARRAY.filter(item=>item.id === parseInt(time)) :[{name:"全部"}];
|
||||
|
||||
let name = time && ARRAY.filter(item=>item.id === parseInt(time)) ;
|
||||
const second_per = (parseInt(data && data.close_issues_count)/parseInt(data && data.issues_count)*100)+'%';
|
||||
const third_per = (parseInt(data && data.close_issues_count)/parseInt(data && data.issues_count)*100)+'%';
|
||||
const fourth_per = (parseInt(data && data.open_issues_count)/parseInt(data && data.issues_count)*100)+'%';
|
||||
const first_per = pr_all_count > 0 ? `${parseFloat(pr_count/pr_all_count).toFixed(2)*100}%` :"50%";
|
||||
const second_per =pr_all_count > 0 ? `${parseFloat(new_pr_count/pr_all_count).toFixed(2)*100}%` :"50%";
|
||||
const third_per =issues_count > 0 ?`${parseFloat(close_issues_count/issues_count).toFixed(2)*100}%` :"50%";
|
||||
const fourth_per =issues_count > 0 ?`${parseFloat(open_issues_count/issues_count).toFixed(2)*100}%` :"50%";
|
||||
|
||||
return(
|
||||
<div className="main">
|
||||
|
||||
|
@ -122,7 +140,7 @@ class Activity extends Component{
|
|||
<div className="orderInfo">
|
||||
<div>
|
||||
<div className="percentLine prPercent">
|
||||
<p className="percent_purple" style={{width:'100%'}}></p>
|
||||
<p className="percent_purple" style={{width:first_per}}></p>
|
||||
<p className="percent_green resetStyle" style={{width:`${second_per}`}}></p>
|
||||
</div>
|
||||
<span>{data && data.pr_all_count}合并请求</span>
|
||||
|
@ -132,25 +150,25 @@ class Activity extends Component{
|
|||
<p className="percent_red" style={{width:`${third_per}`}}></p>
|
||||
<p className="percent_green" style={{width:`${fourth_per}`}}></p>
|
||||
</div>
|
||||
<span>{data && data.issues_count}任务</span>
|
||||
<span>{data && data.issues_count}易修</span>
|
||||
</div>
|
||||
</div>
|
||||
<ul className="percentBox">
|
||||
<li>
|
||||
<span className="purple">{data && data.pr_count}</span>
|
||||
<span className="change" onClick={()=>this.changeTrends("PullRequest","close")}>已处理的合并请求</span>
|
||||
<span className="change" onClick={()=>this.changeTrends("PullRequest","delay")}>已处理的合并请求</span>
|
||||
</li>
|
||||
<li>
|
||||
<span className="green">{data && data.new_pr_count}</span>
|
||||
<span className="change" onClick={()=>this.changeTrends("PullRequest","create")}>未处理的合并请求</span>
|
||||
<span className="change" onClick={()=>this.changeTrends("PullRequest","not_delay")}>未处理的合并请求</span>
|
||||
</li>
|
||||
<li>
|
||||
<span className="red">{data && data.close_issues_count}</span>
|
||||
<span className="change" onClick={()=>this.changeTrends("Issue","close")}>已关闭的任务</span>
|
||||
<span className="change" onClick={()=>this.changeTrends("Issue","delay")}>已关闭的易修</span>
|
||||
</li>
|
||||
<li>
|
||||
<span className="green">{data && data.open_issues_count}</span>
|
||||
<span className="change" onClick={()=>this.changeTrends("Issue","create")}>未处理的任务</span>
|
||||
<span className="change" onClick={()=>this.changeTrends("Issue","not_delay")}>未处理的易修</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -27,7 +27,7 @@ class ActivityItem extends Component {
|
|||
:
|
||||
// 如果是合并请求
|
||||
<p className="itemLine">
|
||||
<Link to={`/${owner}/${projectsId}/pulls/${item.trend_id}/Messagecount`} className="color-blue font-16">{item.name}</Link>
|
||||
<Link to={`/${owner}/${projectsId}/pulls/${item.trend_id}`} className="color-blue font-16">{item.name}</Link>
|
||||
<span className="activity_type">{item.trend_type}</span>
|
||||
</p >
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import React , { useState , useEffect } from 'react';
|
|||
import { Input , Spin , Menu } from 'antd';
|
||||
import { getBranch , getTag } from '../GetData/getData';
|
||||
|
||||
function SelectOverlay({ changeBranch , tagflag , branchList , projectsId , owner , visible }) {
|
||||
function SelectOverlay({ changeBranch , tagflag , projectsId , owner , visible }) {
|
||||
const [ inputValue , setInputValue] = useState(undefined);
|
||||
const [ nav , setNav ] = useState(0);
|
||||
const [ isSpin , setIsSpin ] = useState(true);
|
||||
|
@ -11,21 +11,13 @@ function SelectOverlay({ changeBranch , tagflag , branchList , projectsId , owne
|
|||
const [ datas , setDatas ] = useState(undefined);
|
||||
const [ keys ,setKeys] = useState("branch");
|
||||
|
||||
// useEffect(()=>{
|
||||
// if(visible){
|
||||
// setKeys("branch");
|
||||
// getBranchs(projectsId,owner);
|
||||
// setIsSpin(true);
|
||||
// }
|
||||
// },[visible])
|
||||
|
||||
useEffect(()=>{
|
||||
if(branchList){
|
||||
setData(branchList);
|
||||
setDatas(branchList);
|
||||
setIsSpin(false);
|
||||
if(visible){
|
||||
setKeys("branch");
|
||||
getBranchs(projectsId,owner);
|
||||
setIsSpin(true);
|
||||
}
|
||||
},[branchList])
|
||||
},[visible])
|
||||
|
||||
async function getBranchs(id,owner){
|
||||
let result = await getBranch(id,owner);
|
||||
|
@ -53,8 +45,10 @@ function SelectOverlay({ changeBranch , tagflag , branchList , projectsId , owne
|
|||
setIsSpin(true);
|
||||
if(e.key === "branch"){
|
||||
getBranchs(projectsId,owner);
|
||||
setNav(0);
|
||||
}else{
|
||||
getTags(projectsId,owner);
|
||||
setNav(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
.systemBox{
|
||||
.ant-modal-body{
|
||||
padding:1px 0px 0px 0px;
|
||||
.sysBox{
|
||||
background-image: url('./bg.png');
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% 334px;
|
||||
margin-top: -55px;
|
||||
}
|
||||
.sysnoticeBox{
|
||||
width: 100%;
|
||||
padding:80px 0px 34px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 780px;
|
||||
margin: 0px auto;
|
||||
p.ntitle{
|
||||
height: 33px;
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
color: #31FFF7;
|
||||
line-height: 33px;
|
||||
text-align: center;
|
||||
}
|
||||
p.nSubtitle{
|
||||
height: 25px;
|
||||
line-height: 25px;
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
color: #FFFFFF;
|
||||
margin-top: 60px;
|
||||
padding-left: 20px;
|
||||
}
|
||||
.markdown-body{
|
||||
box-shadow: 0px 0px 17px rgba(0,0,0,0.2);
|
||||
border-radius: 4px;
|
||||
margin-top: 17px!important;
|
||||
}
|
||||
.nContent{
|
||||
padding:20px 34px;
|
||||
background-color: #fff;
|
||||
line-height: 30px;
|
||||
font-size: 15px;
|
||||
font-weight: 400;
|
||||
color: #333;
|
||||
.realmName{
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
ul{
|
||||
width: 50%;
|
||||
padding-left: 0px!important;
|
||||
li{
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
line-height: 32px;
|
||||
text-align: left;
|
||||
color: #000;
|
||||
list-style-type: none!important;
|
||||
&:first-child{
|
||||
color: #E65714;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.nSubdesc{
|
||||
font-size: 15px;
|
||||
font-weight: 400;
|
||||
color: #000000;
|
||||
line-height: 31px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.nInfo{
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #333333;
|
||||
text-align: right;
|
||||
margin-top: 25px;
|
||||
p{
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.nBtn{
|
||||
text-align: center;
|
||||
margin-top: 33px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
import React , { useEffect , useState } from 'react';
|
||||
import { Modal , Button } from 'antd';
|
||||
import './Index.scss';
|
||||
import '../../css/index.scss';
|
||||
import RenderHtml from '../../../components/render-html';
|
||||
import cookie from 'react-cookies';
|
||||
|
||||
function SystemNotice({system_notification,history}){
|
||||
const [ visible , setVisible ] = useState(false);
|
||||
|
||||
useEffect(()=>{
|
||||
if(system_notification && !cookie.load('notice_stage')){
|
||||
setVisible(true);
|
||||
}
|
||||
},[system_notification,history.location])
|
||||
|
||||
function sureContinue() {
|
||||
cookie.remove('notice_stage');
|
||||
|
||||
let inFifteenMinutes = new Date(new Date().getTime() + 24 * 3600 * 1000);//一天
|
||||
// let inFifteenMinutes = new Date(new Date().getTime() + 60 * 1000);//一分钟
|
||||
cookie.save('notice_stage', true,{ expires: inFifteenMinutes,path:"/" });
|
||||
|
||||
setVisible(false);
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal
|
||||
visible = {visible}
|
||||
width="1000px"
|
||||
footer={false}
|
||||
title={false}
|
||||
centered={true}
|
||||
closable={false}
|
||||
wrapClassName={'systemBox'}
|
||||
>
|
||||
<div className="sysBox">
|
||||
<div className="sysnoticeBox">
|
||||
<p className="ntitle">{system_notification && system_notification.subject}</p>
|
||||
<p className="nSubtitle">{system_notification && system_notification.sub_subject}</p>
|
||||
{/* <div className="nContent">
|
||||
<div className="nMaindesc">
|
||||
为了给用户提供更加稳定、优质的服务,我们即将对平台门户首页、平台名称、平台域名进行一次全面升级与变更。原平台名称:Trustie(中文名:确实)将于2021年10月xx日统一更改为Gitlink(中文名:确实开源)。届时平台域名将统一进行更换,更换规则如下
|
||||
</div>
|
||||
<div className="realmName">
|
||||
<ul>
|
||||
<li>原域名:</li>
|
||||
<li>官网顶级域名https://www.trustie.net</li>
|
||||
<li>版本库子域名https://forgeplus.trustie.net</li>
|
||||
<li>论坛子域名https://forum.trustie.net/forums</li>
|
||||
</ul>
|
||||
<ul>
|
||||
<li>更换后域名:</li>
|
||||
<li>官网顶级域名https://www.gitlink.org.cn</li>
|
||||
<li>版本库子域名https://www.git.gitlink.org.cn</li>
|
||||
<li>论坛子域名https://forum.gitlink.org.cn</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className="nSubdesc">
|
||||
自2021年10月xx日起,旧域名将停止访问。因平台名称与域名变更给您带来的不便,我们深表歉意!非常感谢您一直以来对本平台的信任与支持,我们将一如既往地为您提供优质的服务。 特此通知!
|
||||
</div>
|
||||
<div className="nInfo">
|
||||
<p>Gitlink运营团队</p>
|
||||
<p>2021年10月xx日</p>
|
||||
</div>
|
||||
</div> */}
|
||||
<RenderHtml className="break_word_comments imageLayerParent" value={system_notification && system_notification.content} url={history.location}/>
|
||||
<div className="nBtn">
|
||||
<Button type="primary" className="btnblue" onClick={sureContinue}>确认并继续</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
export default SystemNotice;
|
Binary file not shown.
After Width: | Height: | Size: 280 KiB |
|
@ -367,7 +367,6 @@ class NewHeader extends Component {
|
|||
}
|
||||
|
||||
let search_url = settings && settings.common && settings.common.search;
|
||||
let notice_url = settings && settings.common && settings.common.notice;
|
||||
return (
|
||||
<div className="newHeaders" id="nHeader">
|
||||
<div className="headerContent">
|
||||
|
@ -438,7 +437,7 @@ class NewHeader extends Component {
|
|||
</Dropdown>:""
|
||||
}
|
||||
|
||||
{current_user && current_user.login ?
|
||||
{ (settings && settings.common && settings.common.notice) && (current_user && current_user.login)?
|
||||
<Popover
|
||||
overlayClassName="notice-popover"
|
||||
placement={`bottomRight`}
|
||||
|
@ -448,9 +447,9 @@ class NewHeader extends Component {
|
|||
destroyTooltipOnHide
|
||||
>
|
||||
<Link to={"/settings/notice"} className="message-icon">
|
||||
<Badge count={current_user.message_unread_total}>
|
||||
{current_user && <Badge count={current_user.message_unread_total}>
|
||||
<i className="iconfont icon-xiaoxilingdang color-grey-6 ml15 mr15"></i>
|
||||
</Badge>
|
||||
</Badge>}
|
||||
</Link>
|
||||
</Popover>
|
||||
: ""
|
||||
|
|
|
@ -22,6 +22,7 @@ import UpdateDescModal from './sub/UpdateDescModal';
|
|||
import Nodata from '../Nodata';
|
||||
import Invite from './sub/Invite';
|
||||
import CheckProfile from '../Component/ProfileModal/Profile';
|
||||
import RenderHtml from '../../components/render-html';
|
||||
/**
|
||||
* projectDetail.type:0是托管项目,1是镜像项目,2是同步镜像项目(为2时不支持在线创建、在线上传、在线修改、在线删除、创建合并请求等功能)
|
||||
*/
|
||||
|
@ -196,7 +197,7 @@ function CoderDepot(props){
|
|||
let ele = document.getElementById("ptxt");
|
||||
if(ele){
|
||||
let h = ele.offsetHeight;
|
||||
if( h > 18 ) setHideBtn(true);
|
||||
if( h > 35 ) setHideBtn(true);
|
||||
}
|
||||
}
|
||||
},[projectDetail,lastCommit])
|
||||
|
@ -401,22 +402,22 @@ function CoderDepot(props){
|
|||
getPathUrl={getPathUrl}
|
||||
/>
|
||||
:
|
||||
<div>
|
||||
<React.Fragment>
|
||||
<AlignCenter className="mr20">
|
||||
<Link to={`/${owner}/${projectsId}/branches`} className="iconBtn">
|
||||
<i className="iconfont icon-master_icon font-16"></i>
|
||||
<span>分支</span>
|
||||
<span>{projectDetail && projectDetail.branches && projectDetail.branches.total_count}</span>
|
||||
<span>{projectDetail && projectDetail.branches_count}</span>
|
||||
</Link>
|
||||
</AlignCenter>
|
||||
<AlignCenter className="mr20">
|
||||
<Link to={`/${owner}/${projectsId}/tags`} className="iconBtn">
|
||||
<i className="iconfont icon-biaoqianicon font-16"></i>
|
||||
<span>标签</span>
|
||||
<span>{projectDetail && projectDetail.tags && projectDetail.tags.total_count}</span>
|
||||
<span>{projectDetail && projectDetail.tags_count}</span>
|
||||
</Link>
|
||||
</AlignCenter>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
}
|
||||
</AlignCenter>
|
||||
<AlignCenter className="depotBtn">
|
||||
|
@ -425,7 +426,7 @@ function CoderDepot(props){
|
|||
<div className="addOptionBtn">
|
||||
{
|
||||
baseOperate &&
|
||||
<CheckProfile {...props} sureFunc={()=>urlLink(`/${owner}/${projectsId}/pulls/new/${branchName || defaultBranch}`)} >+ 合并请求</CheckProfile>
|
||||
<CheckProfile {...props} sureFunc={()=>urlLink(`/${owner}/${projectsId}/compare/master...${branchName || defaultBranch}`)} >+ 合并请求</CheckProfile>
|
||||
}
|
||||
{
|
||||
baseOper &&
|
||||
|
@ -457,7 +458,7 @@ function CoderDepot(props){
|
|||
<div className="listtablehead">
|
||||
<User url={getImageUrl(`/${lastCommitAuthor && lastCommitAuthor.image_url}`)} name={lastCommitAuthor && lastCommitAuthor.name} id={lastCommitAuthor && lastCommitAuthor.id} login={lastCommitAuthor && lastCommitAuthor.login}/>
|
||||
<div className={hideBtn && hide ? "ellipsistxt hidetxt" :"ellipsistxt"}>
|
||||
<pre id="ptxt"><Link to={`/${owner}/${projectsId}/commits/${truncateCommitId(lastCommit.sha)}`}>{lastCommit.message}</Link></pre>
|
||||
<pre id="ptxt"><Link to={`/${owner}/${projectsId}/commits/${truncateCommitId(lastCommit.sha)}`}><RenderHtml value={lastCommit.message}/></Link></pre>
|
||||
</div>
|
||||
{ hideBtn && <span className="ellipsis" onClick={()=>changeHide(hide)}><i className="iconfont icon-shenglvehao"></i></span> }
|
||||
|
||||
|
|
|
@ -6,7 +6,8 @@ import { AlignTop } from '../Component/layout';
|
|||
import SelectBranch from '../Branch/Select';
|
||||
import Nodata from '../Nodata';
|
||||
|
||||
import User from '../Component/User'
|
||||
import User from '../Component/User';
|
||||
import RenderHtml from '../../components/render-html.jsx';
|
||||
import Tree from './img/tree.png';
|
||||
import axios from 'axios';
|
||||
import {Link} from "react-router-dom";
|
||||
|
@ -158,7 +159,7 @@ class CoderRootCommit extends Component{
|
|||
<div className="commitList-item f-wrap-between">
|
||||
<div>
|
||||
<AlignTop>
|
||||
<div className="commitDesc"><Link to={`/${owner}/${projectsId}/commits/${truncateCommitId(`${item.sha}`)}`} className="font-14 color-grey-3 font-bd">{item.message}</Link></div>
|
||||
<div className="commitDesc"><Link to={`/${owner}/${projectsId}/commits/${truncateCommitId(`${item.sha}`)}`} className="font-14 color-grey-3 font-bd"><RenderHtml value={item.message}/></Link></div>
|
||||
</AlignTop>
|
||||
<p className="f-wrap-alignCenter mt15 pb5">
|
||||
<User
|
||||
|
|
|
@ -27,6 +27,7 @@ class CoderRootFileDetail extends Component {
|
|||
}
|
||||
|
||||
componentDidMount = () => {
|
||||
window.scrollTo(0, 0);
|
||||
const { detail , mdFlag } = this.props;
|
||||
this.setState({
|
||||
value: detail.content,
|
||||
|
@ -214,7 +215,7 @@ class CoderRootFileDetail extends Component {
|
|||
const Option = Select.Option;
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Anchor className="griditemAnchor" offsetTop={70} targetOffset={160}>
|
||||
<Anchor className="griditemAnchor" offsetTop={70}>
|
||||
<div className="griditemCate">
|
||||
{
|
||||
md && readOnly &&
|
||||
|
|
|
@ -3,7 +3,6 @@ import { Route , Switch } from 'react-router-dom';
|
|||
// import Top from './DetailTop';
|
||||
import Loadable from 'react-loadable';
|
||||
import Loading from '../../Loading';
|
||||
import axios from 'axios';
|
||||
import './Index.scss';
|
||||
|
||||
const FileNew = Loadable({
|
||||
|
@ -51,37 +50,37 @@ class CoderRootIndex extends Component{
|
|||
}
|
||||
}
|
||||
|
||||
componentDidMount=()=>{
|
||||
this.Init();
|
||||
}
|
||||
componentDidUpdate=(prevProps)=>{
|
||||
const { location } = this.props;
|
||||
const prevlocation = prevProps && prevProps.location;
|
||||
if (location !== prevlocation) {
|
||||
this.Init();
|
||||
}
|
||||
}
|
||||
// componentDidMount=()=>{
|
||||
// this.Init();
|
||||
// }
|
||||
// componentDidUpdate=(prevProps)=>{
|
||||
// const { location } = this.props;
|
||||
// const prevlocation = prevProps && prevProps.location;
|
||||
// if (location !== prevlocation) {
|
||||
// this.Init();
|
||||
// }
|
||||
// }
|
||||
|
||||
Init=()=>{
|
||||
const { branchName } = this.props.match.params;
|
||||
const { defaultBranch } = this.props;
|
||||
this.getTopCount(branchName || defaultBranch);
|
||||
}
|
||||
// Init=()=>{
|
||||
// const { branchName } = this.props.match.params;
|
||||
// const { defaultBranch } = this.props;
|
||||
// this.getTopCount(branchName || defaultBranch);
|
||||
// }
|
||||
|
||||
// 获取<Top />组件里要显示的数据
|
||||
getTopCount=(branch)=>{
|
||||
const { projectsId , owner } = this.props.match.params;
|
||||
const url = `/${owner}/${projectsId}/top_counts.json`;
|
||||
axios.get(url,{params:{
|
||||
ref:branch
|
||||
}}).then(result=>{
|
||||
if(result){
|
||||
this.setState({
|
||||
coderCount:result.data
|
||||
})
|
||||
}
|
||||
}).catch(error=>{console.log(error);})
|
||||
}
|
||||
// getTopCount=(branch)=>{
|
||||
// const { projectsId , owner } = this.props.match.params;
|
||||
// const url = `/${owner}/${projectsId}/top_counts.json`;
|
||||
// axios.get(url,{params:{
|
||||
// ref:branch
|
||||
// }}).then(result=>{
|
||||
// if(result){
|
||||
// this.setState({
|
||||
// coderCount:result.data
|
||||
// })
|
||||
// }
|
||||
// }).catch(error=>{console.log(error);})
|
||||
// }
|
||||
render(){
|
||||
return(
|
||||
<div className="coderSubPage">
|
||||
|
@ -100,12 +99,12 @@ class CoderRootIndex extends Component{
|
|||
></Route>
|
||||
<Route path="/:owner/:projectsId/:branch/newfile"
|
||||
render={
|
||||
(props) => (<FileNew {...this.props} {...props} {...this.state} getTopCount={this.getTopCount} />)
|
||||
(props) => (<FileNew {...this.props} {...props} {...this.state} />)
|
||||
}
|
||||
></Route>
|
||||
<Route path="/:owner/:projectsId/commits/branch/:branchName"
|
||||
render={
|
||||
() => (<CoderRootCommit {...this.props} {...this.state} commit_class="main" getTopCount={this.getTopCount} />)
|
||||
() => (<CoderRootCommit {...this.props} {...this.state} commit_class="main" />)
|
||||
}
|
||||
></Route>
|
||||
<Route path="/:owner/:projectsId/commits/:sha"
|
||||
|
@ -115,7 +114,7 @@ class CoderRootIndex extends Component{
|
|||
></Route>
|
||||
<Route path="/:owner/:projectsId/commits"
|
||||
render={
|
||||
() => (<CoderRootCommit {...this.props} {...this.state} commit_class="main" getTopCount={this.getTopCount} />)
|
||||
() => (<CoderRootCommit {...this.props} {...this.state} commit_class="main" />)
|
||||
}
|
||||
></Route>
|
||||
{/* <Route path="/:owner/:projectsId/releases/:versionId/update"
|
||||
|
|
|
@ -70,7 +70,7 @@ const MergeIndexDetail = Loadable({
|
|||
})
|
||||
|
||||
const CreateMerge = Loadable({
|
||||
loader: () => import('../Merge/NewMerge'),
|
||||
loader: () => import('../Merge/CreateMerge'),
|
||||
loading: Loading,
|
||||
})
|
||||
|
||||
|
@ -150,7 +150,9 @@ function checkPathname(projectsId, owner, pathname) {
|
|||
name = "about"
|
||||
} else if (url.indexOf("/issues") > -1 || url.indexOf("Milepost") > 0) {
|
||||
name = "issues";
|
||||
} else if (url.indexOf("/pulls") > -1) {
|
||||
} else if (url.indexOf("/pulls") > -1 || url.indexOf("/compare") > -1) {
|
||||
// /pulls,合并请求除新建合并请求外,
|
||||
// /compare,新建合并请求
|
||||
name = "pulls"
|
||||
} else if (url.indexOf("/milestones") > -1) {
|
||||
name = "milestones"
|
||||
|
@ -318,6 +320,9 @@ class Detail extends Component {
|
|||
const url = `/${owner}/${projectsId}/detail.json`;
|
||||
axios.get(url).then((result) => {
|
||||
if (result && result.data) {
|
||||
if (result.data.status === 404) {
|
||||
this.props.history.push('/nopage');
|
||||
}
|
||||
this.setState({
|
||||
projectDetail: result.data,
|
||||
project_id: result.data.project_id,
|
||||
|
@ -503,11 +508,6 @@ class Detail extends Component {
|
|||
this.textFunc(projectDetail.forked_from_project_id, projectDetail.fork_info)
|
||||
: ""
|
||||
}
|
||||
{
|
||||
projectDetail && projectDetail.type && projectDetail.type !== 0 ?
|
||||
<span className="color-grey-9">导入于 <a className="color-grey-6" target="_blank" href={projectDetail.mirror_url}>{projectDetail.mirror_url}</a></span>
|
||||
: ""
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
|
@ -552,7 +552,7 @@ class Detail extends Component {
|
|||
<span className="detail_tag_btn" loading={forkSpin}>
|
||||
<Tooltip title="复刻是fork的中文名,即复制代码仓库" placement="bottom">
|
||||
<a className="detail_tag_btn_name" style={{ cursor: platform ? "pointer" : "default" }} onClick={this.forkFunc}>
|
||||
<i className="iconfont icon-fork color-grey-9 mr3 font-16"></i><span>复刻</span>
|
||||
<i className="iconfont icon-fork color-grey-9 mr3 font-16"></i><span>复刻(Fork)</span>
|
||||
</a>
|
||||
</Tooltip>
|
||||
{
|
||||
|
@ -713,22 +713,32 @@ class Detail extends Component {
|
|||
}
|
||||
></Route>
|
||||
{/* 新建合并请求 */}
|
||||
<Route path="/:owner/:projectsId/pulls/new/:branch"
|
||||
{/* <Route path="/:owner/:projectsId/compare/:branch"
|
||||
render={
|
||||
(props) => (<CreateMerge {...this.props} {...props} {...this.state} {...common} is_fork={true} />)
|
||||
}
|
||||
></Route> */}
|
||||
<Route path="/:owner/:projectsId/compare"
|
||||
render={
|
||||
(props) => (<CreateMerge {...this.props} {...props} {...this.state} {...common} is_fork={true} />)
|
||||
}
|
||||
></Route>
|
||||
<Route path="/:owner/:projectsId/pulls/new"
|
||||
render={
|
||||
(props) => (<CreateMerge {...this.props} {...props} {...this.state} {...common} is_fork={true} />)
|
||||
}
|
||||
></Route>
|
||||
<Route path="/:owner/:projectsId/pulls/:mergeId/UpdateMerge"
|
||||
<Route path="/:owner/:projectsId/pulls/:mergeId/edit"
|
||||
render={
|
||||
(props) => (<UpdateMerge {...this.props} {...props} {...this.state} {...common} />)
|
||||
}
|
||||
></Route>
|
||||
<Route path="/:owner/:projectsId/pulls/:mergeId/Messagecount"
|
||||
<Route path="/:owner/:projectsId/pulls/:mergeId"
|
||||
render={
|
||||
(props) => (<MessageCount {...this.props} {...props} {...this.state} {...common} />)
|
||||
}
|
||||
></Route>
|
||||
<Route path="/:owner/:projectsId/pulls/:mergeId/commits"
|
||||
render={
|
||||
(props) => (<MessageCount {...this.props} {...props} {...this.state} {...common} />)
|
||||
}
|
||||
></Route>
|
||||
<Route path="/:owner/:projectsId/pulls/:mergeId/files"
|
||||
render={
|
||||
(props) => (<MessageCount {...this.props} {...props} {...this.state} {...common} />)
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import { getImageUrl } from 'educoder';
|
|||
import Files from '../Merge/Files';
|
||||
import Tree from "./img/tree.png";
|
||||
import User from "../Component/User";
|
||||
import RenderHtml from "../../components/render-html";
|
||||
import axios from "axios";
|
||||
import { Link } from "react-router-dom";
|
||||
|
||||
|
@ -17,8 +18,11 @@ const Infos = styled.div`
|
|||
border: 1px solid rgba(42, 97, 255, 0.23);
|
||||
border-radius: 3px 3px 0px 0px;
|
||||
padding: 10px 20px 10px 16px;
|
||||
& .f-wrap-between{
|
||||
align-items: center;
|
||||
& .markdown-body table{
|
||||
background: #f1f8ff;
|
||||
}
|
||||
& .btnblue{
|
||||
margin-top: 12px;
|
||||
}
|
||||
& .task-hide{
|
||||
width: 65rem;
|
||||
|
@ -85,9 +89,9 @@ export default (props) => {
|
|||
<div className="f-wrap-between">
|
||||
<div>
|
||||
{commit && commit.message &&
|
||||
<pre className="task-hide">{commit.message}</pre>
|
||||
<RenderHtml className="task-hide" value={commit.message}/>
|
||||
}
|
||||
<Link to={`/${owner}/${projectsId}/tree/${truncateCommitId(sha)}`}><i className="iconfont icon-fenzhi2 font-18"></i>{data.branch}</Link>
|
||||
<Link to={`/${owner}/${projectsId}/tree/${data.branch}`}><i className="iconfont icon-fenzhi2 font-18"></i>{data.branch}</Link>
|
||||
</div>
|
||||
<Button type="primary" onClick={()=>{history.push(`/${owner}/${projectsId}/tree/${truncateCommitId(sha)}`)}} className="btnblue" style={{height:"36px"}}>浏览文件</Button>
|
||||
</div>
|
||||
|
|
|
@ -195,7 +195,7 @@
|
|||
width: 40px;
|
||||
height: 40px;
|
||||
}
|
||||
&:nth-child(5){
|
||||
&:nth-child(5n){
|
||||
margin-right: 0px;
|
||||
}
|
||||
}
|
||||
|
@ -224,7 +224,7 @@
|
|||
height: 8px;
|
||||
width: 8px;
|
||||
left: 0px;
|
||||
top:10px
|
||||
top:8px;
|
||||
}
|
||||
&>span{
|
||||
padding-left: 15px;
|
||||
|
@ -252,7 +252,13 @@
|
|||
border: 1px solid rgba(42, 97, 255, 0.23);
|
||||
background-color: #FAFCFF;
|
||||
.ellipsistxt{
|
||||
margin-top: 6px;
|
||||
&:hover .markdown-body{
|
||||
color: #466AFF;
|
||||
& a{
|
||||
color: #466AFF;
|
||||
}
|
||||
}
|
||||
margin-top: 2px;
|
||||
// cursor: pointer;
|
||||
#ptxt{
|
||||
margin-bottom: 0px;
|
||||
|
@ -263,6 +269,27 @@
|
|||
white-space:-pre-wrap; /* Opera 4-6 */
|
||||
white-space:-o-pre-wrap; /* Opera 7 */
|
||||
word-wrap:break-word;
|
||||
.markdown-body{
|
||||
line-height: 10px;
|
||||
font-size: 14px;
|
||||
& p {
|
||||
margin: 1px 0px 0px !important;
|
||||
font-size: 14px !important;
|
||||
}
|
||||
& ol,ul{
|
||||
padding-bottom: 3px;
|
||||
& li{
|
||||
min-height: 18px;
|
||||
}
|
||||
}
|
||||
& table{
|
||||
line-height: 1;
|
||||
background: #FAFCFF;
|
||||
}
|
||||
&:first-child {
|
||||
margin-top: -1px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
margin-left: 13px;
|
||||
line-height:18px;
|
||||
|
@ -270,7 +297,7 @@
|
|||
width: 0;
|
||||
color: #666;
|
||||
&.hidetxt{
|
||||
height: 18px;
|
||||
height: 24px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
padding-right:8px;
|
||||
|
@ -453,7 +480,7 @@
|
|||
}
|
||||
}
|
||||
.ant-anchor-wrapper{
|
||||
padding-left: 2px;
|
||||
padding-left: 2px!important;
|
||||
.ant-anchor-ink::before{
|
||||
background-color: #fff;
|
||||
}
|
||||
|
@ -463,8 +490,8 @@
|
|||
margin:0px auto;
|
||||
}
|
||||
.griditemAnchor{
|
||||
margin-left: 0px;
|
||||
padding: 0px;
|
||||
margin-left: 0px!important;
|
||||
padding: 0px!important;
|
||||
border-bottom: 1px solid #ddd;
|
||||
.ant-anchor{
|
||||
display: flex;
|
||||
|
|
|
@ -52,12 +52,6 @@ class IndexItem extends Component {
|
|||
<i className="iconfont icon-banbenku font-18 color-green" />
|
||||
</Tooltip>:""
|
||||
}
|
||||
{
|
||||
item.type && item.type === 1 ?
|
||||
<Tooltip title="该项目是一个导入于其他网站的仓库" className="ml5">
|
||||
<i className="iconfont icon-jingxiang font-18 color-green" />
|
||||
</Tooltip>:""
|
||||
}
|
||||
</AlignCenter>
|
||||
<span className="p-r-tags">
|
||||
{
|
||||
|
|
|
@ -734,7 +734,12 @@ a.color-grey-ccc:hover{
|
|||
border: 1px solid rgba(42, 97, 255, 0.23);
|
||||
border-radius: 4px;
|
||||
margin-left: 16px;
|
||||
align-items: center;
|
||||
& .treecopy{
|
||||
margin-top: 20px;
|
||||
}
|
||||
& .markdown-body table{
|
||||
background: #FAFCFF;
|
||||
}
|
||||
&:after,&:before{
|
||||
content: "";
|
||||
position: absolute;
|
||||
|
@ -760,6 +765,9 @@ a.color-grey-ccc:hover{
|
|||
&:before{
|
||||
border-right: 10px solid rgba(42, 97, 255, 0.58);
|
||||
}
|
||||
& .markdown-body table{
|
||||
background: #EEF6FF;
|
||||
}
|
||||
}
|
||||
.treecopy-cont{
|
||||
padding: 4px 15px;
|
||||
|
|
|
@ -50,7 +50,7 @@ function DetailBanner({ history,list , owner , projectsId , isManager , url , pa
|
|||
<Link to={{ pathname: `/${owner}/${projectsId}/issues`, state }}>
|
||||
<Tooltip title="易修是Issue的中文名,即问题列表" placement="bottom">
|
||||
<i className={"iconfont icon-yixiuicon1 color-grey-3 mr5 font-14"}></i>
|
||||
<span>易修</span>
|
||||
<span>易修(Issue)</span>
|
||||
</Tooltip>
|
||||
{projectDetail && projectDetail.issues_count ? <span className="num">{numFormat(projectDetail.issues_count)}</span> : ""}
|
||||
</Link>
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
import React,{ useEffect , useState } from 'react';
|
||||
import SubMenu from '../sub/SubMenu';
|
||||
import { Table , Tooltip } from 'antd';
|
||||
import { Table , Tooltip , Spin } from 'antd';
|
||||
import axios from 'axios';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { truncateCommitId } from '../../common/util';
|
||||
import { getImageUrl } from 'educoder';
|
||||
import Nonedata from '../../Nodata';
|
||||
import './Index.scss';
|
||||
import Tree from '../img/tree.png'
|
||||
import moment from 'moment';
|
||||
|
||||
|
||||
function Tags(props) {
|
||||
|
||||
const [ source , setSource ] = useState([]);
|
||||
const [ source , setSource ] = useState(undefined);
|
||||
const [ isSpin , setIsSpin ] = useState(true);
|
||||
|
||||
const { projectsId , owner } = props.match.params;
|
||||
|
||||
|
@ -21,6 +23,7 @@ function Tags(props) {
|
|||
axios.get(url).then((result) => {
|
||||
if (result) {
|
||||
setSource(result.data);
|
||||
setIsSpin(false);
|
||||
}
|
||||
}).catch(error => {})
|
||||
}
|
||||
|
@ -32,8 +35,13 @@ function Tags(props) {
|
|||
dataIndex:"name",
|
||||
key:1,
|
||||
ellipsis:true,
|
||||
width:"200px",
|
||||
render:(txt,item)=>{
|
||||
return <Link className="hover" to={`/${owner}/${projectsId}/tree/${item.name}`} >{item.name}</Link>
|
||||
return(
|
||||
<div className="tagBranch">
|
||||
<Link className="hover tagClass" to={`/${owner}/${projectsId}/tree/${item.name}`}>{item.name}</Link>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -43,8 +51,22 @@ function Tags(props) {
|
|||
ellipsis:true,
|
||||
render:(txt,item)=>{
|
||||
return (
|
||||
<span className="color-grey-3">
|
||||
<Link className="mr3" style={{fontWeight:"500"}} to={`/${item.commit && item.commit.login}`} >{item.commit && item.commit.name}</Link>
|
||||
<span className="color-grey-3 tagModel">
|
||||
{
|
||||
item.tagger &&
|
||||
<Tooltip placement="top" title={item.tagger.name}>
|
||||
{
|
||||
item.tagger.id ?
|
||||
<Link className="mr3 tagModelImg" to={`/${item.tagger.login}`} >
|
||||
<img src={getImageUrl(`/${item.tagger && item.tagger.image_url}`)} alt=""/>
|
||||
</Link>
|
||||
:
|
||||
<span className="mr3 tagModelImg" style={{cursor:"default"}}>
|
||||
<img src={getImageUrl(`/${item.tagger && item.tagger.image_url}`)} alt=""/>
|
||||
</span>
|
||||
}
|
||||
</Tooltip>
|
||||
}
|
||||
<span>创建于{txt}</span>
|
||||
</span>
|
||||
)
|
||||
|
@ -59,7 +81,7 @@ function Tags(props) {
|
|||
return (
|
||||
<Tooltip placement="top" title={`最后提交日期:${item.created_at_unix ? moment(item.created_at_unix*1000).format('YYYY-MM-DD'):''}`}>
|
||||
<img src={Tree} alt="提交ID" width="22px" className="mr4"/>
|
||||
<Link className="hover color-blue" to={`/${owner}/${projectsId}/commits/${truncateCommitId(`${item.commit && item.commit.sha}`)}`}>{truncateCommitId(item.commit && item.commit.sha)}</Link>
|
||||
<Link className="hover color-blue" to={`/${owner}/${projectsId}/commits/${truncateCommitId(`${item.id}`)}`}>{truncateCommitId(item.id)}</Link>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
@ -79,18 +101,17 @@ function Tags(props) {
|
|||
key:5,
|
||||
ellipsis:true,
|
||||
align:"center",
|
||||
width:"181px",
|
||||
width:"204px",
|
||||
render:(txt,item)=>{
|
||||
return (
|
||||
<div>
|
||||
|
||||
<React.Fragment>
|
||||
<a href={`${item.tarball_url}`} download className="btn-83">
|
||||
<i className="iconfont icon-xiazai-icon font-16 mr5"></i>TAR
|
||||
</a>
|
||||
<a href={`${item.zipball_url}`} download className="btn-83">
|
||||
<i className="iconfont icon-xiazai-icon font-16 mr5"></i>ZIP
|
||||
</a>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -98,7 +119,19 @@ function Tags(props) {
|
|||
return(
|
||||
<div>
|
||||
<SubMenu tab={"tags"} projectsId={projectsId} owner={owner}/>
|
||||
<Table className="tagTable" dataSource={source} columns={columns} pagination={false}></Table>
|
||||
<Spin spinning={isSpin}>
|
||||
<div className="tagSpin">
|
||||
{
|
||||
source && source.length > 0 &&
|
||||
<Table
|
||||
className="tagTable"
|
||||
dataSource={source} columns={columns} pagination={false}></Table>
|
||||
}
|
||||
{
|
||||
source && source.length === 0 && <Nonedata _html={'暂无数据~'}/>
|
||||
}
|
||||
</div>
|
||||
</Spin>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
tr th{
|
||||
background-color: #fff;
|
||||
padding:5px 0px;
|
||||
width: 172px;
|
||||
.ant-table-column-title{
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
|
@ -12,6 +13,9 @@
|
|||
}
|
||||
}
|
||||
tbody{
|
||||
.btn-83{
|
||||
margin:0px 8px;
|
||||
}
|
||||
tr{
|
||||
&:hover td{
|
||||
background-color: #fff!important;
|
||||
|
@ -20,6 +24,10 @@
|
|||
padding:0px;
|
||||
height: 69px;
|
||||
line-height: 69px;
|
||||
color:#333333;
|
||||
div{
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
&:last-child{
|
||||
td{
|
||||
|
@ -28,4 +36,23 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.tagSpin{
|
||||
min-height: 300px;
|
||||
}
|
||||
.tagBranch{
|
||||
padding-right: 15px;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
.tagClass{
|
||||
color:#333333;
|
||||
}
|
||||
}
|
||||
.tagModel{
|
||||
font-weight: 400;
|
||||
.tagModelImg img{
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
|
@ -91,7 +91,7 @@ function Index(props) {
|
|||
<div className="treeabout">
|
||||
{
|
||||
(isManager || isDeveloper) && (projectDetail && projectDetail.type!==2) &&
|
||||
<Link to={`/${owner}/${projectsId}/pulls/new/${i.name}`} className="btn-83">+ 合并请求</Link>
|
||||
<Link to={`/${owner}/${projectsId}/compare/master...${i.name}`} className="btn-83">+ 合并请求</Link>
|
||||
}
|
||||
<Dropdown overlay={menu(i.zip_url,i.tar_url)} trigger={['click']} placement="bottomRight">
|
||||
<a className="btn-83 ml15">下载<i className="iconfont icon-sanjiaoxing-down font-14"></i></a>
|
||||
|
|
|
@ -22,9 +22,14 @@
|
|||
border-bottom: none;
|
||||
}
|
||||
.treeinfo{
|
||||
max-width: 399px;
|
||||
width: 399px;
|
||||
flex:1;
|
||||
flex-direction: column;
|
||||
&>a{
|
||||
display: block;
|
||||
width: 399px;
|
||||
|
||||
}
|
||||
a:hover{
|
||||
span{
|
||||
color: #466AFF!important;
|
||||
|
|
|
@ -15,10 +15,9 @@ function version(props) {
|
|||
const [ releases , setReleases ] = useState(undefined);
|
||||
const [ isSpin , setIsSpin ] = useState(true);
|
||||
const { projectsId ,owner } = props.match.params;
|
||||
const { isManager, isDeveloper, location , user } = props;
|
||||
const { location } = props;
|
||||
const type = props.projectDetail && props.projectDetail.type;
|
||||
const turnFromNew = location && location.query && location.query.turnFromNew;
|
||||
const current_user_login = user && user.login;
|
||||
useEffect(()=>{
|
||||
getIssueList();
|
||||
},[])
|
||||
|
@ -34,7 +33,6 @@ function version(props) {
|
|||
setReleases(result.data.releases);
|
||||
setIsSpin(false);
|
||||
}
|
||||
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
})
|
||||
|
@ -130,6 +128,8 @@ function version(props) {
|
|||
addFunc={addFunc}
|
||||
/>
|
||||
)
|
||||
} else{
|
||||
return (<div></div>)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,448 @@
|
|||
import React, { Component } from 'react';
|
||||
import { Input, Select, Spin, Alert } from 'antd';
|
||||
import axios from 'axios';
|
||||
import MergeForm from './merge_form';
|
||||
import MergeFooter from './merge_footer';
|
||||
|
||||
import '../Order/order.css';
|
||||
import './merge.css';
|
||||
|
||||
/**
|
||||
* 根据url获取目标仓库、目标分支、源仓库、源分支
|
||||
* 路由规则:owner/projectId/compare/merge...pullowner:pullBranch
|
||||
* 可能存在的情况
|
||||
* 1、代码库首页跳转,仓库相同,目标分支为默认分支,owner/projectId/compare/pullBranch
|
||||
* 2、代码库分支列表,仓库相同,目标分支为默认分支,owner/projectId/compare/pullBranch
|
||||
* 3、合并请求列表页(新建、无数据时的提示),仓库相同,源、目标都为默认分支,owner/projectId/compare
|
||||
* 4、新建页面,切换分支、切换目标仓库、刷新页面等,存在所有可能情况
|
||||
*/
|
||||
function getBranchParams(pathname) {
|
||||
const result = {
|
||||
// 目标仓库所有者
|
||||
mergeOwner: undefined,
|
||||
// 目标分支
|
||||
mergeBranch: 'master',
|
||||
// 源仓库所有者
|
||||
pullOwner: undefined,
|
||||
// 源分支
|
||||
pullBranch: 'master',
|
||||
// 仓库名称
|
||||
projectId: undefined,
|
||||
};
|
||||
// 去掉第一个字符/
|
||||
const _pathname = pathname.slice(1);
|
||||
const [ownerProject, branchUrl] = _pathname.split('/compare');
|
||||
const [mergeOwner, projectId] = ownerProject.split('/');
|
||||
// 同仓库时
|
||||
result.mergeOwner = mergeOwner;
|
||||
result.pullOwner = mergeOwner;
|
||||
result.projectId = projectId;
|
||||
if (branchUrl) {
|
||||
// 如果存在具体的分支
|
||||
const _branchUrl = branchUrl.slice(1);
|
||||
if (_branchUrl.indexOf('...') > -1) {
|
||||
// 存在源分支与目标分支
|
||||
const [mergeBranch, pullObj] = _branchUrl.split('...');
|
||||
result.mergeBranch = mergeBranch;
|
||||
if (pullObj.indexOf(':') > -1) {
|
||||
// 存在源仓库
|
||||
const [pullOwner, pullBranch] = pullObj.split(':');
|
||||
result.pullOwner = pullOwner;
|
||||
result.pullBranch = pullBranch;
|
||||
} else {
|
||||
result.pullBranch = pullObj;
|
||||
}
|
||||
} else {
|
||||
result.pullBranch = _branchUrl;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const Option = Select.Option;
|
||||
|
||||
class CreateMerge extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
const { pullBranch, mergeBranch } = getBranchParams(
|
||||
this.props.location.pathname
|
||||
);
|
||||
this.state = {
|
||||
data: undefined,
|
||||
pullBranches: undefined,
|
||||
mergeBranches: undefined,
|
||||
mergeProjects: undefined,
|
||||
merge: mergeBranch || 'master',
|
||||
pull: pullBranch || 'master',
|
||||
id: undefined,
|
||||
// isFork: false,
|
||||
projects_names: undefined,
|
||||
isSpin: true,
|
||||
showMessage: false,
|
||||
merge_head: false, // 是否向fork后的源项目发起合并请求
|
||||
defaultMessage: '必须选择不同的分支',
|
||||
project_id: undefined, // 当前项目的id,也即开始发送合并请求的源项目id
|
||||
merge_project_user: undefined,
|
||||
comparesData: undefined, //提交和文件的内容,保存compare接口返回的数据
|
||||
// 比较分支时的加载效果
|
||||
isCompareSpin: true,
|
||||
// 是否是初次加载,用这个字段来控制提示组件和文件组件的显示、隐藏比直接用isCompareSpin交互友好些
|
||||
isFirstLoading: true,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount = () => {
|
||||
// 初始化时根据url获取目标仓库、分支,源仓库、分支;
|
||||
// 再获取对应的仓库列表、分支列表
|
||||
// 再调用比较接口
|
||||
const branchParams = getBranchParams(this.props.location.pathname);
|
||||
this.getMergeInfo(branchParams);
|
||||
};
|
||||
|
||||
componentDidUpdate = (preProps) => {
|
||||
// url变化触发时(切换源分支、切换目标仓库、切换目标分支;回退)
|
||||
const oldPathname = preProps.location.pathname;
|
||||
const newPathname = this.props.location.pathname;
|
||||
if (oldPathname !== newPathname) {
|
||||
const branchParams = getBranchParams(newPathname);
|
||||
this.getMergeInfo(branchParams);
|
||||
}
|
||||
};
|
||||
|
||||
//获取新建合并请求数据
|
||||
getMergeInfo = (branchParams) => {
|
||||
this.setState({ isSpin: true });
|
||||
const { pullOwner, pullBranch, mergeOwner, mergeBranch, projectId } =
|
||||
branchParams;
|
||||
const url = `/${pullOwner}/${projectId}/pulls/new.json`;
|
||||
axios
|
||||
.get(url)
|
||||
.then((result) => {
|
||||
if (result) {
|
||||
// 如果url上的分支不存在,取默认值master
|
||||
const noMergeBranch =
|
||||
(result.data.branches || []).filter(
|
||||
(branch) => branch.name === mergeBranch
|
||||
).length === 0;
|
||||
const noPullBranch =
|
||||
(result.data.branches || []).filter(
|
||||
(branch) => branch.name === pullBranch
|
||||
).length === 0;
|
||||
this.setState({
|
||||
// isFork: result.data.is_fork,
|
||||
projects_names: result.data.projects_names,
|
||||
mergeProjects: result.data.merge_projects,
|
||||
pullBranches: result.data.branches,
|
||||
mergeBranches: result.data.branches,
|
||||
project_id: result.data.project_id,
|
||||
id: result.data.id,
|
||||
merge: mergeBranch,
|
||||
pull: pullBranch,
|
||||
});
|
||||
|
||||
//判断源分支是否存在
|
||||
if(noPullBranch){
|
||||
this.setState({
|
||||
showMessage: true,
|
||||
defaultMessage:'源分支不存在',
|
||||
isCompareSpin: false,
|
||||
});
|
||||
}else{
|
||||
if(pullOwner === mergeOwner){
|
||||
if (!noMergeBranch) {
|
||||
this.compareProject(true, branchParams);
|
||||
} else {
|
||||
this.setState({
|
||||
showMessage: true,
|
||||
defaultMessage:'目标分支不存在',
|
||||
isCompareSpin: false,
|
||||
});
|
||||
}
|
||||
}else{
|
||||
this.getBranchList(branchParams);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.setState({ isSpin: false });
|
||||
})
|
||||
.catch((error) => {
|
||||
this.setState({ isSpin: false });
|
||||
console.log(error);
|
||||
});
|
||||
};
|
||||
|
||||
// compare接口,获取分支对比信息
|
||||
compareProject = (sameProject, branchParams) => {
|
||||
// const { project } = this.props;
|
||||
// const { owner, projectsId } = this.props.match.params;
|
||||
const { pullOwner, pullBranch, mergeOwner, mergeBranch, projectId } =
|
||||
branchParams;
|
||||
|
||||
let url = `/${mergeOwner}/${projectId}/compare`;
|
||||
if (sameProject) {
|
||||
url += `/${pullBranch}...${mergeBranch}.json`;
|
||||
} else {
|
||||
url += `/${mergeBranch}...${pullOwner}/${projectId}:${pullBranch}.json`;
|
||||
}
|
||||
this.setState({ isSpin: false, isCompareSpin: true });
|
||||
axios
|
||||
.get(url)
|
||||
.then((result) => {
|
||||
if (result) {
|
||||
if (result.data.status === 0) {
|
||||
this.setState({
|
||||
showMessage: false,
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
showMessage: true,
|
||||
defaultMessage: result.data.message,
|
||||
});
|
||||
}
|
||||
this.setState({
|
||||
comparesData: result.data,
|
||||
});
|
||||
}
|
||||
this.setState({
|
||||
isFirstLoading: false,
|
||||
isSpin: false,
|
||||
isCompareSpin: false,
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
this.setState({ isSpin: false, isCompareSpin: false });
|
||||
});
|
||||
};
|
||||
|
||||
// 根据所有者、仓库名,获取分支列表,目前仅涉及目标仓库分支查询
|
||||
getBranchList = (branchParams) => {
|
||||
const { mergeOwner, projectId, mergeBranch } = branchParams;
|
||||
this.setState({ isSpin: true });
|
||||
const url = `/${mergeOwner}/${projectId}/pulls/get_branches.json`;
|
||||
axios
|
||||
.get(url)
|
||||
.then((result) => {
|
||||
if (result) {
|
||||
const noMergeBranch =
|
||||
(result.data || []).filter((branch) => branch.name === mergeBranch)
|
||||
.length === 0;
|
||||
this.setState({
|
||||
mergeBranches: result.data,
|
||||
showMessage: noMergeBranch,
|
||||
defaultMessage: '目标分支不存在',
|
||||
isCompareSpin: false,
|
||||
});
|
||||
!noMergeBranch && this.compareProject(false, branchParams);
|
||||
}
|
||||
this.setState({ isSpin: false });
|
||||
})
|
||||
.catch((error) => {
|
||||
this.setState({ isSpin: false });
|
||||
console.log(error);
|
||||
});
|
||||
};
|
||||
|
||||
// 切换分支事件
|
||||
selectBrach = (type, value) => {
|
||||
const { pullOwner, pullBranch, mergeOwner, mergeBranch, projectId } =
|
||||
getBranchParams(this.props.location.pathname);
|
||||
let _url = `/${mergeOwner}/${projectId}/compare/`;
|
||||
// type为pull时,pullBranch取value,否则取原有值
|
||||
// type为pull时,mergeBranch取原有值,否则取value
|
||||
let _pullBranch = type === 'pull' ? value : pullBranch;
|
||||
let _mergeBranch = type === 'pull' ? mergeBranch : value;
|
||||
if (pullOwner === mergeOwner) {
|
||||
// 如果仓库相同, compare/目标分支...源分支
|
||||
_url += `${_mergeBranch}...${_pullBranch}`;
|
||||
} else {
|
||||
// 如果仓库不同, compare/目标分支...源分支
|
||||
_url += `${_mergeBranch}...${pullOwner}:${_pullBranch}`;
|
||||
}
|
||||
this.props.history.push(_url);
|
||||
};
|
||||
|
||||
// 切换仓库响应事件,目前仅目标分支可切换仓库
|
||||
selectProjectName = (value) => {
|
||||
const { projects_names, id } = this.state;
|
||||
const { pullOwner, pullBranch } = getBranchParams(
|
||||
this.props.location.pathname
|
||||
);
|
||||
let arr =
|
||||
projects_names && projects_names.filter((item) => item.id === value);
|
||||
let identifier = arr && arr[0].project_id;
|
||||
let login = arr && arr[0].project_user_login;
|
||||
// 目标仓库与源仓库不是一个仓库
|
||||
let is_fork = parseInt(value, 10) !== parseInt(id, 10);
|
||||
this.setState({
|
||||
isSpin: true,
|
||||
// merge_head: is_fork,
|
||||
data: {
|
||||
is_original: is_fork,
|
||||
fork_project_id: is_fork ? id : '',
|
||||
merge_user_login: is_fork
|
||||
? projects_names[0].project_user_login
|
||||
: undefined,
|
||||
},
|
||||
});
|
||||
if (login === pullOwner) {
|
||||
// 如果切换后, 仓库与源仓库一致了
|
||||
this.props.history.push(
|
||||
`/${login}/${identifier}/compare/master...${pullBranch}`
|
||||
);
|
||||
} else {
|
||||
this.props.history.push(
|
||||
`/${login}/${identifier}/compare/master...${pullOwner}:${pullBranch}`
|
||||
);
|
||||
}
|
||||
// this.newMergelist(login, identifier);
|
||||
};
|
||||
|
||||
// 渲染分支列表
|
||||
renderBrances = (list) => {
|
||||
if (list && list.length > 0) {
|
||||
return list.map((item, key) => {
|
||||
return (
|
||||
<Option key={key + 1} value={item.name}>
|
||||
{item.name}
|
||||
</Option>
|
||||
);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 渲染项目列表
|
||||
renderProjectNames = (list) => {
|
||||
if (list && list.length > 0) {
|
||||
return list.map((item, key) => {
|
||||
return (
|
||||
<Option key={key + 1} value={item.id}>
|
||||
{item.project_name}
|
||||
</Option>
|
||||
);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 渲染html内容
|
||||
withHtml = (html) => {
|
||||
return <div dangerouslySetInnerHTML={{ __html: html }}></div>;
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
data,
|
||||
pullBranches,
|
||||
mergeBranches,
|
||||
mergeProjects,
|
||||
pull,
|
||||
merge,
|
||||
isSpin,
|
||||
isCompareSpin,
|
||||
isFirstLoading,
|
||||
showMessage,
|
||||
defaultMessage,
|
||||
projects_names,
|
||||
id,
|
||||
comparesData,
|
||||
} = this.state;
|
||||
|
||||
let { project } = this.props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Spin spinning={isSpin || isCompareSpin}>
|
||||
<div className="main">
|
||||
<div className="merge-header width100 inline-block">
|
||||
<div className="width40 pull-left">
|
||||
<div className="color-grey-3 mb10 fwb">源分支:</div>
|
||||
<Input.Group compact className="display-flex">
|
||||
<Select
|
||||
value={id}
|
||||
className="hide-1 task-hide flex1"
|
||||
disabled
|
||||
>
|
||||
{this.renderProjectNames(projects_names)}
|
||||
</Select>
|
||||
<Select
|
||||
value={pull}
|
||||
onSelect={(e) => this.selectBrach('pull', e)}
|
||||
showSearch
|
||||
className="merge-flex1 flex1 matchwidth"
|
||||
dropdownMatchSelectWidth={false}
|
||||
dropdownClassName="overlihide"
|
||||
>
|
||||
{this.renderBrances(pullBranches)}
|
||||
</Select>
|
||||
</Input.Group>
|
||||
</div>
|
||||
<div className="width10 pull-left text-center mt25">
|
||||
<i
|
||||
className={'iconfont icon-youjiang color-grey-c font-32'}
|
||||
></i>
|
||||
</div>
|
||||
<div className="width40 pull-left">
|
||||
<div>
|
||||
<div className="color-grey-3 mb10 fwb">目标分支:</div>
|
||||
<Input.Group compact className="display-flex">
|
||||
<Select
|
||||
value={project && project.id}
|
||||
className="hide-1 task-hide flex1"
|
||||
onSelect={(e) => this.selectProjectName(e)}
|
||||
>
|
||||
{this.renderProjectNames(mergeProjects)}
|
||||
</Select>
|
||||
<Select
|
||||
value={merge}
|
||||
onSelect={(e) => this.selectBrach('merge', e)}
|
||||
showSearch
|
||||
className="merge-flex1 flex1 matchwidth"
|
||||
dropdownMatchSelectWidth={false}
|
||||
dropdownClassName="overlihide"
|
||||
>
|
||||
{this.renderBrances(mergeBranches)}
|
||||
</Select>
|
||||
</Input.Group>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* 非加载状态且有提示 */}
|
||||
{!isCompareSpin && showMessage && (
|
||||
<div className="mb20">
|
||||
<Alert
|
||||
description={this.withHtml(defaultMessage)}
|
||||
type="error"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{/* 非加载状态且可以提交 */}
|
||||
{!isCompareSpin && !showMessage && (
|
||||
<MergeForm
|
||||
{...this.props}
|
||||
merge_type="new"
|
||||
data={data}
|
||||
merge={merge}
|
||||
pull={pull}
|
||||
files_count={
|
||||
comparesData &&
|
||||
comparesData.diff &&
|
||||
comparesData.diff.files_count
|
||||
}
|
||||
commits_count={comparesData && comparesData.commits_count}
|
||||
></MergeForm>
|
||||
)}
|
||||
</div>
|
||||
{!isFirstLoading && (
|
||||
<MergeFooter
|
||||
{...this.props}
|
||||
merge={merge}
|
||||
pull={pull}
|
||||
comparesData={comparesData}
|
||||
></MergeFooter>
|
||||
)}
|
||||
</Spin>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default CreateMerge;
|
|
@ -1,7 +1,7 @@
|
|||
import React ,{useEffect,useRef,useState } from 'react';
|
||||
import React ,{useEffect,useState } from 'react';
|
||||
import { truncateCommitId } from '../common/util';
|
||||
import { AlignCenter , FlexAJ } from '../Component/layout';
|
||||
import { Button, Tooltip,Progress, Popover, Anchor } from 'antd';
|
||||
import { Tooltip,Progress } from 'antd';
|
||||
import './merge.css';
|
||||
import './Index.scss';
|
||||
|
||||
|
@ -16,6 +16,10 @@ function Files({ data,history,owner,projectsId , parentsSha }){
|
|||
}
|
||||
},[data]);
|
||||
|
||||
useEffect(()=>{
|
||||
document.addEventListener('click',()=>{setIsOpen(false)})
|
||||
})
|
||||
|
||||
function showDown(flag,index,isBin){
|
||||
if(!isBin){
|
||||
var lists = files.concat();
|
||||
|
@ -48,7 +52,7 @@ function Files({ data,history,owner,projectsId , parentsSha }){
|
|||
<span className="cursor-pointer" data-clipboard-text={item.name}>{item.name}</span>
|
||||
</AlignCenter>
|
||||
<div className="see-file">
|
||||
<Tooltip placement="top" title={`${item.addition+item.deletion}处更改${item.addition + item.deletion > 0 && ":"}${item.addition>0?item.addition+"处添加":""}${item.addition>0 && item.deletion>0 ?"和":""}${item.deletion>0?item.deletion+"处删除":""}`}>
|
||||
<Tooltip placement="top" title={`${item.addition+item.deletion}处更改${item.addition + item.deletion > 0 ? ":":""}${item.addition>0?item.addition+"处添加":""}${item.addition>0 && item.deletion>0 ?"和":""}${item.deletion>0?item.deletion+"处删除":""}`}>
|
||||
<Progress showInfo = {false} strokeColor = "#2DB44D" size="small" percent={item.addition/(item.addition+item.deletion)*100} />
|
||||
{item.addition >0 && <span className="color-green ml10">+{item.addition}</span>}
|
||||
{item.deletion >0 && <span className="color-red ml10">-{item.deletion}</span>}
|
||||
|
@ -63,7 +67,7 @@ function Files({ data,history,owner,projectsId , parentsSha }){
|
|||
)
|
||||
|
||||
return(
|
||||
<div>
|
||||
<div onClick={(e)=>{e.nativeEvent.stopImmediatePropagation()}}>
|
||||
<AlignCenter className="color-grey-9" style={{position:'relative'}}>
|
||||
<div onClick={()=>{setIsOpen(!isOpen)}}>
|
||||
<i className={`iconfont mr5 ${isOpen? "font-18 icon-sanjiaoxing-down":"font-16 icon-triangle"}`}></i>
|
||||
|
@ -96,7 +100,7 @@ function Files({ data,history,owner,projectsId , parentsSha }){
|
|||
</Tooltip>
|
||||
</AlignCenter>
|
||||
<div className="see-file">
|
||||
<Tooltip placement="top" title={`${item.addition + item.deletion}处更改${item.addition + item.deletion > 0 && ":"} ${item.addition > 0 ? item.addition + "处添加" : ""}${item.addition > 0 && item.deletion > 0 ? "和" : ""}${item.deletion > 0 ? item.deletion + "处删除" : ""}`}>
|
||||
<Tooltip placement="top" title={`${item.addition + item.deletion}处更改${item.addition + item.deletion > 0 ? ":":""} ${item.addition > 0 ? item.addition + "处添加" : ""}${item.addition > 0 && item.deletion > 0 ? "和" : ""}${item.deletion > 0 ? item.deletion + "处删除" : ""}`}>
|
||||
<Progress showInfo = {false} strokeColor = "#2DB44D" size="small" percent={item.addition/(item.addition+item.deletion)*100} />
|
||||
<span className="ml10">{item.addition+item.deletion}处</span>
|
||||
</Tooltip>
|
||||
|
|
|
@ -228,7 +228,7 @@ class MergeDetail extends Component {
|
|||
<div>
|
||||
{
|
||||
data && data.issue.user_permission ?
|
||||
<Link to={`/${owner}/${projectsId}/pulls/${mergeid}/updatemerge`} className="color-blue fr">编辑</Link>
|
||||
<Link to={`/${owner}/${projectsId}/pulls/${mergeid}/edit`} className="color-blue fr">编辑</Link>
|
||||
: ''
|
||||
}
|
||||
</div>
|
||||
|
|
|
@ -62,9 +62,9 @@ class MergeItem extends Component {
|
|||
<p className="mb15 df" style={{ alignItems: "center" }}>
|
||||
<i className={`iconfont icon-hebingqingqiu1 font-14 mr3 i_${status}`}></i>
|
||||
<Link
|
||||
to={`/${owner}/${projectsId}/pulls/${item.pull_request_id}/Messagecount`}
|
||||
to={`/${owner}/${projectsId}/pulls/${item.pull_request_id}`}
|
||||
className="hide-1 font-15 color-grey-3 fwb lineh-30 mr10"
|
||||
style={{ maxWidth: "300px" }}
|
||||
style={{ maxWidth: "600px" }}
|
||||
>
|
||||
{item.name}
|
||||
</Link>
|
||||
|
@ -110,7 +110,7 @@ class MergeItem extends Component {
|
|||
<Tag className="pr-branch-tag">
|
||||
<Link
|
||||
to={`/${item.is_original ? item.fork_project_user : owner}/${ item.is_original ? item.fork_project_identifier : projectsId }/tree/${turnbar(item.pull_request_head)}`}
|
||||
className="maxW200px hide-1 ver-middle"
|
||||
className="maxW200px task-hide ver-middle" style={{maxWidth:"200px"}}
|
||||
>
|
||||
{item.is_original
|
||||
? item.fork_project_user
|
||||
|
@ -134,7 +134,7 @@ class MergeItem extends Component {
|
|||
<Tag className="pr-branch-tag">
|
||||
<Link
|
||||
to={`/${owner}/${projectsId}/tree/${turnbar(item.pull_request_base)}`}
|
||||
className="maxW200px hide-1 ver-middle"
|
||||
className="maxW200px task-hide ver-middle" style={{maxWidth:"200px"}}
|
||||
>
|
||||
{/* {item.is_fork ? item.pull_request_base : `${item.author_name}:${item.pull_request_base}`} */}
|
||||
{project_author_name}:{item.pull_request_base}
|
||||
|
@ -175,7 +175,7 @@ class MergeItem extends Component {
|
|||
{item.journals_count ? (
|
||||
<Link
|
||||
className="mr5 color-grey-8"
|
||||
to={`/${owner}/${projectsId}/pulls/${item.pull_request_id}/Messagecount`}
|
||||
to={`/${owner}/${projectsId}/pulls/${item.pull_request_id}`}
|
||||
>
|
||||
<i className="iconfont icon-huifu1 font-15 mr5 ver-middle"></i>
|
||||
{item.journals_count}
|
||||
|
@ -196,7 +196,7 @@ class MergeItem extends Component {
|
|||
>
|
||||
<div className="grid-item mr15 color-grey-9">
|
||||
<Link
|
||||
to={`/${owner}/${projectsId}/pulls/${item.pull_request_id}/updatemerge`}
|
||||
to={`/${owner}/${projectsId}/pulls/${item.pull_request_id}/edit`}
|
||||
className="color-grey-9"
|
||||
>
|
||||
<i className="iconfont icon-bianji3 font-14 mr5"></i>
|
||||
|
|
|
@ -0,0 +1,210 @@
|
|||
import React, { Component } from 'react';
|
||||
import { Tabs, Spin } from 'antd';
|
||||
import { Link } from 'react-router-dom';
|
||||
import axios from 'axios';
|
||||
|
||||
import Commits from './Commits';
|
||||
import Comments from '../comments/comments';
|
||||
import Files from './Files';
|
||||
|
||||
import '../Order/order.css';
|
||||
import './merge.css';
|
||||
|
||||
const { TabPane } = Tabs;
|
||||
|
||||
class MergeFooter extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
commitsData: [],
|
||||
filesData: undefined,
|
||||
isSpin: false,
|
||||
activeKey: '1',
|
||||
commitCount: 0,
|
||||
filesCount: 0,
|
||||
// 总评论数量,包含回复
|
||||
commentsTotalCount: 0,
|
||||
};
|
||||
}
|
||||
componentDidMount() {
|
||||
this.Init();
|
||||
// 为父组件绑定当前,以方便调用方法
|
||||
this.props.bindFootRef && this.props.bindFootRef(this);
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
// 解决切换tab后浏览器回退不刷新的问题、点击tab后url变化但tab未切换的问题
|
||||
const newPathname = this.props.location.pathname;
|
||||
const prevPathname = prevProps.location.pathname;
|
||||
if (newPathname !== prevPathname) {
|
||||
this.Init(true);
|
||||
}
|
||||
}
|
||||
|
||||
Init = (isTabChange) => {
|
||||
const { data, location, match } = this.props;
|
||||
const { pathname } = location;
|
||||
const { projectsId, owner, mergeId } = match.params;
|
||||
|
||||
let activeKey = '1';
|
||||
if (pathname.indexOf('commits') > -1) {
|
||||
activeKey = '2';
|
||||
this.getCommit(owner, projectsId, mergeId);
|
||||
} else if (pathname.indexOf('files') > -1) {
|
||||
activeKey = '3';
|
||||
this.getFile(owner, projectsId, mergeId);
|
||||
}
|
||||
if (isTabChange && activeKey === '1') {
|
||||
this.refreshComment();
|
||||
}
|
||||
this.setState({
|
||||
activeKey: activeKey,
|
||||
commitCount: data && data.commits_count,
|
||||
filesCount: data && data.files_count,
|
||||
});
|
||||
};
|
||||
|
||||
bindCommentRef = (commentRef) => {
|
||||
this.childComment = commentRef;
|
||||
}
|
||||
|
||||
refreshComment = () => {
|
||||
this.childComment && this.childComment.getjournalslist();
|
||||
}
|
||||
|
||||
getCommit = (owner, projectsId, mergeId) => {
|
||||
this.setState({ isSpin: true });
|
||||
const url = `/${owner}/${projectsId}/pulls/${mergeId}/commits.json`;
|
||||
axios
|
||||
.get(url)
|
||||
.then((result) => {
|
||||
if (result) {
|
||||
this.setState({
|
||||
commitsData: result.data.commits,
|
||||
commitCount: result.data.commits_count,
|
||||
});
|
||||
}
|
||||
this.setState({ isSpin: false });
|
||||
})
|
||||
.catch((error) => {
|
||||
this.setState({ isSpin: false });
|
||||
});
|
||||
};
|
||||
|
||||
getFile = (owner, projectsId, mergeId) => {
|
||||
this.setState({ isSpin: true });
|
||||
const url = `/${owner}/${projectsId}/pulls/${mergeId}/files.json`;
|
||||
axios
|
||||
.get(url)
|
||||
.then((result) => {
|
||||
if (result) {
|
||||
this.setState({
|
||||
filesData: result.data,
|
||||
filesCount: result.data.files_count,
|
||||
});
|
||||
}
|
||||
this.setState({ isSpin: false });
|
||||
})
|
||||
.catch((error) => {
|
||||
this.setState({ isSpin: false });
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { projectsId, owner, mergeId } = this.props.match.params;
|
||||
|
||||
const { order_id, data = {} } = this.props;
|
||||
const {
|
||||
isSpin,
|
||||
activeKey,
|
||||
filesCount,
|
||||
commitCount,
|
||||
filesData,
|
||||
commitsData = [],
|
||||
} = this.state;
|
||||
|
||||
// 评论数量优先取Comment组件中列表接口返回的,其次取合并请求详情接口中的,都没有取默认值0
|
||||
const commentsTotalCount = parseInt(
|
||||
this.state.commentsTotalCount || data.comments_total_count || 0,
|
||||
10
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="main mergeRequest" style={{ paddingTop: '0px' }}>
|
||||
<Spin spinning={isSpin}>
|
||||
<Tabs
|
||||
activeKey={activeKey}
|
||||
className="custom-commit-tabs"
|
||||
animated={false}
|
||||
>
|
||||
<TabPane
|
||||
tab={
|
||||
<Link to={`/${owner}/${projectsId}/pulls/${mergeId}`}>
|
||||
<span className="font-16">评论</span>
|
||||
{commentsTotalCount > 0 && (
|
||||
<span className="tabNum">{commentsTotalCount}</span>
|
||||
)}
|
||||
</Link>
|
||||
}
|
||||
key="1"
|
||||
>
|
||||
<Comments
|
||||
order_id={order_id}
|
||||
showNotification={this.props.showNotification}
|
||||
only_show_content={true}
|
||||
updateCommentsNum={(commentsCount) => {
|
||||
this.setState({ commentsTotalCount: commentsCount || 0 });
|
||||
}}
|
||||
{...this.props}
|
||||
bindCommentRef={this.bindCommentRef}
|
||||
/>
|
||||
</TabPane>
|
||||
{commitCount > 0 && (
|
||||
<TabPane
|
||||
tab={
|
||||
<Link to={`/${owner}/${projectsId}/pulls/${mergeId}/commits`}>
|
||||
<span className="font-16">提交</span>
|
||||
{commitCount > 0 && (
|
||||
<span className="tabNum">{commitCount}</span>
|
||||
)}
|
||||
</Link>
|
||||
}
|
||||
key="2"
|
||||
>
|
||||
{commitsData.length > 0 && (
|
||||
<Commits
|
||||
{...this.props}
|
||||
commits={commitsData}
|
||||
projectsId={projectsId}
|
||||
owner={owner}
|
||||
></Commits>
|
||||
)}
|
||||
</TabPane>
|
||||
)}
|
||||
{filesCount > 0 && (
|
||||
<TabPane
|
||||
tab={
|
||||
<Link to={`/${owner}/${projectsId}/pulls/${mergeId}/files`}>
|
||||
<span className="font-16">文件</span>
|
||||
{filesCount > 0 && (
|
||||
<span className="tabNum">{filesCount}</span>
|
||||
)}
|
||||
</Link>
|
||||
}
|
||||
key="3"
|
||||
>
|
||||
<Files
|
||||
{...this.props}
|
||||
data={filesData}
|
||||
projectsId={projectsId}
|
||||
owner={owner}
|
||||
/>
|
||||
</TabPane>
|
||||
)}
|
||||
</Tabs>
|
||||
</Spin>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
export default MergeFooter;
|
|
@ -1,7 +1,6 @@
|
|||
import React, { Component } from "react";
|
||||
import { Tabs } from 'antd';
|
||||
import { Link } from "react-router-dom";
|
||||
import { AlignCenter } from '../Component/layout';
|
||||
import axios from "axios";
|
||||
import { getImageUrl } from "educoder";
|
||||
import {
|
||||
|
@ -11,7 +10,6 @@ import {
|
|||
Dropdown,
|
||||
Icon,
|
||||
Menu,
|
||||
Select,
|
||||
Tag,
|
||||
Button,
|
||||
Alert,
|
||||
|
@ -19,9 +17,8 @@ import {
|
|||
import "./merge.css";
|
||||
import RenderHtml from "../../components/render-html";
|
||||
import "../Order/order.css";
|
||||
import MergeFooter from "./merge_footer";
|
||||
import MergeLinkFooter from "./MergeLinkFooter";
|
||||
|
||||
const Option = Select.Option;
|
||||
const TextArea = Input.TextArea;
|
||||
|
||||
function turnbar(str){
|
||||
|
@ -61,6 +58,11 @@ class MessageCount extends Component {
|
|||
|
||||
// this.clickBody();
|
||||
};
|
||||
|
||||
bindFootRef = (footRef) => {
|
||||
this.footRef = footRef;
|
||||
}
|
||||
|
||||
clickBody=()=>{
|
||||
document.body.addEventListener('click', e => {
|
||||
let name = e.target.className;
|
||||
|
@ -150,6 +152,8 @@ class MessageCount extends Component {
|
|||
});
|
||||
const { getDetail } = this.props;
|
||||
getDetail && getDetail();
|
||||
// 调用子组件的方法刷新评论列表
|
||||
this.footRef && this.footRef.refreshComment();
|
||||
} else {
|
||||
this.setState({ SpinMerge: false });
|
||||
}
|
||||
|
@ -283,13 +287,13 @@ class MessageCount extends Component {
|
|||
conflict_files && conflict_files.length>0 &&
|
||||
<div>
|
||||
<p className="mt10 font-16 pt10" style={{borderTop:"1px solid #f9d7d5"}}>如下文件有代码冲突:</p>
|
||||
<p>
|
||||
<div>
|
||||
{
|
||||
conflict_files.map((i,k)=>{
|
||||
return <p>{i}</p>
|
||||
return <p key={k}>{i}</p>
|
||||
})
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
@ -336,11 +340,11 @@ class MessageCount extends Component {
|
|||
<div>
|
||||
<div className="main">
|
||||
<div>
|
||||
<div className="grid-item-top pb20 border-1f">
|
||||
<div>
|
||||
<div className="pb20 border-1f df">
|
||||
<div className="flex1">
|
||||
<div className="ver-middle">
|
||||
<span className="mr10 ver-middle">
|
||||
<span className="font-18 fwb">
|
||||
<span className="font-18 fwb" style={{wordBreak:"break-all"}}>
|
||||
{data.issue.subject}
|
||||
</span>
|
||||
</span>
|
||||
|
@ -362,7 +366,7 @@ class MessageCount extends Component {
|
|||
<Tag className="pr-branch-tag">
|
||||
<Link
|
||||
to={`/${data.pull_request.is_original ? data.pull_request.fork_project_user : data.issue.project_author_name}/${data.pull_request.is_original?data.project_identifier:projectsId}/tree/${turnbar(data.pull_request && data.pull_request.head)}`}
|
||||
className="ver-middle"
|
||||
className="ver-middle task-hide" style={{maxWidth:"200px"}} title={`${data.pull_request.is_original ? data.pull_request.fork_project_user : data.issue.project_author_name}: ${data.pull_request && data.pull_request.head}`}
|
||||
>
|
||||
{data.pull_request.is_original ? data.pull_request.fork_project_user : data.issue.project_author_name}: {data.pull_request && data.pull_request.head}
|
||||
</Link>
|
||||
|
@ -377,7 +381,7 @@ class MessageCount extends Component {
|
|||
<Tag className="pr-branch-tag">
|
||||
<Link
|
||||
to={`/${owner}/${projectsId}/tree/${data.pull_request.base}`}
|
||||
className="ver-middle"
|
||||
className="ver-middle task-hide" style={{maxWidth:"200px"}} title={`${data.issue.project_author_name}:${data.pull_request.base}`}
|
||||
>
|
||||
{data.issue.project_author_name}:{data.pull_request.base}
|
||||
</Link>
|
||||
|
@ -441,14 +445,13 @@ class MessageCount extends Component {
|
|||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="ml10">
|
||||
<div className="mt15 text-right" style={{display:"flex",justifyContent:"flex-end"}}>
|
||||
<div className="ml10 text-right">
|
||||
{operate && (
|
||||
<Button
|
||||
type="green"
|
||||
ghost
|
||||
className="ml20"
|
||||
onClick={()=>{this.props.history.push(`/${owner}/${projectsId}/pulls/${mergeId}/UpdateMerge`);}}
|
||||
onClick={()=>{this.props.history.push(`/${owner}/${projectsId}/pulls/${mergeId}/edit`);}}
|
||||
>
|
||||
编辑
|
||||
</Button>
|
||||
|
@ -465,7 +468,6 @@ class MessageCount extends Component {
|
|||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{
|
||||
data.issue.description ?
|
||||
|
@ -543,7 +545,7 @@ class MessageCount extends Component {
|
|||
onChange={this.changbodypr}
|
||||
/>
|
||||
</div>
|
||||
<p
|
||||
<div
|
||||
className="clearfix mt15"
|
||||
style={{ display: this.state.buttonshow }}
|
||||
>
|
||||
|
@ -558,19 +560,19 @@ class MessageCount extends Component {
|
|||
取消
|
||||
</Button>
|
||||
</Spin>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</Spin>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<MergeFooter
|
||||
footer_type={true}
|
||||
<MergeLinkFooter
|
||||
order_id={data && data.issue.id}
|
||||
{...this.props}
|
||||
{...this.state}
|
||||
></MergeFooter>
|
||||
bindFootRef={this.bindFootRef}
|
||||
></MergeLinkFooter>
|
||||
</div>
|
||||
) : (
|
||||
""
|
||||
|
|
|
@ -6,6 +6,11 @@ import "./merge.css";
|
|||
import MergeForm from "./merge_form";
|
||||
import MergeFooter from "./merge_footer";
|
||||
const Option = Select.Option;
|
||||
/**
|
||||
* 此文件已废弃,新文件为CreateMerge.js
|
||||
* 2021.10.12
|
||||
*/
|
||||
|
||||
class NewMerge extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
@ -194,7 +199,7 @@ class NewMerge extends Component {
|
|||
// this.ischeckmerge();
|
||||
let { id ,merge , pull } = this.state;
|
||||
if(type==="pull"){
|
||||
this.props.history.push(`/${owner}/${projectsId}/pulls/new/${pull}`)
|
||||
this.props.history.push(`/${owner}/${projectsId}/compare/${pull}`)
|
||||
this.compareProject(id,value,merge);
|
||||
}else{
|
||||
this.compareProject(id,pull,value);
|
||||
|
@ -216,7 +221,7 @@ class NewMerge extends Component {
|
|||
merge_user_login: is_fork_id ? projects_names[0].project_user_login : undefined
|
||||
}
|
||||
})
|
||||
this.props.history.push(`/${login}/${identifier}/pulls/new`);
|
||||
this.props.history.push(`/${login}/${identifier}/compare`);
|
||||
this.newMergelist(login,identifier);
|
||||
};
|
||||
|
||||
|
|
|
@ -64,12 +64,12 @@ class UpdateMerge extends Component {
|
|||
<div className="color-grey-3 mb10 fwb">源分支:</div>
|
||||
|
||||
<Input.Group compact className="display-flex">
|
||||
<Button className="merge-header-button maxW50 hide-1 task-hide">
|
||||
<Button className="merge-header-button flex1 maxW50 hide-1 task-hide" disabled>
|
||||
{data.is_original ? `${data.fork_project_user_name}/${data.fork_project_identifier}` : `${data.project_author}/${data.project_name}`}
|
||||
</Button>
|
||||
<Select
|
||||
defaultValue={data.is_original ? `${data.fork_project_user}:${pull}` : `${pull}`}
|
||||
className="minW50 merge-flex1"
|
||||
className="minW50 merge-flex1 flex1 matchwidth"
|
||||
disabled
|
||||
></Select>{" "}
|
||||
</Input.Group>{" "}
|
||||
|
@ -83,12 +83,12 @@ class UpdateMerge extends Component {
|
|||
<div>
|
||||
<div className="color-grey-3 mb10 fwb"> 目标分支 : </div>{" "}
|
||||
<Input.Group compact className="display-flex">
|
||||
<Button className="merge-header-button maxW50 hide-1 task-hide">
|
||||
<Button className="merge-header-button flex1 maxW50 hide-1 task-hide" disabled>
|
||||
{`${data.project_author}/${data.project_name}`}
|
||||
</Button>
|
||||
<Select
|
||||
defaultValue={data.is_original ? `${data.project_login}:${merge}` : `${merge}`}
|
||||
className="minW50 merge-flex1"
|
||||
className="minW50 merge-flex1 flex1 matchwidth"
|
||||
disabled
|
||||
></Select>{" "}
|
||||
</Input.Group>{" "}
|
||||
|
|
|
@ -40,6 +40,7 @@ form .ant-cascader-picker, form .ant-select {
|
|||
}
|
||||
.merge-header-button{
|
||||
background:rgba(241,248,255,1);
|
||||
text-align: left;
|
||||
}
|
||||
.width70{
|
||||
width:70%;
|
||||
|
@ -211,5 +212,14 @@ form .ant-cascader-picker, form .ant-select {
|
|||
}
|
||||
|
||||
.mergeRequest .folders{
|
||||
width: 72rem;
|
||||
}
|
||||
/* width: 72rem; */
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.matchwidth .ant-select-selection__rendered{
|
||||
width: 200px;
|
||||
}
|
||||
.overlihide li{
|
||||
max-width: 450px;
|
||||
|
||||
}
|
|
@ -213,7 +213,7 @@ class merge extends Component {
|
|||
|
||||
checkOperation() {
|
||||
const { projectsId,owner } = this.props.match.params;
|
||||
this.props.history.push(`/${owner}/${projectsId}/pulls/new`);
|
||||
this.props.history.push(`/${owner}/${projectsId}/compare/master...master`);
|
||||
}
|
||||
render() {
|
||||
const { projectsId , owner } = this.props.match.params;
|
||||
|
|
|
@ -1,169 +1,84 @@
|
|||
import React, { Component } from "react";
|
||||
import { Tabs, Spin } from "antd";
|
||||
import "../Order/order.css";
|
||||
import "./merge.css";
|
||||
import Commits from "./Commits";
|
||||
import Comments from "../comments/comments";
|
||||
import Files from "./Files";
|
||||
import axios from 'axios';
|
||||
import React, { Component } from 'react';
|
||||
import { Tabs } from 'antd';
|
||||
import Commits from './Commits';
|
||||
import Files from './Files';
|
||||
|
||||
import '../Order/order.css';
|
||||
import './merge.css';
|
||||
|
||||
const { TabPane } = Tabs;
|
||||
|
||||
class MergeFooter extends Component {
|
||||
constructor(props){
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state={
|
||||
pageData:undefined,
|
||||
commitsData:undefined,
|
||||
filesData:undefined,
|
||||
isSpin:false,
|
||||
activeKey:"1",
|
||||
commitCount:0,
|
||||
filesCount:0
|
||||
}
|
||||
}
|
||||
componentDidMount=()=>{
|
||||
const { footer_type ,data } = this.props;
|
||||
if(footer_type){
|
||||
const { projectsId , owner , mergeId } = this.props.match.params;
|
||||
this.getCommit(owner,projectsId,mergeId);
|
||||
this.getFile(owner,projectsId,mergeId);
|
||||
}
|
||||
this.setState({
|
||||
activeKey:footer_type ? "1" : "2",
|
||||
commitCount:data && data.commits_count,
|
||||
filesCount:data && data.files_count
|
||||
})
|
||||
}
|
||||
componentDidUpdate=(prevProps)=>{
|
||||
const { comparesData } = this.props;
|
||||
const { footer_type } = this.props;
|
||||
if(footer_type){
|
||||
const { data } = this.props;
|
||||
if(data !== prevProps.data){
|
||||
this.setState({
|
||||
commitCount:data && data.commits_count,
|
||||
filesCount:data && data.files_count
|
||||
})
|
||||
}
|
||||
}
|
||||
if(comparesData !== prevProps.comparesData){
|
||||
this.setState({
|
||||
activeKey:footer_type ? "1" : "2"
|
||||
})
|
||||
this.changeTab(footer_type ? "1" : "2");
|
||||
}
|
||||
this.state = {
|
||||
activeKey: '1',
|
||||
};
|
||||
}
|
||||
|
||||
changeTab=(index)=>{
|
||||
changeTab = (index) => {
|
||||
this.setState({
|
||||
isSpin:true
|
||||
})
|
||||
this.setState({
|
||||
activeKey:index
|
||||
})
|
||||
const { footer_type , comparesData } = this.props;
|
||||
const { projectsId , owner , mergeId } = this.props.match.params;
|
||||
|
||||
if(footer_type){
|
||||
if(index === "2"){
|
||||
this.getCommit(owner,projectsId,mergeId);
|
||||
}else if(index === "3"){
|
||||
this.getFile(owner,projectsId,mergeId);
|
||||
}else{
|
||||
this.setState({
|
||||
isSpin:false
|
||||
})
|
||||
}
|
||||
}else{
|
||||
this.setState({
|
||||
commitsData:comparesData.commits,
|
||||
filesData:comparesData.diff,
|
||||
commitCount:comparesData.commits_count,
|
||||
filesCount:comparesData.diff && comparesData.diff.files_count,
|
||||
isSpin:false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
getCommit =(owner,projectsId,mergeId)=>{
|
||||
const url = `/${owner}/${projectsId}/pulls/${mergeId}/commits.json`;
|
||||
axios.get(url).then(result=>{
|
||||
if(result){
|
||||
this.setState({
|
||||
commitsData:result.data.commits,
|
||||
isSpin:false,
|
||||
commitCount:result.data.commits_count
|
||||
})
|
||||
}
|
||||
}).catch(error=>{})
|
||||
}
|
||||
|
||||
getFile =(owner,projectsId,mergeId)=>{
|
||||
const url = `/${owner}/${projectsId}/pulls/${mergeId}/files.json`;
|
||||
axios.get(url).then(result=>{
|
||||
if(result){
|
||||
this.setState({
|
||||
filesData:result.data,
|
||||
isSpin:false,
|
||||
filesCount:result.data.files_count,
|
||||
})
|
||||
}
|
||||
}).catch(error=>{})
|
||||
}
|
||||
activeKey: index,
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { projectsId , owner } = this.props.match.params;
|
||||
const { projectsId, owner } = this.props.match.params;
|
||||
const { comparesData = {} } = this.props;
|
||||
const { commits, diff, commits_count } = comparesData;
|
||||
const { activeKey } = this.state;
|
||||
|
||||
const { footer_type, order_id, data , comparesData } = this.props;
|
||||
let { isSpin , activeKey , filesCount, commitCount , filesData , commitsData } = this.state;
|
||||
|
||||
return (
|
||||
!footer_type && !comparesData || (comparesData && ((comparesData.commits && comparesData.commits.length===0)||(comparesData && !comparesData.diff)) )?"":
|
||||
<div className="main mergeRequest" style={{paddingTop:"0px"}}>
|
||||
<Spin spinning={isSpin}>
|
||||
<Tabs
|
||||
activeKey={activeKey}
|
||||
className="custom-commit-tabs"
|
||||
animated={false}
|
||||
onChange={this.changeTab}
|
||||
>
|
||||
{
|
||||
footer_type &&
|
||||
<TabPane
|
||||
tab={
|
||||
<span><span className="font-16">评论</span>
|
||||
{data && parseInt(data.comments_count) > 0 && <span className="tabNum">{data.comments_count}</span>}
|
||||
</span>
|
||||
} key="1">
|
||||
<Comments
|
||||
order_id={order_id}
|
||||
showNotification={this.props.showNotification}
|
||||
only_show_content={true}
|
||||
{...this.props}
|
||||
/>
|
||||
</TabPane>
|
||||
}
|
||||
{
|
||||
commitsData && commitsData.length > 0 &&
|
||||
<TabPane tab={<span><span className="font-16">提交</span>
|
||||
{commitCount > 0 && <span className="tabNum">{commitCount}</span>}
|
||||
</span>} key="2">
|
||||
<Commits {...this.props} commits={commitsData} projectsId={projectsId} owner={owner}></Commits>
|
||||
</TabPane>
|
||||
}
|
||||
{
|
||||
filesData && filesData.files && filesData.files.length>0 &&
|
||||
<TabPane tab={
|
||||
<span><span className="font-16">文件</span>
|
||||
{filesCount > 0 && <span className="tabNum">{filesCount}</span>}
|
||||
</span>
|
||||
} key="3">
|
||||
<Files {...this.props} data={filesData} projectsId={projectsId} owner={owner}/>
|
||||
</TabPane>
|
||||
}
|
||||
|
||||
</Tabs>
|
||||
</Spin>
|
||||
return (commits && commits.length === 0) || !diff ? (
|
||||
''
|
||||
) : (
|
||||
<div className="main mergeRequest" style={{ paddingTop: '0px' }}>
|
||||
<Tabs
|
||||
activeKey={activeKey}
|
||||
className="custom-commit-tabs"
|
||||
animated={false}
|
||||
onChange={this.changeTab}
|
||||
>
|
||||
{commits && commits.length > 0 && (
|
||||
<TabPane
|
||||
tab={
|
||||
<span>
|
||||
<span className="font-16">提交</span>
|
||||
{commits_count > 0 && (
|
||||
<span className="tabNum">{commits_count}</span>
|
||||
)}
|
||||
</span>
|
||||
}
|
||||
key="1"
|
||||
>
|
||||
<Commits
|
||||
{...this.props}
|
||||
commits={commits}
|
||||
projectsId={projectsId}
|
||||
owner={owner}
|
||||
></Commits>
|
||||
</TabPane>
|
||||
)}
|
||||
{diff && diff.files && diff.files.length > 0 && (
|
||||
<TabPane
|
||||
tab={
|
||||
<span>
|
||||
<span className="font-16">文件</span>
|
||||
{diff.files_count > 0 && (
|
||||
<span className="tabNum">{diff.files_count}</span>
|
||||
)}
|
||||
</span>
|
||||
}
|
||||
key="3"
|
||||
>
|
||||
<Files
|
||||
{...this.props}
|
||||
data={diff}
|
||||
projectsId={projectsId}
|
||||
owner={owner}
|
||||
/>
|
||||
</TabPane>
|
||||
)}
|
||||
</Tabs>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -165,7 +165,8 @@ class MergeForm extends Component {
|
|||
this.setState({
|
||||
isSpin: false,
|
||||
});
|
||||
this.props.history.push(`/${owner}/${projectsId}/pulls`);
|
||||
const { pull_request_id } = result.data;
|
||||
this.props.history.push(`/${owner}/${projectsId}/pulls/${pull_request_id}`);
|
||||
const { getDetail } = this.props;
|
||||
getDetail && getDetail();
|
||||
} else {
|
||||
|
@ -195,7 +196,7 @@ class MergeForm extends Component {
|
|||
isSpin: false,
|
||||
});
|
||||
this.props.history.push(
|
||||
`/${owner}/${projectsId}/pulls/${mergeId}/Messagecount`
|
||||
`/${owner}/${projectsId}/pulls/${mergeId}`
|
||||
);
|
||||
} else {
|
||||
this.setState({
|
||||
|
@ -264,7 +265,7 @@ class MergeForm extends Component {
|
|||
},
|
||||
],
|
||||
initialValue: title,
|
||||
})(<Input placeholder="标题" maxLength={50} />)}
|
||||
})(<Input placeholder="标题" maxLength={200} />)}
|
||||
</Form.Item>
|
||||
<MDEditor
|
||||
placeholder={"请输入合并请求的描述..."}
|
||||
|
@ -287,7 +288,7 @@ class MergeForm extends Component {
|
|||
type="default"
|
||||
className="ml30"
|
||||
onClick={()=>{
|
||||
this.props.history.push(merge_type === "new" ? `/${owner}/${projectsId}/pulls` : `/${owner}/${projectsId}/pulls/${mergeId}/detail`)
|
||||
this.props.history.push(merge_type === "new" ? `/${owner}/${projectsId}/pulls` : `/${owner}/${projectsId}/pulls/${mergeId}`)
|
||||
}}
|
||||
>
|
||||
<span className="plr10">取消</span>
|
||||
|
|
|
@ -12,7 +12,7 @@ class Nodata extends Component{
|
|||
<h3>欢迎使用合并请求!</h3>
|
||||
|
||||
<div className="color-grey-8">
|
||||
合并请求可以帮助您与他人协作编写代码。在使用之前,请先创建一个 <Link className="color-blue" to={`/${owner}/${projectsId}/pulls/new`}>合并请求</Link>
|
||||
合并请求可以帮助您与他人协作编写代码。在使用之前,请先创建一个 <Link className="color-blue" to={`/${owner}/${projectsId}/compare/master...master`}>合并请求</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -285,12 +285,16 @@ class Index extends Component {
|
|||
if(value.indexOf("/") > -1){
|
||||
let arr = value.split("/");
|
||||
let first = arr[arr.length-1];
|
||||
if(first.indexOf(".git") > -1){
|
||||
if(first.indexOf(".") > -1){
|
||||
let second = first.split('.')[0];
|
||||
if(!second)return;
|
||||
this.props.form.setFieldsValue({
|
||||
repository_name:second
|
||||
})
|
||||
}else{
|
||||
this.props.form.setFieldsValue({
|
||||
repository_name:first
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -351,7 +355,7 @@ class Index extends Component {
|
|||
required: true, message: '请填写镜像版本库地址'
|
||||
}],
|
||||
})(
|
||||
<Input placeholder="请输入需要导入到本项目的仓库地址" onChange={this.ChangeAddr} />
|
||||
<Input placeholder="请输入需要导入到本项目的仓库地址" onBlur={this.ChangeAddr} />
|
||||
)}
|
||||
</Form.Item>
|
||||
<p className="formTip color-orange">示例:https://github.com/facebook/reack.git</p>
|
||||
|
|
|
@ -83,8 +83,7 @@ class UserSubmitComponent extends Component {
|
|||
if (result.data && result.data.name) {
|
||||
this.props.showNotification("文件新建成功!");
|
||||
if(submitType === "1"){
|
||||
const { getTopCount , getDetail } = this.props;
|
||||
getTopCount && getTopCount(values.branchname);
|
||||
const { getDetail } = this.props;
|
||||
getDetail && getDetail();
|
||||
}
|
||||
let url = `/${owner}/${projectsId}${values.branchname ? `/tree/${turnbar(values.branchname)}`: (branch ? `/tree/${turnbar(branch)}` : "")}`;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import React, { Component } from "react";
|
||||
import Editor from "react-monaco-editor";
|
||||
// import {UnControlled as CodeMirror} from 'react-codemirror2'
|
||||
|
||||
import UserSubmitComponent from "./UserSubmitComponent";
|
||||
|
||||
import "./index.css";
|
||||
|
@ -103,6 +105,17 @@ class m_editor extends Component {
|
|||
editorWillMount={this.editorWillMount}
|
||||
editorDidMount={handleEditorMount}
|
||||
/>
|
||||
{/* <CodeMirror
|
||||
value={editorValue}
|
||||
options={{
|
||||
theme: 'monokai',
|
||||
mode: 'JavaScript',
|
||||
extraKeys: {"Ctrl": "autocomplete"},//ctrl可以弹出提示
|
||||
styleActiveLine: true,
|
||||
lineNumbers: true,
|
||||
readOnly:true
|
||||
}}
|
||||
/> */}
|
||||
</div>
|
||||
{!readOnly && (
|
||||
<div className="editorBorderSubmitBox" style={{marginTop:"20px",padding:"20px"}}>
|
||||
|
|
|
@ -233,7 +233,7 @@ class Detail extends Component {
|
|||
: "合并请求"}
|
||||
】
|
||||
</span>
|
||||
<span className="font-16 fwb">{data && data.subject}</span>
|
||||
<span className="font-16 fwb" style={{wordBreak:"break-all"}}>{data && data.subject}</span>
|
||||
</span>
|
||||
|
||||
{data && data.priority && (
|
||||
|
|
|
@ -320,7 +320,7 @@ class order_form extends Component {
|
|||
message: "请填写易修标题",
|
||||
},
|
||||
]
|
||||
})(<Input placeholder="标题" size="large" maxLength={80}/>)}
|
||||
})(<Input placeholder="标题" size="large" maxLength={200}/>)}
|
||||
</Form.Item>
|
||||
<div className="quillContent">
|
||||
<MDEditor
|
||||
|
|
|
@ -43,8 +43,9 @@ const PrivateLetter = Loadable({
|
|||
});
|
||||
|
||||
function Index(props){
|
||||
const { current_user } = props;
|
||||
const { current_user,mygetHelmetapi } = props;
|
||||
const { pathname } = props.location;
|
||||
const notice_url = mygetHelmetapi && mygetHelmetapi.common && mygetHelmetapi.common.notice;
|
||||
|
||||
return(
|
||||
<div className="newMain clearfix whiteBack">
|
||||
|
@ -59,11 +60,11 @@ function Index(props){
|
|||
<li>个人信息</li>
|
||||
<li className={pathname.indexOf("/settings/profile")>-1 ?"active":""}><Link to={`/settings/profile`}><i className="iconfont icon-gerenziliao mr5 font-14"></i><span className="text-shodow-bold">基本资料</span></Link></li>
|
||||
</ul>
|
||||
<ul className="securityUl ul-border-buttom">
|
||||
{notice_url && <ul className="securityUl ul-border-buttom">
|
||||
<li>消息通知</li>
|
||||
<li className={(pathname.indexOf("/settings/notice")>-1 && pathname.indexOf("/settings/notice/config") == -1) || pathname.indexOf("/settings/notice/privateLetter")>-1 ?"active":""}><Link to={"/settings/notice"}><i className="iconfont icon-wodetongzhi"></i><span className="text-shodow-bold">我的通知</span></Link></li>
|
||||
{/* <li className={pathname.indexOf("/settings/notice/config")>-1 ?"active":""}><Link to={'/settings/notice/config'}><i className="iconfont icon-tongzhiguanli"></i><span className="text-shodow-bold">通知管理</span></Link></li> */}
|
||||
</ul>
|
||||
<li className={pathname.indexOf("/settings/notice/config")>-1 ?"active":""}><Link to={'/settings/notice/config'}><i className="iconfont icon-tongzhiguanli"></i><span className="text-shodow-bold">通知管理</span></Link></li>
|
||||
</ul>}
|
||||
<ul className="securityUl">
|
||||
<li>安全设置</li>
|
||||
<li className={pathname.indexOf("/settings/SSH")>-1 ?"active":""}><Link to={`/settings/SSH`}><i className="iconfont icon-xuanzhongssh_icon mr5 font-14"></i><span className="text-shodow-bold">SSH密钥</span></Link></li>
|
||||
|
@ -72,18 +73,24 @@ function Index(props){
|
|||
<LongWidth>
|
||||
<Gap>
|
||||
<Switch>
|
||||
<Route
|
||||
path="/settings/notice"
|
||||
render={(p) => (
|
||||
<MyNoticeIndex {...props} {...p}/>
|
||||
)}
|
||||
></Route>
|
||||
<Route
|
||||
path="/settings/notice/config"
|
||||
render={(p) => (
|
||||
<NoticeManager {...props} {...p}/>
|
||||
)}
|
||||
></Route>
|
||||
<Route
|
||||
path="/settings/notice/privateLetter"
|
||||
render={(p)=>(
|
||||
<PrivateLetter{...props} {...p}/>
|
||||
)}
|
||||
></Route>
|
||||
<Route
|
||||
path="/settings/notice"
|
||||
render={(p) => (
|
||||
<MyNoticeIndex {...props} {...p}/>
|
||||
)}
|
||||
></Route>
|
||||
<Route
|
||||
path="/settings/SSH/new"
|
||||
render={(p) => (
|
||||
|
@ -102,12 +109,6 @@ function Index(props){
|
|||
<SSHIndex {...props} {...p}/>
|
||||
)}
|
||||
></Route>
|
||||
<Route
|
||||
path="/settings/notice/privateLetter"
|
||||
render={(p)=>(
|
||||
<PrivateLetter{...props} {...p}/>
|
||||
)}
|
||||
></Route>
|
||||
</Switch>
|
||||
</Gap>
|
||||
</LongWidth>
|
||||
|
|
|
@ -1,9 +1,52 @@
|
|||
import { Button, Checkbox } from "antd";
|
||||
import React from "react";
|
||||
|
||||
import { Checkbox } from "antd";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import axios from 'axios';
|
||||
import './Index.scss';
|
||||
|
||||
function NoticeManager(props){
|
||||
const {current_user} = props;
|
||||
|
||||
const [settingTypes, setSettingTypes] = useState();
|
||||
const [userNotification, setUserNotification] = useState();
|
||||
const [userEmail, setUserEmail] = useState();
|
||||
|
||||
function onChange(type,e,setting){
|
||||
let notification_body = userNotification;
|
||||
let email_body = userEmail;
|
||||
if(type){//站内信
|
||||
notification_body[setting] = e.target.checked;
|
||||
}else{//邮件
|
||||
email_body[setting] = e.target.checked;
|
||||
}
|
||||
axios.post(`/users/${current_user.login}/template_message_settings/update_setting.json`,{
|
||||
setting:{
|
||||
notification_body:notification_body,
|
||||
email_body:email_body
|
||||
}
|
||||
}).then(response=>{
|
||||
if(response && response.status === 0){
|
||||
getUserSettings();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function getUserSettings(){
|
||||
axios.get(`/users/${current_user.login}/template_message_settings.json`).then((response)=>{
|
||||
if(response && response.status === 200 ){
|
||||
setUserEmail(response.data.email_body);
|
||||
setUserNotification(response.data.notification_body);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
useEffect(()=>{
|
||||
axios.get("/template_message_settings.json").then(response => {
|
||||
if (response && response.status === 200) {
|
||||
setSettingTypes(response.data.setting_types);
|
||||
}
|
||||
})
|
||||
getUserSettings();
|
||||
},[])
|
||||
|
||||
return(
|
||||
<div className="notice01">
|
||||
|
@ -12,87 +55,23 @@ function NoticeManager(props){
|
|||
</div>
|
||||
<div>
|
||||
<span className="notice-manager-tip">您可以通过通知管理来选择接受通知的方式</span>
|
||||
<div className="manager-cont-top">
|
||||
我创建或负责的
|
||||
</div>
|
||||
<div className="manager-cont">
|
||||
<div className="manager-cont-title">易修状态变更</div>
|
||||
<Checkbox defaultChecked='true' disabled>站内信</Checkbox>
|
||||
<Checkbox >邮件</Checkbox>
|
||||
</div>
|
||||
<div className="manager-cont">
|
||||
<div className="manager-cont-title">易修截止日期到达最后一天</div>
|
||||
<Checkbox defaultChecked='true' disabled>站内信</Checkbox>
|
||||
<Checkbox >邮件</Checkbox>
|
||||
</div>
|
||||
<div className="manager-cont">
|
||||
<div className="manager-cont-title">合并请求状态变更</div>
|
||||
<Checkbox defaultChecked='true' disabled>站内信</Checkbox>
|
||||
<Checkbox >邮件</Checkbox>
|
||||
</div>
|
||||
<div className="manager-cont">
|
||||
<div className="manager-cont-title">易修有新的评论</div>
|
||||
<Checkbox defaultChecked='true'>站内信</Checkbox>
|
||||
<Checkbox >邮件</Checkbox>
|
||||
</div>
|
||||
<div className="manager-cont">
|
||||
<div className="manager-cont-title">合并请求有新的评论</div>
|
||||
<Checkbox defaultChecked='true'>站内信</Checkbox>
|
||||
<Checkbox >邮件</Checkbox>
|
||||
</div>
|
||||
|
||||
<div className="manager-cont-top">
|
||||
我管理的仓库
|
||||
</div>
|
||||
<div className="manager-cont">
|
||||
<div className="manager-cont-title">被关注</div>
|
||||
<Checkbox defaultChecked='true'>站内信</Checkbox>
|
||||
<Checkbox >邮件</Checkbox>
|
||||
</div>
|
||||
<div className="manager-cont">
|
||||
<div className="manager-cont-title">被点赞</div>
|
||||
<Checkbox defaultChecked='true'>站内信</Checkbox>
|
||||
<Checkbox >邮件</Checkbox>
|
||||
</div>
|
||||
<div className="manager-cont">
|
||||
<div className="manager-cont-title">被复刻</div>
|
||||
<Checkbox defaultChecked='true'>站内信</Checkbox>
|
||||
<Checkbox >邮件</Checkbox>
|
||||
</div>
|
||||
<div className="manager-cont">
|
||||
<div className="manager-cont-title">有新的里程碑</div>
|
||||
<Checkbox defaultChecked='true'>站内信</Checkbox>
|
||||
<Checkbox >邮件</Checkbox>
|
||||
</div>
|
||||
|
||||
<div className="manager-cont-top">
|
||||
我关注的仓库
|
||||
</div>
|
||||
<div className="manager-cont">
|
||||
<div className="manager-cont-title">被删除</div>
|
||||
<Checkbox defaultChecked='true'>站内信</Checkbox>
|
||||
<Checkbox >邮件</Checkbox>
|
||||
</div>
|
||||
<div className="manager-cont">
|
||||
<div className="manager-cont-title">被转移</div>
|
||||
<Checkbox defaultChecked='true'>站内信</Checkbox>
|
||||
<Checkbox >邮件</Checkbox>
|
||||
</div>
|
||||
<div className="manager-cont">
|
||||
<div className="manager-cont-title">有新的易修</div>
|
||||
<Checkbox defaultChecked='true'>站内信</Checkbox>
|
||||
<Checkbox >邮件</Checkbox>
|
||||
</div>
|
||||
<div className="manager-cont">
|
||||
<div className="manager-cont-title">有新的合并请求</div>
|
||||
<Checkbox defaultChecked='true'>站内信</Checkbox>
|
||||
<Checkbox >邮件</Checkbox>
|
||||
</div>
|
||||
<div className="manager-cont">
|
||||
<div className="manager-cont-title">有新的版本发布</div>
|
||||
<Checkbox defaultChecked='true'>站内信</Checkbox>
|
||||
<Checkbox >邮件</Checkbox>
|
||||
</div>
|
||||
{settingTypes && userNotification && userEmail && settingTypes.map((item,key)=>{
|
||||
return(
|
||||
item.type_name && <div key={key}>
|
||||
<div className="manager-cont-top">{item.type_name}</div>
|
||||
{item.settings.map((i, k) => {
|
||||
const setting = item.type.substring(item.type.indexOf("::")+2)+"::"+i.key;
|
||||
return (
|
||||
<div className="manager-cont" key={k}>
|
||||
<div className="manager-cont-title">{i.name}</div>
|
||||
<Checkbox disabled = {i.notification_disabled} defaultChecked={userNotification[setting]} onChange={(e)=>{onChange(true,e,setting)}}>站内信</Checkbox>
|
||||
<Checkbox disabled = {i.email_disabled} defaultChecked={userEmail[setting]} onChange={(e)=>{onChange(false,e,setting)}}>邮件</Checkbox>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -9,10 +9,9 @@ import './Index.scss';
|
|||
import '../manager/Index.scss'
|
||||
|
||||
function MyNotice(props) {
|
||||
let current_user = props.current_user;
|
||||
let resetUserInfo = props.resetUserInfo;
|
||||
let { current_user, resetUserInfo, location, mygetHelmetapi, history}= props;
|
||||
//消息悬停框选择tab
|
||||
let popover = props.location.query && props.location.query.noticeType;
|
||||
let popover = location && location.query && location.query.noticeType;
|
||||
let pageSize = 15;
|
||||
const [noticeType, setNoticeType] = useState(popover==="atme"?"2":"0");//消息类别tab栏选择
|
||||
const [selectedNum, setSelectedNum] = useState(0);//@我批量删除选择消息条数
|
||||
|
@ -27,6 +26,18 @@ function MyNotice(props) {
|
|||
const [currentPage, setCurrentPage] = useState(1);//当前页数
|
||||
const [onlyUnread, setOnlyUnread] = useState();
|
||||
|
||||
//登录情况下,通过地址访问,直接跳转:/settings/profile
|
||||
//未登录情况下,通过地址访问,直接跳转:/explore
|
||||
useEffect(()=>{
|
||||
let notice = mygetHelmetapi && mygetHelmetapi.common && mygetHelmetapi.common.notice;
|
||||
let login = current_user && current_user.login;
|
||||
if(!login){
|
||||
history.push(`/explore`);
|
||||
}else if(!notice){
|
||||
history.push(`/settings/profile`);
|
||||
}
|
||||
},[mygetHelmetapi])
|
||||
|
||||
useEffect(()=>{
|
||||
popover==="atme" ? setNoticeType("2"):setNoticeType("0");
|
||||
},[popover])
|
||||
|
@ -46,7 +57,7 @@ function MyNotice(props) {
|
|||
limit: pageSize,
|
||||
page: currentPage,
|
||||
};
|
||||
axios.get(`/users/${current_user.login}/messages.json`, {
|
||||
current_user && axios.get(`/users/${current_user.login}/messages.json`, {
|
||||
params: params,
|
||||
}).then((response) => {
|
||||
if(response && response.data){
|
||||
|
@ -59,7 +70,7 @@ function MyNotice(props) {
|
|||
}
|
||||
|
||||
function readNotice(id){
|
||||
if(id){
|
||||
if(id && current_user){
|
||||
const params = {
|
||||
type: noticeType === "0" ? "notification" : noticeType === "2" ? "atme" : "",
|
||||
ids:id,
|
||||
|
|
|
@ -153,18 +153,22 @@ class Setting extends Component {
|
|||
name: values.project_name,
|
||||
description: values.project_description,
|
||||
private: private_check,
|
||||
identifier:values.project_identifier,
|
||||
...values,
|
||||
}).then((result) => {
|
||||
if (result) {
|
||||
this.props.showNotification(`仓库信息修改成功!`);
|
||||
const { getDetail } = this.props;
|
||||
getDetail && getDetail();
|
||||
this.setState({
|
||||
loading:false
|
||||
})
|
||||
if(values.project_identifier !== projectsId){
|
||||
this.props.history.push(`/${owner}/${values.project_identifier}/settings`);
|
||||
}else{
|
||||
const { getDetail } = this.props;
|
||||
getDetail && getDetail();
|
||||
}
|
||||
}
|
||||
this.setState({
|
||||
loading:false
|
||||
})
|
||||
}).catch((error) => {
|
||||
console.log(error);
|
||||
this.setState({
|
||||
loading:false
|
||||
})
|
||||
|
@ -263,6 +267,11 @@ class Setting extends Component {
|
|||
},
|
||||
],
|
||||
})(<Input placeholder="请输入项目名称" />)}
|
||||
{
|
||||
projectDetail && projectDetail.type && projectDetail.type !== 0 ?
|
||||
<span className="color-grey-9">该项目导入于 <a className="color-grey-6" target="_blank" href={projectDetail.mirror_url}>{projectDetail.mirror_url}</a></span>
|
||||
: ""
|
||||
}
|
||||
</Form.Item>
|
||||
<div className="df" style={{ alignItems: "center" }}>
|
||||
<span className="mr20 mb15 font-16">可见性</span>
|
||||
|
@ -283,6 +292,20 @@ class Setting extends Component {
|
|||
)}
|
||||
</Form.Item>
|
||||
</div>
|
||||
<Form.Item
|
||||
label={<span>项目标识 <span className="color-grey-9">(项目url标识部分,更改项目标识将导致原仓库地址失效)</span></span>}
|
||||
>
|
||||
{getFieldDecorator("project_identifier", {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入项目标识",
|
||||
},
|
||||
],
|
||||
})(
|
||||
<Input placeholder="项目标识请使用与项目相关的英文关键字" maxLength="100" />
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item label="项目简介">
|
||||
{getFieldDecorator("project_description", {
|
||||
rules: [],
|
||||
|
|
|
@ -19,7 +19,6 @@ function List(props){
|
|||
const [ search , setSearch ] = useState(undefined);
|
||||
const [ page , setPage ] = useState(1);
|
||||
const [ sortBy , setSortBy ] = useState("updated_on");
|
||||
const [ sortDirection , setSortDirection ] = useState("asc");
|
||||
|
||||
const OIdentifier = props.match.params.OIdentifier;
|
||||
const organizeDetail = props.organizeDetail;
|
||||
|
@ -37,7 +36,7 @@ function List(props){
|
|||
params:{
|
||||
search,page,limit,
|
||||
sort_by:sortBy,
|
||||
sort_direction:sortDirection
|
||||
sort_direction:"desc"
|
||||
}
|
||||
}).then(result=>{
|
||||
if(result && result.data){
|
||||
|
|
|
@ -10,14 +10,10 @@ function ListItem({item,key,OIdentifier}) {
|
|||
<Link to={`/${OIdentifier}/${item.identifier}`} className="name">{item.name}</Link>
|
||||
{ item.forked_from_project_id && <i className="iconfont icon-fork font-18 color-orange ml8" /> }
|
||||
{
|
||||
item.type && item.type !== 0 ?
|
||||
item.type === 2 ?
|
||||
item.type && item.type === 2 ?
|
||||
<Tooltip title="该项目是一个镜像" className="ml8">
|
||||
<i className="iconfont icon-banbenku font-18 color-green" />
|
||||
</Tooltip>:
|
||||
<span className="ml8">
|
||||
<i className="iconfont icon-jingxiang font-18 color-green" />
|
||||
</span>:""
|
||||
</Tooltip>:""
|
||||
}
|
||||
</span>
|
||||
<ListCount fork={item.forked_count} parise={item.praises_count}/>
|
||||
|
|
|
@ -17,6 +17,7 @@ class children_comments extends Component {
|
|||
page: 1,
|
||||
journal_spin: false,
|
||||
search_count: 0,
|
||||
isSpin: false,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -71,6 +72,9 @@ class children_comments extends Component {
|
|||
.then((result) => {
|
||||
if (result) {
|
||||
this.getChildrenJournals();
|
||||
// 删除回复后,如果需手动调用父组件查询评论列表的接口,以保持角标(评论数量)的一致(合并请求页面),
|
||||
// 否则直接查顶级评论列表,否则只查询当前子评论列表(易修页面)
|
||||
this.props.refreshCommentList && this.props.refreshCommentList();
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
|
@ -80,9 +84,15 @@ class children_comments extends Component {
|
|||
|
||||
// 翻页
|
||||
ChangePage = (page) => {
|
||||
this.state.page = page;
|
||||
this.state.isSpin = true;
|
||||
this.getChildrenJournals();
|
||||
// this.state.page = page;
|
||||
// this.state.isSpin = true;
|
||||
// 使用回调的写法,这样在getChildrenJournals中使用的就是最新的state
|
||||
this.setState({
|
||||
page,
|
||||
isSpin: true
|
||||
}, () => {
|
||||
this.getChildrenJournals();
|
||||
});
|
||||
};
|
||||
|
||||
commentCtx = (v) => {
|
||||
|
@ -183,7 +193,7 @@ class children_comments extends Component {
|
|||
size="large"
|
||||
loading={isSpin}
|
||||
dataSource={journalsdata.issue_journals}
|
||||
renderItem={(item) => <List.Item>{this.renderList(item)}</List.Item>}
|
||||
renderItem={(item) => <List.Item key={item.id}>{this.renderList(item)}</List.Item>}
|
||||
/>
|
||||
{this.Paginations()}
|
||||
</div>
|
||||
|
|
|
@ -35,6 +35,8 @@ class comments extends Component {
|
|||
|
||||
componentDidMount = () => {
|
||||
this.getjournalslist();
|
||||
// 给父组件绑定,以使父组件可以使用组件内方法,用于切换tab时重新请求评论列表、合并请求完之后重新请求评论列表
|
||||
this.props.bindCommentRef && this.props.bindCommentRef(this);
|
||||
};
|
||||
|
||||
//添加评论
|
||||
|
@ -151,6 +153,8 @@ class comments extends Component {
|
|||
isSpin: false,
|
||||
fileList: undefined,
|
||||
});
|
||||
const { updateCommentsNum } = this.props;
|
||||
updateCommentsNum && updateCommentsNum(result.data.journals_total_count);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
|
@ -372,7 +376,7 @@ class comments extends Component {
|
|||
|
||||
const renderList = (item) => {
|
||||
return (
|
||||
<div className="width100">
|
||||
<div className="width100" key={item.id}>
|
||||
<div className="pb5">
|
||||
<Link
|
||||
to={`/${item && item.user_login}`}
|
||||
|
@ -456,6 +460,7 @@ class comments extends Component {
|
|||
parent_id={item.id}
|
||||
onRef={this.onRef}
|
||||
children_comment_id={new_journal_id}
|
||||
refreshCommentList={this.getjournalslist}
|
||||
{...this.props}
|
||||
></ChildrenComments>
|
||||
</div>
|
||||
|
@ -500,7 +505,7 @@ class comments extends Component {
|
|||
loading={isSpin}
|
||||
header=""
|
||||
dataSource={journalsdata.issue_journals}
|
||||
renderItem={(item) => <List.Item>{renderList(item)}</List.Item>}
|
||||
renderItem={(item) => <List.Item key={item.id}>{renderList(item)}</List.Item>}
|
||||
/>
|
||||
)}
|
||||
{this.Paginations()}
|
||||
|
@ -558,7 +563,7 @@ class comments extends Component {
|
|||
header=""
|
||||
dataSource={journalsdata.issue_journals}
|
||||
renderItem={(item) => (
|
||||
<List.Item>{renderList(item)}</List.Item>
|
||||
<List.Item key={item.id}>{renderList(item)}</List.Item>
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
|
|
|
@ -104,6 +104,9 @@ ul,ol,dl{
|
|||
white-space: normal;
|
||||
&:hover{
|
||||
text-decoration: underline;
|
||||
& .markdown-body{
|
||||
color: #466AFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@ export default Form.create()(
|
|||
const { getFieldDecorator, validateFields , setFieldsValue } = props && props.form;
|
||||
// const { username } = props && props.match && props.match.params;
|
||||
const { resetUserInfo , current_user } = props;
|
||||
console.log(props);
|
||||
|
||||
useEffect(()=>{
|
||||
if(current_user && current_user.login){
|
||||
|
|
|
@ -298,7 +298,7 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {
|
|||
.CodeMirror-scroll {
|
||||
overflow: scroll !important;
|
||||
margin-bottom: -30px;
|
||||
margin-right: -30px;
|
||||
margin-right: -30px!important;
|
||||
padding-bottom: 30px;
|
||||
height: 100%;
|
||||
outline: none;
|
||||
|
|
|
@ -153,21 +153,21 @@ class EducoderLogin extends Component {
|
|||
justifyContent: "center",
|
||||
width: "100%",
|
||||
}}>
|
||||
<div className="font-14 color-grey-9 " style={{marginTop:"20px"}}><span className="font-18">©</span> {moment().year()} EduCoder<span className="ml15 mr15">湘ICP备17009477号</span><a href="https://team.trustie.net" style={{"color":"#888"}} target="_blank">Trustie</a> & IntelliDE inside.</div>
|
||||
<div className="font-14 color-grey-9 " style={{marginTop:"20px"}}><span className="font-18">©</span> {moment().year()} GitLink | 确实开源<span className="ml15 mr15">京ICP备13000930号</span><a href="https://team.trustie.net" style={{"color":"#888"}} target="_blank">GitLink</a> & IntelliDE inside.</div>
|
||||
</div>:
|
||||
this.props.mygetHelmetapi===undefined||this.props.mygetHelmetapi.main_site===null|| this.props.mygetHelmetapi.main_site===undefined? <div style={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
width: "100%",
|
||||
}}>
|
||||
<div className="font-14 color-grey-9 " style={{marginTop:"20px"}}><span className="font-18">©</span> {moment().year()} EduCoder<span className="ml15 mr15">湘ICP备17009477号</span><a href="https://team.trustie.net" style={{"color":"#888"}} target="_blank">Trustie</a> & IntelliDE inside.</div>
|
||||
<div className="font-14 color-grey-9 " style={{marginTop:"20px"}}><span className="font-18">©</span> {moment().year()} GitLink | 确实开源<span className="ml15 mr15">京ICP备13000930号</span><a href="https://team.trustie.net" style={{"color":"#888"}} target="_blank">GitLink</a> & IntelliDE inside.</div>
|
||||
</div>:this.props.mygetHelmetapi.main_site===true?
|
||||
<div style={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
width: "100%",
|
||||
}}>
|
||||
<div className="font-14 color-grey-9 " style={{marginTop:"20px"}}><span className="font-18">©</span> {moment().year()} EduCoder<span className="ml15 mr15">湘ICP备17009477号</span><a href="https://team.trustie.net" style={{"color":"#888"}} target="_blank">Trustie</a> & IntelliDE inside.</div>
|
||||
<div className="font-14 color-grey-9 " style={{marginTop:"20px"}}><span className="font-18">©</span> {moment().year()} GitLink | 确实开源<span className="ml15 mr15">京ICP备13000930号</span><a href="https://team.trustie.net" style={{"color":"#888"}} target="_blank">GitLink</a> & IntelliDE inside.</div>
|
||||
</div>
|
||||
:""
|
||||
}
|
||||
|
|
|
@ -142,12 +142,12 @@ class Trialapplication extends Component {
|
|||
if (this.state.Phonenumberisnotcobool === false) {
|
||||
if (this.state.login.length === 0) {
|
||||
this.setState({
|
||||
Phonenumberisnotco: "请输入正确的手机号或邮箱",
|
||||
Phonenumberisnotco: "请输入正确的邮箱账号",
|
||||
})
|
||||
return
|
||||
} else {
|
||||
this.setState({
|
||||
Phonenumberisnotco: "请输入正确的手机号或邮箱",
|
||||
Phonenumberisnotco: "请输入正确的邮箱账号",
|
||||
})
|
||||
}
|
||||
return;
|
||||
|
|
|
@ -158,12 +158,12 @@ class Trialapplicationysl extends Component {
|
|||
if (this.state.Phonenumberisnotcobool === false) {
|
||||
if (this.state.login.length === 0) {
|
||||
this.setState({
|
||||
Phonenumberisnotco: "请输入正确的手机号或邮箱",
|
||||
Phonenumberisnotco: "请输入正确的邮箱账号",
|
||||
})
|
||||
return
|
||||
} else {
|
||||
this.setState({
|
||||
Phonenumberisnotco: "请输入正确的手机号或邮箱",
|
||||
Phonenumberisnotco: "请输入正确的邮箱账号",
|
||||
})
|
||||
}
|
||||
return;
|
||||
|
|
|
@ -7,6 +7,7 @@ import './TPMIndex.css';
|
|||
import LoginDialog from '../login/LoginDialog';
|
||||
import EducoderAccount from '../../forge/Component/EducoderAccount';
|
||||
import ProfileModal from '../../forge/Component/ProfileModal/Index';
|
||||
import SystemNotice from '../../forge/Component/NoticeModal/SystemNotice';
|
||||
|
||||
export function TPMIndexHOC(WrappedComponent) {
|
||||
return class II extends React.Component {
|
||||
|
@ -27,7 +28,7 @@ export function TPMIndexHOC(WrappedComponent) {
|
|||
giteaVisible:false,
|
||||
email:undefined,
|
||||
completeProfile:false,
|
||||
showCP:false
|
||||
showCP:false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -214,9 +215,8 @@ export function TPMIndexHOC(WrappedComponent) {
|
|||
})
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
let { isRender , current_user , giteaVisible , email , completeProfile , showCP } = this.state;
|
||||
let { isRender , current_user , giteaVisible , email , completeProfile , showCP , mygetHelmetapi } = this.state;
|
||||
const common = {
|
||||
showLoginDialog: this.showLoginDialog,
|
||||
checkIfLogin: this.checkIfLogin,
|
||||
|
@ -225,6 +225,11 @@ export function TPMIndexHOC(WrappedComponent) {
|
|||
};
|
||||
return (
|
||||
<div className="indexHOC">
|
||||
<SystemNotice
|
||||
system_notification={mygetHelmetapi && mygetHelmetapi.system_notification}
|
||||
history={this.props.history}
|
||||
login={current_user && current_user.login}
|
||||
/>
|
||||
<EducoderAccount visible={giteaVisible} email={email} onOk={this.onOk}/>
|
||||
<ProfileModal
|
||||
visible={!completeProfile && showCP}
|
||||
|
|
|
@ -699,7 +699,7 @@ class LoginRegisterComponent extends Component {
|
|||
{/*onBlur={(e) => this.inputOnBlur(e)}*/}
|
||||
<Input style={loginInputsyl} type="text" autoComplete="off" onClick={this.changeTypey}
|
||||
className={Phonenumberisnotco && Phonenumberisnotco !== "" ?" color-grey-9 loginInputzhucheyslass bor-reds":" color-grey-9 loginInputzhuche"}
|
||||
placeholder="输入注册手机号或邮箱" value={this.state.login}
|
||||
placeholder="输入注册的邮箱账号" value={this.state.login}
|
||||
// onBlur={(e) => this.inputOnBlurzhuche(e)}
|
||||
onChange={this.loginInputonChange} style={{marginTop: '10px', height: "38px"}}></Input>
|
||||
{
|
||||
|
|
|
@ -7,6 +7,7 @@ import axios from 'axios';
|
|||
import CheckInputysl1 from './CheckInputysl';
|
||||
import CheckInputysl2 from './CheckInputysl';
|
||||
import Notcompletedysl from './Notcompletedysl';
|
||||
import Educoder from '../login/educoder.png';
|
||||
import './common.css'
|
||||
import './commontwo.css'
|
||||
const { TabPane } = Tabs;
|
||||
|
@ -1039,7 +1040,7 @@ class LoginRegisterComponent extends Component {
|
|||
}
|
||||
</style>
|
||||
|
||||
<Input placeholder="请输入登录手机号码或邮箱" value={this.state.login}
|
||||
<Input placeholder="请输入邮箱账号" value={this.state.login}
|
||||
onChange={this.loginInputonChange}
|
||||
name="username"
|
||||
className={Phonenumberisnotco && Phonenumberisnotco !== "" ?" color-grey-9 loginInputzhucheyslass bor-reds":" color-grey-9 loginInputzhuche"}
|
||||
|
@ -1085,28 +1086,14 @@ class LoginRegisterComponent extends Component {
|
|||
|
||||
<Button className="login_btn font-16" type="primary" style={{height:"46px"}} onClick={() => this.postLogin()}
|
||||
size={"large"}>登录</Button>
|
||||
{this.props.mygetHelmetapi&&this.props.mygetHelmetapi.main_site===true?this.state.isphone===true?<p className="clearfix mb10 textcenter">
|
||||
|
||||
<span className={"startlogin"}>———————— 快速登录 ————————</span>
|
||||
<div className={"mt10"}>
|
||||
<a onClick={()=>this.openweixinlogin()}>
|
||||
<img src={require('./img/WeChat.png')} alt="微信登录"/>
|
||||
</a>
|
||||
<a onClick={()=>this.openqqlogin()} className={"ml10"}>
|
||||
<img src={require('./img/qq.png')} alt="qq登录"/>
|
||||
</a>
|
||||
</div>
|
||||
</p>:<p className="clearfix mb10 textcenter">
|
||||
<span className={"startlogin"}>———————— 快速登录 ————————</span>
|
||||
<div className={"mt10"}>
|
||||
{/*<a onClick={()=>this.openweixinlogin()}>*/}
|
||||
{/*<img src={require('./WeChat.png')} alt="微信登录"/>*/}
|
||||
{/*</a>*/}
|
||||
<a onClick={()=>this.openphoneqqlogin()}>
|
||||
<img src={require('./img/qq.png')} alt="qq登录"/>
|
||||
</a>
|
||||
</div>
|
||||
</p>:""}
|
||||
<p className="clearfix mb10 textcenter">
|
||||
<span className={"startlogin"}>———————— 快速登录 ————————</span>
|
||||
<div className={"mt10"}>
|
||||
<a href="https://data.educoder.net/oauth2?call_url=/oauth/authorize?client_id=d060ea87615f6f731880857bccc73f2620b0421b6780532cdf0df33583dbab4d&redirect_uri=https%3A%2F%2Fforgeplus.trustie.net%2Fapi%2Fauth%2Feducoder%2Fcallback&response_type=code">
|
||||
<img src={Educoder} alt="educoder登录" width="46px"/>
|
||||
</a>
|
||||
</div>
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
@ -1115,7 +1102,7 @@ class LoginRegisterComponent extends Component {
|
|||
{
|
||||
weixinlogin===false&&parseInt(tab[0])==1 &&
|
||||
<div style={{width: '340px'}}>
|
||||
<Input placeholder="请使用手机号/邮箱账号进行注册"
|
||||
<Input placeholder="请使用邮箱账号进行注册"
|
||||
className={Phonenumberisnotcos && Phonenumberisnotcos !== "" ?" color-grey-9 loginInputzhucheyslass bor-reds":" color-grey-9 loginInputzhuche"}
|
||||
value={this.state.logins}
|
||||
type="text" autoComplete="off"
|
||||
|
@ -1255,34 +1242,19 @@ class LoginRegisterComponent extends Component {
|
|||
color: '#676767',
|
||||
}}>我已阅读并同意
|
||||
<span>
|
||||
<a href={'https://forge.educoder.net/help?index=4'} target="_blank" className={"color-blue"}>《服务协议条款》</a>
|
||||
<a href={'https://gitlink.org.cn/forums/5029/detail'} target="_blank" className={"color-blue"}>《服务协议条款》</a>
|
||||
</span></span></Checkbox>:""}
|
||||
<Button className=" font-16 mb20" type="primary" style={this.props.mygetHelmetapi&&this.props.mygetHelmetapi.main_site===true?{height:"46px", width: "100%",marginTop:"26px"}:{height:"46px", width: "100%"}} onClick={() => this.postregistered()}
|
||||
size={"large"}>{this.props.weixinlogin?"注册并绑定":"注册"}</Button>
|
||||
|
||||
{this.props.mygetHelmetapi&&this.props.mygetHelmetapi.main_site===true?this.state.isphone===true?<p className="clearfix mb10 textcenter">
|
||||
|
||||
<span className={"startlogin"}>———————— 快速登录 ————————</span>
|
||||
<div className={"mt10"}>
|
||||
<a onClick={()=>this.openweixinlogin()}>
|
||||
<img src={require('./img/WeChat.png')} alt="微信登录"/>
|
||||
</a>
|
||||
<a onClick={()=>this.openqqlogin()} className={"ml10"}>
|
||||
<img src={require('./img/qq.png')} alt="qq登录"/>
|
||||
</a>
|
||||
</div>
|
||||
</p>:<p className="clearfix mb10 textcenter">
|
||||
<span className={"startlogin"}>———————— 快速登录 ————————</span>
|
||||
<div className={"mt10"}>
|
||||
{/*<a onClick={()=>this.openweixinlogin()}>*/}
|
||||
{/*<img src={require('./WeChat.png')} alt="微信登录"/>*/}
|
||||
{/*</a>*/}
|
||||
<a onClick={()=>this.openphoneqqlogin()}>
|
||||
<img src={require('./img/qq.png')} alt="qq登录"/>
|
||||
</a>
|
||||
</div>
|
||||
</p>:""
|
||||
}
|
||||
<p className="clearfix mb10 textcenter">
|
||||
<span className={"startlogin"}>———————— 快速登录 ————————</span>
|
||||
<div className={"mt10"}>
|
||||
<a href="https://data.educoder.net/oauth2?call_url=/oauth/authorize?client_id=d060ea87615f6f731880857bccc73f2620b0421b6780532cdf0df33583dbab4d&redirect_uri=https%3A%2F%2Fforgeplus.trustie.net%2Fapi%2Fauth%2Feducoder%2Fcallback&response_type=code">
|
||||
<img src={Educoder} alt="educoder登录" width="46px"/>
|
||||
</a>
|
||||
</div>
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue