new page + fix bug

This commit is contained in:
caishi 2020-07-10 15:42:57 +08:00
parent b92bdb275e
commit 2f8fd57349
36 changed files with 867 additions and 94 deletions

6
package-lock.json generated
View File

@ -14909,9 +14909,9 @@
} }
}, },
"react-monaco-editor": { "react-monaco-editor": {
"version": "0.36.0", "version": "0.37.0",
"resolved": "https://registry.npmjs.org/react-monaco-editor/-/react-monaco-editor-0.36.0.tgz", "resolved": "https://registry.npmjs.org/react-monaco-editor/-/react-monaco-editor-0.37.0.tgz",
"integrity": "sha512-JVA5SZhOoYZ0DCdTwYgagtRb3jHo4KN7TVFiJauG+ZBAJWfDSTzavPIrwzWbgu8ahhDqDk4jUcYlOJL2BC/0UA==", "integrity": "sha512-4fbmTIPOfEdmAlslYPVXt+TRSd975XwgfxuSEL32efjXQwTzPZWA/Wf5qn8nYBMl+Lfdhu1DGDTLE6CZ4UOjzw==",
"requires": { "requires": {
"@types/react": "^16.x", "@types/react": "^16.x",
"monaco-editor": "*", "monaco-editor": "*",

View File

@ -85,7 +85,7 @@
"react-hot-loader": "^4.12.20", "react-hot-loader": "^4.12.20",
"react-infinite-scroller": "^1.2.4", "react-infinite-scroller": "^1.2.4",
"react-loadable": "^5.3.1", "react-loadable": "^5.3.1",
"react-monaco-editor": "0.36", "react-monaco-editor": "0.37",
"react-player": "^1.15.3", "react-player": "^1.15.3",
"react-redux": "5.0.7", "react-redux": "5.0.7",
"react-router": "^4.2.0", "react-router": "^4.2.0",

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -5,6 +5,48 @@
"css_prefix_text": "icon-", "css_prefix_text": "icon-",
"description": "", "description": "",
"glyphs": [ "glyphs": [
{
"icon_id": "15792809",
"name": "准备中",
"font_class": "zhunbeizhong",
"unicode": "e797",
"unicode_decimal": 59287
},
{
"icon_id": "15792805",
"name": "运行中",
"font_class": "yunhangzhong",
"unicode": "e796",
"unicode_decimal": 59286
},
{
"icon_id": "15792803",
"name": "已通过",
"font_class": "yitongguo",
"unicode": "e795",
"unicode_decimal": 59285
},
{
"icon_id": "15792796",
"name": "未通过",
"font_class": "weitongguo",
"unicode": "e794",
"unicode_decimal": 59284
},
{
"icon_id": "15762732",
"name": "工作流",
"font_class": "gongzuoliu",
"unicode": "e793",
"unicode_decimal": 59283
},
{
"icon_id": "15689245",
"name": "更新成绩",
"font_class": "gengxinchengji",
"unicode": "e790",
"unicode_decimal": 59280
},
{ {
"icon_id": "15605136", "icon_id": "15605136",
"name": "文件", "name": "文件",

View File

@ -20,6 +20,24 @@ Created by iconfont
/> />
<missing-glyph /> <missing-glyph />
<glyph glyph-name="zhunbeizhong" unicode="&#59287;" d="M512 384m-480 0a480 480 0 1 1 960 0 480 480 0 1 1-960 0ZM512-128c-281.6 0-512 230.4-512 512s230.4 512 512 512 512-230.4 512-512-230.4-512-512-512zM512 832C262.4 832 64 633.6 64 384s198.4-448 448-448 448 198.4 448 448-198.4 448-448 448zM320 384m-64 0a64 64 0 1 1 128 0 64 64 0 1 1-128 0ZM512 384m-64 0a64 64 0 1 1 128 0 64 64 0 1 1-128 0ZM704 384m-64 0a64 64 0 1 1 128 0 64 64 0 1 1-128 0Z" horiz-adv-x="1024" />
<glyph glyph-name="yunhangzhong" unicode="&#59286;" d="M512 384m-480 0a480 480 0 1 1 960 0 480 480 0 1 1-960 0ZM512-128c-281.6 0-512 230.4-512 512s230.4 512 512 512 512-230.4 512-512-230.4-512-512-512zM512 832C262.4 832 64 633.6 64 384s198.4-448 448-448 448 198.4 448 448-198.4 448-448 448zM505.6 640v-313.6h294.4c-19.2-128-134.4-230.4-268.8-230.4-153.6 0-275.2 121.6-275.2 268.8C256 512 364.8 627.2 505.6 640z" horiz-adv-x="1024" />
<glyph glyph-name="yitongguo" unicode="&#59285;" d="M512 384m-480 0a480 480 0 1 1 960 0 480 480 0 1 1-960 0ZM512-128c-281.6 0-512 230.4-512 512s230.4 512 512 512 512-230.4 512-512-230.4-512-512-512zM512 832C262.4 832 64 633.6 64 384s198.4-448 448-448 448 198.4 448 448-198.4 448-448 448zM486.4 172.8c-6.4 0-19.2 6.4-25.6 12.8L294.4 358.4c-12.8 12.8-12.8 32 0 44.8 12.8 12.8 32 12.8 44.8 0L486.4 256l262.4 281.6c12.8 12.8 32 12.8 44.8 0 12.8-12.8 12.8-32 0-44.8L512 185.6c-6.4-6.4-12.8-6.4-25.6-12.8z" horiz-adv-x="1024" />
<glyph glyph-name="weitongguo" unicode="&#59284;" d="M512 384m-480 0a480 480 0 1 1 960 0 480 480 0 1 1-960 0ZM512-128c-281.6 0-512 230.4-512 512s230.4 512 512 512 512-230.4 512-512-230.4-512-512-512zM512 832C262.4 832 64 633.6 64 384s198.4-448 448-448 448 198.4 448 448-198.4 448-448 448zM678.4 172.8L544 332.8l-134.4-160-51.2 38.4L499.2 384 358.4 556.8l51.2 38.4 134.4-160 134.4 160 51.2-38.4L588.8 384l140.8-172.8z" horiz-adv-x="1024" />
<glyph glyph-name="gongzuoliu" unicode="&#59283;" d="M837.270588 600.847059H499.952941C421.647059 600.847059 355.388235 667.105882 355.388235 745.411765 349.364706 829.741176 415.623529 896 499.952941 896H843.294118c78.305882 0 144.564706-66.258824 144.564706-144.564706-6.023529-84.329412-72.282353-150.588235-150.588236-150.588235zM499.952941 805.647059c-30.117647 0-54.211765-24.094118-54.211765-54.211765s24.094118-54.211765 54.211765-54.211765H843.294118c30.117647 0 54.211765 24.094118 54.211764 54.211765s-24.094118 54.211765-54.211764 54.211765H499.952941zM548.141176-128H204.8C126.494118-128 60.235294-61.741176 60.235294 16.564706s66.258824 144.564706 144.564706 144.564706h343.341176c78.305882 0 144.564706-66.258824 144.564706-144.564706S626.447059-128 548.141176-128z m-343.341176 204.8c-30.117647 0-54.211765-24.094118-54.211765-54.211765s24.094118-54.211765 54.211765-54.211764h343.341176c30.117647 0 54.211765 24.094118 54.211765 54.211764s-24.094118 54.211765-54.211765 54.211765H204.8zM903.529412-49.694118h-210.82353v90.352942H903.529412c42.164706 0 72.282353 36.141176 72.282353 72.282352v150.588236c0 42.164706-36.141176 72.282353-72.282353 72.282353H180.705882C90.352941 335.811765 12.047059 408.094118 12.047059 498.447059V655.058824C12.047059 745.411765 84.329412 823.717647 180.705882 823.717647h168.658824v-90.352941H180.705882C138.541176 727.341176 108.423529 697.223529 108.423529 655.058824v-144.564706c0-42.164706 36.141176-72.282353 72.282353-72.282353h722.82353c90.352941 0 168.658824-72.282353 168.658823-162.635294v-150.588236c0-102.4-78.305882-174.682353-168.658823-174.682353zM493.929412 384a120.470588 120.470588 0 1 1 240.941176 0 120.470588 120.470588 0 1 1-240.941176 0Z" horiz-adv-x="1084" />
<glyph glyph-name="gengxinchengji" unicode="&#59280;" d="M768-84.8c-96 0-166.4 70.4-166.4 166.4v25.6l64-6.4v-12.8c0-57.6 44.8-102.4 102.4-102.4 19.2 0 44.8 6.4 57.6 19.2l38.4-57.6c-25.6-25.6-64-32-96-32z m147.2 89.6l-57.6 25.6c6.4 19.2 12.8 32 12.8 51.2 0 57.6-44.8 102.4-102.4 102.4-19.2 0-32-6.4-44.8-12.8l-32 57.6c25.6 12.8 51.2 19.2 76.8 19.2 89.6 0 166.4-76.8 166.4-166.4 0-25.6-6.4-57.6-19.2-76.8zM633.6 158.4l57.6-76.8H569.6zM908.8-14.4l64 76.8h-128zM544-57.6H64V864h537.6L864 601.6v-275.2h-64V576L576 800h-448v-793.6H544zM243.2 614.4h198.4v-64H243.2zM242.624 438.08l383.936 6.976 1.152-64-383.936-6.912zM243.2 275.2h326.4v-64H243.2zM857.6 550.4h-320l6.4 320 313.6-320z m-256 64h102.4L601.6 716.8v-102.4z" horiz-adv-x="1024" />
<glyph glyph-name="wenjian1" unicode="&#59278;" d="M574.330435-119.095652H151.373913c-44.521739 0-84.591304 40.069565-84.591304 84.591304V811.408696C66.782609 855.930435 106.852174 896 151.373913 896h681.182609c44.521739 0 84.591304-40.069565 84.591304-84.591304v-436.313044c0-26.713043-17.808696-44.521739-44.521739-44.521739s-44.521739 17.808696-44.521739 44.521739V806.956522H155.826087v-837.008696h418.504348c26.713043 0 44.521739-17.808696 44.521739-44.521739s-22.26087-44.521739-44.521739-44.521739zM249.321739 410.713043h471.930435v-66.782608H249.321739zM512 148.034783m-44.521739 0a44.521739 44.521739 0 1 1 89.043478 0 44.521739 44.521739 0 1 1-89.043478 0ZM690.086957 148.034783m-44.52174 0a44.521739 44.521739 0 1 1 89.043479 0 44.521739 44.521739 0 1 1-89.043479 0ZM850.365217 148.034783m-44.521739 0a44.521739 44.521739 0 1 1 89.043479 0 44.521739 44.521739 0 1 1-89.043479 0ZM249.321739 655.582609h471.930435v-66.782609H249.321739zM249.321739 188.104348h146.921739v-66.782609H249.321739z" horiz-adv-x="1024" /> <glyph glyph-name="wenjian1" unicode="&#59278;" d="M574.330435-119.095652H151.373913c-44.521739 0-84.591304 40.069565-84.591304 84.591304V811.408696C66.782609 855.930435 106.852174 896 151.373913 896h681.182609c44.521739 0 84.591304-40.069565 84.591304-84.591304v-436.313044c0-26.713043-17.808696-44.521739-44.521739-44.521739s-44.521739 17.808696-44.521739 44.521739V806.956522H155.826087v-837.008696h418.504348c26.713043 0 44.521739-17.808696 44.521739-44.521739s-22.26087-44.521739-44.521739-44.521739zM249.321739 410.713043h471.930435v-66.782608H249.321739zM512 148.034783m-44.521739 0a44.521739 44.521739 0 1 1 89.043478 0 44.521739 44.521739 0 1 1-89.043478 0ZM690.086957 148.034783m-44.52174 0a44.521739 44.521739 0 1 1 89.043479 0 44.521739 44.521739 0 1 1-89.043479 0ZM850.365217 148.034783m-44.521739 0a44.521739 44.521739 0 1 1 89.043479 0 44.521739 44.521739 0 1 1-89.043479 0ZM249.321739 655.582609h471.930435v-66.782609H249.321739zM249.321739 188.104348h146.921739v-66.782609H249.321739z" horiz-adv-x="1024" />

Before

Width:  |  Height:  |  Size: 502 KiB

After

Width:  |  Height:  |  Size: 506 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -46,6 +46,11 @@ const Projects = Loadable({
loader: () => import('./forge/Index'), loader: () => import('./forge/Index'),
loading: Loading, loading: Loading,
}) })
//forge项目-devOps详情
const OpsDetail = Loadable({
loader: () => import('./forge/DevOps/opsDetail'),
loading: Loading,
})
//403页面 //403页面
const Shixunauthority = Loadable({ const Shixunauthority = Loadable({
loader: () => import('./modules/403/Shixunauthority'), loader: () => import('./modules/403/Shixunauthority'),
@ -217,6 +222,15 @@ class App extends Component {
<Certifiedprofessional {...this.props} {...this.state} ModalCancelsy={this.ModalCancelsy} ModalshowCancelsy={this.ModalshowCancelsy} /> <Certifiedprofessional {...this.props} {...this.state} ModalCancelsy={this.ModalCancelsy} ModalshowCancelsy={this.ModalshowCancelsy} />
<Router> <Router>
<Switch> <Switch>
{/*项目*/}
<Route
path={"/projects/:projectId/ops/:opsId/detail"}
render={
(props) => {
return (<OpsDetail {...this.props} {...props} {...this.state} />)
}
}>
</Route>
{/*项目*/} {/*项目*/}
<Route <Route
path={"/projects"} path={"/projects"}
@ -226,6 +240,7 @@ class App extends Component {
} }
}> }>
</Route> </Route>
{/*403*/} {/*403*/}
<Route path="/403" component={Shixunauthority} /> <Route path="/403" component={Shixunauthority} />

View File

@ -64,3 +64,28 @@ li.ant-menu-item{
bottom: 10px; bottom: 10px;
} }
} }
.statusColor{
display: inline-block;
padding:0px 10px;
height:20px;
line-height: 20px;
border-radius:11px;
color: #fff;
margin-left: 5px;
&.running{
background:#5091FF;
color: #F1F8FF;
}
&.Preparing{
background:rgba(255,110,33,1);
color:rgba(255,248,244,1);
}
&.pass{
background:#28BD6C;
color: #EEFDF5;
}
&.failed{
background:#F73030;
color:#FCEEEE ;
}
}

View File

@ -0,0 +1,23 @@
import React from 'react';
import './Component.scss';
export const Tags = (status)=>{
switch(status){
case 1:
return(
<span className="statusColor running">运行中</span>
);
case 2:
return (
<span className="statusColor failed">未通过</span>
);
case 3:
return (
<span className="statusColor pass">已通过</span>
);
default:
return (
<span className="statusColor Preparing">准备中</span>
);
}
}

View File

@ -89,6 +89,17 @@ export const Greenback = styled.a`{
min-width:80px; min-width:80px;
text-align:center; text-align:center;
}` }`
export const Blueback = styled.a`{
height:30px;
line-height:30px;
border-radius:2px;
background-color:rgba(80,145,255,1);
color:#fff;
padding:0px 12px;
display:inline-block;
min-width:80px;
text-align:center;
}`
export const Redback = styled.a`{ export const Redback = styled.a`{
height:30px; height:30px;
line-height:30px; line-height:30px;

View File

@ -0,0 +1,69 @@
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';
const P = styled.p`{
width:200px;
line-height:30px;
font-size:16px;
color:#333;
text-align:center;
margin-top:30px;
margin-bottom:30px!important;
}`;
export default Form.create()(
forwardRef(({ form })=>{
const { getFieldDecorator , validateFields } = form;
const helper = useCallback(
(label, name, rules, widget, isRequired) => (
<React.Fragment>
<span className={isRequired?"required":""}>{label}</span>
<Form.Item>
{getFieldDecorator(name, { rules, validateFirst: true })(widget)}
</Form.Item>
</React.Fragment>
),
[]
);
function startActive(){
validateFields((error,value)=>{
if(!error){
console.log(value);
}
})
}
return(
<div className="activatePanel">
<img src={activate} alt="" width="250px"/>
<P>定义DevOps工作流帮助您检测bug发布代码</P>
<Link to={""} style={{color:"#5091FF",marginTop:"20px"}}>了解什么是DevOps</Link>
<Form>
{helper(
"服务器IP地址",
"IP",
[{ required: true, message: "请输入服务器IP地址" }],
<Input placeholder="请输入服务器IP地址" style={{width:"368px"}} size="large" />,true
)}
{helper(
"服务器用户名:",
"username",
[{ required: true, message: "请输入服务器用户名" }],
<Input placeholder="请输入服务器用户名" size="large" />,true
)}
{helper(
"服务器密码:",
"password",
[{ required: true, message: "请输入服务器密码" }],
<Input.Password placeholder="请输入服务器密码" size="large" />,true
)}
</Form>
<Blueback onClick={startActive}>开始激活</Blueback>
</div>
)
})
)

View File

@ -0,0 +1,81 @@
import React , { forwardRef , useCallback , useState } from 'react';
import { Form , AutoComplete } from 'antd';
import { Blueback } from '../Component/layout';
import Editor from "react-monaco-editor";
import Modals from './DisposeModal';
import docker from '../Images/docker.png';
import gradle from '../Images/gradle.png';
import java from '../Images/java.png';
import js from '../Images/js.png';
import php from '../Images/php.png';
import python from '../Images/python.png';
const Option = AutoComplete.Option;
export default Form.create()(
forwardRef(({ form })=>{
const [ visible , setVisible ] = useState(false);
const { getFieldDecorator } = form;
const helper = useCallback(
(label, name, rules, widget, isRequired = false) => (
<React.Fragment>
<span required={isRequired}>{label}</span>
<Form.Item>
{getFieldDecorator(name, { rules, validateFirst: true })(widget)}
</Form.Item>
</React.Fragment>
),
[]
)
//
function changeEditor(){}
//
function changeAuto(){}
return(
<React.Fragment>
<Modals visible={visible} closeFunc={(flag)=>setVisible(flag)}></Modals>
<Form>
<p>编程语言</p>
<ul className="language">
<li><img alt="" src={docker} /></li>
<li><img alt="" src={gradle} /></li>
<li><img alt="" src={java} /></li>
<li><img alt="" src={js} /></li>
<li><img alt="" src={php} /></li>
<li><img alt="" src={python} /></li>
</ul>
{helper(
"",
"tag_name",
[{ required: true, message: "请选择语言" }],
<AutoComplete
placeholder="更多语言"
onChange={changeAuto}
style={{ width: "300px",margin:"15px 0px" }}
>
</AutoComplete>
)}
<p>配置脚本</p>
<div className="editorBody">
<p className="editorHead">
<span>trustie-pipeline.yml</span>
<a><i className="iconfont icon-bianji6 font-14"></i></a>
</p>
<Editor
height="300px"
language={"plaintext"}
theme={"vs-grey"}
defaultValue="请输入内容"
value={"editorValue"}
options={"editor_options"}
onChange={changeEditor}
></Editor>
</div>
<Blueback>确定提交</Blueback>
</Form>
</React.Fragment>
)
})
)

View File

@ -0,0 +1,28 @@
import React from 'react';
import styled from 'styled-components';
import { Modal ,Button } from 'antd';
const Div = styled.div`{
height:130px;
line-height:130px;
text-align:center;
color:#333;
}`
export default (({visible , closeFunc})=>{
return(
<Modal
title="提示"
visible={visible}
closable={true}
footer={
<div>
<Button onClick={()=>closeFunc(false)}>取消</Button>
<Button type={"primary"} onClick={()=>closeFunc(false)} style={{marginLeft:"20px"}}>确定</Button>
</div>
}
onCancel={()=>closeFunc(false)}
>
<Div>工作流配置完成您的DevOps之旅即刻开启</Div>
</Modal>
)
})

View File

@ -0,0 +1,39 @@
import React from 'react';
import { WhiteBack } from '../Component/layout';
import './ops.scss';
import { Route, Switch } from 'react-router-dom';
import Loadable from 'react-loadable';
import Loading from '../../Loading';
const About = Loadable({
loader: () => import('./About'),
loading: Loading,
})
const Infos = Loadable({
loader: () => import('./Infos'),
loading: Loading,
})
export default ((props)=>{
return(
<WhiteBack className="opsPanel">
<Switch {...props}>
<Route path="/projects/:projectsId/ops/dispose"
render={
() => (<Infos {...props} />)
}
></Route>
<Route path="/projects/:projectsId/ops/list"
render={
() => (<Infos {...props} />)
}
></Route>
<Route path="/projects/:projectsId/ops"
render={
() => (<About {...props} />)
}
></Route>
</Switch>
</WhiteBack>
)
})

View File

@ -0,0 +1,39 @@
import React , { useEffect , useState } from 'react';
import { Banner } from '../Component/layout';
import Dispost from './Dispose';
import Structure from './Structure';
import styled from 'styled-components';
const Div = styled.div`{
padding:24px 30px;
}`;
export default ((props)=>{
const [ menu , setMenu ] = useState(false);
useEffect(()=>{
const path = props.location.pathname;
console.log(props.match.params.projectsId)
if(path === `/projects/${props.match.params.projectsId}/ops/list`){
setMenu(true);
}
},[])
return(
<div className="disposePanel">
<Banner>
<span>工作流配置</span>
<span style={{marginLeft:"66px",color:`${ menu ? "#5091FF":"#333" }`}}>构建列表</span>
</Banner>
<Div>
{
menu ?
<Structure {...props}/>
:
<Dispost {...props}/>
}
</Div>
</div>
)
})

View File

@ -0,0 +1,204 @@
import React , { useState } from 'react';
import { FlexAJ , Blueback } from '../Component/layout';
import { Table , Pagination } from 'antd';
import styled from 'styled-components';
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:""
}
];
const Img = styled.img`{
border-radius:50%;
margin-rigth:10px;
width:25px;
height:25px;
}`
export default (()=>{
const [ status ,setStatus ] = useState("1");
const [ page ,setPage ] = useState(1);
const [ total ,setTotal ] = useState(10);
function ChangeStatus(value){
setStatus(value)
}
//
function ChangePage(page){
setPage(page)
}
function renderStatus() {
return(
<ul className="listNav">
{
STATUS.map((item,key)=>{
return <li onClick={()=>ChangeStatus(item.value)} className={ status === item.value ? "active":""}>{item.name}</li>
})
}
</ul>
)
}
function renderStatusBtn(status){
if(status >1 && status <=3){
return(
<a className="color-blue">重新构建</a>
)
}else{
return(
<a className="color-red">撤销构建</a>
)
}
}
function renderTableStatus (status){
switch (status){
case 1:
return(
<span className="statusTag running"><i className="iconfont icon-yunhangzhong"></i>运行中</span>
);
case 2:
return (
<span className="statusTag failed"><i className="iconfont icon-weitongguo"></i>未通过</span>
);
case 3:
return (
<span className="statusTag pass"><i className="iconfont icon-yitongguo"></i>已通过</span>
);
default:
return (
<span className="statusTag Preparing"><i className="iconfont icon-zhunbeizhong"></i>准备中</span>
);
}
}
const column = [
{
title:'序号',
dataIndex:"No",
key:"No",
width:"8%",
render:(item,value,key)=>{
return(
<span>#{key+1}</span>
)
}
},
{
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:"message",
key:"message",
width:"30%",
render:(value,item,key)=>{
let meg = item.message;
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>}
</div>
<FlexAJ>
<Img src={meg.image} />
<div className="task-hide" style={{maxWidth:"300px"}}>{meg.message}</div>
</FlexAJ>
</React.Fragment>
)
}
},
{
title:'开始时间',
dataIndex:"begin",
key:"begin",
width:"15%",
render:(value,item,key)=>{
return (
<span>{value || "--"}</span>
)
}
},
{
title:'运行时间',
dataIndex:"run",
key:"run",
width:"15%",
render:(value,item,key)=>{
return (
<span>{value || "--"}</span>
)
}
},
{
title:'操作',
dataIndex:"operation",
key:"operation",
render:(value,item,key)=>{
return(renderStatusBtn(item.status));
}
}
]
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>
</FlexAJ>
<Table
columns={column}
className="normalTable"
dataSource={datasource}
pagination={false}
></Table>
{
total > LIMIT ?
<div style={{textAlign:'center',margin:"30px 50px"}}>
<Pagination showQuickJumper defaultCurrent={page} total={total} pageSize={LIMIT} onChange={ChangePage}></Pagination>
</div>:""
}
</div>
)
})

121
src/forge/DevOps/ops.scss Normal file
View File

@ -0,0 +1,121 @@
.opsPanel
{
margin:20px auto;
width: 1200px;
// 开始激活页面
.activatePanel{
display: flex;
flex-direction: column;
align-items: center;
padding:60px 0px;
}
.disposePanel{
.language{
display: flex;
li{
margin-right: 20px;
}
}
.editorBody{
border:1px solid #ddd;
margin:20px 0px;
.editorHead{
background-color: #F1F8FF;
height: 48px;
line-height: 48px;
display: flex;
justify-content: space-between;
padding:0px 20px;
border-bottom: 1px solid #ddd;
}
.monaco-editor{
width:1138px!important;
}
}
.ant-modal-close{
top:7px;
}
.listPart{
.listNav{
display: flex;
li{
background-color: #fafafa;
border:1px solid #eee;
border-radius: 5px;
height: 38px;
line-height:38px;
padding:0px 20px;
color: #333;
margin-right: 20px;
cursor: pointer;
&:last-child{
margin-right: 0px;
}
&.active{
border:1px solid #5091FF;
color: #5091FF;
background-color: #fff;
}
}
}
.normalTable{
margin-top: 20px;
.ant-table-thead > tr > th, .ant-table-tbody > tr > td{
padding:10px 5px;
color:#333;
}
.ant-table-thead{
border:1px solid rgba(238,238,238,1)
}
}
}
}
// 列表
.listPart{
.statusTag{
display: flex;
padding:0px 16px;
height: 32px;
line-height: 32px;
border-radius:20px;
float: left;
i{
font-size: 20px!important;
margin-right: 7px;
}
&.running{
background:#F1F8FF;
border:1px solid #5091FF;
color: #5091FF;
}
&.Preparing{
background:rgba(255,248,244,1);
border:1px solid rgba(255,110,33,1);
color:rgba(255,110,33,1) ;
}
&.pass{
background:#EEFDF5;
border:1px solid #28BD6C;
color:#28BD6C ;
}
&.failed{
background:#FCEEEE;
border:1px solid #F73030;
color:#F73030 ;
}
}
}
}
// ops详情
.opsDetailPanel{
height: 100vh;
background-color: #114879;
.opsInfos{
height: 60px;
background-color: #114879;
color:#fff;
padding:0px 20px;
}
}

View File

@ -0,0 +1,19 @@
import React from 'react';
import './ops.scss';
import { FlexAJ, AlignCenter } from '../Component/layout';
import { Tags } from '../Component/OpsStatus';
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>
)
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

BIN
src/forge/Images/docker.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

BIN
src/forge/Images/gradle.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
src/forge/Images/java.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
src/forge/Images/js.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

BIN
src/forge/Images/php.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

BIN
src/forge/Images/python.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -344,6 +344,63 @@ class CoderRootDirectory extends Component {
readOnly readOnly
}) })
} }
downloadUrl = (zip_url,tar_url) => {
return(
<Menu>
{zip_url && (
<Menu.Item>
<a href={zip_url}>ZIP</a>
</Menu.Item>
)}
{tar_url && (
<Menu.Item>
<a href={tar_url}>TAR.GZ</a>
</Menu.Item>
)}
</Menu>
)
}
title = (branchLastCommit,lastCommitAuthor) => {
if (branchLastCommit) {
return (
<div className="f-wrap-alignCenter">
{lastCommitAuthor ? (
<React.Fragment>
{lastCommitAuthor.login ? (
<Link
to={`/users/${lastCommitAuthor.login}/projects`}
className="show-user-link"
>
<img
src={getImageUrl(`images/${lastCommitAuthor.image_url}`)}
className="radius mr10"
width="32"
height="32"
alt=""
/>
<span className="mr15">{lastCommitAuthor.name}</span>
</Link>
) : (
<span className="mr15">{lastCommitAuthor.name}</span>
)}
</React.Fragment>
) : (
""
)}
<span className="color-blue flex-1 hide-1">
{branchLastCommit.message}
</span>
<span>{branchLastCommit.time_from_now}</span>
<span className="commitKey">
{truncateCommitId(branchLastCommit.sha)}
</span>
</div>
);
}
}
render(){ render(){
const { branchLastCommit , lastCommitAuthor , rootList , branch ,filePath , fileDetail , subFileType , readMeContent, isSpin , zip_url , tar_url} = this.state; const { branchLastCommit , lastCommitAuthor , rootList , branch ,filePath , fileDetail , subFileType , readMeContent, isSpin , zip_url , tar_url} = this.state;
const { isManager , isDeveloper , projectDetail } = this.props; const { isManager , isDeveloper , projectDetail } = this.props;
@ -363,90 +420,24 @@ class CoderRootDirectory extends Component {
dataIndex: "commit", dataIndex: "commit",
width: "60%", width: "60%",
render: (text, item) => render: (text, item) =>
item.commit && item.commit.message ? ( item.commit && item.commit.message ?
<span <span className="task-hide" style={{ display: "block", maxWidth: "670px" }} >
className="task-hide"
style={{ display: "block", maxWidth: "670px" }}
>
{item.commit.message} {item.commit.message}
</span> </span>
) : ( : ""
""
),
}, },
{ {
dataIndex: "commit", dataIndex: "commit",
width: "10%", width: "10%",
className: "edu-txt-right", className: "edu-txt-right",
render: (text, item) => render: (text, item) =>
item.commit && item.commit.time_from_now ? ( item.commit && item.commit.time_from_now ?
<a <a title={item.commit.created_at} className="mr12" style={{ cursor: "default", color: "#888" }} >
title={item.commit.created_at}
className="mr12"
style={{ cursor: "default", color: "#888" }}
>
{item.commit.time_from_now} {item.commit.time_from_now}
</a> </a>
) : ( :""
""
),
}, },
]; ];
const title = () => {
if (branchLastCommit) {
return (
<div className="f-wrap-alignCenter">
{lastCommitAuthor ? (
<React.Fragment>
{lastCommitAuthor.login ? (
<Link
to={`/users/${lastCommitAuthor.login}/projects`}
className="show-user-link"
>
<img
src={getImageUrl(`images/${lastCommitAuthor.image_url}`)}
className="radius mr10"
width="32"
height="32"
alt=""
/>
<span className="mr15">{lastCommitAuthor.name}</span>
</Link>
) : (
<span className="mr15">{lastCommitAuthor.name}</span>
)}
</React.Fragment>
) : (
""
)}
<span className="color-blue flex-1 hide-1">
{branchLastCommit.message}
</span>
<span>{branchLastCommit.time_from_now}</span>
<span className="commitKey">
{truncateCommitId(branchLastCommit.sha)}
</span>
</div>
);
} else {
return undefined;
}
};
const downloadUrl = () => (
<Menu>
{zip_url && (
<Menu.Item>
<a href={zip_url}>ZIP</a>
</Menu.Item>
)}
{tar_url && (
<Menu.Item>
<a href={tar_url}>TAR.GZ</a>
</Menu.Item>
)}
</Menu>
);
const urlRoot = filePath === undefined ? "" : `/${filePath}`; const urlRoot = filePath === undefined ? "" : `/${filePath}`;
let array = filePath && filePath.split("/"); let array = filePath && filePath.split("/");
@ -487,7 +478,7 @@ class CoderRootDirectory extends Component {
)} )}
</div> </div>
<div className="f-wrap-alignCenter"> <div className="f-wrap-alignCenter">
{subFileType && parseInt(projectDetail.type) !== 2 && (isManager || isDeveloper) && ( {subFileType && (projectDetail && parseInt(projectDetail.type)) !== 2 && (isManager || isDeveloper) && (
<div> <div>
<span> <span>
<Link <Link
@ -508,7 +499,7 @@ class CoderRootDirectory extends Component {
{projectDetail && projectDetail.clone_url && ( {projectDetail && projectDetail.clone_url && (
<CloneAddress <CloneAddress
http_url={projectDetail.clone_url} http_url={projectDetail.clone_url}
downloadUrl={downloadUrl} downloadUrl={this.downloadUrl(zip_url,tar_url)}
showNotification={this.props.showNotification} showNotification={this.props.showNotification}
></CloneAddress> ></CloneAddress>
)} )}
@ -519,7 +510,7 @@ class CoderRootDirectory extends Component {
<RootTable <RootTable
columns={columns} columns={columns}
data={rootList} data={rootList}
title={() => title()} title={() => this.title(branchLastCommit,lastCommitAuthor)}
></RootTable> ></RootTable>
)} )}
{/* 子目录列表、文件 */} {/* 子目录列表、文件 */}

View File

@ -1,4 +1,4 @@
import React, { Component, Fragment } from 'react'; import React, { Component } from 'react';
import { Spin, Tooltip } from 'antd'; import { Spin, Tooltip } from 'antd';
import { Link, Route, Switch } from 'react-router-dom'; import { Link, Route, Switch } from 'react-router-dom';
import { Content } from '../Component/layout'; import { Content } from '../Component/layout';
@ -114,6 +114,10 @@ const TrendsIndex = Loadable({
loading: Loading, loading: Loading,
}) })
const DevIndex = Loadable({
loader: () => import('../DevOps/Index'),
loading: Loading,
})
/** /**
* permissionManager:管理员Reporter报告人员(只有读取权限)Developer开发人员除不能设置仓库信息外 * permissionManager:管理员Reporter报告人员(只有读取权限)Developer开发人员除不能设置仓库信息外
*/ */
@ -419,7 +423,7 @@ class Detail extends Component {
<img alt="" src={img_1} width="18" />代码库 <img alt="" src={img_1} width="18" />代码库
</Link> </Link>
</li> </li>
<li className={(url.indexOf("orders") > -1 && !(url.indexOf("Milepost") > 0 || url.indexOf("meilpost") > 0 || url.indexOf("tags") > 0)) ? "active" : ""}> <li className={(url.indexOf("/orders") > -1 && !(url.indexOf("Milepost") > 0 || url.indexOf("meilpost") > 0 || url.indexOf("tags") > 0)) ? "active" : ""}>
<Link to={{ pathname: `/projects/${projectsId}/orders`, state }}> <Link to={{ pathname: `/projects/${projectsId}/orders`, state }}>
<img alt="" src={img_2} width="12" />任务 <img alt="" src={img_2} width="12" />任务
{projectDetail && projectDetail.issues_count ? <span>{projectDetail.issues_count}</span> : ""} {projectDetail && projectDetail.issues_count ? <span>{projectDetail.issues_count}</span> : ""}
@ -434,20 +438,26 @@ class Detail extends Component {
</Link> </Link>
</li> </li>
} }
<li className={(url.indexOf("Milepost") > -1 || url.indexOf("meilpost") > -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.pull_requests_count ? <span>{projectDetail.pull_requests_count}</span> : ""} */}
</Link>
</li>
<li className={(url.indexOf("/Milepost") > -1 || url.indexOf("meilpost") > -1) ? "active" : ""}>
<Link to={{ pathname: `/projects/${projectsId}/orders/Milepost`, state }}> <Link to={{ pathname: `/projects/${projectsId}/orders/Milepost`, state }}>
<img alt="" src={img_milepost} width="16" />里程碑 <img alt="" src={img_milepost} width="16" />里程碑
{projectDetail && projectDetail.version_count && <span>{projectDetail.version_count}</span>} {projectDetail && projectDetail.version_count && <span>{projectDetail.version_count}</span>}
</Link> </Link>
</li> </li>
<li className={url.indexOf("trends") > -1 ? "active" : ""}> <li className={url.indexOf("/trends") > -1 ? "active" : ""}>
<Link to={{ pathname: `/projects/${projectsId}/trends`, state }}> <Link to={{ pathname: `/projects/${projectsId}/trends`, state }}>
<img alt="" src={img_6} width="16" />动态 <img alt="" src={img_6} width="16" />动态
</Link> </Link>
</li> </li>
{ {
isManager && isManager &&
<li className={url.indexOf("setting") > 0 ? "active" : ""}><Link to={`/projects/${projectsId}/setting`}><img alt="" src={img_7} width="19" />仓库设置</Link></li> <li className={url.indexOf("/setting") > 0 ? "active" : ""}><Link to={`/projects/${projectsId}/setting`}><img alt="" src={img_7} width="19" />仓库设置</Link></li>
} }
</ul> </ul>
</div> </div>
@ -463,6 +473,12 @@ class Detail extends Component {
: :
<Spin spinning={secondSync} className="spinstyle" tip="正在同步镜像" size="large"> <Spin spinning={secondSync} className="spinstyle" tip="正在同步镜像" size="large">
<Switch {...this.props}> <Switch {...this.props}>
{/* 工作流 */}
<Route path="/projects/:projectsId/ops"
render={
() => (<DevIndex {...this.props} {...this.state} {...common} />)
}
></Route>
{/* 标签列表 */} {/* 标签列表 */}
<Route path="/projects/:projectsId/orders/tags" <Route path="/projects/:projectsId/orders/tags"
render={ render={

View File

@ -246,6 +246,9 @@
align-items: center; align-items: center;
margin-left: 30px margin-left: 30px
} }
.ant-tooltip {
max-width: fit-content!important;
}
.detail_tag_btn_name{ .detail_tag_btn_name{
padding:0px 10px; padding:0px 10px;
display: flex; display: flex;

View File

@ -267,7 +267,7 @@ class NewMerge extends Component {
</div> </div>
</div> </div>
{show_message ? ( {show_message ? (
<div className="mb50 mt50"> <div className="mb20">
<Alert description={withHtml(default_message)} type="error" /> <Alert description={withHtml(default_message)} type="error" />
</div> </div>
) : ( ) : (

View File

@ -409,7 +409,7 @@ class merge extends Component {
</div> </div>
{data && data.search_count && data.search_count > 0 ? ( {data && data.search_count && data.search_count > 0 ? (
<div> <div style={{minHeight:"400px"}}>
<Spin spinning={isSpin}> <Spin spinning={isSpin}>
<OrderItem <OrderItem
issues={issues} issues={issues}

View File

@ -235,7 +235,7 @@ class MergeForm extends Component {
return ( return (
<div> <div>
<Spin spinning={isSpin}> <Spin spinning={isSpin}>
<div className="mt20 mb20"> <div className="mb20">
<span className="font-16 fwb mr10 ver-middle"> <span className="font-16 fwb mr10 ver-middle">
{merge_type === "new" ? "新建" : "编辑"}合并请求: {merge_type === "new" ? "新建" : "编辑"}合并请求:
</span> </span>

View File

@ -109,6 +109,11 @@ form.ant-form{
line-height: 22px; line-height: 22px;
} }
} }
form{
.ant-row.ant-form-item{
margin-bottom: 15px;
}
}
@media screen and (max-width: 1000px){ @media screen and (max-width: 1000px){
.main{ .main{
width: 750px; width: 750px;