forked from Gitlink/forgeplus-react
Merge pull request '更新' (#507) from durian/forgeplus-react:branch_label_revision into gitlink_server
This commit is contained in:
commit
f56384156d
|
@ -2,13 +2,13 @@ import React from 'react';
|
|||
import { Modal } from 'antd';
|
||||
import './Index.scss';
|
||||
|
||||
function Modals({title,children,btn,onCancel,visible}) {
|
||||
function Modals({title,children,btn,onCancel,visible, width}) {
|
||||
return(
|
||||
<Modal
|
||||
visible={visible}
|
||||
onCancel={onCancel}
|
||||
title={title}
|
||||
width={"520px"}
|
||||
width={width || '520px'}
|
||||
footer={btn}
|
||||
centered={true}
|
||||
wrapClassName={"deleteBox"}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import SubMenu from '../sub/SubMenu';
|
||||
import { Table, Tooltip, Spin,Pagination } from 'antd';
|
||||
import { Table, Tooltip, Spin,Pagination, Button, message } from 'antd';
|
||||
import axios from 'axios';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { truncateCommitId } from '../../common/util';
|
||||
|
@ -9,14 +9,18 @@ import Nonedata from '../../Nodata';
|
|||
import './Index.scss';
|
||||
import Tree from '../img/tree.png'
|
||||
import moment from 'moment';
|
||||
import CopyTool from '../../Component/CopyTool';
|
||||
import Modals from '../../Component/PublicModal/Index';
|
||||
|
||||
function Tags(props) {
|
||||
|
||||
const [reload, setReload] = useState(undefined);
|
||||
const [source, setSource] = useState(undefined);
|
||||
const [isSpin, setIsSpin] = useState(true);
|
||||
const [page, setPage] = useState(1);
|
||||
const [total,setTotal] =useState(0);
|
||||
const [limit,setLimit] =useState(10);
|
||||
// 删除标签
|
||||
const [visible, setVisible] = useState(false);
|
||||
const { projectsId, owner } = props.match.params;
|
||||
const { projectDetail} = props;
|
||||
|
||||
|
@ -30,7 +34,7 @@ function Tags(props) {
|
|||
useEffect(() => {
|
||||
if (projectsId) {
|
||||
setIsSpin(true);
|
||||
const url = `/${owner}/${projectsId}/tags.json`;
|
||||
const url = `/v1/${owner}/${projectsId}/tags.json`;
|
||||
axios.get(url, {
|
||||
params: {
|
||||
limit,
|
||||
|
@ -44,7 +48,7 @@ function Tags(props) {
|
|||
}
|
||||
}).catch(error => { })
|
||||
}
|
||||
}, [owner, projectsId,page]);
|
||||
}, [owner, projectsId, page, limit, reload]);
|
||||
|
||||
const columns = [
|
||||
{
|
||||
|
@ -52,54 +56,53 @@ function Tags(props) {
|
|||
dataIndex: "name",
|
||||
key: 1,
|
||||
ellipsis: true,
|
||||
width: "200px",
|
||||
width: "240px",
|
||||
render: (txt, item) => {
|
||||
return (
|
||||
<div className="tagBranch">
|
||||
<Link className="hover tagClass" to={`/${owner}/${projectsId}/tree/${item.name}`}>{item.name}</Link>
|
||||
<Link className="hover tagClass font-16" to={`/${owner}/${projectsId}/tree/${item.name}`}>{item.name}</Link>
|
||||
<div className="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>最后一次提交于{item.time_ago}</span>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "创建时间",
|
||||
dataIndex: "time_ago",
|
||||
key: 2,
|
||||
ellipsis: true,
|
||||
render: (txt, item) => {
|
||||
return (
|
||||
<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>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "提交ID",
|
||||
dataIndex: "id",
|
||||
key: 3,
|
||||
ellipsis: true,
|
||||
width: "240px",
|
||||
render: (txt, item) => {
|
||||
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.id}`)}`}>{truncateCommitId(item.id)}</Link>
|
||||
</Tooltip>
|
||||
<div className="treeCopyTag">
|
||||
<div className='treeCopyTagBox'>
|
||||
<span style={{lineHeight: '30px'}}>
|
||||
<img src={Tree} alt="sha" width={"16px"}/>
|
||||
<Tooltip placement="top" title={`最后提交日期:${item.created_at_unix ? moment(item.created_at_unix * 1000).format('YYYY-MM-DD') : ''}`}>
|
||||
<Link className="hover color-blue" to={`/${owner}/${projectsId}/commits/${truncateCommitId(`${item.id}`)}`}>{truncateCommitId(item.id)}</Link>
|
||||
</Tooltip>
|
||||
<input type="text" id={`value${truncateCommitId(`${item.id}`)}`} value={`${truncateCommitId(item.id)}`}/>
|
||||
</span>
|
||||
<CopyTool beforeText="复制commit id" afterText="复制成功" inputId={`value${truncateCommitId(`${item.id}`)}`}/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
},
|
||||
|
@ -116,24 +119,39 @@ function Tags(props) {
|
|||
title: "下载",
|
||||
dataIndex: "stage_type",
|
||||
key: 5,
|
||||
ellipsis: true,
|
||||
align: "center",
|
||||
width: "204px",
|
||||
width: "460px",
|
||||
render: (txt, item) => {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<a href={`${item.tarball_url}`} download className="btn-83">
|
||||
<a href={`${item.tarball_url}`} download className="btn-83" style={{width: '76px'}}>
|
||||
<i className="iconfont icon-xiazai-icon font-16 mr5"></i>TAR
|
||||
</a>
|
||||
<a href={`${item.zipball_url}`} download className="btn-83">
|
||||
<a href={`${item.zipball_url}`} download className="btn-83" style={{width: '76px'}}>
|
||||
<i className="iconfont icon-xiazai-icon font-16 mr5"></i>ZIP
|
||||
</a>
|
||||
{item.has_release ? <Tooltip title={`该标签已绑定发行版,不支持创建`}><a className="btn-83 disabledBut">创建发行版</a></Tooltip> : <Link to={`/${owner}/${projectsId}/releases/new?tag=${item.name}`} className="btn-83">创建发行版</Link>}
|
||||
{item.has_release ? <Tooltip title={`该标签已绑定发行版,不支持删除操作`}><Button style={{width: '76px'}} disabled className='ml8'>删除</Button></Tooltip> : <Button className='f6_bor_but ml8' style={{width: '76px'}} onClick={()=>{setVisible(item)}}>删除</Button>}
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
// 删除标签确认函数
|
||||
function deleteLabel(){
|
||||
axios.delete(`/v1/${owner}/${projectsId}/tags/${visible.name}.json`).then(res=>{
|
||||
if(res && res.data){
|
||||
setVisible(false);
|
||||
!res.data.status && message.success('删除成功');
|
||||
if(page>1 && (source && source.length===1)){
|
||||
setPage(page-1);
|
||||
}else{
|
||||
setReload(Math.random());
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
@ -147,24 +165,54 @@ function Tags(props) {
|
|||
className="tagTable"
|
||||
dataSource={source} columns={columns} pagination={false}></Table>
|
||||
}
|
||||
{total > limit ? (
|
||||
<div className="mt30 mb50 edu-txt-center">
|
||||
<Pagination
|
||||
simple
|
||||
<div className="mt30 mb50 edu-txt-right">
|
||||
{total > limit && <Pagination
|
||||
current={page}
|
||||
total={total}
|
||||
pageSize={limit}
|
||||
onChange={(e)=>{setPage(e)}}
|
||||
></Pagination>
|
||||
showSizeChanger={true}
|
||||
onShowSizeChange={(current, pageSize)=>{setPage(1);setLimit(pageSize);}}
|
||||
showQuickJumper={true}
|
||||
></Pagination>}
|
||||
</div>
|
||||
{/* {total > limit ? (
|
||||
<div className="mt30 mb50 edu-txt-right">
|
||||
{total > limit && <Pagination
|
||||
current={page}
|
||||
total={total}
|
||||
pageSize={limit}
|
||||
onChange={(e)=>{setPage(e)}}
|
||||
showSizeChanger={true}
|
||||
onShowSizeChange={(current, pageSize)=>{setPage(1);setLimit(pageSize);}}
|
||||
showQuickJumper={true}
|
||||
></Pagination>}
|
||||
</div>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
)} */}
|
||||
{
|
||||
source && source.length === 0 && <Nonedata _html={'暂无数据~'} />
|
||||
}
|
||||
</div>
|
||||
</Spin>
|
||||
<Modals
|
||||
title="删除标签"
|
||||
onCancel={()=>{setVisible(false)}}
|
||||
visible={Boolean(visible)}
|
||||
width="456px"
|
||||
btn={
|
||||
<div>
|
||||
<Button size={"large"} onClick={()=>{setVisible(false)}}>取消</Button>
|
||||
<Button type={'danger'} ghost size={"large"} onClick={deleteLabel}>确认删除</Button>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div className="contents mb30" style={{justifyContent: 'flex-start'}}>
|
||||
<i className='iconfont icon-shanchu_tc_icon1 font-36 mr18' style={{color: '#ca0002'}}></i>
|
||||
<p style={{color: '#333'}}>确定删除{visible.name}标签?</p>
|
||||
</div>
|
||||
</Modals>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,16 +1,7 @@
|
|||
.tagTable{
|
||||
margin-top: 30px;
|
||||
thead{
|
||||
tr th{
|
||||
background-color: #fff;
|
||||
padding:5px 0px;
|
||||
width: 172px;
|
||||
.ant-table-column-title{
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
margin-top: 9px;
|
||||
thead tr th{
|
||||
display: none;
|
||||
}
|
||||
tbody{
|
||||
.btn-83{
|
||||
|
@ -21,9 +12,8 @@
|
|||
background-color: #fff!important;
|
||||
}
|
||||
td{
|
||||
padding:0px;
|
||||
padding:20px 16px 15px;
|
||||
height: 69px;
|
||||
line-height: 69px;
|
||||
color:#333333;
|
||||
div{
|
||||
font-weight: 500;
|
||||
|
@ -36,23 +26,90 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
.disabledBut{
|
||||
color: rgba(0, 0, 0, 0.25) !important;
|
||||
background-color: #f5f5f5;
|
||||
border-color: #d9d9d9;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
.tagSpin{
|
||||
min-height: 300px;
|
||||
position: relative;
|
||||
}
|
||||
.tagBranch{
|
||||
padding-right: 15px;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
.tagClass{
|
||||
color:#333333;
|
||||
font-weight:700;
|
||||
color:#40424a;
|
||||
}
|
||||
}
|
||||
.tagModel{
|
||||
font-weight: 400;
|
||||
color:#898d9d;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
.tagModelImg img{
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
.f6_bor_but, .f6_bor_but:focus{
|
||||
color:#f60011;
|
||||
background-color:rgba(196, 0, 14, 0.09);
|
||||
border:1px solid #f60011;
|
||||
border-radius:5px;
|
||||
&:hover{
|
||||
color:#f60011;
|
||||
background-color:rgba(196, 0, 14, 0.18);
|
||||
border-color:#ff727c;
|
||||
}
|
||||
&:active{
|
||||
color:#f60011;
|
||||
background-color:rgba(196, 0, 14, 0.22);
|
||||
border-color:#f60011;
|
||||
}
|
||||
}
|
||||
.treeCopyTag{
|
||||
flex:1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
.treeCopyTagBox{
|
||||
height: 32px;
|
||||
background: #FAFBFC;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #D0D0D0;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
// position: relative;
|
||||
&>span{
|
||||
padding:0px 15px;
|
||||
border-right: 1px solid rgba(153, 153, 153, 0.4);
|
||||
height: 100%;
|
||||
width: 135px;
|
||||
img{
|
||||
margin-right: 4px;
|
||||
}
|
||||
a{
|
||||
color: #466AFF;
|
||||
&:hover{
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
&>i{
|
||||
margin:0px 12px;
|
||||
color: #333!important;
|
||||
}
|
||||
input{
|
||||
position: absolute;
|
||||
z-index: 0;
|
||||
opacity: 0;
|
||||
top: 65px;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,22 +3,53 @@ import CopyTool from '../../Component/CopyTool';
|
|||
import { truncateCommitId } from '../../common/util';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { getImageUrl , turnbar } from 'educoder';
|
||||
import { Dropdown , Menu , Spin } from 'antd';
|
||||
import { Button, Dropdown , Input, Menu , message, Modal, Select, Spin, Table, Tooltip } from 'antd';
|
||||
import Modals from '../../Component/PublicModal/Index';
|
||||
import './Index.scss';
|
||||
|
||||
import Tree from '../img/tree.png';
|
||||
import Axios from 'axios';
|
||||
|
||||
function Index(props) {
|
||||
const [ reload, setReload] = useState(undefined);
|
||||
const [ list , setList ] = useState([]);
|
||||
const [ isSpin , setIsSpin ] = useState(true);
|
||||
// 删除分支
|
||||
const [visible, setVisible] = useState(false);
|
||||
// 新建分支
|
||||
const [addBranch, setAddBranch] = useState(false);
|
||||
const [newBranchName, setNewBranchName] = useState(undefined);
|
||||
const [newFormBranchName, setNewFormBranchName] = useState(undefined);
|
||||
const [newBranchError, setNewBranchError] = useState(undefined);
|
||||
// 通过分支名搜索分支
|
||||
const [name, setName] = useState(undefined);
|
||||
// 分页
|
||||
const [current, setCurrent] = useState(1);
|
||||
const [total, setTotal] = useState(0);
|
||||
const [pageSize, setPageSize] = useState(10);
|
||||
|
||||
const { projectsId , owner } = props.match.params;
|
||||
const { isManager , isDeveloper , projectDetail , defaultBranch } = props;
|
||||
|
||||
const { isManager , isDeveloper , projectDetail , defaultBranch, getDetail } = props;
|
||||
|
||||
useEffect(()=>{
|
||||
getList();
|
||||
},[])
|
||||
// getList();
|
||||
const url = `/v1/${owner}/${projectsId}/branches.json`;
|
||||
Axios.get(url,{
|
||||
params:{
|
||||
keyword: name,
|
||||
page: current,
|
||||
limit: pageSize
|
||||
}
|
||||
}).then(result=>{
|
||||
if(result){
|
||||
const {branches, total_count} = result.data;
|
||||
setTotal(total_count)
|
||||
setList(branches);
|
||||
setNewFormBranchName(branches[0].name);
|
||||
}
|
||||
setIsSpin(false);
|
||||
}).catch(error=>{setIsSpin(false);})
|
||||
},[name, reload, pageSize, current])
|
||||
|
||||
useEffect(()=>{
|
||||
if(projectDetail && document.title.indexOf('所有分支-') === -1){
|
||||
|
@ -35,6 +66,105 @@ function Index(props) {
|
|||
</Menu>
|
||||
)
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: "分支名称",
|
||||
dataIndex: "name",
|
||||
key: 1,
|
||||
ellipsis: true,
|
||||
width: "160px",
|
||||
className: "branchNameColumn",
|
||||
render: (txt, item) => {
|
||||
return (
|
||||
<Link to={`/${owner}/${projectsId}/tree/${turnbar(txt)}`} className="task-hide">{txt}</Link>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "更新信息",
|
||||
dataIndex: "commit",
|
||||
key: 3,
|
||||
ellipsis: true,
|
||||
width: "240px",
|
||||
render: (txt, item) => {
|
||||
return (
|
||||
<div className='treeinfo'>
|
||||
{
|
||||
txt && txt.committer && txt.committer.id?
|
||||
<Link to={`/${ txt.committer.login}`}>
|
||||
<img style={{borderRadius:"50%"}} src={getImageUrl(`/${ txt.committer.image_url}`)} alt="" className='branchLastUpdateUserImage'/>
|
||||
<span style={{fontWeight:"500"}}>{txt && txt.committer && txt.committer.name}</span>
|
||||
</Link>
|
||||
:
|
||||
<React.Fragment>
|
||||
<img style={{borderRadius:"50%"}} src={getImageUrl(`/${ txt.committer.image_url}`)} alt="" className='branchLastUpdateUserImage'/>
|
||||
<span style={{fontWeight:"500"}}>{txt && txt.committer && txt.committer.name}</span>
|
||||
</React.Fragment>
|
||||
}
|
||||
<span className="color-grey-3">更新于{txt && txt.time_ago}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "commit信息",
|
||||
dataIndex: "commit_id",
|
||||
key: 4,
|
||||
ellipsis: true,
|
||||
width: "300px",
|
||||
render: (txt, item) => {
|
||||
return <div className="treecopy">
|
||||
<div className='treeCopyBox'>
|
||||
<span>
|
||||
<img src={Tree} alt="sha" width={"16px"}/>
|
||||
<Link to={`/${owner}/${projectsId}/commits/${truncateCommitId(txt)}`}>{truncateCommitId(txt)}</Link>
|
||||
<input type="text" id={`value${truncateCommitId(txt)}`} value={`${truncateCommitId(txt)}`}/>
|
||||
</span>
|
||||
<CopyTool beforeText="复制commit id" afterText="复制成功" inputId={`value${truncateCommitId(txt)}`}/>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "分支类型",
|
||||
dataIndex: "default_branch",
|
||||
key: 5,
|
||||
render: (txt, item) => {
|
||||
return isManager ? txt === item.name ? <a className='btn-83' style={{width: '93px'}}>默认分支</a> : <Select value={1} onChange={(value)=>{updateDefaultBranch(value, item)}}>
|
||||
<Select.Option value={0}>默认分支</Select.Option>
|
||||
<Select.Option value={1}>普通分支</Select.Option>
|
||||
</Select> : txt === item.name ? '默认分支' : '普通分支'
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
dataIndex: "name",
|
||||
key: 6,
|
||||
align: "center",
|
||||
width: "320px",
|
||||
className: "branchActionColumn",
|
||||
render: (txt, item) => {
|
||||
return (
|
||||
<div className="treeabout">
|
||||
{
|
||||
(isManager || isDeveloper) && (projectDetail && projectDetail.type!==2) &&
|
||||
<Tooltip title={`以${txt}为源分支创建一个合并请求`}><Link to={
|
||||
// 如果项目是fork的项目,pr自动指向源仓库,否则指向本仓库默认分支
|
||||
projectDetail && projectDetail.fork_info?
|
||||
`/${projectDetail.fork_info.fork_project_user_login}/${projectDetail.fork_info.fork_project_identifier}/compare/${turnbar(txt || defaultBranch)}...${owner + ':' + turnbar(txt)}`
|
||||
:`/${owner}/${projectsId}/compare/${turnbar(defaultBranch)}...${turnbar(txt)}`
|
||||
} className="btn-83">+ 合并请求</Link></Tooltip>
|
||||
}
|
||||
<Dropdown overlay={menu(item.zip_url,item.tar_url)} trigger={['click']} placement="bottomRight">
|
||||
<a className="btn-83" style={{width: '76px'}}>下载<i className="iconfont icon-sanjiaoxing-down font-14"></i></a>
|
||||
</Dropdown>
|
||||
{txt === item.default_branch ? <Tooltip title={`该分支为默认分支,不支持删除操作`}><Button style={{width: '76px'}} disabled>删除</Button></Tooltip> : <Button className='f6_bor_but' style={{width: '76px'}} onClick={()=>{setVisible(item)}}>删除</Button>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
function getList() {
|
||||
const url = `/${owner}/${projectsId}/branches_slice.json`;
|
||||
Axios.get(url).then(result=>{
|
||||
|
@ -45,10 +175,109 @@ function Index(props) {
|
|||
}).catch(error=>{setIsSpin(false);})
|
||||
}
|
||||
|
||||
// 删除分支确认函数
|
||||
function deleteLabel(){
|
||||
Axios.delete(`/v1/${owner}/${projectsId}/branches/${visible.name}.json`).then(res=>{
|
||||
if(res && res.data){
|
||||
if(current>1 && (list && list.length===1)){
|
||||
setCurrent(current-1);
|
||||
}else{
|
||||
setReload(Math.random());
|
||||
}
|
||||
setVisible(false);
|
||||
!res.data.status && message.success('删除成功');
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 新建分支确认函数
|
||||
function createBranch(){
|
||||
setNewBranchError(undefined);
|
||||
if(!newBranchName){
|
||||
setNewBranchError("请输入新建分支名称");
|
||||
}else{
|
||||
Axios.post(`/v1/${owner}/${projectsId}/branches.json`, {
|
||||
new_branch_name: newBranchName,
|
||||
old_branch_name: newFormBranchName
|
||||
}).then(res=>{
|
||||
if(res && res.data){
|
||||
// 重新请求仓库详情接口,更新分支总数信息
|
||||
getDetail();
|
||||
setReload(Math.random());
|
||||
setAddBranch(false);
|
||||
message.success('新建分支成功');
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 新建分支名检查格式
|
||||
function checkNewBranchName(e) {
|
||||
setNewBranchError(undefined);
|
||||
const value = e.target.value;
|
||||
if (value) {
|
||||
const str = '^*/';
|
||||
let reg = /\\/g;
|
||||
if(reg.test(value)){
|
||||
setNewBranchError('分支名不能包含下列任何字符:^ * \\ /');
|
||||
}else{
|
||||
for(var i=0;i<str.length;i++){
|
||||
let s = str[i];
|
||||
if(value.indexOf(s) > -1){
|
||||
setNewBranchError('分支名不能包含下列任何字符:^ * \\ /');
|
||||
return;
|
||||
}else{
|
||||
setNewBranchName(e.target.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 更新默认仓库分支
|
||||
function updateDefaultBranch(value, info){
|
||||
Axios.patch(`/v1/${owner}/${projectsId}/branches/update_default_branch.json`,{
|
||||
name: info.name
|
||||
}).then(res=>{
|
||||
if(res && res.data){
|
||||
setReload(Math.random());
|
||||
!res.data.status && message.success('操作成功');
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 改变pagesize
|
||||
function onShowSizeChange(current, pageSize){
|
||||
window.scrollTo(0, 0);
|
||||
setCurrent(1);
|
||||
setPageSize(pageSize);
|
||||
}
|
||||
|
||||
// 切换页数
|
||||
function changePage(page, pageSize){
|
||||
window.scrollTo(0, 0);
|
||||
setCurrent(page);
|
||||
}
|
||||
|
||||
return(
|
||||
<Spin spinning={isSpin}>
|
||||
<div style={{paddingTop:"10px",minHeight:"400px",paddingBottom:"30px"}}>
|
||||
{
|
||||
<div className='branchListActionBox'>
|
||||
<Input.Search placeholder='请输入分支名称' style={{width: '354px'}} className='searchBranch' onSearch={(value)=>{setName(value)}} allowClear/>
|
||||
<div>
|
||||
{isManager && <Link to={`/${owner}/${projectsId}/settings/branches`} className="btn-83" style={{width: '102px'}}><i className="iconfont icon-xuanzhongjibenshezhiicon font-14 mr5"></i>分支设置</Link>}
|
||||
<Button type='primary' onClick={()=>{setAddBranch(true);}}>+ 新建分支</Button>
|
||||
</div>
|
||||
</div>
|
||||
<Table
|
||||
rowKey={'name'}
|
||||
className='branchListTable'
|
||||
dataSource={list}
|
||||
columns={columns}
|
||||
pagination={{current: current, pageSize: pageSize, total: total, showSizeChanger: true, onShowSizeChange:onShowSizeChange, showQuickJumper: true, onChange: changePage}}
|
||||
>
|
||||
</Table>
|
||||
{/* {
|
||||
list && list.length>0 && list.map((item,key)=>{
|
||||
return(
|
||||
<React.Fragment>
|
||||
|
@ -112,8 +341,47 @@ function Index(props) {
|
|||
</React.Fragment>
|
||||
)
|
||||
})
|
||||
}
|
||||
} */}
|
||||
</div>
|
||||
<Modals
|
||||
title="删除分支"
|
||||
onCancel={()=>{setVisible(false)}}
|
||||
visible={Boolean(visible)}
|
||||
width="456px"
|
||||
btn={
|
||||
<div>
|
||||
<Button size={"large"} onClick={()=>{setVisible(false)}}>取消</Button>
|
||||
<Button type={'danger'} ghost size={"large"} onClick={deleteLabel}>确认删除</Button>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<div className="contents mb30" style={{justifyContent: 'flex-start'}}>
|
||||
<i className='iconfont icon-shanchu_tc_icon1 font-36 mr18' style={{color: '#ca0002'}}></i>
|
||||
<p style={{color: '#333'}}>确定删除{visible.name}分支?</p>
|
||||
</div>
|
||||
</Modals>
|
||||
<Modal
|
||||
title="新建分支"
|
||||
onCancel={()=>{setAddBranch(false)}}
|
||||
visible={addBranch}
|
||||
width="388px"
|
||||
footer={
|
||||
<Button type={'primary'} style={{width:'334px', height: '42px'}} onClick={createBranch}>确认新建</Button>
|
||||
}
|
||||
className="createNewBranchModal"
|
||||
>
|
||||
<div className="mb30" style={{justifyContent: 'flex-start'}}>
|
||||
<div className='font-15 createBranchLabel'>分支名称</div>
|
||||
<Input placeholder='请输入分支名称' className='createBranchInput' onChange={checkNewBranchName} maxLength={100}/>
|
||||
<div className='newBranchError mt5'>{newBranchError}</div>
|
||||
<div className='font-15 createBranchLabel mt20'>分支起点</div>
|
||||
<Select showSearch style={{width: '340px'}} className='createBranchInput' defaultValue={list[0] && list[0].name} onChange={(value)=>{setNewFormBranchName(value)}} getPopupContainer={triggerNode => triggerNode.parentNode}>
|
||||
{list && list.map((item, index)=>{
|
||||
return <Select.Option value={item.name} key={index}>{item.name}</Select.Option>
|
||||
})}
|
||||
</Select>
|
||||
</div>
|
||||
</Modal>
|
||||
</Spin>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,3 +1,98 @@
|
|||
.treeinfo{
|
||||
.branchLastUpdateUserImage{
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
.f6_bor_but, .f6_bor_but:focus{
|
||||
color:#f60011;
|
||||
background-color:rgba(196, 0, 14, 0.09);
|
||||
border:1px solid #f60011;
|
||||
border-radius:5px;
|
||||
&:hover{
|
||||
color:#f60011;
|
||||
background-color:rgba(196, 0, 14, 0.18);
|
||||
border-color:#ff727c;
|
||||
}
|
||||
&:active{
|
||||
color:#f60011;
|
||||
background-color:rgba(196, 0, 14, 0.22);
|
||||
border-color:#f60011;
|
||||
}
|
||||
}
|
||||
.branchListTable{
|
||||
.ant-table-thead > tr > th{
|
||||
border-top: 1px solid rgba(42, 97, 255, 0.23);
|
||||
border-bottom: 1px solid rgba(42, 97, 255, 0.23) !important;
|
||||
background-color:#fafcff;
|
||||
}
|
||||
.ant-table-column-title{
|
||||
color:#40424a;
|
||||
}
|
||||
.ant-table-thead > tr:first-child > th:last-child{
|
||||
border-right: 1px solid rgba(42, 97, 255, 0.23);
|
||||
}
|
||||
.ant-table-thead > tr:first-child > th:first-child{
|
||||
border-left: 1px solid rgba(42, 97, 255, 0.23);
|
||||
}
|
||||
.ant-table-tbody > tr > td{
|
||||
border-color: #eeeeee;
|
||||
padding: 18.5px 16px;
|
||||
}
|
||||
.branchNameColumn{
|
||||
border-left: 1px solid #d0d0d0;
|
||||
}
|
||||
.branchActionColumn{
|
||||
border-right: 1px solid #d0d0d0;
|
||||
}
|
||||
.task-hide{
|
||||
color: $primary-color;
|
||||
}
|
||||
.ant-table-empty .ant-table-placeholder{
|
||||
border-left: 1px solid #d0d0d0;
|
||||
border-right: 1px solid #d0d0d0;
|
||||
}
|
||||
}
|
||||
.branchListActionBox{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin: 20px 0 30px;
|
||||
}
|
||||
.createNewBranchModal{
|
||||
.ant-modal-title{
|
||||
text-align: left;
|
||||
color:#333333;
|
||||
font-size:17px;
|
||||
font-weight: normal !important;
|
||||
}
|
||||
.ant-modal-header{
|
||||
border-bottom: none;
|
||||
background-color:rgba(70, 106, 255, 0.05);
|
||||
}
|
||||
.ant-modal-close{right: 5px;}
|
||||
.ant-modal-close-x{font-size: 26px;}
|
||||
.ant-modal-footer{
|
||||
border-top: none;
|
||||
text-align: center;
|
||||
padding-bottom: 53px;
|
||||
}
|
||||
.ant-modal-content{
|
||||
background-image:linear-gradient(359.37deg,#ebf3ff 0%,#f8fbff 55.01%,#f1f5ff 100%);
|
||||
}
|
||||
.createBranchLabel{
|
||||
color:#27282d;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.createBranchInput, .createBranchInput .ant-select-selection{
|
||||
border-color:#9eaacb;
|
||||
background-color: transparent !important;
|
||||
}
|
||||
.newBranchError{
|
||||
color:#df0002;
|
||||
}
|
||||
}
|
||||
.branchSort{
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
|
@ -49,14 +144,16 @@
|
|||
}
|
||||
.treecopy{
|
||||
flex:1;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
// justify-content: center;
|
||||
&>div:not(.treeCopyBox){
|
||||
position: relative;
|
||||
}
|
||||
&>div{
|
||||
height: 32px;
|
||||
background: #FAFBFC;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #D0D0D0;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -64,6 +161,7 @@
|
|||
padding:0px 15px;
|
||||
border-right: 1px solid rgba(153, 153, 153, 0.4);
|
||||
height: 100%;
|
||||
width: 135px;
|
||||
img{
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ const Span = styled.span`
|
|||
export default Form.create()(
|
||||
forwardRef(
|
||||
(
|
||||
{ form, projectDetail , match, showNotification, history },
|
||||
{ form, projectDetail , match, showNotification, history, getDetail },
|
||||
ref
|
||||
) => {
|
||||
const { getFieldDecorator, validateFields, setFieldsValue } = form;
|
||||
|
@ -35,7 +35,8 @@ export default Form.create()(
|
|||
const [options , setOptions] = useState(undefined);
|
||||
const stable = history && history.location && history.location.state&&history.location.state.stable;
|
||||
const { projectsId, versionId , owner } = match.params;
|
||||
|
||||
const urlSearch = new URLSearchParams(history.location.search);
|
||||
|
||||
useEffect(()=>{
|
||||
if(projectDetail && projectDetail.default_branch){
|
||||
setBranch(projectDetail.default_branch);
|
||||
|
@ -121,6 +122,8 @@ export default Form.create()(
|
|||
})
|
||||
.then(result => {
|
||||
if (result) {
|
||||
// 重新请求仓库详情接口,更新标签总数信息
|
||||
getDetail();
|
||||
showNotification("版本发布成功!");
|
||||
history.push(`/${owner}/${projectsId}/releases`);
|
||||
}
|
||||
|
@ -153,7 +156,8 @@ export default Form.create()(
|
|||
callback();
|
||||
}
|
||||
}}],
|
||||
validateFirst: true
|
||||
validateFirst: true,
|
||||
initialValue: urlSearch.get('tag')
|
||||
})(
|
||||
<AutoComplete
|
||||
placeholder="标记一个版本"
|
||||
|
|
|
@ -60,11 +60,12 @@
|
|||
.body-show{
|
||||
padding: 5px 10px 10px 10px;
|
||||
}
|
||||
.version-user{display: flex;}
|
||||
& .version-user>a>span{
|
||||
display: inline-block;
|
||||
& img{
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -214,8 +214,8 @@ class CreateMerge extends Component {
|
|||
const url = `/${owner}/${identifier}/branches.json`;
|
||||
let check = await axios.get(url).then((result) => {
|
||||
if(result.data){
|
||||
let pfilter = (result.data || []).filter(i => i.name === branch).length === 0;
|
||||
let mfilter = (result.data || []).filter(i => i.name === mergebranch).length === 0;
|
||||
let pfilter = (result.data || []).filter(i => i.name === decodeURIComponent(branch)).length === 0;
|
||||
let mfilter = (result.data || []).filter(i => i.name === decodeURIComponent(mergebranch)).length === 0;
|
||||
if(type === "pull"){
|
||||
this.setState({
|
||||
pullBranches:result.data,
|
||||
|
|
|
@ -244,6 +244,7 @@ class UserSubmitComponent extends Component {
|
|||
<Input
|
||||
placeholder={`请输入分支名称`}
|
||||
style={{ width: "220px" }}
|
||||
maxLength={100}
|
||||
/>
|
||||
)}
|
||||
</Form.Item>
|
||||
|
|
Loading…
Reference in New Issue