Merge pull request 'merge old version' (#260) from feature_noti_v2 into feature_notification_v2

This commit is contained in:
baladiwei 2021-11-12 14:07:07 +08:00
commit ed3bf55f90
59 changed files with 1436 additions and 537 deletions

View File

@ -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{

View File

@ -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} />)
}

View File

@ -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>

View File

@ -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 >
}

View File

@ -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);
}
}

View File

@ -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;
}
}
}
}

View File

@ -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

View File

@ -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>
: ""

View File

@ -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> }

View File

@ -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

View File

@ -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 &&

View File

@ -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"

View File

@ -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} />)
}

View File

@ -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>

View File

@ -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;

View File

@ -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">
{

View File

@ -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;

View File

@ -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>

View File

@ -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>
)
}

View File

@ -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%;
}
}

View File

@ -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>

View File

@ -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;

View File

@ -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>)
}
}

View File

@ -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;

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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退taburltab
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;
// Comment0
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;

View File

@ -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>
) : (
""

View File

@ -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);
};

View File

@ -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>{" "}

View File

@ -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;
}

View File

@ -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;

View File

@ -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>
);
}

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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)}` : "")}`;

View File

@ -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"}}>

View File

@ -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 && (

View File

@ -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

View File

@ -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>

View File

@ -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>
)

View File

@ -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,

View File

@ -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: [],

View File

@ -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){

View File

@ -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}/>

View File

@ -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>

View File

@ -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>
)}
/>
)}

View File

@ -104,6 +104,9 @@ ul,ol,dl{
white-space: normal;
&:hover{
text-decoration: underline;
& .markdown-body{
color: #466AFF;
}
}
}

View File

@ -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){

View File

@ -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;

View File

@ -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>&nbsp;{moment().year()}&nbsp;EduCoder<span className="ml15 mr15">ICP17009477</span><a href="https://team.trustie.net" style={{"color":"#888"}} target="_blank">Trustie</a>&nbsp;&nbsp;&nbsp;&amp;&nbsp;&nbsp;&nbsp;IntelliDE inside.</div>
<div className="font-14 color-grey-9 " style={{marginTop:"20px"}}><span className="font-18">©</span>&nbsp;{moment().year()}&nbsp;GitLink | <span className="ml15 mr15">ICP13000930</span><a href="https://team.trustie.net" style={{"color":"#888"}} target="_blank">GitLink</a>&nbsp;&nbsp;&nbsp;&amp;&nbsp;&nbsp;&nbsp;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>&nbsp;{moment().year()}&nbsp;EduCoder<span className="ml15 mr15">ICP17009477</span><a href="https://team.trustie.net" style={{"color":"#888"}} target="_blank">Trustie</a>&nbsp;&nbsp;&nbsp;&amp;&nbsp;&nbsp;&nbsp;IntelliDE inside.</div>
<div className="font-14 color-grey-9 " style={{marginTop:"20px"}}><span className="font-18">©</span>&nbsp;{moment().year()}&nbsp;GitLink | <span className="ml15 mr15">ICP13000930</span><a href="https://team.trustie.net" style={{"color":"#888"}} target="_blank">GitLink</a>&nbsp;&nbsp;&nbsp;&amp;&nbsp;&nbsp;&nbsp;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>&nbsp;{moment().year()}&nbsp;EduCoder<span className="ml15 mr15">ICP17009477</span><a href="https://team.trustie.net" style={{"color":"#888"}} target="_blank">Trustie</a>&nbsp;&nbsp;&nbsp;&amp;&nbsp;&nbsp;&nbsp;IntelliDE inside.</div>
<div className="font-14 color-grey-9 " style={{marginTop:"20px"}}><span className="font-18">©</span>&nbsp;{moment().year()}&nbsp;GitLink | <span className="ml15 mr15">ICP13000930</span><a href="https://team.trustie.net" style={{"color":"#888"}} target="_blank">GitLink</a>&nbsp;&nbsp;&nbsp;&amp;&nbsp;&nbsp;&nbsp;IntelliDE inside.</div>
</div>
:""
}

View File

@ -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;

View File

@ -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;

View File

@ -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}

View File

@ -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>
{

View File

@ -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>
}