issue:11627
This commit is contained in:
parent
0ce695ba08
commit
c255a36c9d
File diff suppressed because it is too large
Load Diff
|
|
@ -182,7 +182,7 @@
|
|||
"eslintConfig": {
|
||||
"extends": "react-app"
|
||||
},
|
||||
"proxy": "http://localhost:3000",
|
||||
"proxy": "http://172.16.100.182:81",
|
||||
"port": "3007",
|
||||
"devDependencies": {
|
||||
"@babel/runtime": "7.0.0-beta.51",
|
||||
|
|
@ -199,6 +199,7 @@
|
|||
"mockjs": "^1.1.0",
|
||||
"optimize-css-assets-webpack-plugin": "^5.0.3",
|
||||
"purgecss": "^2.1.2",
|
||||
"react-json-view": "^1.12.3",
|
||||
"reqwest": "^2.0.5",
|
||||
"resize-observer-polyfill": "^1.5.1",
|
||||
"terser-webpack-plugin": "^2.3.5",
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ broadcastChannelOnmessage('refreshPage', () => {
|
|||
|
||||
function locationurl(list) {
|
||||
if (window.location.port !== "3007") {
|
||||
window.location.href = list
|
||||
window.location.href = list
|
||||
}
|
||||
}
|
||||
// TODO 开发期多个身份切换
|
||||
|
|
@ -24,20 +24,21 @@ if (isDev) {
|
|||
parsed = queryString.parse(_search);
|
||||
}
|
||||
debugType = window.location.search.indexOf('debug=t') !== -1 ? 'teacher' :
|
||||
window.location.search.indexOf('debug=s') !== -1 ? 'student' :
|
||||
window.location.search.indexOf('debug=a') !== -1 ? 'admin' : parsed.debug || 'admin'
|
||||
}
|
||||
window.location.search.indexOf('debug=s') !== -1 ? 'student' :
|
||||
window.location.search.indexOf('debug=a') !== -1 ? 'admin' : parsed.debug || 'admin'
|
||||
}
|
||||
window._debugType = debugType;
|
||||
export function initAxiosInterceptors(props) {
|
||||
// 判断网络是否连接
|
||||
initOnlineOfflineListener();
|
||||
|
||||
// var proxy = "http://172.16.100.220:81";
|
||||
var proxy = 'http://172.16.100.130:81'
|
||||
// var proxy = 'http://172.16.100.130:81'
|
||||
var proxy = 'http://172.16.100.182:81'
|
||||
//响应前的设置
|
||||
axios.interceptors.request.use(
|
||||
config => {
|
||||
if(config.url.indexOf("http") !== -1) {
|
||||
if (config.url.indexOf("http") !== -1) {
|
||||
return config
|
||||
}
|
||||
requestProxy(config);
|
||||
|
|
@ -59,7 +60,7 @@ export function initAxiosInterceptors(props) {
|
|||
},
|
||||
err => {
|
||||
return Promise.reject(err);
|
||||
});
|
||||
});
|
||||
|
||||
axios.interceptors.response.use(function (response) {
|
||||
if (response === undefined) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React , { Component } from 'react';
|
||||
import { Dropdown , Menu , Icon , Pagination , Spin } from 'antd';
|
||||
import React, { Component } from 'react';
|
||||
import { Dropdown, Menu, Icon, Pagination, Spin } from 'antd';
|
||||
import '../css/index.scss';
|
||||
import '../Branch/branch.css';
|
||||
import '../Branch/branch.scss';
|
||||
import './activity.css';
|
||||
import NoneData from '../Nodata';
|
||||
|
||||
|
|
@ -11,126 +11,126 @@ import axios from 'axios';
|
|||
const LIMIT = 15;
|
||||
const ARRAY = [
|
||||
{
|
||||
id:1,
|
||||
name:'1天'
|
||||
id: 1,
|
||||
name: '1天'
|
||||
},
|
||||
{
|
||||
id:3,
|
||||
name:'3天'
|
||||
id: 3,
|
||||
name: '3天'
|
||||
},
|
||||
{
|
||||
id:7,
|
||||
name:'1周'
|
||||
id: 7,
|
||||
name: '1周'
|
||||
},
|
||||
{
|
||||
id:30,
|
||||
name:'1个月'
|
||||
id: 30,
|
||||
name: '1个月'
|
||||
}
|
||||
]
|
||||
|
||||
class Activity extends Component{
|
||||
constructor(props){
|
||||
class Activity extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state={
|
||||
time:'30',
|
||||
type:undefined,
|
||||
state:undefined,
|
||||
page:1,
|
||||
this.state = {
|
||||
time: '30',
|
||||
type: undefined,
|
||||
state: undefined,
|
||||
page: 1,
|
||||
|
||||
data:undefined,
|
||||
project_trends:undefined,
|
||||
data: undefined,
|
||||
project_trends: undefined,
|
||||
|
||||
isSpin:false
|
||||
isSpin: false
|
||||
}
|
||||
}
|
||||
componentDidMount=()=>{
|
||||
const { time,type,status,page } = this.state;
|
||||
componentDidMount = () => {
|
||||
const { time, type, status, page } = this.state;
|
||||
this.setState({
|
||||
isSpin:true
|
||||
isSpin: true
|
||||
})
|
||||
this.getInfo(time,type,status,page);
|
||||
this.getInfo(time, type, status, page);
|
||||
}
|
||||
|
||||
getInfo =(time,type,status,page)=>{
|
||||
const { projectsId , owner } = this.props.match.params;
|
||||
const url = `/${owner}/${projectsId}/activity.json`;
|
||||
axios.get(url,{
|
||||
params:{
|
||||
time,type,status,page
|
||||
getInfo = (time, type, status, page) => {
|
||||
const { projectsId, owner } = this.props.match.params;
|
||||
const url = `/${owner}/${projectsId}/activity.json`;
|
||||
axios.get(url, {
|
||||
params: {
|
||||
time, type, status, page
|
||||
}
|
||||
}).then(result=>{
|
||||
if(result){
|
||||
}).then(result => {
|
||||
if (result) {
|
||||
this.setState({
|
||||
data:result.data,
|
||||
project_trends:result.data.project_trends,
|
||||
isSpin:false
|
||||
data: result.data,
|
||||
project_trends: result.data.project_trends,
|
||||
isSpin: false
|
||||
})
|
||||
}
|
||||
}).catch(error=>{
|
||||
}).catch(error => {
|
||||
console.log(error);
|
||||
})
|
||||
}
|
||||
|
||||
// 切换周期
|
||||
changeTime=(e)=>{
|
||||
changeTime = (e) => {
|
||||
this.setState({
|
||||
time:e.key,
|
||||
isSpin:true
|
||||
time: e.key,
|
||||
isSpin: true
|
||||
})
|
||||
const { type,status,page } = this.state;
|
||||
this.getInfo(e.key,type,status,page);
|
||||
const { type, status, page } = this.state;
|
||||
this.getInfo(e.key, type, status, page);
|
||||
}
|
||||
//筛选
|
||||
changeTrends=(type,status)=>{
|
||||
//筛选
|
||||
changeTrends = (type, status) => {
|
||||
this.setState({
|
||||
type,status
|
||||
type, status
|
||||
})
|
||||
const {time,page}=this.state;
|
||||
this.getInfo(time,type,status,page);
|
||||
}
|
||||
const { time, page } = this.state;
|
||||
this.getInfo(time, type, status, page);
|
||||
}
|
||||
// 分页
|
||||
ChangePage=(page)=>{
|
||||
ChangePage = (page) => {
|
||||
this.setState({
|
||||
page
|
||||
})
|
||||
const { time,type,status } = this.state;
|
||||
this.getInfo(time,type,status,page);
|
||||
const { time, type, status } = this.state;
|
||||
this.getInfo(time, type, status, page);
|
||||
}
|
||||
menu =()=> (
|
||||
menu = () => (
|
||||
<Menu>
|
||||
{
|
||||
ARRAY && ARRAY.map((item,key)=>{
|
||||
return(
|
||||
ARRAY && ARRAY.map((item, key) => {
|
||||
return (
|
||||
<Menu.Item key={item.id} onClick={this.changeTime}>{item.name}</Menu.Item>
|
||||
)
|
||||
})
|
||||
}
|
||||
</Menu>
|
||||
)
|
||||
render(){
|
||||
const { time , data , page , project_trends , isSpin } = this.state;
|
||||
render() {
|
||||
const { time, data, page, project_trends, isSpin } = this.state;
|
||||
|
||||
let name = time && ARRAY.filter(item=>item.id === parseInt(time)) ;
|
||||
const second_per = (parseInt(data && data.close_issues_count)/parseInt(data && data.issues_count)*100)+'%';
|
||||
const third_per = (parseInt(data && data.close_issues_count)/parseInt(data && data.issues_count)*100)+'%';
|
||||
const fourth_per = (parseInt(data && data.open_issues_count)/parseInt(data && data.issues_count)*100)+'%';
|
||||
return(
|
||||
let name = time && ARRAY.filter(item => item.id === parseInt(time));
|
||||
const second_per = (parseInt(data && data.close_issues_count) / parseInt(data && data.issues_count) * 100) + '%';
|
||||
const third_per = (parseInt(data && data.close_issues_count) / parseInt(data && data.issues_count) * 100) + '%';
|
||||
const fourth_per = (parseInt(data && data.open_issues_count) / parseInt(data && data.issues_count) * 100) + '%';
|
||||
return (
|
||||
<div className="main">
|
||||
|
||||
|
||||
<div className="normalBox">
|
||||
<div class="normalBox-title">概览</div>
|
||||
<div className="orderInfo">
|
||||
<div>
|
||||
<div className="percentLine prPercent">
|
||||
<p className="percent_purple" style={{width:'100%'}}></p>
|
||||
<p className="percent_green resetStyle" style={{width:`${second_per}`}}></p>
|
||||
<p className="percent_purple" style={{ width: '100%' }}></p>
|
||||
<p className="percent_green resetStyle" style={{ width: `${second_per}` }}></p>
|
||||
</div>
|
||||
<span>{data && data.pr_all_count}合并请求</span>
|
||||
</div>
|
||||
<div>
|
||||
<div className="percentLine">
|
||||
<p className="percent_red" style={{width:`${third_per}`}}></p>
|
||||
<p className="percent_green" style={{width:`${fourth_per}`}}></p>
|
||||
<p className="percent_red" style={{ width: `${third_per}` }}></p>
|
||||
<p className="percent_green" style={{ width: `${fourth_per}` }}></p>
|
||||
</div>
|
||||
<span>{data && data.issues_count}任务</span>
|
||||
</div>
|
||||
|
|
@ -138,19 +138,19 @@ class Activity extends Component{
|
|||
<ul className="percentBox">
|
||||
<li>
|
||||
<span className="purple">{data && data.pr_count}</span>
|
||||
<span className="change" onClick={()=>this.changeTrends("PullRequest","close")}>已处理的合并请求</span>
|
||||
<span className="change" onClick={() => this.changeTrends("PullRequest", "close")}>已处理的合并请求</span>
|
||||
</li>
|
||||
<li>
|
||||
<span className="green">{data && data.new_pr_count}</span>
|
||||
<span className="change" onClick={()=>this.changeTrends("PullRequest","create")}>未处理的合并请求</span>
|
||||
<span className="change" onClick={() => this.changeTrends("PullRequest", "create")}>未处理的合并请求</span>
|
||||
</li>
|
||||
<li>
|
||||
<span className="red">{data && data.close_issues_count}</span>
|
||||
<span className="change" onClick={()=>this.changeTrends("Issue","close")}>已关闭的任务</span>
|
||||
<span className="change" onClick={() => this.changeTrends("Issue", "close")}>已关闭的任务</span>
|
||||
</li>
|
||||
<li>
|
||||
<span className="green">{data && data.open_issues_count}</span>
|
||||
<span className="change" onClick={()=>this.changeTrends("Issue","create")}>未处理的任务</span>
|
||||
<span className="change" onClick={() => this.changeTrends("Issue", "create")}>未处理的任务</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
@ -159,7 +159,7 @@ class Activity extends Component{
|
|||
<Dropdown overlay={this.menu()} trigger={['click']} placement="bottomLeft">
|
||||
<a className="ant-dropdown-link">
|
||||
<span className="color-grey-9 mr3">周期:</span>
|
||||
{name && name.length>0 && name[0].name} <Icon type="down" />
|
||||
{name && name.length > 0 && name[0].name} <Icon type="down" />
|
||||
</a>
|
||||
</Dropdown>
|
||||
</div>
|
||||
|
|
@ -167,17 +167,17 @@ class Activity extends Component{
|
|||
<Spin spinning={isSpin}>
|
||||
{
|
||||
project_trends && project_trends.length > 0 ?
|
||||
<div className="activity_list">
|
||||
{
|
||||
project_trends && project_trends.map((item,key)=>{
|
||||
return(
|
||||
<ActivityItem item={item} {...this.props} ></ActivityItem>
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
:
|
||||
<NoneData _html="暂时还没有相关数据!" />
|
||||
<div className="activity_list">
|
||||
{
|
||||
project_trends && project_trends.map((item, key) => {
|
||||
return (
|
||||
<ActivityItem item={item} {...this.props} ></ActivityItem>
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
:
|
||||
<NoneData _html="暂时还没有相关数据!" />
|
||||
}
|
||||
</Spin>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,39 +1,27 @@
|
|||
import React, { Component } from 'react';
|
||||
import { Dropdown, Icon, Tooltip } from 'antd';
|
||||
import "./branch.css";
|
||||
import React, { useState } from 'react';
|
||||
import { Menu } from 'antd';
|
||||
import "./branch.scss";
|
||||
import CopyTool from '../Component/CopyTool';
|
||||
|
||||
class CloneAddress extends Component {
|
||||
// 点击按钮复制功能
|
||||
jsCopy = () => {
|
||||
var e = document.getElementById("copy_rep_content");
|
||||
e.select();
|
||||
document.execCommand("Copy");
|
||||
}
|
||||
|
||||
render() {
|
||||
const { http_url, downloadUrl } = this.props;
|
||||
return (
|
||||
<div className="gitAddressClone">
|
||||
{/* <p className="addressTips"><span>版本库地址已变更,请基于新地址提交代码</span></p> */}
|
||||
{
|
||||
http_url && <span>HTTP</span>
|
||||
}
|
||||
<input type="text" id="copy_rep_content" value={http_url} />
|
||||
<Tooltip title="复制链接">
|
||||
<span className="color-blue" onClick={() => this.jsCopy()}><i className="iconfont icon-fuzhi"></i></span>
|
||||
</Tooltip>
|
||||
{
|
||||
downloadUrl &&
|
||||
<span>
|
||||
<Dropdown overlay={downloadUrl} trigger={['click']} placement="bottomRight">
|
||||
<a className="ant-dropdown-link">
|
||||
<Icon type="cloud-download" className="font-18 fl color-blue" />
|
||||
</a>
|
||||
</Dropdown>
|
||||
</span>
|
||||
}
|
||||
function CloneAddress({ http_url, ssh_url, zip_url, tar_url }) {
|
||||
const [key, setKey] = useState("HTTP");
|
||||
return (
|
||||
<div className="downMenu">
|
||||
<div>
|
||||
<Menu className="urlMenu" selectedKeys={[key]} mode={"horizontal"}>
|
||||
<Menu.Item key="HTTP" onClick={(e) => { setKey(e.key) }}>HTTP</Menu.Item>
|
||||
{ssh_url && <Menu.Item key="SSH" onClick={(e) => { setKey(e.key) }}>SSH</Menu.Item>}
|
||||
</Menu>
|
||||
<div className="gitAddressClone">
|
||||
<input type="text" id="copy_rep_content" value={key === "HTTP" ? http_url : ssh_url} />
|
||||
<CopyTool inputId="copy_rep_content" className="copytool" />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<Menu className="edu-txt-center">
|
||||
{zip_url && <Menu.Item style={{ borderTop: "1px solid #eee" }}><a href={zip_url}>下载 ZIP</a></Menu.Item>}
|
||||
{tar_url && <Menu.Item><a href={tar_url}>下载 TAR.GZ</a></Menu.Item>}
|
||||
</Menu>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default CloneAddress;
|
||||
|
|
@ -1,73 +1,73 @@
|
|||
import React , { useState , useEffect } from 'react';
|
||||
import { Popover , Input , Spin } from 'antd';
|
||||
import './branch.css';
|
||||
import { getBranch , getTag } from '../GetData/getData';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { Popover, Input, Spin } from 'antd';
|
||||
import './branch.scss';
|
||||
import { getBranch, getTag } from '../GetData/getData';
|
||||
|
||||
|
||||
export default (({ projectsId , branch , owner , changeBranch , branchList , tagflag = true })=>{
|
||||
const [ showValue , setShowValue ] = useState(branch);
|
||||
const [ inputValue , setInputValue] = useState(undefined);
|
||||
const [ nav , setNav ] = useState(0);
|
||||
const [ isSpin , setIsSpin ] = useState(true);
|
||||
const [ flag , setFlag ] = useState(false);
|
||||
export default (({ projectsId, branch, owner, changeBranch, branchList, tagflag = true }) => {
|
||||
const [showValue, setShowValue] = useState(branch);
|
||||
const [inputValue, setInputValue] = useState(undefined);
|
||||
const [nav, setNav] = useState(0);
|
||||
const [isSpin, setIsSpin] = useState(true);
|
||||
const [flag, setFlag] = useState(false);
|
||||
|
||||
const [ data , setData ] = useState(undefined);
|
||||
const [ datas , setDatas ] = useState(undefined);
|
||||
const [data, setData] = useState(undefined);
|
||||
const [datas, setDatas] = useState(undefined);
|
||||
|
||||
useEffect(()=>{
|
||||
useEffect(() => {
|
||||
setShowValue(branch);
|
||||
},[branch])
|
||||
}, [branch])
|
||||
|
||||
useEffect(()=>{
|
||||
useEffect(() => {
|
||||
document.body.addEventListener('click', e => {
|
||||
let name = e.target.className;
|
||||
let turn = name === "ant-input OptionsInput" || name === "navli active"|| name === "navli" || name === "padding10 bor-bottom-greyE";
|
||||
if(turn){
|
||||
let turn = name === "ant-input OptionsInput" || name === "navli active" || name === "navli" || name === "padding10 bor-bottom-greyE";
|
||||
if (turn) {
|
||||
return;
|
||||
}else{
|
||||
} else {
|
||||
setFlag(false);
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
useEffect(()=>{
|
||||
if(branchList){
|
||||
useEffect(() => {
|
||||
if (branchList) {
|
||||
setData(branchList);
|
||||
setDatas(branchList);
|
||||
setIsSpin(false);
|
||||
}
|
||||
},[branchList])
|
||||
}, [branchList])
|
||||
|
||||
|
||||
async function getBranchs(id,owner){
|
||||
let result = await getBranch(id,owner);
|
||||
async function getBranchs(id, owner) {
|
||||
let result = await getBranch(id, owner);
|
||||
setData(result);
|
||||
setDatas(result);
|
||||
setIsSpin(false);
|
||||
}
|
||||
async function getTags(id,owner){
|
||||
let result = await getTag(id,owner);
|
||||
async function getTags(id, owner) {
|
||||
let result = await getTag(id, owner);
|
||||
setData(result);
|
||||
setDatas(result);
|
||||
setIsSpin(false);
|
||||
}
|
||||
|
||||
function changeInputValue(e){
|
||||
function changeInputValue(e) {
|
||||
setInputValue(e.target.value);
|
||||
let filter = e.target.value ? data && data.length>0 && data.filter(item=>item.name.indexOf(e.target.value)>-1) : data;
|
||||
let filter = e.target.value ? data && data.length > 0 && data.filter(item => item.name.indexOf(e.target.value) > -1) : data;
|
||||
setDatas(filter);
|
||||
}
|
||||
|
||||
function changeNav(nav){
|
||||
function changeNav(nav) {
|
||||
setNav(nav);
|
||||
setIsSpin(true);
|
||||
if(nav === 0){
|
||||
getBranchs(projectsId,owner);
|
||||
}else{
|
||||
getTags(projectsId,owner);
|
||||
if (nav === 0) {
|
||||
getBranchs(projectsId, owner);
|
||||
} else {
|
||||
getTags(projectsId, owner);
|
||||
}
|
||||
}
|
||||
function chooseitem(value){
|
||||
function chooseitem(value) {
|
||||
// setShowValue(value);
|
||||
changeBranch(value);
|
||||
}
|
||||
|
|
@ -76,33 +76,33 @@ export default (({ projectsId , branch , owner , changeBranch , branchList , tag
|
|||
const menu = (
|
||||
<div>
|
||||
<div className="padding10 bor-bottom-greyE">
|
||||
<Input
|
||||
placeholder="请输入分支或标签名称搜索"
|
||||
autocomplete="off" className="OptionsInput" value={inputValue}
|
||||
onChange={changeInputValue} style={{width:"220px"}}
|
||||
<Input
|
||||
placeholder="请输入分支或标签名称搜索"
|
||||
autocomplete="off" className="OptionsInput" value={inputValue}
|
||||
onChange={changeInputValue} style={{ width: "220px" }}
|
||||
/>
|
||||
<ul className="navUl">
|
||||
<li className={nav === 0?"navli active":"navli"} onClick={()=>changeNav(0)}><i className="iconfont icon-fenzhi1 font-14 mr3"></i>分支列表</li>
|
||||
{ tagflag && <li className={nav === 1?"navli active":"navli"} onClick={()=>changeNav(1)}><i className="iconfont icon-biaoqian3 font-14 mr3"></i>标签列表</li> }
|
||||
<li className={nav === 0 ? "navli active" : "navli"} onClick={() => changeNav(0)}><i className="iconfont icon-fenzhi1 font-14 mr3"></i>分支列表</li>
|
||||
{tagflag && <li className={nav === 1 ? "navli active" : "navli"} onClick={() => changeNav(1)}><i className="iconfont icon-biaoqian3 font-14 mr3"></i>标签列表</li>}
|
||||
</ul>
|
||||
</div>
|
||||
<Spin spinning={isSpin}>
|
||||
<ul className="OptionsUl" id="ul-btn">
|
||||
{
|
||||
datas && datas.length>0 ?
|
||||
datas.map((item,key)=>{
|
||||
return(
|
||||
<li key={key} onClick={()=>chooseitem(item.name)}><a className="task-hide ulALink">{item.name}</a></li>
|
||||
)
|
||||
}):
|
||||
<p className="listTips">暂无{inputValue}{nav === 0 ?"分支":"标签"}~</p>
|
||||
datas && datas.length > 0 ?
|
||||
datas.map((item, key) => {
|
||||
return (
|
||||
<li key={key} onClick={() => chooseitem(item.name)}><a className="task-hide ulALink">{item.name}</a></li>
|
||||
)
|
||||
}) :
|
||||
<p className="listTips">暂无{inputValue}{nav === 0 ? "分支" : "标签"}~</p>
|
||||
}
|
||||
</ul>
|
||||
</Spin>
|
||||
</div>
|
||||
);
|
||||
return(
|
||||
<Popover placement="bottom" visible={flag} content={menu} onClick={()=>setFlag(!flag)} overlayClassName="branch-tagBox-list">
|
||||
return (
|
||||
<Popover placement="bottom" visible={flag} content={menu} onClick={() => setFlag(!flag)} overlayClassName="branch-tagBox-list">
|
||||
<div className="branch-tagBox">
|
||||
{/* {nav === 0 ?"分支":"标签"} */}
|
||||
<span className="color-grey-9 mr3 ml8"><i className="iconfont icon-fenzhi2 font-18"></i></span>
|
||||
|
|
|
|||
|
|
@ -1,84 +0,0 @@
|
|||
.branchDropdown{
|
||||
border:1px solid #eee;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
min-width: 220px;
|
||||
}
|
||||
.branchDropdown .ant-dropdown-trigger{
|
||||
width: 100%;
|
||||
padding:0px 15px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
.branchOptions{
|
||||
width: 220px;
|
||||
box-shadow: 0px 0px 3px 1px rgba(134, 134, 134, 0.4);
|
||||
border-radius: 3px;
|
||||
background: #fff;
|
||||
max-height: 300px;
|
||||
}
|
||||
.OptionsUl{
|
||||
max-height: 220px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.OptionsUl li{
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
cursor: pointer;
|
||||
padding:0px 10px;
|
||||
}
|
||||
.OptionsUl li:hover{
|
||||
background-color: #F0F0F0;
|
||||
}
|
||||
.OptionsUl li a{
|
||||
display: block;
|
||||
}
|
||||
.OptionsInput{
|
||||
height: 32px;
|
||||
padding-left: 4px;
|
||||
line-height: 32px;
|
||||
width: 100%;
|
||||
}
|
||||
.branch-tagBox{
|
||||
border:1px solid #eee;
|
||||
border-radius: 3px;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
min-width: 140px;
|
||||
}
|
||||
.branch-tagBox-list .ant-popover-arrow{
|
||||
display: none;
|
||||
}
|
||||
.branch-tagBox-list.ant-popover.ant-popover-placement-bottom{
|
||||
padding-top:0px;
|
||||
}
|
||||
.branch-tagBox .ant-dropdown-link{
|
||||
display: block;
|
||||
flex:1;
|
||||
}
|
||||
.branch-tagBox-list .ant-popover-inner-content{
|
||||
padding:0px;
|
||||
}
|
||||
.navUl{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 5px;
|
||||
}
|
||||
.navUl li{
|
||||
cursor: pointer;
|
||||
}
|
||||
.navUl li.active{
|
||||
color:#5091FF;
|
||||
}
|
||||
.listTips{
|
||||
padding:20px 0px;
|
||||
text-align: center;
|
||||
}
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
.branchDropdown {
|
||||
border: 1px solid #eee;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
min-width: 220px;
|
||||
}
|
||||
|
||||
.branchDropdown .ant-dropdown-trigger {
|
||||
width: 100%;
|
||||
padding: 0px 15px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.branchOptions {
|
||||
width: 220px;
|
||||
box-shadow: 0px 0px 3px 1px rgba(134, 134, 134, 0.4);
|
||||
border-radius: 3px;
|
||||
background: #fff;
|
||||
max-height: 300px;
|
||||
}
|
||||
|
||||
.OptionsUl {
|
||||
max-height: 220px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.OptionsUl li {
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
cursor: pointer;
|
||||
padding: 0px 10px;
|
||||
}
|
||||
|
||||
.OptionsUl li:hover {
|
||||
background-color: #F0F0F0;
|
||||
}
|
||||
|
||||
.OptionsUl li a {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.OptionsInput {
|
||||
height: 32px;
|
||||
padding-left: 4px;
|
||||
line-height: 32px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.branch-tagBox {
|
||||
border: 1px solid #eee;
|
||||
border-radius: 3px;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
min-width: 140px;
|
||||
}
|
||||
|
||||
.branch-tagBox-list .ant-popover-arrow {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.branch-tagBox-list.ant-popover.ant-popover-placement-bottom {
|
||||
padding-top: 0px;
|
||||
}
|
||||
|
||||
.branch-tagBox .ant-dropdown-link {
|
||||
display: block;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.branch-tagBox-list .ant-popover-inner-content {
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.navUl {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.navUl li {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.navUl li.active {
|
||||
color: #5091FF;
|
||||
}
|
||||
|
||||
.listTips {
|
||||
padding: 20px 0px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.urlMenu {
|
||||
line-height: 30px;
|
||||
margin-bottom: 10px;
|
||||
padding: 15px 20px 0px 20px;
|
||||
border-bottom: none;
|
||||
|
||||
li.ant-menu-item {
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
padding: 0px 5px;
|
||||
margin-right: 20px !important;
|
||||
|
||||
&.ant-menu-item-selected,
|
||||
&.ant-menu-item-active {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
&.ant-menu-item-selected {
|
||||
border-color: #466aff !important;
|
||||
}
|
||||
|
||||
&.ant-menu-item-active {
|
||||
border-color: transparent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.copytool {
|
||||
margin: 0px 10px;
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
import React, { useState, useCallback, memo } from 'react';
|
||||
import { Tooltip } from 'antd';
|
||||
|
||||
CopyTool.defaultProps = {
|
||||
beforeText: '复制链接', //浮动过去显示的文字
|
||||
afterText: '复制成功', //点击后显示的文字
|
||||
className: '', //传给svg的class
|
||||
inputId: 'copyText', //要复制的文本的ID
|
||||
timeOut: true, //复制后将浮动的文字改为beforeText
|
||||
};
|
||||
|
||||
|
||||
function CopyTool({ beforeText, afterText, className, inputId, timeOut }) {
|
||||
const [title, setTitle] = useState(() => {
|
||||
return beforeText;
|
||||
});
|
||||
|
||||
// 复制链接
|
||||
const copyUrl = useCallback(() => {
|
||||
const copyEle = document.querySelector(`#${inputId}`); // 获取要复制的节点
|
||||
if (!copyEle) {
|
||||
console.error("您的CopyTool未设置正确的inputId");
|
||||
return;
|
||||
}
|
||||
copyEle.select(); // 执行选中元素
|
||||
if (document.execCommand('copy')) {
|
||||
document.execCommand('copy');
|
||||
}
|
||||
document.getSelection().removeAllRanges();
|
||||
|
||||
setTitle(afterText);
|
||||
if (timeOut) {
|
||||
setTimeout(function () {
|
||||
setTitle(beforeText);
|
||||
}, 1500)
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
placement="top"
|
||||
title={title}
|
||||
onVisibleChange={() => { setTitle(beforeText) }}
|
||||
>
|
||||
<i className={`iconfont icon-fuzhiicon ${className}`} style={{ color: '#466aff' }} onClick={copyUrl}></i>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
export default memo(CopyTool);
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
import React from 'react';
|
||||
import { AlignCenter } from '../layout';
|
||||
import { Button } from 'antd';
|
||||
import Modals from '../PublicModal/Index';
|
||||
|
||||
function DeleteBox({
|
||||
visible ,
|
||||
onCancel ,
|
||||
onSuccess ,
|
||||
title ,
|
||||
subTitle,
|
||||
content
|
||||
}) {
|
||||
return(
|
||||
<Modals
|
||||
title={title}
|
||||
btn={
|
||||
<div>
|
||||
<Button size={'large'} onClick={onCancel}>取消</Button>
|
||||
<Button type={"danger"} size={"large"} onClick={onSuccess}>确认删除</Button>
|
||||
</div>
|
||||
}
|
||||
onCancel={onCancel}
|
||||
visible={visible}
|
||||
>
|
||||
<div className="desc">
|
||||
<AlignCenter className="descMain"><i className="iconfont icon-shanchu_tc_icon mr10"></i>{content}</AlignCenter>
|
||||
<p className="task-hide-2" style={{WebkitLineClamp:5}}>删除后未来事件将不会推送至此Webhook地址:<span title={subTitle}>{subTitle}</span></p>
|
||||
</div>
|
||||
</Modals>
|
||||
)
|
||||
}
|
||||
export default DeleteBox;
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
import React, {useEffect, useRef, useState} from 'react';
|
||||
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api.js';
|
||||
import './Component.scss';
|
||||
|
||||
function Monaco(props) {
|
||||
const {
|
||||
style = { // dom节点样式
|
||||
height: '400px',
|
||||
},
|
||||
value = '', // 代码文本
|
||||
onChange = () => { // 改变的事件
|
||||
},
|
||||
fontSize = 14, // 代码字体大小
|
||||
monacoOptions = {
|
||||
scrollBeyondLastLine: false,
|
||||
lineNumbers: "off",
|
||||
wordWrap: true,
|
||||
overviewRulerBorder: true,
|
||||
lineHeight: 24,
|
||||
readOnly:true
|
||||
}, // monaco 自定义属性
|
||||
language = 'html', // 语言 支持 js ts sql css json html等
|
||||
} = props;
|
||||
const editOrRef = useRef();
|
||||
const ThisEditor = useRef();
|
||||
useEffect(() => {
|
||||
ThisEditor.current = monaco.editor.create(editOrRef.current, {
|
||||
value: value || '',
|
||||
language,
|
||||
theme: "vs-grey",
|
||||
fontSize: fontSize + 'px',
|
||||
minimap: { // 关闭代码缩略图
|
||||
enabled: false,
|
||||
},
|
||||
...monacoOptions,
|
||||
});
|
||||
|
||||
ThisEditor.current.onDidChangeModelContent((e) => {
|
||||
let newValue = ThisEditor.current.getValue();
|
||||
onChange(newValue);
|
||||
});
|
||||
return () => {
|
||||
ThisEditor.current.dispose();
|
||||
ThisEditor.current = undefined; // 清除编辑器对象
|
||||
}
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
if (ThisEditor.current) {
|
||||
ThisEditor.current.updateOptions({
|
||||
fontSize: fontSize + 'px',
|
||||
})
|
||||
}
|
||||
}, [fontSize]);
|
||||
|
||||
return (
|
||||
<div style={style} ref={editOrRef}>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Monaco;
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
import React from 'react';
|
||||
import { Modal } from 'antd';
|
||||
import './Index.scss';
|
||||
|
||||
function Modals({title,children,btn,onCancel,visible}) {
|
||||
return(
|
||||
<Modal
|
||||
visible={visible}
|
||||
onCancel={onCancel}
|
||||
title={title}
|
||||
width={"520px"}
|
||||
footer={btn}
|
||||
centered={true}
|
||||
wrapClassName={"deleteBox"}
|
||||
>
|
||||
{children}
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
export default Modals;
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
.deleteBox{
|
||||
z-index: 1033;
|
||||
.ant-modal-close-x{
|
||||
font-size: 17px!important;
|
||||
}
|
||||
.ant-modal-header{
|
||||
background-color: #f8f8f8;
|
||||
padding:10px 30px;
|
||||
.ant-modal-title{
|
||||
text-align: left;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
.ant-modal-close{
|
||||
top:0px !important;
|
||||
font-size: 24px !important;
|
||||
}
|
||||
.ant-modal-body{
|
||||
padding:30px 50px;
|
||||
p{
|
||||
font-size: 14px;
|
||||
line-height: 26px;
|
||||
color:#666;
|
||||
word-break: break-all;
|
||||
}
|
||||
.desc{
|
||||
.descMain{
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 20px;
|
||||
margin-bottom: 10px;
|
||||
i.red{
|
||||
color:#DF0002;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.ant-modal-footer{
|
||||
border-top: none;
|
||||
text-align: center;
|
||||
padding-bottom: 40px;
|
||||
button,a{
|
||||
width: 96px;
|
||||
height: 32px;
|
||||
margin:0px 20px;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
&.ant-btn{
|
||||
border-color: #D0D0D0;
|
||||
color: #666;
|
||||
&:hover,&:active,&:focus{
|
||||
background: #f3f4f6;
|
||||
}
|
||||
}
|
||||
&.ant-btn-danger{
|
||||
background-color: #fff;
|
||||
color: #DF0002;
|
||||
border-color: #D0D0D0;
|
||||
&:hover,&:active,&:focus{
|
||||
border-color: #DF0002;
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
&.ant-btn.ant-btn-primary{
|
||||
background-color: #466AFF;
|
||||
color: #fff;
|
||||
border-color: #466AFF;
|
||||
&:hover,&:focus,&:active{
|
||||
background-color: rgba(70,106,255,0.85);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,6 +7,8 @@ export const Banner = styled.div`{
|
|||
border-bottom:1px solid #eee;
|
||||
background-color:#fff;
|
||||
border-radius:5px 5px 0px 0px;
|
||||
justify-content: space-between;
|
||||
display: flex;
|
||||
}`
|
||||
export const AlignCenterBetween = styled.div`{
|
||||
display:flex;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React , { useEffect , useState } from 'react';
|
||||
import { WhiteBack , Box , LongWidth , ShortWidth , Gap , AlignCenter , FlexAJ } from '../Component/layout';
|
||||
import { Dropdown , Menu , Divider , Spin, Button } from 'antd';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { WhiteBack, Box, LongWidth, ShortWidth, Gap, AlignCenter, FlexAJ } from '../Component/layout';
|
||||
import { Dropdown, Menu, Divider, Spin, Button } from 'antd';
|
||||
import { getImageUrl } from "educoder";
|
||||
import { Link } from 'react-router-dom';
|
||||
import CloneAddress from '../Branch/CloneAddress';
|
||||
|
|
@ -24,45 +24,46 @@ import Invite from './sub/Invite';
|
|||
* projectDetail.type:0是托管项目,1是镜像项目,2是同步镜像项目(为2时不支持在线创建、在线上传、在线修改、在线删除、创建合并请求等功能)
|
||||
*/
|
||||
|
||||
function turnbar(str){
|
||||
if(str && str.length>0 && str.indexOf("/")>-1){
|
||||
return str.replaceAll('/','%2F');
|
||||
function turnbar(str) {
|
||||
if (str && str.length > 0 && str.indexOf("/") > -1) {
|
||||
return str.replaceAll('/', '%2F');
|
||||
}
|
||||
return str;
|
||||
}
|
||||
function returnbar(str){
|
||||
if(str && str.length>0 && str.indexOf("%2F")>-1){
|
||||
return str.replaceAll('%2F','/');
|
||||
function returnbar(str) {
|
||||
if (str && str.length > 0 && str.indexOf("%2F") > -1) {
|
||||
return str.replaceAll('%2F', '/');
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
function CoderDepot(props){
|
||||
const [ projectDetail , setProjectDetail ]= useState(undefined);
|
||||
const [ inviteCode , setInviteCode ] = useState(undefined);
|
||||
const [ treeValue , setTreeValue ] = useState(undefined);
|
||||
const [ treeValuePath , setTreeValuePath ] = useState(undefined);
|
||||
const [ lastCommit,setLastCommit ] = useState(undefined);
|
||||
const [ lastCommitAuthor,setLastCommitAuthor ] = useState(undefined);
|
||||
const [ type ,setType ] = useState('dir');
|
||||
const [ hide , setHide ] = useState(true);
|
||||
const [ hideBtn , setHideBtn ] = useState(false);
|
||||
const [ commitCount ,setCommitCount ] = useState(0);
|
||||
const [ dirInfo ,setDirInfo ] = useState(undefined);//文件夹目录列表
|
||||
const [ fileInfo ,setFileInfo ] = useState(undefined);//文件内容信息
|
||||
const [ zip_url , setZip_url ] = useState(undefined);
|
||||
const [ tar_url , setTar_url ] = useState(undefined);
|
||||
const [ readOnly , setReadOnly] = useState(true);
|
||||
const [ isSpin , setIsSpin] = useState(true);
|
||||
const [ visible ,setVisible ] = useState(false);
|
||||
const [ mainFlag ,setMainFlag ] = useState(false);
|
||||
const [ openModal , setOpenModal ] = useState(false);
|
||||
const [ desc , setDesc ] = useState(undefined);
|
||||
const [ website , setWebsite ] = useState(undefined);
|
||||
const [ lesson_url , setLessonUrl ] = useState(undefined);
|
||||
const [ readme , setReadme ] = useState(undefined);
|
||||
const [ defaultBranch , setDefaultBranch ] = useState(undefined);
|
||||
const [ editReadme , setEditReadme ] = useState(false);
|
||||
function CoderDepot(props) {
|
||||
const [projectDetail, setProjectDetail] = useState(undefined);
|
||||
const [inviteCode, setInviteCode] = useState(undefined);
|
||||
const [treeValue, setTreeValue] = useState(undefined);
|
||||
const [treeValuePath, setTreeValuePath] = useState(undefined);
|
||||
const [lastCommit, setLastCommit] = useState(undefined);
|
||||
const [lastCommitAuthor, setLastCommitAuthor] = useState(undefined);
|
||||
const [type, setType] = useState('dir');
|
||||
const [hide, setHide] = useState(true);
|
||||
const [hideBtn, setHideBtn] = useState(false);
|
||||
const [commitCount, setCommitCount] = useState(0);
|
||||
const [dirInfo, setDirInfo] = useState(undefined);//文件夹目录列表
|
||||
const [fileInfo, setFileInfo] = useState(undefined);//文件内容信息
|
||||
const [zip_url, setZip_url] = useState(undefined);
|
||||
const [tar_url, setTar_url] = useState(undefined);
|
||||
const [readOnly, setReadOnly] = useState(true);
|
||||
const [isSpin, setIsSpin] = useState(true);
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [mainFlag, setMainFlag] = useState(false);
|
||||
const [openModal, setOpenModal] = useState(false);
|
||||
const [desc, setDesc] = useState(undefined);
|
||||
const [website, setWebsite] = useState(undefined);
|
||||
const [lesson_url, setLessonUrl] = useState(undefined);
|
||||
const [readme, setReadme] = useState(undefined);
|
||||
const [defaultBranch, setDefaultBranch] = useState(undefined);
|
||||
const [editReadme, setEditReadme] = useState(false);
|
||||
const [downLoadType, setDownLoadType] = useState("http");
|
||||
|
||||
const owner = props.match.params.owner;
|
||||
const projectsId = props.match.params.projectsId;
|
||||
|
|
@ -71,8 +72,8 @@ function CoderDepot(props){
|
|||
const details = props.projectDetail;
|
||||
let pathname = props.history.location.pathname;
|
||||
|
||||
useEffect(()=>{
|
||||
if(details){
|
||||
useEffect(() => {
|
||||
if (details) {
|
||||
setProjectDetail(details);
|
||||
setDesc(details.description);
|
||||
setWebsite(details.website);
|
||||
|
|
@ -80,40 +81,40 @@ function CoderDepot(props){
|
|||
setDefaultBranch(details.default_branch);
|
||||
setInviteCode(details.invite_code);
|
||||
}
|
||||
},[details])
|
||||
}, [details])
|
||||
|
||||
useEffect(()=>{
|
||||
if(treeValue){
|
||||
useEffect(() => {
|
||||
if (treeValue) {
|
||||
setTreeValuePath(treeValue.split('/'));
|
||||
}else{
|
||||
} else {
|
||||
setTreeValuePath(undefined);
|
||||
}
|
||||
},[treeValue])
|
||||
}, [treeValue])
|
||||
|
||||
|
||||
useEffect(()=>{
|
||||
if (projectsId && owner && defaultBranch){
|
||||
let b = turnbar(branchName) ;
|
||||
if(pathname.indexOf(`/projects/${owner}/${projectsId}`) > -1 && pathname.indexOf(`/tree/${b}/`) > -1) {
|
||||
useEffect(() => {
|
||||
if (projectsId && owner && defaultBranch) {
|
||||
let b = turnbar(branchName);
|
||||
if (pathname.indexOf(`/projects/${owner}/${projectsId}`) > -1 && pathname.indexOf(`/tree/${b}/`) > -1) {
|
||||
let url = pathname.split(`/tree/${b}/`)[1];
|
||||
setTreeValue(url);
|
||||
getFileInfo(url,branchName);
|
||||
getFileInfo(url, branchName);
|
||||
setType("file");
|
||||
}else{
|
||||
} else {
|
||||
setTreeValue(undefined);
|
||||
getDirInfo(branchName || defaultBranch);
|
||||
setType("dir");
|
||||
}
|
||||
}
|
||||
},[projectsId,owner,pathname,defaultBranch])
|
||||
}
|
||||
}, [projectsId, owner, pathname, defaultBranch])
|
||||
|
||||
// 获取主目录列表
|
||||
function getDirInfo(branch){
|
||||
function getDirInfo(branch) {
|
||||
setIsSpin(true);
|
||||
const url = `/${owner}/${projectsId}/entries.json`;
|
||||
|
||||
axios.get(url, {
|
||||
params: { ref: branch }
|
||||
axios.get(url, {
|
||||
params: { ref: branch }
|
||||
}).then((result) => {
|
||||
if (result) {
|
||||
setCommitCount(result.data.commits_count);
|
||||
|
|
@ -130,38 +131,37 @@ function CoderDepot(props){
|
|||
setEditReadme(false);
|
||||
setHide(true);
|
||||
}
|
||||
setTimeout(function(){setIsSpin(false);},500);
|
||||
}).catch(error=>{setIsSpin(false);})
|
||||
setTimeout(function () { setIsSpin(false); }, 500);
|
||||
}).catch(error => { setIsSpin(false); })
|
||||
}
|
||||
|
||||
useEffect(()=>{
|
||||
if(projectDetail && lastCommit)
|
||||
{
|
||||
useEffect(() => {
|
||||
if (projectDetail && lastCommit) {
|
||||
let ele = document.getElementById("ptxt");
|
||||
if(ele){
|
||||
if (ele) {
|
||||
let h = ele.offsetHeight;
|
||||
if( h > 18 ) setHideBtn(true);
|
||||
if (h > 18) setHideBtn(true);
|
||||
}
|
||||
}
|
||||
},[projectDetail,lastCommit])
|
||||
}, [projectDetail, lastCommit])
|
||||
// 获取子目录列表
|
||||
function getFileInfo(path, ref){
|
||||
function getFileInfo(path, ref) {
|
||||
setIsSpin(true);
|
||||
const url = `/${owner}/${projectsId}/sub_entries.json`;
|
||||
axios.get(url, {
|
||||
params:{
|
||||
filepath:path,
|
||||
ref:ref || branchName,
|
||||
axios.get(url, {
|
||||
params: {
|
||||
filepath: path,
|
||||
ref: ref || branchName,
|
||||
type
|
||||
}
|
||||
}).then((result) => {
|
||||
if (result) {
|
||||
let en = result.data.entries;
|
||||
if(en.type){
|
||||
if (en.type) {
|
||||
setDirInfo(undefined);
|
||||
setFileInfo(en);
|
||||
setType(en.type);
|
||||
}else{
|
||||
} else {
|
||||
setFileInfo(undefined);
|
||||
setDirInfo(en);
|
||||
setType("dir");
|
||||
|
|
@ -173,65 +173,65 @@ function CoderDepot(props){
|
|||
setReadOnly(!editReadme);
|
||||
setHide(true);
|
||||
}
|
||||
setTimeout(function(){setIsSpin(false);},500)
|
||||
}).catch(error=>{setIsSpin(false);})
|
||||
setTimeout(function () { setIsSpin(false); }, 500)
|
||||
}).catch(error => { setIsSpin(false); })
|
||||
}
|
||||
|
||||
// 切换分支或者标签
|
||||
function changeBranch(value){
|
||||
function changeBranch(value) {
|
||||
let checkvalue = turnbar(value);
|
||||
let url = `/projects/${owner}/${projectsId}${value && `/tree/${checkvalue}`}${treeValue ? `/${treeValue}`:""}`;
|
||||
let url = `/projects/${owner}/${projectsId}${value && `/tree/${checkvalue}`}${treeValue ? `/${treeValue}` : ""}`;
|
||||
props.history.push(url);
|
||||
}
|
||||
|
||||
|
||||
// 文件相关的下拉项
|
||||
function fileMenu(){
|
||||
function fileMenu() {
|
||||
let b = branchName || defaultBranch;
|
||||
let checkvalue = turnbar(b);
|
||||
return (
|
||||
<Menu>
|
||||
<Menu.Item><a onClick={()=>urlLink(`/projects/${owner}/${projectsId}/${checkvalue}/uploadfile${treeValue === undefined ? "" : `/${treeValue}`}`)}>上传文件</a></Menu.Item>
|
||||
<Menu.Item><a onClick={()=>urlLink(`/projects/${owner}/${projectsId}/${checkvalue}/newfile${treeValue === undefined ? "" : `/${treeValue}`}`)}>新建文件</a></Menu.Item>
|
||||
</Menu>
|
||||
<Menu>
|
||||
<Menu.Item><a onClick={() => urlLink(`/projects/${owner}/${projectsId}/${checkvalue}/uploadfile${treeValue === undefined ? "" : `/${treeValue}`}`)}>上传文件</a></Menu.Item>
|
||||
<Menu.Item><a onClick={() => urlLink(`/projects/${owner}/${projectsId}/${checkvalue}/newfile${treeValue === undefined ? "" : `/${treeValue}`}`)}>新建文件</a></Menu.Item>
|
||||
</Menu>
|
||||
)
|
||||
}
|
||||
|
||||
function getPathUrl(array,index){
|
||||
if(array && array.length>0 && index){
|
||||
function getPathUrl(array, index) {
|
||||
if (array && array.length > 0 && index) {
|
||||
let str = "";
|
||||
for(let i=0;i<index;i++){
|
||||
for (let i = 0; i < index; i++) {
|
||||
str += `/${array[i]}`;
|
||||
}
|
||||
return str.substr(1);
|
||||
}
|
||||
}
|
||||
// 页面地址返回到主目录
|
||||
function returnMain(){
|
||||
function returnMain() {
|
||||
setTreeValue(undefined);
|
||||
let branch = branchName || defaultBranch;
|
||||
let checkvalue = turnbar(branch);
|
||||
props.history.push(`/projects/${owner}/${projectsId}/tree/${checkvalue}`);
|
||||
};
|
||||
// 子目录路径返回链接
|
||||
function returnUlr(url){
|
||||
function returnUlr(url) {
|
||||
let enBranch = turnbar(branchName);
|
||||
props.history.push(`/projects/${owner}/${projectsId}/tree${enBranch?`/${enBranch}`:""}/${url}`);
|
||||
props.history.push(`/projects/${owner}/${projectsId}/tree${enBranch ? `/${enBranch}` : ""}/${url}`);
|
||||
}
|
||||
// 点击跳转到子目录
|
||||
function goToSubRoot(path,type,filename){
|
||||
if(type!=="submodule"){
|
||||
function goToSubRoot(path, type, filename) {
|
||||
if (type !== "submodule") {
|
||||
let enBranch = branchName || defaultBranch;
|
||||
let checkvalue = turnbar(enBranch);
|
||||
setType(type);
|
||||
props.history.push(`/projects/${owner}/${projectsId}${`/tree/${checkvalue}`}${path?`/${path}`:""}`);
|
||||
props.history.push(`/projects/${owner}/${projectsId}${`/tree/${checkvalue}`}${path ? `/${path}` : ""}`);
|
||||
}
|
||||
}
|
||||
|
||||
function onEdit(readOnly){
|
||||
function onEdit(readOnly) {
|
||||
setReadOnly(readOnly);
|
||||
setEditReadme(false);
|
||||
}
|
||||
function ChangeFile(path, readOnly){
|
||||
function ChangeFile(path, readOnly) {
|
||||
//点击直接跳转页面 加载一次路由
|
||||
let enBranch = branchName || defaultBranch;
|
||||
let checkvalue = turnbar(enBranch);
|
||||
|
|
@ -240,12 +240,12 @@ function CoderDepot(props){
|
|||
setEditReadme(true);
|
||||
};
|
||||
|
||||
function changeHide(hide){
|
||||
function changeHide(hide) {
|
||||
setHide(!hide);
|
||||
}
|
||||
|
||||
function urlLink(link){
|
||||
if(props.checkIfLogin()===false){
|
||||
function urlLink(link) {
|
||||
if (props.checkIfLogin() === false) {
|
||||
props.showLoginDialog()
|
||||
return false;
|
||||
}
|
||||
|
|
@ -253,25 +253,20 @@ function CoderDepot(props){
|
|||
}
|
||||
|
||||
const downloadMenu = (
|
||||
<div className="downMenu">
|
||||
<div style={{padding:"20px",borderBottom:"1px solid #eee"}}>
|
||||
<CloneAddress
|
||||
http_url={projectDetail && projectDetail.clone_url}
|
||||
showNotification={props.showNotification}/>
|
||||
</div>
|
||||
<Menu className="edu-txt-center">
|
||||
<Menu.Item><a href={zip_url}>下载 ZIP</a></Menu.Item>
|
||||
<Menu.Item><a href={tar_url}>下载 TAR.GZ</a></Menu.Item>
|
||||
</Menu>
|
||||
</div>
|
||||
<CloneAddress
|
||||
http_url={projectDetail && projectDetail.clone_url}
|
||||
ssh_url={(projectDetail && props && props.platform) && projectDetail.ssh_url}
|
||||
zip_url={(props && props.platform) && zip_url}
|
||||
tar_url={(props && props.platform) && tar_url}
|
||||
showNotification={props.showNotification} />
|
||||
)
|
||||
// 确认修改简介、website、实践课程链接
|
||||
function okUpdate(d,w,l){
|
||||
function okUpdate(d, w, l) {
|
||||
const url = `/${owner}/${projectsId}.json`;
|
||||
axios.put(url,{
|
||||
description:d,website:w,lesson_url:l
|
||||
}).then(result=>{
|
||||
if(result && result.data && result.data.id){
|
||||
axios.put(url, {
|
||||
description: d, website: w, lesson_url: l
|
||||
}).then(result => {
|
||||
if (result && result.data && result.data.id) {
|
||||
setDesc(result.data.description);
|
||||
setWebsite(result.data.website);
|
||||
setLessonUrl(result.data.lesson_url);
|
||||
|
|
@ -279,35 +274,35 @@ function CoderDepot(props){
|
|||
})
|
||||
}
|
||||
let n = fileInfo && fileInfo.name;
|
||||
const mdFlag = n && n.substring(n.length-3,n.length) === ".md";
|
||||
const mdFlag = n && n.substring(n.length - 3, n.length) === ".md";
|
||||
|
||||
const { current_user } = props;
|
||||
const fileOperate = type === "dir" && projectDetail && projectDetail.type !== 2 && ((projectDetail.permission && projectDetail.permission !=="Reporter") || (current_user && current_user.admin));
|
||||
return(
|
||||
const fileOperate = type === "dir" && projectDetail && projectDetail.type !== 2 && ((projectDetail.permission && projectDetail.permission !== "Reporter") || (current_user && current_user.admin));
|
||||
return (
|
||||
<WhiteBack>
|
||||
<UpdateDescModal desc={desc} website={website} lesson_url={lesson_url} visible={openModal} onCancel={()=>setOpenModal(false)} onOk={okUpdate}/>
|
||||
<UpdateDescModal desc={desc} website={website} lesson_url={lesson_url} visible={openModal} onCancel={() => setOpenModal(false)} onOk={okUpdate} />
|
||||
<Spin spinning={isSpin}>
|
||||
{
|
||||
(dirInfo || fileInfo) &&
|
||||
(dirInfo || fileInfo) &&
|
||||
<React.Fragment>
|
||||
<DrawerPanel
|
||||
history={props.history}
|
||||
owner={owner}
|
||||
projectsId={projectsId}
|
||||
<DrawerPanel
|
||||
history={props.history}
|
||||
owner={owner}
|
||||
projectsId={projectsId}
|
||||
name={projectDetail && projectDetail.name}
|
||||
branch={branchName || defaultBranch}
|
||||
visible={visible}
|
||||
onClose={()=>setVisible(false)}
|
||||
list = {mainFlag ? dirInfo : undefined}
|
||||
branch={branchName || defaultBranch}
|
||||
visible={visible}
|
||||
onClose={() => setVisible(false)}
|
||||
list={mainFlag ? dirInfo : undefined}
|
||||
/>
|
||||
<div className="drawerBtn" onClick={()=>setVisible(true)}>
|
||||
<div className="drawerBtn" onClick={() => setVisible(true)}>
|
||||
<i className="iconfont icon-youjiantou font-16"></i>
|
||||
<span>目录</span>
|
||||
</div>
|
||||
</React.Fragment>
|
||||
}
|
||||
<div style={{minHeight:"500px"}}>
|
||||
{
|
||||
<div style={{ minHeight: "500px" }}>
|
||||
{
|
||||
projectDetail &&
|
||||
<Box className="Panels">
|
||||
<LongWidth>
|
||||
|
|
@ -317,17 +312,17 @@ function CoderDepot(props){
|
|||
<div className="mr20">
|
||||
{
|
||||
props && props.platform ?
|
||||
<SelectBranch
|
||||
repo_id={projectDetail && projectDetail.repo_id}
|
||||
projectsId={projectsId}
|
||||
branch={branchName || defaultBranch}
|
||||
changeBranch={changeBranch}
|
||||
owner={owner}
|
||||
history={props.history}
|
||||
branchList={projectDetail && projectDetail.branches && projectDetail.branches.list}
|
||||
></SelectBranch>
|
||||
:
|
||||
<span>分支:<span className="color-grey-6">{branchName || defaultBranch}</span></span>
|
||||
<SelectBranch
|
||||
repo_id={projectDetail && projectDetail.repo_id}
|
||||
projectsId={projectsId}
|
||||
branch={branchName || defaultBranch}
|
||||
changeBranch={changeBranch}
|
||||
owner={owner}
|
||||
history={props.history}
|
||||
branchList={projectDetail && projectDetail.branches && projectDetail.branches.list}
|
||||
></SelectBranch>
|
||||
:
|
||||
<span>分支:<span className="color-grey-6">{branchName || defaultBranch}</span></span>
|
||||
}
|
||||
</div>
|
||||
<AlignCenter className="mr20">
|
||||
|
|
@ -346,17 +341,17 @@ function CoderDepot(props){
|
|||
<AlignCenter>
|
||||
<div className="mr20 addOptionBtn">
|
||||
{
|
||||
projectDetail.type !== 2 &&
|
||||
<a onClick={()=>urlLink(`/projects/${owner}/${projectsId}/pulls/new`)} >+ 合并请求</a>
|
||||
projectDetail.type !== 2 &&
|
||||
<a onClick={() => urlLink(`/projects/${owner}/${projectsId}/pulls/new`)} >+ 合并请求</a>
|
||||
}
|
||||
<a onClick={()=>urlLink(`/projects/${owner}/${projectsId}/issues/new`)} >+ 任务</a>
|
||||
<a onClick={() => urlLink(`/projects/${owner}/${projectsId}/issues/new`)} >+ 任务</a>
|
||||
</div>
|
||||
{ fileOperate &&
|
||||
{fileOperate &&
|
||||
<Dropdown overlay={fileMenu()} className="mr20" trigger={['click']}>
|
||||
<Button type="default">文件 <i className="iconfont icon-sanjiaoxing-down ml3 font-14 color-grey-9"></i></Button>
|
||||
</Dropdown>
|
||||
}
|
||||
|
||||
|
||||
<Dropdown overlay={downloadMenu} placement="bottomRight" trigger={['click']}>
|
||||
<Button type={'primary'}>下载 <i className="iconfont icon-sanjiaoxing-down ml3 font-14 color-white"></i></Button>
|
||||
</Dropdown>
|
||||
|
|
@ -364,81 +359,81 @@ function CoderDepot(props){
|
|||
</FlexAJ>
|
||||
{
|
||||
dirInfo || fileInfo ?
|
||||
<div className="listtable">
|
||||
{
|
||||
lastCommit &&
|
||||
<div className="listtablehead">
|
||||
<User url={getImageUrl(`/${lastCommitAuthor && lastCommitAuthor.image_url}`)} name={lastCommitAuthor && lastCommitAuthor.name} id={lastCommitAuthor && lastCommitAuthor.id} login={lastCommitAuthor && lastCommitAuthor.login}/>
|
||||
<div className={hideBtn && hide ? "ellipsistxt hidetxt" :"ellipsistxt"}>
|
||||
<pre id="ptxt">{lastCommit && lastCommit.message}</pre>
|
||||
</div>
|
||||
{ hideBtn && <span className="ellipsis" onClick={()=>changeHide(hide)}><i className="iconfont icon-shenglvehao"></i></span> }
|
||||
<div className="listtable">
|
||||
{
|
||||
lastCommit &&
|
||||
<div className="listtablehead">
|
||||
<User url={getImageUrl(`/${lastCommitAuthor && lastCommitAuthor.image_url}`)} name={lastCommitAuthor && lastCommitAuthor.name} id={lastCommitAuthor && lastCommitAuthor.id} login={lastCommitAuthor && lastCommitAuthor.login} />
|
||||
<div className={hideBtn && hide ? "ellipsistxt hidetxt" : "ellipsistxt"}>
|
||||
<pre id="ptxt">{lastCommit && lastCommit.message}</pre>
|
||||
</div>
|
||||
{hideBtn && <span className="ellipsis" onClick={() => changeHide(hide)}><i className="iconfont icon-shenglvehao"></i></span>}
|
||||
|
||||
<span className="ml12 color-grey-9 mt3">{lastCommit && lastCommit.time_from_now}</span>
|
||||
{ commitCount ? <Link to={`/projects/${owner}/${projectsId}/commits`} className="ml12 color-grey-9"><i className="iconfont icon-tijiao mr3 font-17 color-grey-9"></i>{commitCount}次提交</Link>:"" }
|
||||
</div>
|
||||
}
|
||||
<ul className="listtablebody">
|
||||
{
|
||||
treeValuePath && treeValuePath.length > 0 &&
|
||||
<Path
|
||||
identifier={projectDetail && projectDetail.identifier}
|
||||
treeValuePath={treeValuePath}
|
||||
returnUlr={returnUlr}
|
||||
returnMain={returnMain}
|
||||
getPathUrl={getPathUrl}
|
||||
/>
|
||||
<span className="ml12 color-grey-9 mt3">{lastCommit && lastCommit.time_from_now}</span>
|
||||
{commitCount ? <Link to={`/projects/${owner}/${projectsId}/commits`} className="ml12 color-grey-9"><i className="iconfont icon-tijiao mr3 font-17 color-grey-9"></i>{commitCount}次提交</Link> : ""}
|
||||
</div>
|
||||
}
|
||||
{
|
||||
dirInfo && dirInfo.length > 0 &&
|
||||
dirInfo.map((item,key)=>{
|
||||
return(
|
||||
<Catalogue
|
||||
owner={owner}
|
||||
item={item}
|
||||
projectsId={projectsId}
|
||||
goToSubRoot={goToSubRoot}
|
||||
/>
|
||||
)
|
||||
})
|
||||
}
|
||||
{
|
||||
fileInfo &&
|
||||
<CoderRootFileDetail
|
||||
{...props}
|
||||
detail={fileInfo}
|
||||
readOnly={readOnly}
|
||||
md={mdFlag}
|
||||
onEdit={onEdit}
|
||||
currentBranch={branchName || defaultBranch}
|
||||
type={projectDetail.type}
|
||||
></CoderRootFileDetail>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
: ""
|
||||
<ul className="listtablebody">
|
||||
{
|
||||
treeValuePath && treeValuePath.length > 0 &&
|
||||
<Path
|
||||
identifier={projectDetail && projectDetail.identifier}
|
||||
treeValuePath={treeValuePath}
|
||||
returnUlr={returnUlr}
|
||||
returnMain={returnMain}
|
||||
getPathUrl={getPathUrl}
|
||||
/>
|
||||
}
|
||||
{
|
||||
dirInfo && dirInfo.length > 0 &&
|
||||
dirInfo.map((item, key) => {
|
||||
return (
|
||||
<Catalogue
|
||||
owner={owner}
|
||||
item={item}
|
||||
projectsId={projectsId}
|
||||
goToSubRoot={goToSubRoot}
|
||||
/>
|
||||
)
|
||||
})
|
||||
}
|
||||
{
|
||||
fileInfo &&
|
||||
<CoderRootFileDetail
|
||||
{...props}
|
||||
detail={fileInfo}
|
||||
readOnly={readOnly}
|
||||
md={mdFlag}
|
||||
onEdit={onEdit}
|
||||
currentBranch={branchName || defaultBranch}
|
||||
type={projectDetail.type}
|
||||
></CoderRootFileDetail>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
: ""
|
||||
}
|
||||
{
|
||||
(dirInfo && dirInfo.length === 0) && (fileInfo && fileInfo.length === 0) ? <Nodata _html="暂未发现文件"/> :""
|
||||
}
|
||||
(dirInfo && dirInfo.length === 0) && (fileInfo && fileInfo.length === 0) ? <Nodata _html="暂未发现文件" /> : ""
|
||||
}
|
||||
{/* readme文件显示(显示文件详情时不显示readme文件) */}
|
||||
{ dirInfo && (readme && readme.content) ? <ReadMe ChangeFile={ChangeFile} readme={readme} operate={props && (props.isManager || props.isDeveloper) && projectDetail.type !==2 } history={props.history} /> :"" }
|
||||
{dirInfo && (readme && readme.content) ? <ReadMe ChangeFile={ChangeFile} readme={readme} operate={props && (props.isManager || props.isDeveloper) && projectDetail.type !== 2} history={props.history} /> : ""}
|
||||
</div>
|
||||
</LongWidth>
|
||||
{
|
||||
!fileInfo &&
|
||||
!fileInfo &&
|
||||
<ShortWidth>
|
||||
<Gap style={{paddingLeft:"30px"}}>
|
||||
<Gap style={{ paddingLeft: "30px" }}>
|
||||
<div className="panelmenu">
|
||||
<FlexAJ className="font-18 color-grey-6 mb20" style={{lineHeight:"28px"}}>简介
|
||||
{projectDetail.permission && (projectDetail.permission==="Admin" || projectDetail.permission==="Owner") && <i onClick={()=>setOpenModal(true)} className="iconfont icon-anquanshezhi color-grey-9 font-15"></i>}
|
||||
<FlexAJ className="font-18 color-grey-6 mb20" style={{ lineHeight: "28px" }}>简介
|
||||
{projectDetail.permission && (projectDetail.permission === "Admin" || projectDetail.permission === "Owner") && <i onClick={() => setOpenModal(true)} className="iconfont icon-anquanshezhi color-grey-9 font-15"></i>}
|
||||
</FlexAJ>
|
||||
{desc && <p className="font-14 color-grey-9 mb15 task-hide-2" style={{lineHeight:"22px",WebkitLineClamp:"4",textAlign:"justify",wordBreak:"break-all"}}>{desc}</p>}
|
||||
{desc && <p className="font-14 color-grey-9 mb15 task-hide-2" style={{ lineHeight: "22px", WebkitLineClamp: "4", textAlign: "justify", wordBreak: "break-all" }}>{desc}</p>}
|
||||
{
|
||||
website &&
|
||||
<p className="color-grey-6 df">
|
||||
<i className="iconfont icon-lianjie2 font-15 mr10 color-grey-9"></i>
|
||||
<a href={website} target="_blank" style={{wordBreak:"break-all",lineHeight:"20px",marginTop:"5px",textDecoration:"underline"}}>{website}</a>
|
||||
<a href={website} target="_blank" style={{ wordBreak: "break-all", lineHeight: "20px", marginTop: "5px", textDecoration: "underline" }}>{website}</a>
|
||||
</p>
|
||||
}
|
||||
<p>
|
||||
|
|
@ -458,10 +453,10 @@ function CoderDepot(props){
|
|||
}
|
||||
</div>
|
||||
{
|
||||
inviteCode &&
|
||||
inviteCode &&
|
||||
<div>
|
||||
<Divider />
|
||||
<Invite code={inviteCode} className={"detailsCode"}/>
|
||||
<Invite code={inviteCode} className={"detailsCode"} />
|
||||
</div>
|
||||
}
|
||||
{
|
||||
|
|
@ -469,7 +464,7 @@ function CoderDepot(props){
|
|||
<div>
|
||||
<Divider />
|
||||
<p className="font-16 color-grey-6">实践课程</p>
|
||||
<a href={lesson_url} target="_blank" className="color-grey-6" style={{textDecoration:"underline"}}>{lesson_url}</a>
|
||||
<a href={lesson_url} target="_blank" className="color-grey-6" style={{ textDecoration: "underline" }}>{lesson_url}</a>
|
||||
</div>
|
||||
}
|
||||
{/* 发布 */}
|
||||
|
|
@ -477,7 +472,7 @@ function CoderDepot(props){
|
|||
projectDetail && projectDetail.release_versions &&
|
||||
<React.Fragment>
|
||||
<Divider />
|
||||
<Releases owner={owner} projectsId={projectsId} releaseVersions={projectDetail.release_versions} history={props.history}/>
|
||||
<Releases owner={owner} projectsId={projectsId} releaseVersions={projectDetail.release_versions} history={props.history} />
|
||||
</React.Fragment>
|
||||
}
|
||||
{/* 贡献者 */}
|
||||
|
|
@ -486,10 +481,10 @@ function CoderDepot(props){
|
|||
<Contributors contributors={projectDetail && projectDetail.contributors} owner={owner} projectsId={projectsId} />
|
||||
}
|
||||
{/* 语言 */}
|
||||
{ projectDetail && projectDetail.languages &&
|
||||
{projectDetail && projectDetail.languages &&
|
||||
<React.Fragment>
|
||||
<Divider />
|
||||
<LanguagePower languages={projectDetail.languages}/>
|
||||
<LanguagePower languages={projectDetail.languages} />
|
||||
</React.Fragment>
|
||||
}
|
||||
</Gap>
|
||||
|
|
|
|||
|
|
@ -1,46 +1,53 @@
|
|||
/* recommandProjects */
|
||||
.recommandProjects{
|
||||
.recommandProjects {
|
||||
display: flex;
|
||||
max-width: 1200px;
|
||||
margin:20px auto;
|
||||
margin: 20px auto;
|
||||
}
|
||||
.recommandProjects >div{
|
||||
|
||||
.recommandProjects>div {
|
||||
background-color: #fff;
|
||||
border-radius: 10px;
|
||||
width: 220px;
|
||||
margin-right: 25px;
|
||||
cursor: pointer;
|
||||
border: 1px solid #eee;
|
||||
&:last-child{
|
||||
|
||||
&:last-child {
|
||||
margin-right: 0px;
|
||||
}
|
||||
}
|
||||
.recommandProjects > div:hover{
|
||||
|
||||
.recommandProjects>div:hover {
|
||||
box-shadow: 0px 2px 20px 0px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
.recommandProjects > div .mainInfo{
|
||||
|
||||
.recommandProjects>div .mainInfo {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 160px;
|
||||
border-bottom: 1px solid #eee;
|
||||
padding:20px;
|
||||
padding: 20px;
|
||||
box-sizing: border-box;
|
||||
img{
|
||||
|
||||
img {
|
||||
height: 50px;
|
||||
width:50px;
|
||||
width: 50px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.name{
|
||||
|
||||
.name {
|
||||
font-size: 13px;
|
||||
color: #666;
|
||||
height: 18px;
|
||||
line-height: 18px;
|
||||
margin-top:12px;
|
||||
margin-top: 12px;
|
||||
}
|
||||
.school{
|
||||
margin-top:12px;
|
||||
|
||||
.school {
|
||||
margin-top: 12px;
|
||||
color: #333;
|
||||
font-size: 16px;
|
||||
height: 22px;
|
||||
|
|
@ -48,24 +55,28 @@
|
|||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
max-width:100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
}
|
||||
.recommandProjects{
|
||||
.baseInfo{
|
||||
padding:18px 15px;
|
||||
|
||||
.recommandProjects {
|
||||
.baseInfo {
|
||||
padding: 18px 15px;
|
||||
display: flex;
|
||||
font-size: 12px;
|
||||
color:#888;
|
||||
.look{
|
||||
i{
|
||||
color: #888;
|
||||
|
||||
.look {
|
||||
i {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
margin-right: 10px;
|
||||
}
|
||||
.type{
|
||||
flex:1;
|
||||
width:0;
|
||||
|
||||
.type {
|
||||
flex: 1;
|
||||
width: 0;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
|
|
@ -73,268 +84,323 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// coderDepot
|
||||
.Panels{
|
||||
.Panels {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
.panelmenu{
|
||||
padding-top:30px;
|
||||
|
||||
.panelmenu {
|
||||
padding-top: 30px;
|
||||
}
|
||||
.addOptionBtn{
|
||||
|
||||
.addOptionBtn {
|
||||
height: 32px;
|
||||
line-height: 30px;
|
||||
display: flex;
|
||||
border:1px solid #d9d9d9;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 2px;
|
||||
a{
|
||||
padding:0px 13px;
|
||||
|
||||
a {
|
||||
padding: 0px 13px;
|
||||
color: rgba(0, 0, 0, 0.65);
|
||||
cursor: pointer;
|
||||
}
|
||||
& > a:first-child{
|
||||
|
||||
&>a:first-child {
|
||||
border-right: 1px solid #d9d9d9;
|
||||
}
|
||||
}
|
||||
.infoCount{
|
||||
|
||||
.infoCount {
|
||||
display: inline-block;
|
||||
padding:0px 5px;
|
||||
padding: 0px 5px;
|
||||
height: 16px;
|
||||
line-height: 16px;
|
||||
background-color: #eee;
|
||||
color:#999;
|
||||
color: #999;
|
||||
border-radius: 12px;
|
||||
margin-left: 10px;
|
||||
font-size: 12px;
|
||||
}
|
||||
.attrPerson{
|
||||
|
||||
.attrPerson {
|
||||
padding-top: 15px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
a{
|
||||
|
||||
a {
|
||||
margin: 10px 10px 0px 0px;
|
||||
img{
|
||||
|
||||
img {
|
||||
border-radius: 50%;
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
}
|
||||
&:nth-child(6){
|
||||
|
||||
&:nth-child(6) {
|
||||
margin-right: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.progress{
|
||||
|
||||
.progress {
|
||||
display: flex;
|
||||
border-radius: 10px;
|
||||
height: 7px;
|
||||
margin-top: 12px;
|
||||
span{
|
||||
&:first-child{
|
||||
|
||||
span {
|
||||
&:first-child {
|
||||
border-radius: 10px 0px 0px 10px;
|
||||
}
|
||||
&:last-child{
|
||||
|
||||
&:last-child {
|
||||
border-radius: 0px 10px 10px 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.progresstip{
|
||||
|
||||
.progresstip {
|
||||
margin-top: 15px;
|
||||
flex-wrap: wrap;
|
||||
i.zero{
|
||||
|
||||
i.zero {
|
||||
position: absolute;
|
||||
display: block;
|
||||
border-radius: 50%;
|
||||
height: 8px;
|
||||
width: 8px;
|
||||
left: 0px;
|
||||
top:10px
|
||||
top: 10px
|
||||
}
|
||||
&>span{
|
||||
|
||||
&>span {
|
||||
padding-left: 15px;
|
||||
position: relative;
|
||||
min-width: 33.5%;
|
||||
span{
|
||||
|
||||
span {
|
||||
color: #666;
|
||||
&:last-child{
|
||||
|
||||
&:last-child {
|
||||
color: #999;
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.listtable{
|
||||
|
||||
.listtable {
|
||||
margin-top: 20px;
|
||||
border:1px solid #d9d9d9;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 4px;
|
||||
.listtablehead{
|
||||
|
||||
.listtablehead {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
border-bottom: 1px solid #d9d9d9;
|
||||
padding:7px 20px;
|
||||
padding: 7px 20px;
|
||||
border-radius: 4px 4px 0px 0px;
|
||||
background-color: #FAFBFC;
|
||||
.ellipsistxt{
|
||||
|
||||
.ellipsistxt {
|
||||
margin-top: 6px;
|
||||
#ptxt{
|
||||
|
||||
#ptxt {
|
||||
margin-bottom: 0px;
|
||||
word-break: break-all;
|
||||
overflow: unset;
|
||||
white-space:pre-wrap; /* css3.0 */
|
||||
white-space:-moz-pre-wrap; /* Firefox */
|
||||
white-space:-pre-wrap; /* Opera 4-6 */
|
||||
white-space:-o-pre-wrap; /* Opera 7 */
|
||||
word-wrap:break-word;
|
||||
white-space: pre-wrap;
|
||||
/* css3.0 */
|
||||
white-space: -moz-pre-wrap;
|
||||
/* Firefox */
|
||||
white-space: -pre-wrap;
|
||||
/* Opera 4-6 */
|
||||
white-space: -o-pre-wrap;
|
||||
/* Opera 7 */
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
margin-left: 13px;
|
||||
line-height:18px;
|
||||
flex:1;
|
||||
width: 0;
|
||||
color: #666;
|
||||
&.hidetxt{
|
||||
|
||||
&.hidetxt {
|
||||
height: 18px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
padding-right:8px;
|
||||
&::after{
|
||||
padding-right: 8px;
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
content:"...";
|
||||
content: "...";
|
||||
}
|
||||
}
|
||||
}
|
||||
.ellipsis{
|
||||
|
||||
.ellipsis {
|
||||
margin-left: 8px;
|
||||
cursor: pointer;
|
||||
border-radius: 2px;
|
||||
background-color: #c1c1c1;
|
||||
padding:0px 4px;
|
||||
padding: 0px 4px;
|
||||
height: 14px;
|
||||
line-height: 14px;
|
||||
margin-top: 9px;
|
||||
i{
|
||||
font-size: 15px!important;
|
||||
|
||||
i {
|
||||
font-size: 15px !important;
|
||||
color: #fff;
|
||||
height: 14px;
|
||||
line-height: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.listtablebody{
|
||||
li.listtablepath{
|
||||
a{color: #40a9ff;}
|
||||
p{
|
||||
margin-bottom: 0px!important;
|
||||
|
||||
.listtablebody {
|
||||
li.listtablepath {
|
||||
a {
|
||||
color: #40a9ff;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 0px !important;
|
||||
}
|
||||
}
|
||||
& > li{
|
||||
|
||||
&>li {
|
||||
height: 42px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid #d9d9d9;
|
||||
padding:0px 20px 0px 24px;
|
||||
& > span:first-child{
|
||||
padding: 0px 20px 0px 24px;
|
||||
|
||||
&>span:first-child {
|
||||
width: 30%;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
& > span:nth-child(2){
|
||||
|
||||
&>span:nth-child(2) {
|
||||
width: 60%;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
& > span:nth-child(3){
|
||||
|
||||
&>span:nth-child(3) {
|
||||
width: 10%;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
&> li:last-child{
|
||||
|
||||
&>li:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.drawerBtn{
|
||||
|
||||
.drawerBtn {
|
||||
position: fixed;
|
||||
left: -13px;
|
||||
border:1px solid rgb(207,205,223);
|
||||
border: 1px solid rgb(207, 205, 223);
|
||||
width: 34px;
|
||||
border-radius: 0px 12px 12px 0px;
|
||||
height: 70px;
|
||||
top:50%;
|
||||
top: 50%;
|
||||
margin-top: -35px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
justify-content: center;
|
||||
&:hover{
|
||||
box-shadow: 1px 0px 7px rgba(0,0,0,0.1);
|
||||
|
||||
&:hover {
|
||||
box-shadow: 1px 0px 7px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
span{
|
||||
|
||||
span {
|
||||
writing-mode: vertical-lr;
|
||||
color: #202429;
|
||||
width: 25px;
|
||||
}
|
||||
i{
|
||||
|
||||
i {
|
||||
color: #24292e;
|
||||
height: 18px;
|
||||
line-height: 18px;
|
||||
width: 18px;
|
||||
}
|
||||
}
|
||||
.downMenu{
|
||||
box-shadow: 0px 0px 9px rgba(134, 134, 134,0.4);
|
||||
|
||||
.downMenu {
|
||||
width: 329px;
|
||||
box-shadow: 0px 0px 9px rgba(134, 134, 134, 0.4);
|
||||
background-color: #fff;
|
||||
.ant-menu-vertical .ant-menu-item:hover{
|
||||
|
||||
.ant-menu-vertical .ant-menu-item:hover {
|
||||
background-color: #e6f7ff;
|
||||
}
|
||||
}
|
||||
|
||||
.menuslist{
|
||||
.menuslist {
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
padding:10px 15px;
|
||||
padding: 10px 15px;
|
||||
border-radius: 4px;
|
||||
.ant-dropdown-menu-item{
|
||||
|
||||
.ant-dropdown-menu-item {
|
||||
border-radius: 8px;
|
||||
text-align: left!important;
|
||||
a{
|
||||
text-align: left !important;
|
||||
|
||||
a {
|
||||
width: 350px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
.ant-dropdown-menu-item.active{
|
||||
|
||||
.ant-dropdown-menu-item.active {
|
||||
background-color: #e6f7ff;
|
||||
}
|
||||
}
|
||||
.catelogue{
|
||||
border:1px solid rgb(211, 211, 211);
|
||||
|
||||
.catelogue {
|
||||
border: 1px solid rgb(211, 211, 211);
|
||||
font-size: 15px;
|
||||
font-weight: normal;
|
||||
border-radius: 5px;
|
||||
margin-right: 10px;
|
||||
padding:0px 10px;
|
||||
padding: 0px 10px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
color: #666!important;
|
||||
color: #666 !important;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
span{
|
||||
|
||||
span {
|
||||
margin-top: 1px;
|
||||
}
|
||||
}
|
||||
.submoduleStyle{
|
||||
|
||||
.submoduleStyle {
|
||||
cursor: default;
|
||||
i{
|
||||
|
||||
i {
|
||||
cursor: default;
|
||||
}
|
||||
&:hover{
|
||||
|
||||
&:hover {
|
||||
color: #05101a;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -7,7 +7,7 @@ import "./setting.scss";
|
|||
import Loadable from "react-loadable";
|
||||
import Loading from "../../Loading";
|
||||
import { Box, Long, Short, Gap } from '../Component/layout';
|
||||
import {Badge} from 'antd'
|
||||
import { Badge } from 'antd'
|
||||
|
||||
const BranchNew = Loadable({
|
||||
loader: () => import("./BranchRule"),
|
||||
|
|
@ -25,6 +25,14 @@ const Setting = Loadable({
|
|||
loader: () => import("./Setting"),
|
||||
loading: Loading,
|
||||
});
|
||||
const WebhookNew = Loadable({
|
||||
loader: () => import("./Webhooks/New"),
|
||||
loading: Loading,
|
||||
});
|
||||
const Webhook = Loadable({
|
||||
loader: () => import("./Webhooks/Index"),
|
||||
loading: Loading,
|
||||
});
|
||||
const Collaborator = Loadable({
|
||||
loader: () => import("./Collaborator"),
|
||||
loading: Loading,
|
||||
|
|
@ -43,7 +51,7 @@ const ManageNew = Loadable({
|
|||
});
|
||||
class Index extends Component {
|
||||
render() {
|
||||
const { projectsId , owner } = this.props.match.params;
|
||||
const { projectsId, owner } = this.props.match.params;
|
||||
const { pathname } = this.props.history.location;
|
||||
|
||||
const flag = pathname === `/projects/${owner}/${projectsId}/setting`;
|
||||
|
|
@ -70,6 +78,18 @@ class Index extends Component {
|
|||
</Link>
|
||||
</p>
|
||||
</li>
|
||||
<li
|
||||
className={
|
||||
pathname.indexOf("setting/webhooks") > -1 ? "active" : ""
|
||||
}
|
||||
>
|
||||
<p>
|
||||
<Link to={`/projects/${owner}/${projectsId}/setting/webhooks`} className="w-100">
|
||||
<i className="iconfont icon-a-xuanzhongwebhookicon font-18 mr10 color-grey-9"></i>
|
||||
网络钩子
|
||||
</Link>
|
||||
</p>
|
||||
</li>
|
||||
<li
|
||||
className={
|
||||
pathname.indexOf("setting/audit") > -1 ? "active" : ""
|
||||
|
|
@ -77,8 +97,8 @@ class Index extends Component {
|
|||
>
|
||||
<p>
|
||||
<Link to={`/projects/${owner}/${projectsId}/setting/audit`} className="w-100">
|
||||
<i className="iconfont icon-zhongqingdianxinicon10 font-18 mr10"></i>
|
||||
{(this.props.projectDetail && this.props.projectDetail.pending_verify_count) ? <Badge dot offset={[6,-2]}><span style={{color:'#05101a',fontSize:'16px'}}>审核管理</span></Badge> : '审核管理'}
|
||||
<i className="iconfont icon-zhongqingdianxinicon10 font-18 mr10"></i>
|
||||
{(this.props.projectDetail && this.props.projectDetail.pending_verify_count) ? <Badge dot offset={[6, -2]}><span style={{ color: '#05101a', fontSize: '16px' }}>审核管理</span></Badge> : '审核管理'}
|
||||
</Link>
|
||||
</p>
|
||||
</li>
|
||||
|
|
@ -89,7 +109,7 @@ class Index extends Component {
|
|||
>
|
||||
<p>
|
||||
<Link to={`/projects/${owner}/${projectsId}/setting/branch`} className="w-100">
|
||||
<i className="iconfont icon-fenzhi font-20 mr10"></i>
|
||||
<i className="iconfont icon-fenzhi font-20 mr10"></i>
|
||||
分支设置
|
||||
</Link>
|
||||
</p>
|
||||
|
|
@ -122,6 +142,25 @@ class Index extends Component {
|
|||
<Long>
|
||||
<Gap className="list-r-Info">
|
||||
<Switch {...this.props}>
|
||||
{/* webhooks */}
|
||||
<Route
|
||||
path="/projects/:owner/:projectsId/setting/webhooks/new"
|
||||
render={(props) => (
|
||||
<WebhookNew {...this.props} {...props} {...this.state} />
|
||||
)}
|
||||
></Route>
|
||||
<Route
|
||||
path="/projects/:owner/:projectsId/setting/webhooks/:id"
|
||||
render={(props) => (
|
||||
<WebhookNew {...this.props} {...props} {...this.state} />
|
||||
)}
|
||||
></Route>
|
||||
<Route
|
||||
path="/projects/:owner/:projectsId/setting/webhooks"
|
||||
render={(props) => (
|
||||
<Webhook {...this.props} {...props} {...this.state} />
|
||||
)}
|
||||
></Route>
|
||||
{/* 协作者 */}
|
||||
<Route
|
||||
path="/projects/:owner/:projectsId/setting/collaborator"
|
||||
|
|
@ -151,7 +190,7 @@ class Index extends Component {
|
|||
<Route
|
||||
path="/projects/:owner/:projectsId/setting/branch"
|
||||
render={(props) => (
|
||||
<Branch {...this.props} {...props } {...this.state} />
|
||||
<Branch {...this.props} {...props} {...this.state} />
|
||||
)}
|
||||
></Route>
|
||||
<Route
|
||||
|
|
|
|||
|
|
@ -0,0 +1,111 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { Banner, FlexAJ } from '../../Component/layout';
|
||||
import DeleteBox from '../../Component/DeleteModal/Index';
|
||||
import './Index.scss';
|
||||
import { Button, List, Pagination } from 'antd';
|
||||
import { Link } from 'react-router-dom';
|
||||
import axios from 'axios';
|
||||
|
||||
const limit = 15;
|
||||
function Index(props) {
|
||||
const [data, setData] = useState(undefined);
|
||||
const [page, setPage] = useState(1);
|
||||
const [total, setTotal] = useState(1);
|
||||
const [deleteId, setDeleteId] = useState(undefined);
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [url, setUrl] = useState(undefined);
|
||||
|
||||
const { owner, projectsId } = props.match.params;
|
||||
|
||||
useEffect(() => {
|
||||
if (owner && projectsId) {
|
||||
getData();
|
||||
}
|
||||
}, [owner, projectsId, page])
|
||||
|
||||
function getData() {
|
||||
const url = `/${owner}/${projectsId}/webhooks.json`;
|
||||
axios.get(url, {
|
||||
params: { page, limit }
|
||||
}).then(result => {
|
||||
if (result && result.data) {
|
||||
setData(result.data.webhooks);
|
||||
setTotal(result.data.total_count);
|
||||
}
|
||||
}).catch(error => { })
|
||||
}
|
||||
|
||||
function deleteFunc(id, url) {
|
||||
setDeleteId(id);
|
||||
setUrl(url);
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
function onSuccess() {
|
||||
if (deleteId) {
|
||||
const url = `/${owner}/${projectsId}/webhooks/${deleteId}.json`;
|
||||
axios.delete(url).then(result => {
|
||||
if (result) {
|
||||
props.showNotification("webhook删除成功!");
|
||||
if (page > 1 && data.length === 1) {
|
||||
setPage(page - 1);
|
||||
} else {
|
||||
getData();
|
||||
}
|
||||
setVisible(false);
|
||||
}
|
||||
}).catch(error => { })
|
||||
}
|
||||
}
|
||||
|
||||
function addFunc() {
|
||||
if (total >= 50) {
|
||||
return props.showNotification("webhooks数量已到上限!请删除暂不使用的webhooks以进行添加操作");
|
||||
}
|
||||
props.history.push(`/projects/${owner}/${projectsId}/setting/webhooks/new`)
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<DeleteBox
|
||||
visible={visible}
|
||||
onCancel={() => setVisible(false)}
|
||||
onSuccess={onSuccess}
|
||||
title="删除Webhook"
|
||||
content="您确定要删除此Webhook吗?"
|
||||
subTitle={`删除后未来事件将不会推送至此Webhook地址:${url}`}
|
||||
/>
|
||||
<Banner>
|
||||
<span>Webhooks(网络钩子)</span>
|
||||
<Button type="primary" size="large" onClick={addFunc}>添加Webhook</Button>
|
||||
</Banner>
|
||||
<div className="hookpanel">
|
||||
<p className="color-grey-3">每当特定事件(如push代码,合并请求被编辑)发生时,我们将通过webhook给您提供的远程URL发送post请求。您可以在我们的<a className="color-blue hoverLine" target="_blank" href="https://forum.trustie.net/forums/3408/detail">webhooks指南</a>中了解更多信息</p>
|
||||
{
|
||||
data && data.length > 0 &&
|
||||
<List>
|
||||
{data.map((i, k) => {
|
||||
return (
|
||||
<List.Item key={k}>
|
||||
<i className="iconfont icon-a-xuanzhongwebhookicon color-grey-d mr12 font-17"></i>
|
||||
<Link to={`/${owner}/${projectsId}/settings/webhooks/${i.id}`} className="webName">{i.url}</Link>
|
||||
<span>
|
||||
<Button ghost type={"primary"} onClick={() => { props.history.push(`/projects/${owner}/${projectsId}/settings/webhooks/${i.id}`) }}>编辑</Button>
|
||||
<Button ghost className="ml20" type="danger" onClick={() => { deleteFunc(i.id, i.url) }}>删除</Button>
|
||||
</span>
|
||||
</List.Item>
|
||||
)
|
||||
})}
|
||||
</List>
|
||||
}
|
||||
{
|
||||
total > limit &&
|
||||
<div className="edu-txt-center mt20 mb20">
|
||||
<Pagination current={page} total={total} onChange={e => { setPage(e) }} pageSize={limit} />
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default Index;
|
||||
|
|
@ -0,0 +1,171 @@
|
|||
.hookpanel{
|
||||
&>p{
|
||||
padding:20px 25px 0px 20px;
|
||||
}
|
||||
.ant-list{
|
||||
.ant-list-item{
|
||||
padding:15px 20px;
|
||||
&:last-child{
|
||||
border-bottom: 1px solid #e8e8e8;
|
||||
}
|
||||
.webName{
|
||||
flex:1;
|
||||
margin-right: 15px;
|
||||
word-break: break-all;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.newPanel{
|
||||
.ant-form .ant-form-item-label label{
|
||||
font-size: 16px;
|
||||
}
|
||||
.has-success .ant-form-explain{
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
line-height: 20px;
|
||||
margin-top: 5px;
|
||||
word-break: break-all;
|
||||
}
|
||||
.ant-form{
|
||||
.ant-row{
|
||||
padding:0px 194px 0px 20px;
|
||||
&.topLine{
|
||||
border-top: 1px solid #EEEEEE;
|
||||
padding-top:20px;
|
||||
margin-top: 25px;
|
||||
}
|
||||
&.bottomLine{
|
||||
border-bottom: 1px solid #EEEEEE;
|
||||
padding-bottom:20px;
|
||||
margin-bottom: 25px;
|
||||
.ant-checkbox + span{
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.eventCb{
|
||||
padding:0px 194px 0px 45px;
|
||||
.ant-checkbox-group{
|
||||
width: 100%;
|
||||
}
|
||||
.colSpan{
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
&>span{
|
||||
width: 50%;
|
||||
margin:0px;
|
||||
display: block;
|
||||
&>span{
|
||||
display: block;
|
||||
padding-left: 24px;
|
||||
margin-bottom: 20px;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.ant-form-item-children{
|
||||
display: block;
|
||||
}
|
||||
.ant-checkbox + span{
|
||||
color: #333;
|
||||
&>span{
|
||||
color: #333333;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
padding-left: 24px;
|
||||
font-size: 12px;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
.deschead{
|
||||
background: #FAFCFF;
|
||||
border-radius: 4px 4px 0px 0px;
|
||||
border: 1px solid rgba(42, 97, 255, 0.23);
|
||||
height: 50px;
|
||||
padding:0px 20px;
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.deschead.mg{
|
||||
margin:20px!important;
|
||||
padding:0px 12px;
|
||||
}
|
||||
.historyColl{
|
||||
.ant-collapse-header{
|
||||
background-color: #fff;
|
||||
}
|
||||
.panelHeader{
|
||||
display: flex;
|
||||
span{
|
||||
width: 20%;
|
||||
color: #333;
|
||||
font-weight: 400;
|
||||
}
|
||||
.time{
|
||||
text-align: right;
|
||||
}
|
||||
.name{
|
||||
flex:1;
|
||||
}
|
||||
}
|
||||
.ant-collapse-content-box{
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
.contentMenu{
|
||||
li{
|
||||
font-weight: 500;
|
||||
}
|
||||
margin-left:14px;
|
||||
}
|
||||
.contentPanel{
|
||||
.retitle{
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
margin:20px 0px 10px!important;
|
||||
}
|
||||
.con{
|
||||
background: #EEEEEE;
|
||||
border-radius: 4px;
|
||||
padding:15px;
|
||||
max-height: 400px;
|
||||
overflow: auto;
|
||||
p{
|
||||
font-size: 13px;
|
||||
color:#333;
|
||||
line-height: 28px;
|
||||
&>span:first-child{
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
.conEditor{
|
||||
.overflow-guard{
|
||||
border-radius: 4px;
|
||||
}
|
||||
.margin-view-overlays{
|
||||
background-color: #eee;
|
||||
&>div{
|
||||
background-color: #eee;
|
||||
}
|
||||
}
|
||||
.lines-content{
|
||||
background-color: #eee;
|
||||
}
|
||||
.view-lines{
|
||||
&>div{
|
||||
background-color: #eee;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,339 @@
|
|||
import React, { forwardRef, useEffect, useState } from 'react';
|
||||
import { Form, Input, Button, Select, Radio, Checkbox } from 'antd';
|
||||
import { Banner } from '../../Component/layout';
|
||||
import { Link } from 'react-router-dom';
|
||||
import axios from 'axios';
|
||||
import PushHistory from './sub/PushHistory';
|
||||
import DeleteBox from '../../Component/DeleteModal/Index';
|
||||
import './Index.scss';
|
||||
|
||||
// ,"issue_assign","issue_label","issue_milestone","issue_comment","issue_only","fork",
|
||||
//"pull_request_milestone","pull_request_sync","pull_request_comment","repository","pull_request_label"
|
||||
const eventArray = [
|
||||
"create", "delete", "push", "pull_request_assign", "pull_request_review", "pull_request_only"
|
||||
]
|
||||
function New({ form, match, showNotification, history }) {
|
||||
const [httpValue, setHttpValue] = useState("POST");
|
||||
const [posthttpValue, setPostHttpValue] = useState("json");
|
||||
const [condition, setCondition] = useState("push");
|
||||
const [event, setEvent] = useState(["push"]);
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [data, setData] = useState(undefined);
|
||||
const [eventFlag, setEventFlag] = useState(false);
|
||||
|
||||
const { getFieldDecorator, validateFields, setFieldsValue } = form;
|
||||
const { id, owner, projectsId } = match.params;
|
||||
|
||||
function compareArray(params) {
|
||||
if (params && params.length > 0) {
|
||||
if (params.length === 1 && params[0] === "push") {
|
||||
setEvent(['push']);
|
||||
return "push";
|
||||
} else if (params.length === eventArray.length) {
|
||||
setEvent(eventArray);
|
||||
return "all";
|
||||
} else {
|
||||
setEvent([]);
|
||||
return "forevent";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (id) {
|
||||
Init();
|
||||
} else {
|
||||
let e = compareArray(event);
|
||||
setCondition(e);
|
||||
setFieldsValue({
|
||||
url: "",
|
||||
secret: "",
|
||||
http_method: httpValue,
|
||||
content_type: posthttpValue,
|
||||
eventCondition: condition,
|
||||
event: event,
|
||||
branch_filter: "*",
|
||||
active: true
|
||||
})
|
||||
}
|
||||
}, [id])
|
||||
|
||||
function Init() {
|
||||
const url = `/${owner}/${projectsId}/webhooks/${id}/edit.json`;
|
||||
axios.get(url).then(result => {
|
||||
if (result) {
|
||||
let e = compareArray(result.data.events);
|
||||
setFieldsValue({
|
||||
...result.data,
|
||||
eventCondition: e,
|
||||
active: result.data.is_active
|
||||
})
|
||||
setData(result.data);
|
||||
setHttpValue(result.data.http_method);
|
||||
setCondition(e);
|
||||
setEvent(result.data.events);
|
||||
}
|
||||
}).catch(error => { })
|
||||
}
|
||||
|
||||
function changeHTTP(value) {
|
||||
setHttpValue(value);
|
||||
}
|
||||
|
||||
function changeCondition(e) {
|
||||
setCondition(e.target.value);
|
||||
if (e.target.value === "push") {
|
||||
setEvent(["push"])
|
||||
} else if (e.target.value === "all") {
|
||||
setEvent(eventArray)
|
||||
} else {
|
||||
setEvent([])
|
||||
}
|
||||
}
|
||||
|
||||
function submit() {
|
||||
validateFields((error, values) => {
|
||||
if (!error) {
|
||||
if (values.eventCondition === "forevent" && event.length === 0) {
|
||||
setEventFlag(true);
|
||||
return;
|
||||
}
|
||||
let e = values.eventCondition === "push" ? ['push'] : values.eventCondition === "all" ? eventArray : event;
|
||||
|
||||
if (id) {
|
||||
// 编辑
|
||||
const url = `/${owner}/${projectsId}/webhooks/${id}.json`;
|
||||
axios.patch(url, {
|
||||
webhook: {
|
||||
...values,
|
||||
events: e
|
||||
}
|
||||
}).then(result => {
|
||||
if (result) {
|
||||
showNotification("webhook更新成功!");
|
||||
history.push(`/projects/${owner}/${projectsId}/setting/webhooks`);
|
||||
}
|
||||
}).catch(error => { })
|
||||
} else {
|
||||
// 保存
|
||||
const url = `/${owner}/${projectsId}/webhooks.json`;
|
||||
axios.post(url, {
|
||||
webhook: {
|
||||
...values,
|
||||
events: e
|
||||
}
|
||||
}).then(result => {
|
||||
if (result && result.data && result.data.id) {
|
||||
showNotification("webhook新建成功!");
|
||||
history.push(`/projects/${owner}/${projectsId}/setting/webhooks`);
|
||||
}
|
||||
}).catch(error => { })
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function checkAddr(rule, value, callback) {
|
||||
let reg = /(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?/;
|
||||
if (!value) {
|
||||
callback();
|
||||
}
|
||||
if (!reg.test(value)) {
|
||||
callback("请输入有效的URL");
|
||||
}
|
||||
callback();
|
||||
}
|
||||
|
||||
function deleteFunc() {
|
||||
if (id) {
|
||||
setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
function onSuccess() {
|
||||
if (id) {
|
||||
const url = `/${owner}/${projectsId}/webhooks/${id}.json`;
|
||||
axios.delete(url).then(result => {
|
||||
if (result) {
|
||||
showNotification("webhook删除成功!");
|
||||
history.push(`/projects/${owner}/${projectsId}/setting/webhooks`);
|
||||
}
|
||||
}).catch(error => { })
|
||||
}
|
||||
}
|
||||
|
||||
const radioStyle = {
|
||||
display: 'block',
|
||||
height: '30px',
|
||||
lineHeight: '30px',
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="newPanel">
|
||||
<DeleteBox
|
||||
visible={visible}
|
||||
onCancel={() => setVisible(false)}
|
||||
onSuccess={onSuccess}
|
||||
title="删除Webhook"
|
||||
content="您确定要删除此Webhook吗?"
|
||||
subTitle={`${data && data.url}`}
|
||||
/>
|
||||
<Banner>
|
||||
<span>
|
||||
<Link to={`/${owner}/${projectsId}/settings/webhooks`} className="color-blue">Webhooks</Link>
|
||||
<i className="iconfont icon-youjiantou ml5 mr5 font-12"></i>
|
||||
<span>{id ? "更新" : "添加"}Webhook</span>
|
||||
</span>
|
||||
</Banner>
|
||||
<div>
|
||||
<p className="deschead mg"><span>当webhook被触发时,我们将向以下URL发送通知,包括已选择事件的详细信息。更多信息可查阅<a className="color-blue hoverLine" target="_blank" href="https://forum.trustie.net/forums/3408/detail">webhooks指南</a>。</span></p>
|
||||
<Form>
|
||||
<input type="password" style={{ display: "none" }} />
|
||||
<Form.Item label="目标URL" colon={false}>
|
||||
{getFieldDecorator("url", {
|
||||
rules: [
|
||||
{ required: true, message: "请输入目标URL" },
|
||||
{
|
||||
validator: checkAddr
|
||||
}
|
||||
]
|
||||
})(
|
||||
<Input placeholder="请输入目标URL" maxLength="100" size="large" autocomplete='off' />
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item label="Webhook密钥" colon={false}>
|
||||
{getFieldDecorator("secret", {
|
||||
rules: []
|
||||
})(
|
||||
<Input.Password placeholder="请输入Webhook密钥" autocomplete='new-password' size="large" maxLength={"50"} />
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item label="Http请求方法" colon={false}>
|
||||
{getFieldDecorator("http_method", {
|
||||
rules: []
|
||||
})(
|
||||
<Select onSelect={changeHTTP} size="large">
|
||||
<Select.Option value="GET">GET</Select.Option>
|
||||
<Select.Option value="POST">POST</Select.Option>
|
||||
</Select>
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="POST请求类型"
|
||||
colon={false}
|
||||
style={{ display: httpValue === "POST" ? "block" : "none" }}
|
||||
>
|
||||
{getFieldDecorator("content_type", {
|
||||
rules: []
|
||||
})(
|
||||
<Select size="large">
|
||||
<Select.Option value="json">application/json</Select.Option>
|
||||
<Select.Option value="form">application/x-www-form-urlencoded</Select.Option>
|
||||
</Select>
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item label="您希望哪些事件触发此webhook?" colon={false} className="topLine">
|
||||
{getFieldDecorator("eventCondition", {
|
||||
rules: []
|
||||
})(
|
||||
<Radio.Group onChange={changeCondition}>
|
||||
<Radio style={radioStyle} value="push">只是push事件</Radio>
|
||||
<Radio style={radioStyle} value="all">所有事件</Radio>
|
||||
<Radio style={radioStyle} value="forevent">自定义事件</Radio>
|
||||
</Radio.Group>
|
||||
)}
|
||||
</Form.Item>
|
||||
<div className="eventCb"
|
||||
style={{ display: condition === "forevent" ? "block" : "none" }}
|
||||
>
|
||||
<Checkbox.Group value={event} onChange={(e) => { setEvent(e) }}>
|
||||
<p className="color-grey-3 mb10">代码库事件</p>
|
||||
<div className="colSpan">
|
||||
<span>
|
||||
<Checkbox value="push">推送</Checkbox>
|
||||
<span>git推送到存储库</span>
|
||||
</span>
|
||||
{/* <span>
|
||||
<Checkbox value="repository">代码库</Checkbox>
|
||||
<span>创建或删除代码库</span>
|
||||
</span> */}
|
||||
<span>
|
||||
<Checkbox value="create">创建</Checkbox>
|
||||
<span>创建分支或标签</span>
|
||||
</span>
|
||||
<span>
|
||||
<Checkbox value="delete">删除</Checkbox>
|
||||
<span>删除分支或标签</span>
|
||||
</span>
|
||||
</div>
|
||||
<p className="color-grey-3 mt10 mb10">合并请求事件</p>
|
||||
<div className="colSpan">
|
||||
<span>
|
||||
<Checkbox value="pull_request_only">合并请求</Checkbox>
|
||||
<span>合并请求被打开、被关闭、被重新打开或被编辑</span>
|
||||
</span>
|
||||
<span>
|
||||
<Checkbox value="pull_request_assign">合并请求分配</Checkbox>
|
||||
<span>合并请求被分配或取消分配</span>
|
||||
</span>
|
||||
{/* <span>
|
||||
<Checkbox value="pull_request_milestone">合并请求收入里程碑</Checkbox>
|
||||
<span>合并请求被记录或取消记录于里程碑中</span>
|
||||
</span> */}
|
||||
{/* <span>
|
||||
<Checkbox value="pull_request_comment">合并请求被评论</Checkbox>
|
||||
<span>合并请求评论被创建、编辑或删除</span>
|
||||
</span> */}
|
||||
{/* <span>
|
||||
<Checkbox value="pull_request_label">合并请求标签</Checkbox>
|
||||
<span>合并请求的标签被更新或清除</span>
|
||||
</span> */}
|
||||
{/* <span>
|
||||
<Checkbox value="pull_request_review">合并请求审查</Checkbox>
|
||||
<span>合并请求被批准、拒绝或提出审查意见,审查人员的修改,审查线程已解决或未解决</span>
|
||||
</span> */}
|
||||
{/* <span>
|
||||
<Checkbox value="pull_request_sync">合并请求被同步</Checkbox>
|
||||
<span>合并请求被同步</span>
|
||||
</span> */}
|
||||
</div>
|
||||
</Checkbox.Group>
|
||||
{eventFlag && <span style={{ color: "#DF0002" }}>请选择自定义事件!</span>}
|
||||
</div>
|
||||
<Form.Item
|
||||
label="分支过滤"
|
||||
className="topLine"
|
||||
help={<span>推送、创建,删除分支事件的分支白名单,使用 glob 模式匹配指定。若为空或 *,则将报告所有分支的事件。语法文档见<a href="http://github.com/gobwas/glob" target="_blank" className="hoverLine color-blue">github.com/gobwas/glob</a>。示例:master,{'{'}master,release*{'}'}。</span>}
|
||||
colon={false}
|
||||
style={{ marginTop: '15px' }}
|
||||
>
|
||||
{getFieldDecorator("branch_filter", {
|
||||
rules: []
|
||||
})(
|
||||
<Input size="large" />
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
className="topLine bottomLine"
|
||||
colon={false}
|
||||
style={{ height: "110px", paddingBottom: "0px" }}
|
||||
>
|
||||
{getFieldDecorator("active", {
|
||||
valuePropName: "checked"
|
||||
})(
|
||||
<Checkbox>激活<span className="subCbDesc">激活后触发事件的信息将发送到此Webhook地址</span></Checkbox>
|
||||
)}
|
||||
</Form.Item>
|
||||
|
||||
<Button type="primary" onClick={submit} className="ml20" style={{ width: id ? "" : "100px" }}>{id ? "更新Webhook" : "添加"}</Button>
|
||||
{
|
||||
id && <Button type="danger" className="ml20" onClick={deleteFunc}>删除</Button>
|
||||
}
|
||||
</Form>
|
||||
</div>
|
||||
{id && <PushHistory id={id} owner={owner} projectsId={projectsId} showNotification={showNotification} />}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default Form.create()(forwardRef(New));
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 778 B |
|
|
@ -0,0 +1,82 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { Button, Collapse , Tooltip , Spin } from 'antd';
|
||||
import axios from 'axios';
|
||||
import Content from './historyContent';
|
||||
import Fault from '../images/fault.png';
|
||||
const { Panel } = Collapse;
|
||||
|
||||
function PushHistory({id,owner,projectsId,showNotification}) {
|
||||
const [ list , setList ] = useState(undefined);
|
||||
const [ isSpin , setIsSpin ] = useState(false);
|
||||
|
||||
useEffect(()=>{
|
||||
if(id && owner && projectsId){
|
||||
Init();
|
||||
}
|
||||
},[id,owner,projectsId])
|
||||
|
||||
function Init() {
|
||||
const url = `/${owner}/${projectsId}/webhooks/${id}/tasks.json`;
|
||||
axios.get(url,{
|
||||
params:{page:1,limit:10}
|
||||
}).then(result=>{
|
||||
if(result && result.data){
|
||||
setList(result.data.tasks);
|
||||
setIsSpin(false);
|
||||
}
|
||||
}).catch(error=>{})
|
||||
}
|
||||
|
||||
function testFunc() {
|
||||
setIsSpin(true);
|
||||
const url = `/${owner}/${projectsId}/webhooks/${id}/test.json`;
|
||||
axios.post(url).then(result=>{
|
||||
if(result && result.data){
|
||||
// Init();
|
||||
showNotification("测试推送已经加入到队列,请耐心等待数秒再刷新推送记录!");
|
||||
setIsSpin(false);
|
||||
}
|
||||
}).catch(error=>{setIsSpin(false);})
|
||||
}
|
||||
|
||||
return(
|
||||
<div className="pt30">
|
||||
<div className="deschead">
|
||||
<span className="font-16">最近推送历史</span>
|
||||
<span>
|
||||
<a className="color-blue" onClick={Init}>刷新</a>
|
||||
<Button type="primary" className="ml20" onClick={testFunc} loading={isSpin}>测试推送</Button>
|
||||
</span>
|
||||
</div>
|
||||
{
|
||||
list && list.length>0 &&
|
||||
<Collapse accordion bordered={false} className="historyColl">
|
||||
{
|
||||
list.map((i,k)=>{
|
||||
return(
|
||||
<Panel header={
|
||||
<div className="panelHeader">
|
||||
{
|
||||
i.is_succeed ?
|
||||
<Tooltip title={<span className="pl20 pr20">响应成功,类型:{i.response_content && i.response_content.status}</span>}>
|
||||
<i className="iconfont icon-chenggongicon font-14 mr10" style={{color:"#2DB44D"}}></i>
|
||||
</Tooltip>
|
||||
:
|
||||
<img src={Fault} alt="" className="mr10" height="15px" style={{marginTop:"2px"}}/>
|
||||
}
|
||||
<span className="name">{i.uuid}</span>
|
||||
{/* <span>{i.type}</span> */}
|
||||
<span className="time">{i.delivered_time}</span>
|
||||
</div>
|
||||
}>
|
||||
<Content request_content={i.request_content && i.request_content.headers} payload_content={i.payload_content} response_content={i.response_content}/>
|
||||
</Panel>
|
||||
)
|
||||
})
|
||||
}
|
||||
</Collapse>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default PushHistory;
|
||||
|
|
@ -0,0 +1,144 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { Menu , Tag } from 'antd';
|
||||
import Nodata from '../../../Nodata';
|
||||
import ReactJson from 'react-json-view';
|
||||
import Editor from "../../../Component/Monaco";
|
||||
|
||||
function HistoryContent({request_content,payload_content,response_content}) {
|
||||
const [ key , setKey ] = useState("request");
|
||||
const [ requestHeader , setRequestHeader ] = useState(undefined);
|
||||
const [ responseHeader , setResponseHeader ] = useState(undefined);
|
||||
|
||||
useEffect(()=>{
|
||||
if(request_content){
|
||||
let arr = [];
|
||||
Object.keys(request_content).map((item,key)=>{
|
||||
arr.push({name:item,value:request_content[item],k:key});
|
||||
})
|
||||
setRequestHeader(arr);
|
||||
}
|
||||
},[request_content])
|
||||
|
||||
useEffect(()=>{
|
||||
if(response_content && response_content.headers){
|
||||
let arr = [];
|
||||
Object.keys(response_content.headers).map((item,key)=>{
|
||||
arr.push({name:item,value:response_content.headers[item],k:key});
|
||||
})
|
||||
setResponseHeader(arr);
|
||||
}
|
||||
},[response_content])
|
||||
|
||||
function isJSON(str) {
|
||||
if (typeof str === 'string') {
|
||||
try {
|
||||
var obj=JSON.parse(str);
|
||||
if(typeof obj === 'object' && obj ){
|
||||
return true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
} catch(e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return(
|
||||
<div className="contentPanel">
|
||||
<div>
|
||||
<Menu selectedKeys={[key]} onSelect={(e)=>setKey(e.key)} mode={"horizontal"} className="contentMenu">
|
||||
<Menu.Item key={"request"}><i className="iconfont icon-qingqiuicon font-15 mr5"></i>请求内容</Menu.Item>
|
||||
<Menu.Item key={"response"}><i className="iconfont icon-xiangyingicon font-16 mr5"></i>响应内容
|
||||
{response_content && <Tag color={response_content.status === 200 ? "#2DB44D":"#CA0002"} style={{margin:"0px",marginLeft:"3px",fontSize:"12px"}}>{response_content.status}</Tag>}
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
</div>
|
||||
<div style={{paddingLeft:"16px"}}>
|
||||
{
|
||||
key === "request" ?
|
||||
<div>
|
||||
{
|
||||
requestHeader && requestHeader.length > 0 &&
|
||||
<div>
|
||||
<p className="retitle">头信息</p>
|
||||
<div className="con">
|
||||
{
|
||||
requestHeader.map((i,k)=>{
|
||||
return(
|
||||
<p><span>{i.name}: </span><span>{i.value}</span></p>
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
{
|
||||
payload_content &&
|
||||
<div>
|
||||
<p className="retitle">内容</p>
|
||||
<div className="con">
|
||||
<ReactJson
|
||||
src={payload_content}
|
||||
name={false}
|
||||
displayObjectSize={false}
|
||||
displayDataTypes={false}
|
||||
enableClipboard={false}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
:
|
||||
<div>
|
||||
{
|
||||
(!responseHeader && ((response_content && !response_content.body) || !response_content))?
|
||||
<Nodata _html="暂无数据~"/>
|
||||
:""
|
||||
}
|
||||
{
|
||||
responseHeader && responseHeader.length > 0 &&
|
||||
<div>
|
||||
<p className="retitle">头信息</p>
|
||||
<div className="con">
|
||||
{
|
||||
responseHeader.map((i,k)=>{
|
||||
return(
|
||||
<p><span>{i.name}: </span><span>{i.value}</span></p>
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
{
|
||||
response_content && response_content.body &&
|
||||
<div>
|
||||
<p className="retitle">响应体</p>
|
||||
{
|
||||
isJSON(response_content.body) ?
|
||||
<div className="con">
|
||||
<ReactJson
|
||||
enableClipboard={false}
|
||||
src={JSON.parse(response_content.body)}
|
||||
name={false}
|
||||
displayObjectSize={false}
|
||||
displayDataTypes={false}
|
||||
/>
|
||||
</div>
|
||||
:
|
||||
<div className="conEditor">
|
||||
<Editor value={response_content.body}/>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default HistoryContent;
|
||||
Loading…
Reference in New Issue