个人中心-工作流CI

This commit is contained in:
caishi 2020-09-04 18:00:22 +08:00
parent 3169867415
commit 6795e61870
9 changed files with 350 additions and 10 deletions

View File

@ -100,6 +100,7 @@ li.ant-menu-item{
right:240px;
z-index: 10000;
}
@media screen and (max-width: 1800px){
.handleBox{
right:190px;

View File

@ -0,0 +1,24 @@
import React from 'react';
import { Modal , Button } from 'antd';
import './Component.scss';
function Modals({visible,title,content,onOk,onCancel}){
return(
<Modal
className="modalsStyle"
visible={visible}
title={title}
onCancel={onCancel}
closable={true}
footer={
<div>
<Button onClick={onCancel}>取消</Button>
<Button type={"primary"} style={{marginLeft:"20px"}} onClick={onOk}>确定</Button>
</div>
}
>
{content}
</Modal>
)
}
export default Modals;

View File

@ -156,9 +156,12 @@ function About(props, ref) {
<Blueback onClick={goStep}>下一步</Blueback>
</React.Fragment>
:""}
{step === 1 &&(
{step >= 1 &&(
<div style={{textAlign:'center',marginTop:"20px"}}>
<p style={{ maxWidth: "300px",textAlign:"left",color:"#999" }}>初始化配置已完成请前往:<br/><a target="_blank" href={redirectUrl} className="color-blue">{redirectUrl}</a> 进入认证</p>
{
step === 1 &&
<p style={{ maxWidth: "300px",textAlign:"left",color:"#999" }}>初始化配置已完成请前往:<br/><a target="_blank" href={redirectUrl} className="color-blue">{redirectUrl}</a> 进入认证</p>
}
<Blueback onClick={startActive} className="mt20">开始激活</Blueback>
</div>
)}

View File

@ -136,7 +136,24 @@ form{
vertical-align: middle;
}
.pd510{padding: 5px 10px;}
.modalsStyle{
.ant-modal-content{
&>.ant-modal-header{
text-align: left!important;
}
}
.ant-modal-body{
max-width: 400px;
margin:0px auto;
text-align: left;
min-height: 140px;
display: flex;
align-items: center;
}
.ant-modal-close-x{
margin-top:8px;
}
}
.list-l-Menu{
margin-bottom: 12px;
border-radius:2px;

View File

@ -0,0 +1,71 @@
import React , { useEffect , useState } from 'react';
import { Button ,Spin , Pagination } from 'antd';
import Nodata from '../Nodata';
import axios from 'axios';
const limit = 10;
function CIList(props){
const [ page , setPage ] = useState(1);
const [ total , setTotal ] = useState(0);
const [ isSpining , setIsSpining] = useState(true);
const [ list , setList ] = useState(undefined);
let user = props.current_user;
useEffect(()=>{
setIsSpining(true);
if(user && user.login){
const url = `/users/${user.login}/projects.json`;
axios.get(url,{
params:{
limit , page
}
}).then(result=>{
if(result && result.data){
setList(result.data.projects);
setTotal(result.data.count);
setIsSpining(false);
}
}).catch(error=>{
console.log(error);
})
}
},[user,page])
function changePage(page){
setPage(page);
}
return(
<div style={{minHeight:"400px"}}>
<Spin spinning={isSpining}>
{
list && list.length > 0 ?
<ul className="CIList">
{list.map((item,key)=>{
return(
<li>
<span>
<span>{item.author && item.author.name}/{item.name}</span>
{ item.open_devops ?
<span className="authTag green ml20">已激活</span>
:
<span className="authTag red ml20">未激活</span>
}
</span>
{ !item.open_devops && <Button type={"primary"} onClick={()=>{props.history.push(`/projects/${item.author && item.author.login}/${item.identifier}/devops`)}}>马上激活</Button> }
</li>
)
})}
</ul>
:<Nodata _html="暂无数据"/>
}
{
total > limit &&
<div className="mt20 mb30" style={{textAlign:"center"}}>
<Pagination simple onChange={changePage} pageSize={limit} current={page} total={total}></Pagination>
</div>
}
</Spin>
</div>
)
}
export default CIList;

View File

@ -0,0 +1,154 @@
import React , { useEffect , useState , forwardRef , useCallback } from 'react';
import { Button , Modal , Form , Input } from 'antd';
import { AlignCenter } from '../Component/layout';
import axios from 'axios';
import Modals from '../Component/Modal';
const TIPS = "解除CI服务器绑定后您所有的项目构建数据将被清空。确定解除绑定";
function CIdispose(props){
const [ CIData , setCIData ] = useState(undefined);
const [ step , setStep ] = useState(0);
const [ visible, setVisible ] = useState(false);
const [ bindVisible, setBindVisible ] = useState(false);
const [ btnLoading , setBtnLoading ] = useState(false);
const { form: { getFieldDecorator, validateFields , setFieldsValue } } = props;
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>
),
[]
);
useEffect(()=>{
getInit();
},[])
function getInit(){
const url = `/users/ci/cloud_account.json`;
axios.get(url).then(result=>{
if(result && result.data){
setCIData(result.data.cloud_account);
setStep(result.data.step);
}
}).catch(error=>{
console.log(error);
})
}
//
function cancelBind(){
const url = `/users/ci/cloud_account/unbind.json`;
axios.delete(url).then(result=>{
if(result && result.data){
props.showNotification("成功解除绑定!");
setVisible(false);
getInit();
}
}).catch(error=>{
console.log(error);
})
}
function onCancel(){
setVisible(false);
}
//
function sureBindInfo(){
validateFields((error, values) => {
if (!error) {
setBtnLoading(true);
const url = `/users/ci/cloud_account/bind.json`;
axios.post(url,{
...values
}).then(result=>{
setBtnLoading(false);
if(result && result.data){
setBindVisible(false);
setCIData(result.data.cloud_account);
setStep(result.data.step);
props.showNotification("服务器绑定成功!");
}
})
}
})
}
//
function cancelBindInfo(){
setBindVisible(false);
setFieldsValue({
ip_num:undefined,
secret:undefined,
account:undefined
})
}
return(
<div className="disposeInfo">
<Modal
className="modalsStyle"
visible={bindVisible}
title={"绑定CI服务器地址"}
onCancel={cancelBindInfo}
closable={true}
footer={
<div>
<Button onClick={cancelBindInfo}>取消</Button>
<Button loading={btnLoading} type={"primary"} style={{marginLeft:"20px"}} onClick={sureBindInfo}>确定</Button>
</div>
}
>
<Form style={{marginTop:"20px"}}>
{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>
</Modal>
<Modals visible={visible} title={"解除绑定"} content={TIPS} onOk={cancelBind} onCancel={onCancel}/>
<div className="disposeItem">
<AlignCenter>
<span>CI服务器地址</span>
{CIData && step >= 1 && <span className="ml10">{CIData.ip}</span>}
{ step === 0 && <span className="ml10 authTag red">未绑定</span> }
{ step === 1 && <span className="ml10 authTag red">未认证</span> }
{ step === 2 && <span className="ml10 authTag green">已认证</span> }
</AlignCenter>
<AlignCenter>
{ step === 0 && <Button type={'primary'} onClick={()=>setBindVisible(true)} >马上绑定</Button> }
{ step === 1 && <Button type={'primary'} style={{color:"#fff"}} href={CIData && CIData.redirect_url} target="_blank">马上认证</Button> }
{ step >= 1 && <Button type={'danger'} className="ml20" onClick={()=>setVisible(true)}>解除绑定</Button> }
</AlignCenter>
</div>
</div>
)
}
export default Form.create()(forwardRef(CIdispose));;

View File

@ -70,4 +70,52 @@ $flex:flex;
margin: 8px 0 0 0 !important;
}
}
}
ul.ant-menu.menuStyle{
padding:0px 30px;
font-size: 16px;
li{
height: 70px;
line-height: 70px;
padding:0px;
margin-right: 30px!important;
}
}
.disposeInfo{
padding:0px 30px;
min-height: 400px;
.disposeItem{
display: flex;
justify-content: space-between;
padding:30px 0px;
border-bottom: 1px solid #eee;
}
}
.authTag{
display: inline-block;
padding:0px 10px;
border-radius: 12px;
font-size: 12px;
height: 22px;
line-height: 22px;
&.red{
border:1px solid #F73030;
color: #F73030;
}
&.green{
border:1px solid #28BD6C;
color: #28BD6C;
}
}
.CIList{
padding:0px 30px;
min-height: 400px;
li{
display: flex;
justify-content: space-between;
padding:28px 0px;
border-bottom: 1px solid #eee;
}
}

View File

@ -252,10 +252,10 @@ class Infos extends Component {
</ul>
</div>
{/* <div className="bgcF">
<div className="bgcF">
<ul className="list-l-Menu">
<li className="MenuTitle">
<i className="iconfont icon-xiangmuleixing font-15 mr5"></i>
<i className="iconfont icon-gongzuoliu font-15 mr5"></i>
DevOps工作流
<i className="iconfont icon-youjiantou font-15 mr20 color-grey-9 pull-right"></i>
</li>
@ -267,16 +267,16 @@ class Infos extends Component {
</span>
</p>
</li>
<li className={project_type && project_type === "CDService" ? "active" : ""} onClick={() => this.change_devops_type("CDService")}>
{/* <li className={project_type && project_type === "CDService" ? "active" : ""} onClick={() => this.change_devops_type("CDService")}>
<p>
<span className="font-16">CD服务</span>
<span className="color-blue">
{user && user.common_projects_count}
</span>
</p>
</li>
</li> */}
</ul>
</div> */}
</div>
{/* <div className="bgcF">
<div className="list-l-Menu">

View File

@ -1,8 +1,30 @@
import React , { useEffect , useState } from 'react';
import { Menu } from 'antd';
import './Index.scss';
import CIdispose from './CIdispose';
import CIList from './CIList';
function DevOpsCI(){
function DevOpsCI(props){
const [ selectKey , setSelectKey ] = useState("dispose");
function changeKeys(e){
setSelectKey(e.key);
}
return(
<div>111</div>
<div>
<Menu mode="horizontal" className="menuStyle" onClick={changeKeys} selectedKeys={[selectKey]}>
<Menu.Item key="dispose">服务器配置</Menu.Item>
<Menu.Item key="list">项目列表</Menu.Item>
</Menu>
{
selectKey === "dispose" ?
<CIdispose {...props}/>
:
<CIList {...props}/>
}
</div>
)
}
export default DevOpsCI;