forked from Gitlink/forgeplus-react
devops
This commit is contained in:
parent
cefd974498
commit
dfbcc09e5b
|
@ -3,15 +3,15 @@ import './Component.scss';
|
|||
|
||||
export const Tags = (status)=>{
|
||||
switch(status){
|
||||
case 1:
|
||||
case "running":
|
||||
return(
|
||||
<span className="statusColor running">运行中</span>
|
||||
);
|
||||
case 2:
|
||||
case "failure":
|
||||
return (
|
||||
<span className="statusColor failed">未通过</span>
|
||||
);
|
||||
case 3:
|
||||
case "success":
|
||||
return (
|
||||
<span className="statusColor pass">已通过</span>
|
||||
);
|
||||
|
|
|
@ -1,27 +1,33 @@
|
|||
import React , { forwardRef , useCallback } from 'react';
|
||||
import activate from '../Images/activate.png';
|
||||
import { Blueback } from '../Component/layout';
|
||||
import styled from 'styled-components';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Form , Input } from 'antd';
|
||||
import axios from 'axios';
|
||||
import React, { forwardRef, useCallback, useState , useEffect } from "react";
|
||||
import activate from "../Images/activate.png";
|
||||
import { Blueback } from "../Component/layout";
|
||||
import styled from "styled-components";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Form, Input, Modal, Button } from "antd";
|
||||
import axios from "axios";
|
||||
|
||||
const P = styled.p`
|
||||
{
|
||||
width: 200px;
|
||||
line-height: 30px;
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
text-align: center;
|
||||
margin-top: 30px;
|
||||
margin-bottom: 30px !important;
|
||||
}
|
||||
`;
|
||||
function About(props, ref) {
|
||||
const { form: { getFieldDecorator, validateFields } } = props;
|
||||
const [step, setStep] = useState(1);
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [firstCompleted, setFirstCompleted] = useState(false);
|
||||
|
||||
const P = styled.p`{
|
||||
width:200px;
|
||||
line-height:30px;
|
||||
font-size:16px;
|
||||
color:#333;
|
||||
text-align:center;
|
||||
margin-top:30px;
|
||||
margin-bottom:30px!important;
|
||||
}`;
|
||||
function About( props , ref){
|
||||
const { form: { getFieldDecorator , validateFields } } = props;
|
||||
|
||||
const helper = useCallback(
|
||||
(label, name, rules, widget, isRequired) => (
|
||||
<React.Fragment>
|
||||
<span className={isRequired?"required":""}>{label}</span>
|
||||
<span className={isRequired ? "required" : ""}>{label}</span>
|
||||
<Form.Item>
|
||||
{getFieldDecorator(name, { rules, validateFirst: true })(widget)}
|
||||
</Form.Item>
|
||||
|
@ -29,52 +35,140 @@ function About( props , ref){
|
|||
),
|
||||
[]
|
||||
);
|
||||
// 下一步
|
||||
function goStep() {
|
||||
if (!firstCompleted) {
|
||||
let projectsId = props.match.params.projectsId;
|
||||
validateFields((error, values) => {
|
||||
if (!error) {
|
||||
const url = `/dev_ops/cloud_accounts.json`;
|
||||
axios.post(url, {
|
||||
...values,
|
||||
project_id: projectsId,
|
||||
})
|
||||
.then((result) => {
|
||||
if (result && result.data.redirect_url) {
|
||||
setVisible(true);
|
||||
setFirstCompleted(true);
|
||||
// window.location.href = result.data.redirect_url;
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
setStep(2);
|
||||
}
|
||||
}
|
||||
// 弹框确定
|
||||
function sure(){
|
||||
setVisible(false)
|
||||
setStep(2);
|
||||
}
|
||||
|
||||
// 开始激活
|
||||
function startActive(){
|
||||
let projectsId = props.match.params.projectsId;
|
||||
validateFields((error,values)=>{
|
||||
if(!error){
|
||||
const url = `/dev_ops/cloud_accounts.json`;
|
||||
axios.post(url,{
|
||||
...values,
|
||||
project_id:projectsId
|
||||
}).then(result=>{
|
||||
if(result && result.data.redirect_url){
|
||||
window.location.href = result.data.redirect_url;
|
||||
}
|
||||
}).catch(error=>{
|
||||
console.log(error);
|
||||
})
|
||||
validateFields((error, values) => {
|
||||
if(!values){
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
return(
|
||||
return (
|
||||
<div className="activatePanel">
|
||||
<img src={activate} alt="" width="250px"/>
|
||||
<Modal
|
||||
title="提示"
|
||||
visible={visible}
|
||||
closable={true}
|
||||
onCancel={() => setVisible(false)}
|
||||
footer={
|
||||
<React.Fragment>
|
||||
<Button onClick={() => setVisible(false)}>取消</Button>
|
||||
<Button
|
||||
onClick={sure}
|
||||
type={"primary"}
|
||||
className="ml20"
|
||||
>
|
||||
确定
|
||||
</Button>
|
||||
</React.Fragment>
|
||||
}
|
||||
>
|
||||
<div style={{ display: "flex", justifyContent: "center" }}>
|
||||
<p style={{ maxWidth: "260px" }}>
|
||||
初始化配置已完成,请前往:
|
||||
<br />
|
||||
<a
|
||||
target="_blank"
|
||||
href="http://ip:80/login/oauth/authorize"
|
||||
className="color-blue"
|
||||
>
|
||||
http://ip:80/login/oauth/authorize
|
||||
</a>
|
||||
<br />
|
||||
进入认证
|
||||
</p>
|
||||
</div>
|
||||
</Modal>
|
||||
<img src={activate} alt="" width="250px" />
|
||||
<P>定义DevOps工作流,帮助您检测bug、发布代码…</P>
|
||||
<Link to={""} style={{color:"#5091FF",marginBottom:"20px"}}>了解什么是DevOps?</Link>
|
||||
<Form>
|
||||
{helper(
|
||||
"服务器IP地址:",
|
||||
"ip_num",
|
||||
[{ required: true, message: "请输入服务器IP地址" }],
|
||||
<Input placeholder="请输入服务器IP地址" style={{width:"368px"}} size="large" />,true
|
||||
)}
|
||||
{helper(
|
||||
"服务器用户名:",
|
||||
"account",
|
||||
[{ required: true, message: "请输入服务器用户名" }],
|
||||
<Input placeholder="请输入服务器用户名" size="large" />,true
|
||||
)}
|
||||
{helper(
|
||||
"服务器密码:",
|
||||
"secret",
|
||||
[{ required: true, message: "请输入服务器密码" }],
|
||||
<Input.Password placeholder="请输入服务器密码" size="large" />,true
|
||||
)}
|
||||
</Form>
|
||||
<Blueback onClick={startActive}>开始激活</Blueback>
|
||||
<Link to={""} style={{ color: "#5091FF", marginBottom: "20px" }}>
|
||||
了解什么是DevOps?
|
||||
</Link>
|
||||
{step === 1 ? (
|
||||
<React.Fragment>
|
||||
<Form>
|
||||
<p className="mb20" style={{width:"370px"}}>请仔细核对您的服务器信息,一旦确认提交将无法修改</p>
|
||||
{helper(
|
||||
"服务器IP地址:",
|
||||
"ip_num",
|
||||
[{ required: true, message: "请输入服务器IP地址" }],
|
||||
<Input
|
||||
placeholder="请输入服务器IP地址"
|
||||
style={{ width: "368px" }}
|
||||
size="large"
|
||||
disabled={firstCompleted}
|
||||
/>,
|
||||
true
|
||||
)}
|
||||
{helper(
|
||||
"服务器用户名:",
|
||||
"account",
|
||||
[{ required: true, message: "请输入服务器用户名" }],
|
||||
<Input placeholder="请输入服务器用户名" size="large" disabled={firstCompleted} />,
|
||||
true
|
||||
)}
|
||||
{helper(
|
||||
"服务器密码:",
|
||||
"secret",
|
||||
[{ required: true, message: "请输入服务器密码" }],
|
||||
<Input.Password placeholder="请输入服务器密码" size="large" disabled={firstCompleted}/>,
|
||||
true
|
||||
)}
|
||||
</Form>
|
||||
<Blueback onClick={goStep}>下一步</Blueback>
|
||||
</React.Fragment>
|
||||
) : (
|
||||
<div>
|
||||
<Form>
|
||||
<p className="mb20" style={{width:"370px"}}>认证成功后,请前往<a target="_blank" href="http://ip:80/account" className="color-blue">http://ip:80/account</a>获取token值,并将获取的token值填入输入框</p>
|
||||
{helper(
|
||||
"token值:",
|
||||
"token",
|
||||
[{ required: true, message: "请输入token值" }],
|
||||
<Input placeholder="请输入token值" size="large" />,
|
||||
true
|
||||
)}
|
||||
<div style={{ display: "flex", justifyContent: "center" }}>
|
||||
<Button onClick={()=>setStep(1)}>返回上一步</Button>
|
||||
<Blueback onClick={startActive} className="ml20">开始激活</Blueback>
|
||||
</div>
|
||||
</Form>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
export default Form.create()(forwardRef(About));
|
||||
export default Form.create()(forwardRef(About));
|
||||
|
|
|
@ -1,42 +1,80 @@
|
|||
import React from 'react';
|
||||
import { FlexAJ , Blueline , AlignCenter } from '../Component/layout';
|
||||
import styled from 'styled-components';
|
||||
import { Menu } from 'antd';
|
||||
import { TagsLine } from '../Component/OpsStatus';
|
||||
import React, { useEffect ,useState } from "react";
|
||||
import { FlexAJ, Blueline, AlignCenter } from "../Component/layout";
|
||||
import styled from "styled-components";
|
||||
import { Menu , Popconfirm } from "antd";
|
||||
import { TagsLine } from "../Component/OpsStatus";
|
||||
import { Time } from "../Utils/Time";
|
||||
import { truncateCommitId } from "../common/util";
|
||||
|
||||
|
||||
const SubMenu = Menu.SubMenu;
|
||||
const Img = styled.img`{
|
||||
width:25px;
|
||||
height:25px;
|
||||
border-radius:50%;
|
||||
margin-right:10px;
|
||||
}`
|
||||
export default (()=>{
|
||||
return(
|
||||
const Img = styled.img`
|
||||
{
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
border-radius: 50%;
|
||||
margin-right: 10px;
|
||||
}
|
||||
`;
|
||||
export default ({ data , repeatSet }) => {
|
||||
const [ tamp , setTamp ] = useState(undefined);
|
||||
const [ sha , setSha ] = useState(undefined);
|
||||
useEffect(()=>{
|
||||
if(data && data.started){
|
||||
let t = parseInt(data.started) * 1000;
|
||||
let time = Time(t);
|
||||
setTamp(time);
|
||||
}
|
||||
if(data && data.after){
|
||||
setSha(truncateCommitId(data.after));
|
||||
}
|
||||
},[data])
|
||||
|
||||
return (
|
||||
<div>
|
||||
<FlexAJ className="leftheader">
|
||||
<AlignCenter>
|
||||
<Img src="https://dss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=2091711702,2468700162&fm=111&gp=0.jpg"/>
|
||||
<span className="nest">开始时间:<span>2020.07.10 15:30</span></span>
|
||||
<span className="nest">运行时间:<span>20s</span></span>
|
||||
<Img src={data && data.author_avatar} />
|
||||
{data && data.started && (
|
||||
<span className="nest">
|
||||
开始时间:<span> {tamp}</span>
|
||||
</span>
|
||||
)}
|
||||
{data && data.timestamp && (
|
||||
<span className="nest">
|
||||
运行时间:<span>{data && data.timestamp}s</span>
|
||||
</span>
|
||||
)}
|
||||
</AlignCenter>
|
||||
<Blueline>重新创建</Blueline>
|
||||
<Popconfirm title="是否重新创建?" okText="确定" cancelText="取消" onConfirm={repeatSet}>
|
||||
<Blueline>重新创建</Blueline>
|
||||
</Popconfirm>
|
||||
</FlexAJ>
|
||||
<div className="leftMainContent">
|
||||
<AlignCenter className="contentBranch">
|
||||
<i className="iconfont icon-fenzhi1"></i>
|
||||
<span>分支:</span>
|
||||
<span className="branchname">master</span>
|
||||
<span className="branchsha">8b3476f5</span>
|
||||
<span className="branchname">{data && data.source}</span>
|
||||
<span className="branchsha">{sha}</span>
|
||||
</AlignCenter>
|
||||
</div>
|
||||
<Menu mode='inline' className="leftMenu">
|
||||
<SubMenu title={<div><i className="iconfont icon-gongzuoliu font-14 mr4"></i><span>CI</span></div>}>
|
||||
<Menu mode="inline" className="leftMenu">
|
||||
<SubMenu
|
||||
title={
|
||||
<div>
|
||||
<i className="iconfont icon-gongzuoliu font-14 mr4"></i>
|
||||
<span>CI</span>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<Menu.Item>
|
||||
<FlexAJ><span>Build setup 01 {TagsLine(1)}</span><span>20s</span></FlexAJ>
|
||||
<FlexAJ>
|
||||
<span>Build setup 01 {TagsLine(1)}</span>
|
||||
<span>20s</span>
|
||||
</FlexAJ>
|
||||
</Menu.Item>
|
||||
</SubMenu>
|
||||
</Menu>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,240 +1,318 @@
|
|||
import React , { useState , useEffect } from 'react';
|
||||
import { FlexAJ , AlignCenter , Blueback } from '../Component/layout';
|
||||
import { Table , Pagination } from 'antd';
|
||||
import { truncateCommitId } from '../common/util';
|
||||
import styled from 'styled-components';
|
||||
import axios from 'axios';
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { FlexAJ, AlignCenter, Blueback } from "../Component/layout";
|
||||
import { Table, Pagination, Popconfirm } from "antd";
|
||||
import { truncateCommitId } from "../common/util";
|
||||
import styled from "styled-components";
|
||||
import axios from "axios";
|
||||
import { Time } from "../Utils/Time";
|
||||
|
||||
const STATUS = [
|
||||
{name:"所有",value:"1"},
|
||||
{name:"准备中",value:"2"},
|
||||
{name:"运行中",value:"3"},
|
||||
{name:"已完成",value:"4"}
|
||||
]
|
||||
const LIMIT = 15;
|
||||
const datasource = [
|
||||
{
|
||||
status:2,
|
||||
author:"caishi",
|
||||
message:{
|
||||
branch:"master",
|
||||
sha:"8b3476f5",
|
||||
image:"https://dss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=2034740944,4251903193&fm=26&gp=0.jpg",
|
||||
message:"将分支“ 221063-improve-buy-ci-minutes-link”"
|
||||
},
|
||||
begin:"2020-07-08",
|
||||
run:"20s"
|
||||
},
|
||||
{
|
||||
status:1,
|
||||
author:"caishi",
|
||||
message:{
|
||||
branch:"master",
|
||||
sha:"8b3476f5",
|
||||
image:"https://dss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=2034740944,4251903193&fm=26&gp=0.jpg",
|
||||
message:"将分支“ 221063-improve-buy-ci-minutes-link”"
|
||||
},
|
||||
begin:"2020-07-08",
|
||||
run:""
|
||||
}
|
||||
{ name: "所有", value: "1" },
|
||||
{ name: "准备中", value: "2" },
|
||||
{ name: "运行中", value: "3" },
|
||||
{ name: "已完成", value: "4" },
|
||||
];
|
||||
const LIMIT = 15;
|
||||
const Img = styled.img`
|
||||
{
|
||||
border-radius: 50%;
|
||||
margin-rigth: 10px;
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
}
|
||||
`;
|
||||
export default (props) => {
|
||||
const [status, setStatus] = useState("1");
|
||||
const [page, setPage] = useState(1);
|
||||
const [total, setTotal] = useState(10);
|
||||
const [data, setData] = useState(undefined);
|
||||
const [tableLoading, setTableLoading] = useState(true);
|
||||
|
||||
const Img = styled.img`{
|
||||
border-radius:50%;
|
||||
margin-rigth:10px;
|
||||
width:25px;
|
||||
height:25px;
|
||||
}`
|
||||
export default ((props)=>{
|
||||
const [ status ,setStatus ] = useState("1");
|
||||
const [ page ,setPage ] = useState(1);
|
||||
const [ total ,setTotal ] = useState(10);
|
||||
const [ data , setData ] = useState(undefined);
|
||||
|
||||
let projectsId = props.match.params.projectsId;
|
||||
|
||||
useEffect(()=>{
|
||||
if(projectsId){
|
||||
const url ='/dev_ops/builds.json';
|
||||
axios.get(url,{
|
||||
params:{
|
||||
project_id:projectsId
|
||||
}
|
||||
}).then(result=>{
|
||||
if(result){
|
||||
let list = result.data && result.data.map((item,key)=>{
|
||||
return {
|
||||
status:item.status,
|
||||
author:item.sender,
|
||||
message:{
|
||||
branch:item.source,
|
||||
image:item.author_avatar,
|
||||
message:item.message,
|
||||
sha:truncateCommitId(item.after)
|
||||
},
|
||||
started:item.started,
|
||||
timestamp:item.timestamp
|
||||
}
|
||||
})
|
||||
setData(list);
|
||||
}
|
||||
}).catch(error=>{
|
||||
console.log(error);
|
||||
})
|
||||
let projectsId = props.match.params.projectsId;
|
||||
useEffect(() => {
|
||||
if (projectsId) {
|
||||
Init();
|
||||
}
|
||||
},[])
|
||||
}, []);
|
||||
|
||||
function ChangeStatus(value){
|
||||
setStatus(value)
|
||||
function Init() {
|
||||
const url = "/dev_ops/builds.json";
|
||||
axios
|
||||
.get(url, {
|
||||
params: {
|
||||
project_id: projectsId,
|
||||
},
|
||||
})
|
||||
.then((result) => {
|
||||
if (result) {
|
||||
let list =
|
||||
result.data &&
|
||||
result.data.map((item, key) => {
|
||||
return {
|
||||
status: item.status,
|
||||
author: item.sender,
|
||||
message: {
|
||||
branch: item.source,
|
||||
image: item.author_avatar,
|
||||
message: item.message,
|
||||
sha: truncateCommitId(item.after),
|
||||
},
|
||||
started: item.started
|
||||
? Time(parseInt(item.started) * 1000)
|
||||
: "--",
|
||||
timestamp: item.timestamp,
|
||||
number: item.number,
|
||||
id:item.id
|
||||
};
|
||||
});
|
||||
setData(list);
|
||||
setTableLoading(false);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
function ChangeStatus(value) {
|
||||
setStatus(value);
|
||||
}
|
||||
// 切换分页
|
||||
function ChangePage(page){
|
||||
setPage(page)
|
||||
function ChangePage(page) {
|
||||
setPage(page);
|
||||
}
|
||||
function renderStatus() {
|
||||
return(
|
||||
return (
|
||||
<ul className="listNav">
|
||||
{
|
||||
STATUS.map((item,key)=>{
|
||||
return <li onClick={()=>ChangeStatus(item.value)} className={ status === item.value ? "active":""}>{item.name}</li>
|
||||
})
|
||||
}
|
||||
{STATUS.map((item, key) => {
|
||||
return (
|
||||
<li
|
||||
onClick={() => ChangeStatus(item.value)}
|
||||
className={status === item.value ? "active" : ""}
|
||||
>
|
||||
{item.name}
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
)
|
||||
);
|
||||
}
|
||||
function renderStatusBtn(status){
|
||||
if(status === "failure" || status ==="success"){
|
||||
return(
|
||||
<a className="color-blue">重新构建</a>
|
||||
)
|
||||
}else{
|
||||
return(
|
||||
<a className="color-red">撤销构建</a>
|
||||
)
|
||||
function renderStatusBtn(status, number) {
|
||||
if (status === "failure" || status === "success") {
|
||||
return (
|
||||
<Popconfirm
|
||||
title="确认重新构建?"
|
||||
onConfirm={(e) => repeatSet(e,number)}
|
||||
onCancel={(e)=>{e.stopPropagation()}}
|
||||
cancelText="取消"
|
||||
okText="确定"
|
||||
>
|
||||
<a className="color-blue" onClick={(e)=>{e.stopPropagation()}}>重新构建</a>
|
||||
</Popconfirm>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<Popconfirm
|
||||
title="确认撤销构建?"
|
||||
onConfirm={(e) => cancelSet(e,number)}
|
||||
onCancel={(e)=>{e.stopPropagation()}}
|
||||
cancelText="取消"
|
||||
okText="确定"
|
||||
>
|
||||
<a className="color-red" onClick={(e)=>{e.stopPropagation()}}>撤销构建</a>
|
||||
</Popconfirm>
|
||||
);
|
||||
}
|
||||
}
|
||||
function renderTableStatus (status){
|
||||
switch (status){
|
||||
// 重新构建
|
||||
function repeatSet(e,number) {
|
||||
e.stopPropagation();
|
||||
setTableLoading(true);
|
||||
const url = `/dev_ops/builds/${number}.json`;
|
||||
axios.post(url, { project_id: projectsId })
|
||||
.then((result) => {
|
||||
if (result) {
|
||||
props.showNotification("工作流正在重新构建!");
|
||||
Init();
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
// 撤销构建
|
||||
function cancelSet(e,number) {
|
||||
e.stopPropagation();
|
||||
setTableLoading(true);
|
||||
const url = `/dev_ops/builds/${number}.json`;
|
||||
axios.delete(url, {
|
||||
params:{project_id: projectsId}
|
||||
})
|
||||
.then((result) => {
|
||||
if (result) {
|
||||
props.showNotification("撤销构建成功!");
|
||||
Init(projectsId);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
function renderTableStatus(status) {
|
||||
switch (status) {
|
||||
case "running":
|
||||
return(
|
||||
<span className="statusTag running"><i className="iconfont icon-yunhangzhong"></i>运行中</span>
|
||||
return (
|
||||
<span className="statusTag running">
|
||||
<i className="iconfont icon-yunhangzhong"></i>运行中
|
||||
</span>
|
||||
);
|
||||
case "failure":
|
||||
return (
|
||||
<span className="statusTag failed"><i className="iconfont icon-weitongguo"></i>未通过</span>
|
||||
<span className="statusTag failed">
|
||||
<i className="iconfont icon-weitongguo"></i>未通过
|
||||
</span>
|
||||
);
|
||||
case "success":
|
||||
return (
|
||||
<span className="statusTag pass"><i className="iconfont icon-yitongguo"></i>已通过</span>
|
||||
<span className="statusTag pass">
|
||||
<i className="iconfont icon-yitongguo"></i>已通过
|
||||
</span>
|
||||
);
|
||||
default:
|
||||
return (
|
||||
<span className="statusTag Preparing"><i className="iconfont icon-zhunbeizhong"></i>准备中</span>
|
||||
<span className="statusTag Preparing">
|
||||
<i className="iconfont icon-zhunbeizhong"></i>准备中
|
||||
</span>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function clickRows(event,e){
|
||||
props.history.push(`/projects/${projectsId}/ops/${e.number}/detail`);
|
||||
}
|
||||
const column = [
|
||||
{
|
||||
title:'序号',
|
||||
dataIndex:"No",
|
||||
key:"No",
|
||||
width:"8%",
|
||||
render:(item,value,key)=>{
|
||||
return(
|
||||
<span>#{key+1}</span>
|
||||
)
|
||||
}
|
||||
title: "序号",
|
||||
dataIndex: "number",
|
||||
key: "number",
|
||||
width: "8%",
|
||||
render: ( value, item, key) => {
|
||||
return <span>#{value}</span>;
|
||||
},
|
||||
},
|
||||
{
|
||||
title:'状态',
|
||||
dataIndex:"status",
|
||||
key:"status",
|
||||
width:"12%",
|
||||
render:(value,item,key)=>{
|
||||
return(renderTableStatus(value))
|
||||
}
|
||||
title: "状态",
|
||||
dataIndex: "status",
|
||||
key: "status",
|
||||
width: "12%",
|
||||
render: (value, item, key) => {
|
||||
return renderTableStatus(value);
|
||||
},
|
||||
},
|
||||
{
|
||||
title:'构建人',
|
||||
dataIndex:"author",
|
||||
key:"author",
|
||||
width:"12%",
|
||||
align:"center"
|
||||
title: "构建人",
|
||||
dataIndex: "author",
|
||||
key: "author",
|
||||
width: "12%",
|
||||
align: "center",
|
||||
},
|
||||
{
|
||||
title:'提交信息',
|
||||
dataIndex:"message",
|
||||
key:"message",
|
||||
width:"30%",
|
||||
render:(value,item,key)=>{
|
||||
title: "提交信息",
|
||||
dataIndex: "message",
|
||||
key: "message",
|
||||
width: "30%",
|
||||
render: (value, item, key) => {
|
||||
let meg = item.message;
|
||||
return (
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div>
|
||||
{ meg.branch && <span className="mr10 color-grey-8"><i className="iconfont icon-fenzhi1 font-16 mr5"></i>分支{meg.branch}</span>}
|
||||
{ meg.sha && <span className="color-orange">{meg.sha}</span>}
|
||||
{meg.branch && (
|
||||
<span className="mr10 color-grey-8">
|
||||
<i className="iconfont icon-fenzhi1 font-16 mr5"></i>分支
|
||||
{meg.branch}
|
||||
</span>
|
||||
)}
|
||||
{meg.sha && <span className="color-orange">{meg.sha}</span>}
|
||||
</div>
|
||||
<AlignCenter>
|
||||
<Img src={meg.image} />
|
||||
<div className="task-hide ml5" style={{maxWidth:"300px"}}>{meg.message}</div>
|
||||
<div className="task-hide ml5" style={{ maxWidth: "300px" }}>
|
||||
{meg.message}
|
||||
</div>
|
||||
</AlignCenter>
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title:'开始时间',
|
||||
dataIndex:"started",
|
||||
key:"started",
|
||||
width:"15%",
|
||||
render:(value,item,key)=>{
|
||||
return (
|
||||
<span>{value || "--"}</span>
|
||||
)
|
||||
}
|
||||
title: "开始时间",
|
||||
dataIndex: "started",
|
||||
key: "started",
|
||||
width: "15%",
|
||||
render: (value, item, key) => {
|
||||
return <span>{value || "--"}</span>;
|
||||
},
|
||||
},
|
||||
{
|
||||
title:'运行时间',
|
||||
dataIndex:"timestamp",
|
||||
key:"timestamp",
|
||||
width:"15%",
|
||||
render:(value,item,key)=>{
|
||||
return (
|
||||
<span>{value || value === 0 ? `${value}s` : "--"}</span>
|
||||
)
|
||||
}
|
||||
title: "运行时间",
|
||||
dataIndex: "timestamp",
|
||||
key: "timestamp",
|
||||
width: "15%",
|
||||
render: (value, item, key) => {
|
||||
return <span>{value || value === 0 ? `${value}s` : "--"}</span>;
|
||||
},
|
||||
},
|
||||
{
|
||||
title:'操作',
|
||||
dataIndex:"operation",
|
||||
key:"operation",
|
||||
render:(value,item,key)=>{
|
||||
return(renderStatusBtn(item.status));
|
||||
}
|
||||
}
|
||||
]
|
||||
return(
|
||||
title: "操作",
|
||||
dataIndex: "operation",
|
||||
key: "operation",
|
||||
render: (value, item, key) => {
|
||||
return renderStatusBtn(item.status, item.number);
|
||||
},
|
||||
},
|
||||
];
|
||||
return (
|
||||
<div className="listPart">
|
||||
<FlexAJ>
|
||||
{renderStatus()}
|
||||
<span>
|
||||
<Blueback className="mr30">手动创建</Blueback>
|
||||
<span className="mr30"><i className="iconfont icon-fenzhi1 font-16 mr5 color-blue"></i>分支</span>
|
||||
<span><i className="iconfont icon-biaoqian3 font-16 mr5 color-blue"></i>标签</span>
|
||||
<span className="mr30">
|
||||
<i className="iconfont icon-fenzhi1 font-16 mr5 color-blue"></i>分支
|
||||
</span>
|
||||
<span>
|
||||
<i className="iconfont icon-biaoqian3 font-16 mr5 color-blue"></i>
|
||||
标签
|
||||
</span>
|
||||
</span>
|
||||
</FlexAJ>
|
||||
<Table
|
||||
onRow={(record,index)=>{
|
||||
return{
|
||||
onClick:(event)=>clickRows(event,record)
|
||||
}
|
||||
}}
|
||||
columns={column}
|
||||
className="normalTable"
|
||||
dataSource={data}
|
||||
pagination={false}
|
||||
loading={tableLoading}
|
||||
></Table>
|
||||
{
|
||||
total > LIMIT ?
|
||||
<div style={{textAlign:'center',margin:"30px 50px"}}>
|
||||
<Pagination showQuickJumper defaultCurrent={page} total={total} pageSize={LIMIT} onChange={ChangePage}></Pagination>
|
||||
</div>:""
|
||||
}
|
||||
{total > LIMIT ? (
|
||||
<div style={{ textAlign: "center", margin: "30px 50px" }}>
|
||||
<Pagination
|
||||
showQuickJumper
|
||||
defaultCurrent={page}
|
||||
total={total}
|
||||
pageSize={LIMIT}
|
||||
onChange={ChangePage}
|
||||
></Pagination>
|
||||
</div>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
})
|
||||
);
|
||||
};
|
||||
|
|
|
@ -70,6 +70,9 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
.ant-modal-close{
|
||||
top:7px;
|
||||
}
|
||||
// 列表
|
||||
.listPart{
|
||||
.statusTag{
|
||||
|
|
|
@ -1,33 +1,90 @@
|
|||
import React from 'react';
|
||||
import './ops.scss';
|
||||
import { FlexAJ, AlignCenter } from '../Component/layout';
|
||||
import { Tags } from '../Component/OpsStatus';
|
||||
import SplitPane from 'react-split-pane';
|
||||
import LeftPanel from './OpsDetailLeftpanel';
|
||||
import RightPanel from './OpsDetailRightpanel';
|
||||
import React, { useEffect, useState , useRef , useContext } from "react";
|
||||
import "./ops.scss";
|
||||
import { FlexAJ, AlignCenter } from "../Component/layout";
|
||||
import { Tags } from "../Component/OpsStatus";
|
||||
import SplitPane from "react-split-pane";
|
||||
import LeftPanel from "./OpsDetailLeftpanel";
|
||||
import RightPanel from "./OpsDetailRightpanel";
|
||||
import axios from "axios";
|
||||
import { Spin } from "antd";
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
export default (props) => {
|
||||
const [data, setData] = useState(undefined);
|
||||
const [stages, setStages] = useState(undefined);
|
||||
const [spinning, setSpinning] = useState(true);
|
||||
|
||||
export default (()=>{
|
||||
return(
|
||||
<div className="opsDetailPanel">
|
||||
<FlexAJ className="opsInfos">
|
||||
<AlignCenter>
|
||||
<span>#1</span>
|
||||
<span className="ml10">将分支“221063-improve-buy-ci-minutes-link”合并到“221063-improve-buy-ci-minutes-link"</span>
|
||||
{Tags(1)}
|
||||
</AlignCenter>
|
||||
<a style={{color:"#ddd"}}><i className="iconfont icon-yiguanbi font-15 mr5"></i>退出</a>
|
||||
</FlexAJ>
|
||||
<div className="opsSection">
|
||||
<SplitPane className="outer-split-pane" split="vertical" minSize={468} maxSize={-350} defaultSize="40%">
|
||||
<section className="leftSection">
|
||||
<LeftPanel />
|
||||
</section>
|
||||
<section className="rightSection">
|
||||
<RightPanel />
|
||||
</section>
|
||||
</SplitPane>
|
||||
let projectId = props.match.params.projectId;
|
||||
let opsId = props.match.params.opsId;
|
||||
|
||||
useEffect(() => {
|
||||
if (opsId && projectId) {
|
||||
Init();
|
||||
}
|
||||
}, [opsId]);
|
||||
|
||||
function Init(){
|
||||
const url = `/dev_ops/builds/${opsId}.json`;
|
||||
axios.get(url, {
|
||||
params: {
|
||||
project_id: projectId,
|
||||
},
|
||||
})
|
||||
.then((result) => {
|
||||
if (result && result.data) {
|
||||
setSpinning(false);
|
||||
setData(result.data);
|
||||
setStages(result.data.stages);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
|
||||
// 重新构建
|
||||
function repeatSet() {
|
||||
const url = `/dev_ops/builds/${data && data.number}.json`;
|
||||
axios.post(url, { project_id: projectId })
|
||||
.then((result) => {
|
||||
if (result) {
|
||||
Init();
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
}
|
||||
return (
|
||||
<Spin spinning={spinning}>
|
||||
<div className="opsDetailPanel">
|
||||
<FlexAJ className="opsInfos">
|
||||
<AlignCenter>
|
||||
<span>#{data && data.number}</span>
|
||||
<span className="ml10">{data && data.message}</span>
|
||||
{Tags(`${data && data.status}`)}
|
||||
</AlignCenter>
|
||||
<Link style={{ color: "#ddd" }} to={`/projects/${projectId}/ops/list`}>
|
||||
<i className="iconfont icon-yiguanbi font-15 mr5"></i>退出
|
||||
</Link>
|
||||
</FlexAJ>
|
||||
<div className="opsSection">
|
||||
<SplitPane
|
||||
className="outer-split-pane"
|
||||
split="vertical"
|
||||
minSize={468}
|
||||
maxSize={-350}
|
||||
defaultSize="40%"
|
||||
>
|
||||
<section className="leftSection">
|
||||
<LeftPanel data={data} repeatSet={repeatSet}/>
|
||||
</section>
|
||||
<section className="rightSection">
|
||||
<RightPanel data={data} />
|
||||
</section>
|
||||
</SplitPane>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
});
|
||||
</Spin>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -438,12 +438,12 @@ class Detail extends Component {
|
|||
</Link>
|
||||
</li>
|
||||
}
|
||||
{/* <li className={url.indexOf("/ops") > -1 ? "active" : ""}>
|
||||
<li className={url.indexOf("/ops") > -1 ? "active" : ""}>
|
||||
<Link to={{ pathname: `/projects/${projectsId}/ops`, state }}>
|
||||
<i className="iconfont icon-gongzuoliu font-13 mr8"></i>工作流
|
||||
{projectDetail && projectDetail.ops_count ? <span>{projectDetail.ops_count}</span> : ""}
|
||||
</Link>
|
||||
</li> */}
|
||||
</li>
|
||||
<li className={(url.indexOf("/Milepost") > -1 || url.indexOf("meilpost") > -1) ? "active" : ""}>
|
||||
<Link to={{ pathname: `/projects/${projectsId}/orders/Milepost`, state }}>
|
||||
<img alt="" src={img_milepost} width="16" />里程碑
|
||||
|
|
|
@ -26,7 +26,7 @@ export function getDateTime(value, dataformat) {
|
|||
return date.format(dataformat);
|
||||
}
|
||||
|
||||
export default function Time(UTCtiem) {
|
||||
export function Time(UTCtiem) {
|
||||
var dateTime = new Date(UTCtiem);
|
||||
|
||||
var year = dateTime.getFullYear();
|
||||
|
|
Loading…
Reference in New Issue