forked from Gitlink/forgeplus-react
Merge pull request 'FIX 代码库二级页面升级改版' (#121) from feature_repo_second_page into pre_develop_dev
This commit is contained in:
commit
3be536d37a
|
@ -0,0 +1,2 @@
|
||||||
|
{
|
||||||
|
}
|
|
@ -3425,9 +3425,9 @@
|
||||||
"integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw=="
|
"integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw=="
|
||||||
},
|
},
|
||||||
"clipboard": {
|
"clipboard": {
|
||||||
"version": "2.0.6",
|
"version": "2.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.8.tgz",
|
||||||
"integrity": "sha512-g5zbiixBRk/wyKakSwCKd7vQXDjFnAMGHoEyBogG/bw9kTD9GvdAvaoRR1ALcEzt3pVKxZR0pViekPMIS0QyGg==",
|
"integrity": "sha512-Y6WO0unAIQp5bLmk1zdThRhgJt/x3ks6f30s3oE3H1mgIEU33XyQjEf8gsf6DxC7NPX8Y1SsNWjUjL/ywLnnbQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"good-listener": "^1.2.2",
|
"good-listener": "^1.2.2",
|
||||||
"select": "^1.1.2",
|
"select": "^1.1.2",
|
||||||
|
@ -7286,7 +7286,8 @@
|
||||||
"ansi-regex": {
|
"ansi-regex": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
||||||
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
|
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"aproba": {
|
"aproba": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
|
@ -7703,7 +7704,8 @@
|
||||||
"safe-buffer": {
|
"safe-buffer": {
|
||||||
"version": "5.1.2",
|
"version": "5.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"safer-buffer": {
|
"safer-buffer": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
|
@ -7759,6 +7761,7 @@
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||||
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ansi-regex": "^2.0.0"
|
"ansi-regex": "^2.0.0"
|
||||||
}
|
}
|
||||||
|
@ -7802,12 +7805,14 @@
|
||||||
"wrappy": {
|
"wrappy": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
|
||||||
|
"optional": true
|
||||||
},
|
},
|
||||||
"yallist": {
|
"yallist": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
|
||||||
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
|
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
|
||||||
|
"optional": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
"case-sensitive-paths-webpack-plugin": "2.1.1",
|
"case-sensitive-paths-webpack-plugin": "2.1.1",
|
||||||
"chalk": "1.1.3",
|
"chalk": "1.1.3",
|
||||||
"classnames": "^2.2.5",
|
"classnames": "^2.2.5",
|
||||||
"clipboard": "^2.0.6",
|
"clipboard": "^2.0.8",
|
||||||
"code-prettify": "^0.1.0",
|
"code-prettify": "^0.1.0",
|
||||||
"codemirror": "^5.53.0",
|
"codemirror": "^5.53.0",
|
||||||
"connected-react-router": "4.4.1",
|
"connected-react-router": "4.4.1",
|
||||||
|
@ -125,7 +125,7 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node --max_old_space_size=15360 scripts/start.js",
|
"start": "node --max_old_space_size=15360 scripts/start.js",
|
||||||
"build": "cross-env NODE_ENV=production node --max_old_space_size=15360 scripts/build.js",
|
"build": "cross-env NODE_ENV=production node --max_old_space_size=15360 scripts/build.js",
|
||||||
"test-build": "NODE_ENV=testBuild node --max_old_space_size=15360 scripts/build.js",
|
"test-build": "cross-env NODE_ENV=testBuild node --max_old_space_size=15360 scripts/build.js",
|
||||||
"pre-build": "NODE_ENV=preBuild node --max_old_space_size=15360 scripts/build.js",
|
"pre-build": "NODE_ENV=preBuild node --max_old_space_size=15360 scripts/build.js",
|
||||||
"gen_stats": "NODE_ENV=production webpack --profile --config=./config/webpack.config.prod.js --json > stats.json",
|
"gen_stats": "NODE_ENV=production webpack --profile --config=./config/webpack.config.prod.js --json > stats.json",
|
||||||
"ana": "webpack-bundle-analyzer ./stats.json",
|
"ana": "webpack-bundle-analyzer ./stats.json",
|
||||||
|
|
|
@ -1520,7 +1520,15 @@ a.edu-txt-w80,
|
||||||
.font-16 {
|
.font-16 {
|
||||||
font-size: 16px !important;
|
font-size: 16px !important;
|
||||||
}
|
}
|
||||||
|
.weight400{
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
.weight500{
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
.weight{
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
.font-17 {
|
.font-17 {
|
||||||
font-size: 17px !important;
|
font-size: 17px !important;
|
||||||
}
|
}
|
||||||
|
@ -1540,6 +1548,9 @@ a.edu-txt-w80,
|
||||||
.font-25 {
|
.font-25 {
|
||||||
font-size: 25px !important;
|
font-size: 25px !important;
|
||||||
}
|
}
|
||||||
|
.font-26 {
|
||||||
|
font-size: 26px !important;
|
||||||
|
}
|
||||||
|
|
||||||
.font-24 {
|
.font-24 {
|
||||||
font-size: 24px !important;
|
font-size: 24px !important;
|
||||||
|
@ -1561,6 +1572,9 @@ a.edu-txt-w80,
|
||||||
font-size: 36px !important;
|
font-size: 36px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.font-40 {
|
||||||
|
font-size: 40px !important;
|
||||||
|
}
|
||||||
.font-50 {
|
.font-50 {
|
||||||
font-size: 50px !important;
|
font-size: 50px !important;
|
||||||
}
|
}
|
||||||
|
@ -1746,6 +1760,14 @@ a.decoration {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mb12 {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mb13 {
|
||||||
|
margin-bottom: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
.mb14 {
|
.mb14 {
|
||||||
margin-bottom: 14px;
|
margin-bottom: 14px;
|
||||||
}
|
}
|
||||||
|
@ -1927,7 +1949,9 @@ a.decoration {
|
||||||
}
|
}
|
||||||
|
|
||||||
.mr20 {
|
.mr20 {
|
||||||
margin-right: 20px;
|
margin-right: 10px;
|
||||||
|
margin-left: 10px;
|
||||||
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mr25 {
|
.mr25 {
|
||||||
|
@ -1935,7 +1959,7 @@ a.decoration {
|
||||||
}
|
}
|
||||||
|
|
||||||
.mr30 {
|
.mr30 {
|
||||||
margin-right: 30px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mr35 {
|
.mr35 {
|
||||||
|
@ -2460,7 +2484,7 @@ a:hover{
|
||||||
.color-grey-B3 {
|
.color-grey-B3 {
|
||||||
color: #B3B3B3 !important;
|
color: #B3B3B3 !important;
|
||||||
}
|
}
|
||||||
`
|
|
||||||
.color-grey-B4 {
|
.color-grey-B4 {
|
||||||
color: #B4B4B4 !important;
|
color: #B4B4B4 !important;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "iconfont"; /* Project id 2340181 */
|
font-family: "iconfont"; /* Project id 2340181 */
|
||||||
src: url('iconfont.woff2?t=1631773579834') format('woff2'),
|
src: url('iconfont.woff2?t=1632964996877') format('woff2'),
|
||||||
url('iconfont.woff?t=1631773579834') format('woff'),
|
url('iconfont.woff?t=1632964996877') format('woff'),
|
||||||
url('iconfont.ttf?t=1631773579834') format('truetype');
|
url('iconfont.ttf?t=1632964996877') format('truetype');
|
||||||
}
|
}
|
||||||
|
|
||||||
.iconfont {
|
.iconfont {
|
||||||
|
@ -13,6 +13,30 @@
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-wenjian7:before {
|
||||||
|
content: "\e8e0";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-xiangyoujiantou:before {
|
||||||
|
content: "\e8de";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-xiangzuojiantou:before {
|
||||||
|
content: "\e8df";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-a-liulanicon2x:before {
|
||||||
|
content: "\e8dd";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-wenjianicon:before {
|
||||||
|
content: "\e8dc";
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-a-yuanquan2x:before {
|
||||||
|
content: "\e8db";
|
||||||
|
}
|
||||||
|
|
||||||
.icon-xiangmubiaoqian:before {
|
.icon-xiangmubiaoqian:before {
|
||||||
content: "\e8da";
|
content: "\e8da";
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -5,6 +5,48 @@
|
||||||
"css_prefix_text": "icon-",
|
"css_prefix_text": "icon-",
|
||||||
"description": "",
|
"description": "",
|
||||||
"glyphs": [
|
"glyphs": [
|
||||||
|
{
|
||||||
|
"icon_id": "24656750",
|
||||||
|
"name": "文件",
|
||||||
|
"font_class": "wenjian7",
|
||||||
|
"unicode": "e8e0",
|
||||||
|
"unicode_decimal": 59616
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "630094",
|
||||||
|
"name": "向右箭头",
|
||||||
|
"font_class": "xiangyoujiantou",
|
||||||
|
"unicode": "e8de",
|
||||||
|
"unicode_decimal": 59614
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "630095",
|
||||||
|
"name": "向左箭头",
|
||||||
|
"font_class": "xiangzuojiantou",
|
||||||
|
"unicode": "e8df",
|
||||||
|
"unicode_decimal": 59615
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "24600282",
|
||||||
|
"name": "浏览icon@2x",
|
||||||
|
"font_class": "a-liulanicon2x",
|
||||||
|
"unicode": "e8dd",
|
||||||
|
"unicode_decimal": 59613
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "24567893",
|
||||||
|
"name": "文件icon",
|
||||||
|
"font_class": "wenjianicon",
|
||||||
|
"unicode": "e8dc",
|
||||||
|
"unicode_decimal": 59612
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"icon_id": "24527422",
|
||||||
|
"name": "圆圈@2x",
|
||||||
|
"font_class": "a-yuanquan2x",
|
||||||
|
"unicode": "e8db",
|
||||||
|
"unicode_decimal": 59611
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"icon_id": "24378423",
|
"icon_id": "24378423",
|
||||||
"name": "项目标签",
|
"name": "项目标签",
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -69,7 +69,7 @@ export function appendFileSizeToUploadFile(item) {
|
||||||
}
|
}
|
||||||
export function appendFileSizeToUploadFileAll(fileList) {
|
export function appendFileSizeToUploadFileAll(fileList) {
|
||||||
return fileList.map(item => {
|
return fileList.map(item => {
|
||||||
if (item.name.indexOf(uploadNameSizeSeperator) == -1) {
|
if (item.name.indexOf(uploadNameSizeSeperator) === -1) {
|
||||||
return Object.assign({}, item, { name: `${item.name}${uploadNameSizeSeperator}${bytesToSize(item.size)}` })
|
return Object.assign({}, item, { name: `${item.name}${uploadNameSizeSeperator}${bytesToSize(item.size)}` })
|
||||||
}
|
}
|
||||||
return item
|
return item
|
||||||
|
|
|
@ -1,32 +1,60 @@
|
||||||
import React , { useState , useEffect } from 'react';
|
import React , { useState , useEffect , useRef } from 'react';
|
||||||
import { Popover , Dropdown , Input , Spin } from 'antd';
|
import { Dropdown} from 'antd';
|
||||||
import './branch.scss';
|
import './branch.scss';
|
||||||
import { getBranch , getTag } from '../GetData/getData';
|
|
||||||
import SelectOverlay from './SelectOverlay';
|
import SelectOverlay from './SelectOverlay';
|
||||||
|
import { findDOMNode } from 'react-dom';
|
||||||
|
|
||||||
export default (({ projectsId , branch , owner , changeBranch , branchList , tagflag = true })=>{
|
export default (({ projectsId , branch , owner , changeBranch , branchList , tagflag = true })=>{
|
||||||
const [ showValue , setShowValue ] = useState(branch);
|
const [ showValue , setShowValue ] = useState(branch);
|
||||||
|
const [ visible , setVisible ] = useState(false);
|
||||||
|
|
||||||
|
const refFa = useRef(null);
|
||||||
|
const refBox = useRef(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
document.addEventListener('click', clickMe , false);
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const clickMe = ({ target }) => {
|
||||||
|
// 查找父组件
|
||||||
|
const faComponent = findDOMNode(refFa.current);
|
||||||
|
const boxComponent = findDOMNode(refBox.current);
|
||||||
|
|
||||||
|
if (faComponent && boxComponent) {
|
||||||
|
const isChild = faComponent.contains(target);
|
||||||
|
const isBox = boxComponent.contains(target);
|
||||||
|
if(!isChild && !isBox){
|
||||||
|
setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
setShowValue(branch);
|
setShowValue(branch);
|
||||||
},[branch])
|
},[branch])
|
||||||
|
|
||||||
|
function ChangeB(params) {
|
||||||
|
setVisible(false);
|
||||||
|
changeBranch(params);
|
||||||
|
}
|
||||||
|
|
||||||
const menu = (
|
const menu = (
|
||||||
<SelectOverlay
|
<div ref={refFa}>
|
||||||
changeBranch={changeBranch}
|
<SelectOverlay
|
||||||
tagflag={tagflag}
|
changeBranch={ChangeB}
|
||||||
projectsId={projectsId}
|
tagflag={tagflag}
|
||||||
owner={owner}
|
projectsId={projectsId}
|
||||||
branchList={branchList}
|
owner={owner}
|
||||||
|
branchList={branchList}
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
return(
|
return(
|
||||||
<Dropdown placement='bottomLeft' overlay={menu} overlayClassName="branch-tagBox-list" trigger={['click']} >
|
<Dropdown placement='bottomLeft' visible={visible} overlay={menu} overlayClassName="branch-tagBox-list" trigger={['click']} >
|
||||||
<div className="branch-tagBox">
|
<div className="branch-tagBox" ref={refBox} onClick={()=>setVisible(visible ? false : true)}>
|
||||||
{/* {nav === 0 ?"分支":"标签"} */}
|
{/* {nav === 0 ?"分支":"标签"} */}
|
||||||
<span className="color-grey-9 mr3 ml8"><i className="iconfont icon-fenzhi2 font-18"></i></span>
|
<span className="color-grey-9 mr3 ml8"><i className="iconfont icon-fenzhi2 font-18"></i></span>
|
||||||
<span className="ant-dropdown-link task-hide" style={{fontWeight:"500"}}>
|
<span className="ant-dropdown-link task-hide" style={{fontWeight:"500",minWidth:"45px",maxWidth:"270px"}}>
|
||||||
{showValue}
|
{showValue}
|
||||||
</span>
|
</span>
|
||||||
<i className="showtag iconfont icon-sanjiaoxing-down font-15 color-grey-9 mr5 ml5 mt1" />
|
<i className="showtag iconfont icon-sanjiaoxing-down font-15 color-grey-9 mr5 ml5 mt1" />
|
||||||
|
|
|
@ -55,7 +55,7 @@ function SelectOverlay({ changeBranch , tagflag , branchList , projectsId , owne
|
||||||
<div className="padding15" style={{paddingBottom:"0px"}}>
|
<div className="padding15" style={{paddingBottom:"0px"}}>
|
||||||
<Input
|
<Input
|
||||||
prefix={<i className="iconfont icon-sousuo_icon1 font-14"></i>}
|
prefix={<i className="iconfont icon-sousuo_icon1 font-14"></i>}
|
||||||
placeholder="请输入分支或标签名称搜索"
|
placeholder={`请输入分支${tagflag ? "或标签" :""}名称搜索`}
|
||||||
autocomplete="off" className="OptionsInput"
|
autocomplete="off" className="OptionsInput"
|
||||||
value={inputValue}
|
value={inputValue}
|
||||||
onChange={changeInputValue}
|
onChange={changeInputValue}
|
||||||
|
|
|
@ -87,6 +87,13 @@
|
||||||
line-height: 30px;
|
line-height: 30px;
|
||||||
padding:0px 5px;
|
padding:0px 5px;
|
||||||
margin-left: 20px!important;
|
margin-left: 20px!important;
|
||||||
|
&.ant-menu-item-selected{
|
||||||
|
border-color:#466aff!important;
|
||||||
|
color:#466aff!important;
|
||||||
|
}
|
||||||
|
&.ant-menu-item-active{
|
||||||
|
border-color:transparent ;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,7 +116,7 @@
|
||||||
color: #333;
|
color: #333;
|
||||||
}
|
}
|
||||||
&.ant-menu-item-selected{
|
&.ant-menu-item-selected{
|
||||||
border-color:#1890ff!important;
|
border-color:#466aff!important;
|
||||||
}
|
}
|
||||||
&.ant-menu-item-active{
|
&.ant-menu-item-active{
|
||||||
border-color:transparent ;
|
border-color:transparent ;
|
||||||
|
|
|
@ -2,8 +2,7 @@ import React from 'react';
|
||||||
import { AlignTop } from '../Component/layout';
|
import { AlignTop } from '../Component/layout';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
function Releases({owner,projectsId,releaseVersions , baseOperate , projectType}){
|
function Releases({ owner, projectsId, releaseVersions, distribution }) {
|
||||||
|
|
||||||
return(
|
return(
|
||||||
<div>
|
<div>
|
||||||
<Link to={`/${owner}/${projectsId}/releases`} className="font-16 color-ooo hoverA">
|
<Link to={`/${owner}/${projectsId}/releases`} className="font-16 color-ooo hoverA">
|
||||||
|
@ -16,8 +15,9 @@ function Releases({owner,projectsId,releaseVersions , baseOperate , projectType}
|
||||||
return(
|
return(
|
||||||
key === 0 &&<AlignTop className="mt10">
|
key === 0 &&<AlignTop className="mt10">
|
||||||
<div>
|
<div>
|
||||||
<p className="font-16 color-grey-6">
|
<p className="font-16 color-grey-6" style={{display:'flex',alignItems:'center'}}>
|
||||||
<Link to={`/${owner}/${projectsId}/releases`}>{item.name}</Link>
|
{/* 如果是点击最新则发行版列表页只展示最新的一个 */}
|
||||||
|
<Link to={{pathname:`/${owner}/${projectsId}/releases`,query:{turnFromNew:true}}} style={{maxWidth:'200px',overflow: 'hidden',whiteSpace: 'nowrap',textOverflow:'ellipsis'}}>{item.name}</Link>
|
||||||
<span className="font-12 laterest ml5">最新</span>
|
<span className="font-12 laterest ml5">最新</span>
|
||||||
</p>
|
</p>
|
||||||
<p className="color-grey-3 font-12">{item.created_at}</p>
|
<p className="color-grey-3 font-12">{item.created_at}</p>
|
||||||
|
@ -27,7 +27,8 @@ function Releases({owner,projectsId,releaseVersions , baseOperate , projectType}
|
||||||
})
|
})
|
||||||
:
|
:
|
||||||
<div className="mt8">
|
<div className="mt8">
|
||||||
您暂未发布任何版本{baseOperate && projectType !==2 && <Link className="color-blue ml20" to={`/${owner}/${projectsId}/releases/new`}>创建新版本</Link>}
|
您暂未发布任何版本
|
||||||
|
{distribution && <Link className="color-blue ml20" to={{pathname:`/${owner}/${projectsId}/releases/new`,state:{stable:true}}}>创建新版本</Link>}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { Link } from 'react-router-dom';
|
||||||
export default ({ url , name , column , id , login })=>{
|
export default ({ url , name , column , id , login })=>{
|
||||||
const Img = styled.span`
|
const Img = styled.span`
|
||||||
display:flex;
|
display:flex;
|
||||||
|
font-weight: bold;
|
||||||
${column && "flex-direction: column;text-align:center;"}
|
${column && "flex-direction: column;text-align:center;"}
|
||||||
align-items: center;
|
align-items: center;
|
||||||
& img{
|
& img{
|
||||||
|
|
|
@ -51,7 +51,7 @@ function PipelineName({visible,onCancel,onOk,value ,branchList}){
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
</Select>
|
</Select>
|
||||||
<Select mode="multiple" allowClear value={eventValue} dropdownClassName="chooseCon" style={{width:"180px",marginLeft:"10px"}} onChange={(e)=>{console.log(e);setEventValue(e)}}>
|
<Select mode="multiple" allowClear value={eventValue} dropdownClassName="chooseCon" style={{width:"180px",marginLeft:"10px"}} onChange={(e)=>{setEventValue(e)}}>
|
||||||
{
|
{
|
||||||
EVENT.map((item,key)=>{
|
EVENT.map((item,key)=>{
|
||||||
return(
|
return(
|
||||||
|
|
|
@ -24,7 +24,6 @@ function onLayout(term, el) {
|
||||||
entry.target.offsetHeight,
|
entry.target.offsetHeight,
|
||||||
term,
|
term,
|
||||||
);
|
);
|
||||||
console.log('cols, rows', cols, rows);
|
|
||||||
term.resize(cols, rows);
|
term.resize(cols, rows);
|
||||||
mediator.publish('ssh-xterm-resize', {
|
mediator.publish('ssh-xterm-resize', {
|
||||||
columns: cols,
|
columns: cols,
|
||||||
|
@ -139,12 +138,10 @@ export default ({ sshConfigData, sid }) => {
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
isFirstConnected.current = true;
|
isFirstConnected.current = true;
|
||||||
console.log('event:', event);
|
|
||||||
|
|
||||||
const data = Base64.decode(event.data.toString());
|
const data = Base64.decode(event.data.toString());
|
||||||
let w = term._core._renderService.dimensions.actualCellWidth || 9.5;
|
let w = term._core._renderService.dimensions.actualCellWidth || 9.5;
|
||||||
|
|
||||||
console.log('data:', data, w, term);
|
|
||||||
term.write(data);
|
term.write(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ function Footer(){
|
||||||
|
|
||||||
return(
|
return(
|
||||||
<div>
|
<div>
|
||||||
<div style={{height:"497px"}}></div>
|
<div style={{height:"543px"}}></div>
|
||||||
<div className="newFooter edu-txt-center">
|
<div className="newFooter edu-txt-center">
|
||||||
{value && showhtml(value)}
|
{value && showhtml(value)}
|
||||||
{/* <div className="footerInfos">
|
{/* <div className="footerInfos">
|
||||||
|
|
|
@ -120,7 +120,6 @@ class NewHeader extends Component {
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
HideAddcoursestypess = (i) => {
|
HideAddcoursestypess = (i) => {
|
||||||
console.log("调用了");
|
|
||||||
this.setState({
|
this.setState({
|
||||||
Addcoursestypes: false,
|
Addcoursestypes: false,
|
||||||
mydisplay: true,
|
mydisplay: true,
|
||||||
|
@ -269,7 +268,7 @@ class NewHeader extends Component {
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
<li><Link to={`/settings/profile`}>设置</Link></li>
|
{/* <li><Link to={`/settings/profile`}>设置</Link></li> */}
|
||||||
<Menu.Item><a onClick={() => this.educoderloginysl()}>退出</a></Menu.Item>
|
<Menu.Item><a onClick={() => this.educoderloginysl()}>退出</a></Menu.Item>
|
||||||
</Menu>
|
</Menu>
|
||||||
)
|
)
|
||||||
|
|
|
@ -67,6 +67,7 @@ function CoderDepot(props){
|
||||||
const [ editReadme , setEditReadme ] = useState(false);
|
const [ editReadme , setEditReadme ] = useState(false);
|
||||||
const [ pullsFlag , setPullsFlag ] = useState(true);
|
const [ pullsFlag , setPullsFlag ] = useState(true);
|
||||||
const [ issuesFlag , setIssuesFlag ] = useState(true);
|
const [ issuesFlag , setIssuesFlag ] = useState(true);
|
||||||
|
const [ releaseVersions , setReleaseVersions] = useState(undefined);
|
||||||
|
|
||||||
const owner = props.match.params.owner;
|
const owner = props.match.params.owner;
|
||||||
const projectsId = props.match.params.projectsId;
|
const projectsId = props.match.params.projectsId;
|
||||||
|
@ -74,7 +75,8 @@ function CoderDepot(props){
|
||||||
branchName = returnbar(branchName);
|
branchName = returnbar(branchName);
|
||||||
const details = props.projectDetail;
|
const details = props.projectDetail;
|
||||||
let pathname = props.history.location.pathname;
|
let pathname = props.history.location.pathname;
|
||||||
|
//distribution:判断此用户是否可以创建发行版
|
||||||
|
const distribution = details && details.type != 2 && (details.permission === "Admin" || details.permission === "Owner" || details.permission === "Manager");
|
||||||
const { bannerList } = props;
|
const { bannerList } = props;
|
||||||
|
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
|
@ -119,14 +121,47 @@ function CoderDepot(props){
|
||||||
setTreeValue(url);
|
setTreeValue(url);
|
||||||
getFileInfo(url,branchName);
|
getFileInfo(url,branchName);
|
||||||
setType("file");
|
setType("file");
|
||||||
|
// getReadmeInfo(url,branchName);
|
||||||
|
// setReadme(undefined);
|
||||||
}else{
|
}else{
|
||||||
setTreeValue(undefined);
|
setTreeValue(undefined);
|
||||||
getDirInfo(branchName || defaultBranch);
|
getDirInfo(branchName || defaultBranch);
|
||||||
setType("dir");
|
setType("dir");
|
||||||
|
// getReadmeInfo('', branchName || defaultBranch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},[projectsId,owner,pathname,defaultBranch])
|
},[projectsId,owner,pathname,defaultBranch])
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
axios.get(`/${owner}/${projectsId}/releases.json`).then((result)=>{
|
||||||
|
if(result && result.data){
|
||||||
|
const release = {
|
||||||
|
"list":result.data.releases,
|
||||||
|
"total_count":result.data.releases.length
|
||||||
|
}
|
||||||
|
setReleaseVersions(release);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},[])
|
||||||
|
|
||||||
|
// 获取readme信息
|
||||||
|
function getReadmeInfo(path, ref) {
|
||||||
|
axios.get(`/${owner}/${projectsId}/readme.json`, {
|
||||||
|
params:{
|
||||||
|
owner: owner,
|
||||||
|
repo: projectsId,
|
||||||
|
filepath:path,
|
||||||
|
ref:ref || branchName
|
||||||
|
}
|
||||||
|
}).then((result) => {
|
||||||
|
if (result) {
|
||||||
|
setReadme(result.data);
|
||||||
|
} else {
|
||||||
|
setReadme(undefined);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 获取主目录列表
|
// 获取主目录列表
|
||||||
function getDirInfo(branch){
|
function getDirInfo(branch){
|
||||||
setIsSpin(true);
|
setIsSpin(true);
|
||||||
|
@ -146,9 +181,10 @@ function CoderDepot(props){
|
||||||
setLastCommitAuthor(c && c.committer);
|
setLastCommitAuthor(c && c.committer);
|
||||||
setMainFlag(true);
|
setMainFlag(true);
|
||||||
setReadOnly(true);
|
setReadOnly(true);
|
||||||
setReadme(result.data.readme);
|
// setReadme(result.data.readme);
|
||||||
setEditReadme(false);
|
setEditReadme(false);
|
||||||
setHide(true);
|
setHide(true);
|
||||||
|
getReadmeInfo('', branchName || defaultBranch);
|
||||||
}
|
}
|
||||||
setTimeout(function(){setIsSpin(false);},500);
|
setTimeout(function(){setIsSpin(false);},500);
|
||||||
}).catch(error=>{setIsSpin(false);})
|
}).catch(error=>{setIsSpin(false);})
|
||||||
|
@ -181,15 +217,18 @@ function CoderDepot(props){
|
||||||
setDirInfo(undefined);
|
setDirInfo(undefined);
|
||||||
setFileInfo(en);
|
setFileInfo(en);
|
||||||
setType(en.type);
|
setType(en.type);
|
||||||
|
setReadme(undefined);
|
||||||
}else{
|
}else{
|
||||||
setFileInfo(undefined);
|
setFileInfo(undefined);
|
||||||
setDirInfo(en);
|
setDirInfo(en);
|
||||||
setType("dir");
|
setType("dir");
|
||||||
|
getReadmeInfo(path, branchName || defaultBranch);
|
||||||
}
|
}
|
||||||
let c = result.data.last_commit
|
let c = result.data.last_commit
|
||||||
setLastCommit(c && c.commit);
|
setLastCommit(c && c.commit);
|
||||||
setLastCommitAuthor(c && c.committer);
|
setLastCommitAuthor(c && c.committer);
|
||||||
setMainFlag(false);
|
setMainFlag(false);
|
||||||
|
setReadOnly(true);
|
||||||
setReadOnly(!editReadme);
|
setReadOnly(!editReadme);
|
||||||
setHide(true);
|
setHide(true);
|
||||||
}
|
}
|
||||||
|
@ -301,6 +340,7 @@ function CoderDepot(props){
|
||||||
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 { current_user } = props;
|
||||||
|
const baseOper = projectDetail && projectDetail.permission;
|
||||||
const baseOperate = projectDetail && projectDetail.permission && projectDetail.permission !=="Reporter";
|
const baseOperate = projectDetail && projectDetail.permission && projectDetail.permission !=="Reporter";
|
||||||
const fileOperate = type === "dir" && projectDetail && projectDetail.type !== 2 && ((projectDetail.permission && projectDetail.permission !=="Reporter") || (current_user && current_user.admin));
|
const fileOperate = type === "dir" && projectDetail && projectDetail.type !== 2 && ((projectDetail.permission && projectDetail.permission !=="Reporter") || (current_user && current_user.admin));
|
||||||
|
|
||||||
|
@ -348,34 +388,47 @@ function CoderDepot(props){
|
||||||
branchList={projectDetail && projectDetail.branches && projectDetail.branches.list}
|
branchList={projectDetail && projectDetail.branches && projectDetail.branches.list}
|
||||||
></SelectBranch>
|
></SelectBranch>
|
||||||
:
|
:
|
||||||
<span>分支:<span className="color-grey-6">{branchName || defaultBranch}</span></span>
|
<span>分支:<span className="color-grey-6">{branchName || defaultBranch}</span></span>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<AlignCenter className="mr20">
|
{
|
||||||
<Link to={`/${owner}/${projectsId}/branches`} className="iconBtn">
|
treeValuePath && treeValuePath.length > 0 ?
|
||||||
<i className="iconfont icon-master_icon font-16"></i>
|
<Path
|
||||||
<span>分支</span>
|
identifier={projectDetail && projectDetail.identifier}
|
||||||
<span>{projectDetail && projectDetail.branches && projectDetail.branches.total_count}</span>
|
treeValuePath={treeValuePath}
|
||||||
</Link>
|
returnUlr={returnUlr}
|
||||||
</AlignCenter>
|
returnMain={returnMain}
|
||||||
<AlignCenter className="mr20">
|
getPathUrl={getPathUrl}
|
||||||
<Link to={`/${owner}/${projectsId}/tags`} className="iconBtn">
|
/>
|
||||||
<i className="iconfont icon-biaoqianicon font-16"></i>
|
:
|
||||||
<span>标签</span>
|
<div>
|
||||||
<span>{projectDetail && projectDetail.tags && projectDetail.tags.total_count}</span>
|
<AlignCenter className="mr20">
|
||||||
</Link>
|
<Link to={`/${owner}/${projectsId}/branches`} className="iconBtn">
|
||||||
</AlignCenter>
|
<i className="iconfont icon-master_icon font-16"></i>
|
||||||
|
<span>分支</span>
|
||||||
|
<span>{projectDetail && projectDetail.branches && projectDetail.branches.total_count}</span>
|
||||||
|
</Link>
|
||||||
|
</AlignCenter>
|
||||||
|
<AlignCenter className="mr20">
|
||||||
|
<Link to={`/${owner}/${projectsId}/tags`} className="iconBtn">
|
||||||
|
<i className="iconfont icon-biaoqianicon font-16"></i>
|
||||||
|
<span>标签</span>
|
||||||
|
<span>{projectDetail && projectDetail.tags && projectDetail.tags.total_count}</span>
|
||||||
|
</Link>
|
||||||
|
</AlignCenter>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</AlignCenter>
|
</AlignCenter>
|
||||||
<AlignCenter className="depotBtn">
|
<AlignCenter className="depotBtn">
|
||||||
{
|
{
|
||||||
baseOperate && ((projectDetail.type !== 2 && pullsFlag) || issuesFlag )&&
|
((baseOperate && projectDetail.type !== 2 && pullsFlag) || (baseOper && issuesFlag)) &&
|
||||||
<div className="addOptionBtn">
|
<div className="addOptionBtn">
|
||||||
{
|
{
|
||||||
projectDetail.type !== 2 && pullsFlag &&
|
baseOperate && projectDetail.type !== 2 && pullsFlag &&
|
||||||
<CheckProfile {...props} sureFunc={()=>urlLink(`/${owner}/${projectsId}/pulls/new`)} >+ 合并请求</CheckProfile>
|
<CheckProfile {...props} sureFunc={()=>urlLink(`/${owner}/${projectsId}/pulls/new/${branchName || defaultBranch}`)} >+ 合并请求</CheckProfile>
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
issuesFlag &&
|
baseOper && issuesFlag &&
|
||||||
<CheckProfile {...props} sureFunc={()=>urlLink(`/${owner}/${projectsId}/issues/new`)} >+ 易修</CheckProfile>
|
<CheckProfile {...props} sureFunc={()=>urlLink(`/${owner}/${projectsId}/issues/new`)} >+ 易修</CheckProfile>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
@ -403,8 +456,8 @@ function CoderDepot(props){
|
||||||
lastCommit &&
|
lastCommit &&
|
||||||
<div className="listtablehead">
|
<div className="listtablehead">
|
||||||
<User url={getImageUrl(`/${lastCommitAuthor && lastCommitAuthor.image_url}`)} name={lastCommitAuthor && lastCommitAuthor.name} id={lastCommitAuthor && lastCommitAuthor.id} login={lastCommitAuthor && lastCommitAuthor.login}/>
|
<User url={getImageUrl(`/${lastCommitAuthor && lastCommitAuthor.image_url}`)} name={lastCommitAuthor && lastCommitAuthor.name} id={lastCommitAuthor && lastCommitAuthor.id} login={lastCommitAuthor && lastCommitAuthor.login}/>
|
||||||
<div onClick={()=>props.history.push(`/${owner}/${projectsId}/commits/${truncateCommitId(lastCommit.sha)}`)} className={hideBtn && hide ? "ellipsistxt hidetxt" :"ellipsistxt"}>
|
<div className={hideBtn && hide ? "ellipsistxt hidetxt" :"ellipsistxt"}>
|
||||||
<pre id="ptxt">{lastCommit.message}</pre>
|
<pre id="ptxt"><Link to={`/${owner}/${projectsId}/commits/${truncateCommitId(lastCommit.sha)}`}>{lastCommit.message}</Link></pre>
|
||||||
</div>
|
</div>
|
||||||
{ hideBtn && <span className="ellipsis" onClick={()=>changeHide(hide)}><i className="iconfont icon-shenglvehao"></i></span> }
|
{ hideBtn && <span className="ellipsis" onClick={()=>changeHide(hide)}><i className="iconfont icon-shenglvehao"></i></span> }
|
||||||
|
|
||||||
|
@ -418,16 +471,6 @@ function CoderDepot(props){
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
<ul className="listtablebody">
|
<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 && dirInfo.length > 0 &&
|
||||||
dirInfo.map((item,key)=>{
|
dirInfo.map((item,key)=>{
|
||||||
|
@ -461,11 +504,11 @@ function CoderDepot(props){
|
||||||
(dirInfo && dirInfo.length === 0) && !fileInfo ? <Nodata _html="暂未发现文件"/> :""
|
(dirInfo && dirInfo.length === 0) && !fileInfo ? <Nodata _html="暂未发现文件"/> :""
|
||||||
}
|
}
|
||||||
{/* readme文件显示(显示文件详情时不显示readme文件) */}
|
{/* readme文件显示(显示文件详情时不显示readme文件) */}
|
||||||
{ dirInfo && (readme && readme.content) ? <ReadMe ChangeFile={ChangeFile} readme={readme} operate={props && (props.isManager || props.isDeveloper) && projectDetail.type !==2 } history={props.history} /> :"" }
|
{ (readme && readme.content) ? <ReadMe ChangeFile={ChangeFile} readme={readme} operate={props && (props.isManager || props.isDeveloper) && projectDetail.type !==2 } history={props.history} /> :"" }
|
||||||
</div>
|
</div>
|
||||||
</LongWidth>
|
</LongWidth>
|
||||||
{
|
{
|
||||||
!fileInfo &&
|
(!(treeValuePath && treeValuePath.length > 0) && !fileInfo) &&
|
||||||
<ShortWidth>
|
<ShortWidth>
|
||||||
<Gap style={{paddingLeft:"30px"}}>
|
<Gap style={{paddingLeft:"30px"}}>
|
||||||
<div className="panelmenu">
|
<div className="panelmenu">
|
||||||
|
@ -516,16 +559,15 @@ function CoderDepot(props){
|
||||||
}
|
}
|
||||||
{/* 发布 */}
|
{/* 发布 */}
|
||||||
{
|
{
|
||||||
projectDetail && projectDetail.release_versions &&
|
releaseVersions &&
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Divider />
|
<Divider />
|
||||||
<Releases
|
<Releases
|
||||||
owner={owner}
|
owner={owner}
|
||||||
projectsId={projectsId}
|
projectsId={projectsId}
|
||||||
releaseVersions={projectDetail.release_versions}
|
releaseVersions={releaseVersions}
|
||||||
history={props.history}
|
history={props.history}
|
||||||
baseOperate={baseOperate}
|
distribution={distribution}
|
||||||
projectType={projectDetail.type}
|
|
||||||
/>
|
/>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
}
|
}
|
||||||
|
@ -535,7 +577,7 @@ function CoderDepot(props){
|
||||||
<Contributors contributors={projectDetail.contributors} owner={owner} projectsId={projectsId} />
|
<Contributors contributors={projectDetail.contributors} owner={owner} projectsId={projectsId} />
|
||||||
}
|
}
|
||||||
{/* 语言 */}
|
{/* 语言 */}
|
||||||
{ projectDetail && projectDetail.languages &&
|
{ projectDetail && projectDetail.languages &&
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Divider />
|
<Divider />
|
||||||
<LanguagePower languages={projectDetail.languages}/>
|
<LanguagePower languages={projectDetail.languages}/>
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { result } from 'lodash';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,92 +0,0 @@
|
||||||
import React , { useState, useEffect } from 'react';
|
|
||||||
import { Link } from "react-router-dom";
|
|
||||||
import { Dropdown , Menu , Icon , Tooltip , Spin } from 'antd';
|
|
||||||
import { truncateCommitId } from '../common/util';
|
|
||||||
import { getBranch } from '../GetData/getData';
|
|
||||||
import Nodata from '../Nodata';
|
|
||||||
import './list.scss';
|
|
||||||
|
|
||||||
function turnbar(str){
|
|
||||||
if(str && str.length>0 && str.indexOf("/")>-1){
|
|
||||||
return str.replaceAll('/','%2F');
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
export default ((props)=>{
|
|
||||||
const [ data , setData ] =useState(undefined);
|
|
||||||
const [ isSpin , setIsSpin ] =useState(true);
|
|
||||||
|
|
||||||
const { projectsId , owner } = props.match.params;
|
|
||||||
const { isManager , isDeveloper , projectDetail } = props;
|
|
||||||
useEffect(()=>{
|
|
||||||
getBranchs(projectsId, owner);
|
|
||||||
},[projectsId])
|
|
||||||
|
|
||||||
async function getBranchs(id,owner){
|
|
||||||
let result = await getBranch(id,owner);
|
|
||||||
setData(result);
|
|
||||||
setIsSpin(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
const list =()=>{
|
|
||||||
if(data && data.length>0){
|
|
||||||
return(
|
|
||||||
<React.Fragment>
|
|
||||||
<ul className="branchUl">
|
|
||||||
{
|
|
||||||
data.map((item,key)=>{
|
|
||||||
return(
|
|
||||||
<li key={key}>
|
|
||||||
<div>
|
|
||||||
<Link to={`/${owner}/${projectsId}/tree/${turnbar(item.name)}`} className="color-blue font-15" style={{"maxWidth":"100px"}}>{item.name}</Link>
|
|
||||||
<p className="f-wrap-alignCenter mt15">
|
|
||||||
<Link to={`/${owner}/${projectsId}/commits/${truncateCommitId(`${item.last_commit.sha}`)}`} className="mr5 commitKey" style={{marginLeft:0}}>{item.last_commit && truncateCommitId(item.last_commit.sha)}</Link>
|
|
||||||
<span className="color-grey-3 hide-1 messages leftPoint">{item.last_commit && item.last_commit.message}</span>
|
|
||||||
<span className="color-grey-8 ml30">最后更新于{item.last_commit && item.last_commit.time_from_now}</span>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<span>
|
|
||||||
{
|
|
||||||
(isManager || isDeveloper) && (projectDetail && projectDetail.type!==2) &&
|
|
||||||
<Link to={`/${owner}/${projectsId}/pulls/new/${item.name}`} className="mr20 color-blue mr30">创建合并请求</Link>
|
|
||||||
}
|
|
||||||
<Dropdown overlay={menu(item.zip_url,item.tar_url)} trigger={['click']} placement="bottomRight" className="color-green-file">
|
|
||||||
<a className="ant-dropdown-link">
|
|
||||||
<Tooltip title={`下载分支${item.name}`}><Icon type="cloud-download" className="font-18"/></Tooltip>
|
|
||||||
</a>
|
|
||||||
</Dropdown>
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</ul>
|
|
||||||
</React.Fragment>
|
|
||||||
)
|
|
||||||
}else if(data && data.length === 0){
|
|
||||||
return ( <Nodata _html="暂无数据"/>)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const menu =(zip_url,tar_url)=> (
|
|
||||||
<Menu>
|
|
||||||
<Menu.Item key={'0'}><a href={zip_url}>ZIP</a></Menu.Item>
|
|
||||||
<Menu.Item key={'1'}><a href={tar_url}>TAR.GZ</a></Menu.Item>
|
|
||||||
</Menu>
|
|
||||||
)
|
|
||||||
|
|
||||||
return(
|
|
||||||
<React.Fragment>
|
|
||||||
<div className="main">
|
|
||||||
<Spin spinning={isSpin}>
|
|
||||||
<div className="branchTable">
|
|
||||||
<p className="branchTitle bor-bottom-greyE">分支列表</p>
|
|
||||||
<div style={{minHeight:"400px"}}>{list()}</div>
|
|
||||||
</div>
|
|
||||||
</Spin>
|
|
||||||
</div>
|
|
||||||
</React.Fragment>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,18 @@
|
||||||
import React , { Component } from 'react';
|
import React , { Component } from 'react';
|
||||||
import { Spin , Pagination } from 'antd';
|
import { Spin , Pagination, Timeline } from 'antd';
|
||||||
import { getImageUrl } from 'educoder';
|
import { getImageUrl } from 'educoder';
|
||||||
import { truncateCommitId } from '../common/util';
|
import { truncateCommitId ,timeFormat } from '../common/util';
|
||||||
import { AlignTop } from '../Component/layout';
|
import { AlignTop } from '../Component/layout';
|
||||||
import SelectBranch from '../Branch/Select';
|
import SelectBranch from '../Branch/Select';
|
||||||
import Nodata from '../Nodata';
|
import Nodata from '../Nodata';
|
||||||
|
|
||||||
|
import User from '../Component/User'
|
||||||
|
import Tree from './img/tree.png';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import {Link} from "react-router-dom";
|
import {Link} from "react-router-dom";
|
||||||
|
import CopyTool from '../Component/CopyTool';
|
||||||
|
|
||||||
|
import './tree/Index.scss'
|
||||||
|
|
||||||
function returnbar(str){
|
function returnbar(str){
|
||||||
if(str && str.length>0 && str.indexOf("%2F")>-1){
|
if(str && str.length>0 && str.indexOf("%2F")>-1){
|
||||||
|
@ -15,14 +20,16 @@ function returnbar(str){
|
||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//代码库--提交页面
|
||||||
class CoderRootCommit extends Component{
|
class CoderRootCommit extends Component{
|
||||||
constructor(props){
|
constructor(props){
|
||||||
super(props)
|
super(props);
|
||||||
this.state={
|
this.state={
|
||||||
commitDatas:undefined,
|
commitDatas:undefined,
|
||||||
dataCount:undefined,
|
dataCount:undefined,
|
||||||
limit:20,
|
limit:10,
|
||||||
page:1,
|
page: 1,
|
||||||
isSpining:false,
|
isSpining:false,
|
||||||
branchList:undefined
|
branchList:undefined
|
||||||
}
|
}
|
||||||
|
@ -50,20 +57,34 @@ class CoderRootCommit extends Component{
|
||||||
this.Init();
|
this.Init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UrlParamHash(url){
|
||||||
|
const params = {};
|
||||||
|
let h;
|
||||||
|
let hash = url.slice(url.indexOf('?')+1).split('&');
|
||||||
|
for(let i = 0; i<hash.length;i++){
|
||||||
|
h = hash[i].split('=');
|
||||||
|
params[h[0]] = h[1];
|
||||||
|
}
|
||||||
|
return params;
|
||||||
|
}
|
||||||
|
|
||||||
Init =()=>{
|
Init =()=>{
|
||||||
const { branchName } = this.props.match.params;
|
const { branchName } = this.props.match.params;
|
||||||
const { page , limit } = this.state;
|
const { limit } = this.state;
|
||||||
|
const {search} = this.props.location;
|
||||||
|
const realPage = (search && this.UrlParamHash(search).page) ? parseInt(this.UrlParamHash(search).page) : 1;
|
||||||
this.setState({
|
this.setState({
|
||||||
isSpining:true
|
isSpining:true,
|
||||||
|
page:realPage
|
||||||
})
|
})
|
||||||
this.getCommitList( branchName , page , limit );
|
this.getCommitList( branchName , realPage , limit );
|
||||||
}
|
}
|
||||||
|
|
||||||
getCommitList=(branch , page , limit)=>{
|
getCommitList=(branch , page , limit)=>{
|
||||||
this.setState({
|
this.setState({
|
||||||
isSpining:true
|
isSpining:true
|
||||||
})
|
})
|
||||||
console.log(returnbar(branch));
|
|
||||||
const { projectsId , owner } = this.props.match.params;
|
const { projectsId , owner } = this.props.match.params;
|
||||||
const url = `/${owner}/${projectsId}/commits.json`;
|
const url = `/${owner}/${projectsId}/commits.json`;
|
||||||
axios.get(url,{
|
axios.get(url,{
|
||||||
|
@ -86,7 +107,8 @@ class CoderRootCommit extends Component{
|
||||||
image_url:item.author && item.author.image_url,
|
image_url:item.author && item.author.image_url,
|
||||||
sha:item.sha,
|
sha:item.sha,
|
||||||
time_from_now:item.time_from_now,
|
time_from_now:item.time_from_now,
|
||||||
message:item.message
|
message:item.message,
|
||||||
|
timestamp:item.timestamp
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
this.setState({
|
this.setState({
|
||||||
|
@ -105,10 +127,9 @@ class CoderRootCommit extends Component{
|
||||||
}
|
}
|
||||||
|
|
||||||
ChangePage=(page)=>{
|
ChangePage=(page)=>{
|
||||||
const { branchName } = this.props.match.params;
|
this.props.history.push({pathname: this.props.history.location.pathname,search: `page=${page}`})
|
||||||
const { limit } = this.state;
|
|
||||||
this.getCommitList(branchName , page , limit);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render(){
|
render(){
|
||||||
const { commitDatas , dataCount , limit , page , isSpining , branchList } = this.state;
|
const { commitDatas , dataCount , limit , page , isSpining , branchList } = this.state;
|
||||||
const { projectDetail, commit_class , defaultBranch } = this.props;
|
const { projectDetail, commit_class , defaultBranch } = this.props;
|
||||||
|
@ -129,46 +150,50 @@ class CoderRootCommit extends Component{
|
||||||
></SelectBranch>
|
></SelectBranch>
|
||||||
</div>
|
</div>
|
||||||
<Spin spinning={isSpining}>
|
<Spin spinning={isSpining}>
|
||||||
<div className="commonBox">
|
<Timeline className="commitList">
|
||||||
<div className="commonBox-title">
|
{
|
||||||
<div className="f-wrap-between" style={{alignItems:"center"}}>
|
commitDatas && commitDatas.length > 0 && commitDatas.map((item,k)=>{
|
||||||
<span className="font-16">{dataCount}次提交代码({branch})</span>
|
return(
|
||||||
</div>
|
<Timeline.Item key={k} dot={page ===1 && k===0 ?<span className="new-conmmit">最新</span>:<i className="iconfont icon-a-yuanquan2x"></i>}>
|
||||||
</div>
|
<div className="commitList-item f-wrap-between">
|
||||||
<div className="commitList">
|
<div>
|
||||||
{
|
<AlignTop>
|
||||||
commitDatas && commitDatas.length > 0 && commitDatas.map((item,k)=>{
|
<div className="commitDesc"><Link to={`/${owner}/${projectsId}/commits/${truncateCommitId(`${item.sha}`)}`} className="font-14 color-grey-3 font-bd">{item.message}</Link></div>
|
||||||
return(
|
</AlignTop>
|
||||||
<div key={k}>
|
<p className="f-wrap-alignCenter mt15 pb5">
|
||||||
<AlignTop>
|
<User
|
||||||
<Link to={`/${owner}/${projectsId}/commits/${truncateCommitId(`${item.sha}`)}`} className="commitKey" style={{marginLeft:0,marginTop:"3px"}}>{truncateCommitId(`${item.sha}`)}</Link>
|
id={item.id}
|
||||||
<Link to={`/${owner}/${projectsId}/commits/${truncateCommitId(`${item.sha}`)}`} className="commitDesc">{item.message}</Link>
|
url={(item.image_url && getImageUrl(`/${item.image_url}`)) || "https://dss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3025493530,1989042357&fm=26&gp=0.jpg"}
|
||||||
</AlignTop>
|
name={item.name}
|
||||||
<p className="f-wrap-alignCenter mt15">
|
login={item.login}
|
||||||
{
|
/>
|
||||||
item.id ?
|
{item.timestamp && <label className="font-14 color-grey-3 ml3">提交于 {timeFormat(item.timestamp)}</label>}
|
||||||
<Link to={`/${item.login}`} className="show-user-link">
|
</p>
|
||||||
{item.image_url?<img src={getImageUrl(`/${item.image_url}`)} alt="" width="28px" height="28px" className="mr15 radius"/>:""}
|
</div>
|
||||||
<label className="font-14 color-grey-6" style={{verticalAlign:'middle'}}>{item.name ?`${item.name}:`:""}提交于 {item.time_from_now}</label>
|
<div>
|
||||||
</Link>:
|
<div className="treecopy">
|
||||||
<span className="show-user-link">
|
<div>
|
||||||
{item.image_url?<img src={getImageUrl(`/${item.image_url}`)} alt="" width="28px" height="28px" className="mr15 radius"/>:""}
|
<span className="treecopy-cont shadow">
|
||||||
<label className="font-14 color-grey-6" style={{verticalAlign:'middle'}}>{item.name ?`${item.name}:`:""}提交于 {item.time_from_now}</label>
|
<img src={Tree} alt="sha" width={"16px"}/>
|
||||||
</span>
|
<Link to={`/${owner}/${projectsId}/commits/${truncateCommitId(`${item.sha}`)}`}>{truncateCommitId(`${item.sha}`)}</Link>
|
||||||
}
|
<input type="text" id={`value${k}`} value={`${truncateCommitId(`${item.sha}`)}`}/>
|
||||||
|
</span>
|
||||||
</p>
|
<CopyTool beforeText="复制commit id" afterText="复制成功" inputId={`value${k}`}/>
|
||||||
|
</div>
|
||||||
|
<button className="btn-83" onClick={()=>{window.location.href=`/${owner}/${projectsId}/tree/${truncateCommitId(item.sha)}`}}>浏览文件</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
</Timeline.Item>
|
||||||
})
|
)
|
||||||
}
|
})
|
||||||
{commitDatas && commitDatas.length === 0 && <Nodata _html="暂无数据"/>}
|
}
|
||||||
</div>
|
{commitDatas && commitDatas.length === 0 && <Nodata _html="暂无数据"/>}
|
||||||
</div>
|
</Timeline>
|
||||||
{
|
{
|
||||||
dataCount > limit ?
|
dataCount > limit ?
|
||||||
<div className="edu-txt-center pt30 mb30">
|
<div className="edu-txt-center pt30 mb30">
|
||||||
<Pagination simple defaultCurrent={page} total={dataCount} pageSize={limit} onChange={this.ChangePage}></Pagination>
|
<Pagination simple current={page} total={dataCount} pageSize={limit} onChange={this.ChangePage}></Pagination>
|
||||||
</div>
|
</div>
|
||||||
:""
|
:""
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
import { Popconfirm , Select } from "antd";
|
import { Popconfirm , Select , Dropdown , Spin , Anchor } from "antd";
|
||||||
import "./list.scss";
|
import "./list.scss";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import Meditor from "../Newfile/m_editor";
|
import Meditor from "../Newfile/m_editor";
|
||||||
import RenderHtml from "../../components/render-html";
|
import RenderHtml from "../../components/render-html";
|
||||||
|
import ReadmeCatelogue from "./sub/ReadmeCatelogue";
|
||||||
|
|
||||||
|
const $ = window.$;
|
||||||
function bytesToSize(bytes) {
|
function bytesToSize(bytes) {
|
||||||
if (bytes === 0) return "0 B";
|
if (bytes === 0) return "0 B";
|
||||||
let k = 1024,
|
let k = 1024,
|
||||||
|
@ -19,7 +21,8 @@ class CoderRootFileDetail extends Component {
|
||||||
value: undefined,
|
value: undefined,
|
||||||
language: undefined,
|
language: undefined,
|
||||||
languages: undefined,
|
languages: undefined,
|
||||||
description: props.detail.content
|
description: props.detail.content,
|
||||||
|
menuList:undefined
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,6 +172,31 @@ class CoderRootFileDetail extends Component {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
renderMenulist=()=>{
|
||||||
|
const { description } = this.state;
|
||||||
|
if(description){
|
||||||
|
const items = $.map($("#files-md").find("h1,h2,h3,h4,h5,h6"), function (el, _) {
|
||||||
|
const anchor = el.id;
|
||||||
|
const level = el.tagName.replace("H", "");
|
||||||
|
const href = `#${anchor}`;
|
||||||
|
return { href:`${href}`,text:el.textContent , level:level }
|
||||||
|
});
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
menu=()=>{
|
||||||
|
const menuList = this.renderMenulist();
|
||||||
|
if(menuList && menuList.length > 0){
|
||||||
|
return(
|
||||||
|
<ReadmeCatelogue menuList={menuList} hash={this.props.history.location.hash}/>
|
||||||
|
)
|
||||||
|
}else{
|
||||||
|
return <Spin />
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
readOnly,
|
readOnly,
|
||||||
|
@ -186,79 +214,88 @@ class CoderRootFileDetail extends Component {
|
||||||
const Option = Select.Option;
|
const Option = Select.Option;
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<div className="grid-item branchTitle">
|
<Anchor className="griditemAnchor" offsetTop={70} targetOffset={160}>
|
||||||
<div className="grid-item">
|
<div className="griditemCate">
|
||||||
<span className="ml20 color-grey-6 font-16">
|
{
|
||||||
|
md && readOnly &&
|
||||||
|
<Dropdown overlay={this.menu()} trigger={['hover']} overlayClassName="menuslist">
|
||||||
|
<span className="catelogue mr20">
|
||||||
|
<i className="iconfont icon-muluicon font-12 mr5"></i>
|
||||||
|
<span>目录</span>
|
||||||
|
</span>
|
||||||
|
</Dropdown>
|
||||||
|
}
|
||||||
|
<span className="color-grey-6 font-16">
|
||||||
{bytesToSize(detail && detail.size)}
|
{bytesToSize(detail && detail.size)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-right">
|
<p className="text-right">
|
||||||
{flag && platform && (
|
{flag && platform && (
|
||||||
<div>
|
<div>
|
||||||
{readOnly ? (
|
{readOnly ? (
|
||||||
<span>
|
<span>
|
||||||
{
|
{
|
||||||
!detail.direct_download?
|
!detail.direct_download?
|
||||||
<span>
|
<span>
|
||||||
<a onClick={() => this.DownLoadFile(detail.download_url)} className="ml20">
|
<a onClick={() => this.DownLoadFile(detail.download_url)} className="ml20">
|
||||||
<i className="iconfont icon-xiazai1 font-15 color-grey-6"></i>
|
<i className="iconfont icon-xiazai1 font-15 color-grey-6"></i>
|
||||||
</a>
|
|
||||||
{
|
|
||||||
type !==2 &&
|
|
||||||
<a onClick={() => this.EditFile(false)} className="ml20">
|
|
||||||
<i className="iconfont icon-bianji1 font-15 color-grey-6"></i>
|
|
||||||
</a>
|
</a>
|
||||||
}
|
{
|
||||||
</span>:""
|
type !==2 &&
|
||||||
}
|
<a onClick={() => this.EditFile(false)} className="ml20">
|
||||||
</span>
|
<i className="iconfont icon-bianji1 font-15 color-grey-6"></i>
|
||||||
) : (
|
</a>
|
||||||
<React.Fragment>
|
}
|
||||||
<Select
|
</span>:""
|
||||||
showSearch={true}
|
}
|
||||||
placeholder={"请选择文本语言"}
|
</span>
|
||||||
style={{ width: 200 }}
|
) : (
|
||||||
value={language}
|
<React.Fragment>
|
||||||
onChange={this.select_language}
|
<Select
|
||||||
>
|
showSearch={true}
|
||||||
<Option value={undefined}>请选择文本语言</Option>
|
placeholder={"请选择文本语言"}
|
||||||
{languages &&
|
style={{ width: 200 }}
|
||||||
languages.map((item, key) => {
|
value={language}
|
||||||
return (
|
onChange={this.select_language}
|
||||||
<Option value={item} key={key}>
|
>
|
||||||
{item}
|
<Option value={undefined}>请选择文本语言</Option>
|
||||||
</Option>
|
{languages &&
|
||||||
);
|
languages.map((item, key) => {
|
||||||
})}
|
return (
|
||||||
</Select>
|
<Option value={item} key={key}>
|
||||||
<button
|
{item}
|
||||||
type="button"
|
</Option>
|
||||||
className="ant-btn ant-btn-sm ml20"
|
);
|
||||||
onClick={() => this.EditFile(true)}
|
})}
|
||||||
>
|
</Select>
|
||||||
<span>取 消</span>
|
<button
|
||||||
</button>
|
type="button"
|
||||||
</React.Fragment>
|
className="ant-btn ant-btn-sm ml20"
|
||||||
)}
|
onClick={() => this.EditFile(true)}
|
||||||
{
|
>
|
||||||
type !==2 &&
|
<span>取 消</span>
|
||||||
<Popconfirm
|
</button>
|
||||||
title="确认删除这个文件?"
|
</React.Fragment>
|
||||||
className="ml20"
|
)}
|
||||||
okText="确定"
|
{
|
||||||
cancelText="取消"
|
type !==2 &&
|
||||||
onConfirm={this.deleteFile}
|
<Popconfirm
|
||||||
>
|
title="确认删除这个文件?"
|
||||||
<a>
|
className="ml20"
|
||||||
<i className="iconfont icon-shanchu font-15 color-grey-6"></i>
|
okText="确定"
|
||||||
</a>
|
cancelText="取消"
|
||||||
</Popconfirm>
|
onConfirm={this.deleteFile}
|
||||||
}
|
>
|
||||||
|
<a>
|
||||||
</div>
|
<i className="iconfont icon-shanchu font-15 color-grey-6"></i>
|
||||||
)}
|
</a>
|
||||||
</p>
|
</Popconfirm>
|
||||||
</div>
|
}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</Anchor>
|
||||||
<div>
|
<div>
|
||||||
{detail.image_type ? (
|
{detail.image_type ? (
|
||||||
<div className="edu-txt-center pt20 pb20">
|
<div className="edu-txt-center pt20 pb20">
|
||||||
|
@ -272,7 +309,7 @@ class CoderRootFileDetail extends Component {
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
md && readOnly ?
|
md && readOnly ?
|
||||||
<div className="files-md">
|
<div className="files-md" id="files-md">
|
||||||
<RenderHtml className="file-md imageLayerParent" value={description} url={this.props.history.location}/>
|
<RenderHtml className="file-md imageLayerParent" value={description} url={this.props.history.location}/>
|
||||||
</div>
|
</div>
|
||||||
:
|
:
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import React , { Component } from 'react';
|
import React , { Component } from 'react';
|
||||||
import { Route , Switch } from 'react-router-dom';
|
import { Route , Switch } from 'react-router-dom';
|
||||||
import Top from './DetailTop';
|
// import Top from './DetailTop';
|
||||||
import Loadable from 'react-loadable';
|
import Loadable from 'react-loadable';
|
||||||
import Loading from '../../Loading';
|
import Loading from '../../Loading';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
import './Index.scss';
|
||||||
|
|
||||||
const FileNew = Loadable({
|
const FileNew = Loadable({
|
||||||
loader: () => import('../Newfile/Index'),
|
loader: () => import('../Newfile/Index'),
|
||||||
|
@ -18,25 +19,25 @@ const CoderRootCommit = Loadable({
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
})
|
})
|
||||||
const CoderRootBranch = Loadable({
|
const CoderRootBranch = Loadable({
|
||||||
loader: () => import('./CoderRootBranch'),
|
loader: () => import('./tree/Index'),
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
})
|
})
|
||||||
const CoderRootTag = Loadable({
|
const CoderRootTag = Loadable({
|
||||||
loader: () => import('./CoderRootTag'),
|
loader: () => import('./tag/Index'),
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
})
|
})
|
||||||
const CoderRootVersion = Loadable({
|
const CoderRootVersion = Loadable({
|
||||||
loader: () => import('../Version/version'),
|
loader: () => import('./version/Index'),
|
||||||
loading: Loading,
|
|
||||||
})
|
|
||||||
const CoderRootVersionNew = Loadable({
|
|
||||||
loader: () => import('../Version/New'),
|
|
||||||
loading: Loading,
|
|
||||||
})
|
|
||||||
const CoderRootVersionUpdate = Loadable({
|
|
||||||
loader: () => import('../Version/New'),
|
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
})
|
})
|
||||||
|
// const CoderRootVersionNew = Loadable({
|
||||||
|
// loader: () => import('./version/New'),
|
||||||
|
// loading: Loading,
|
||||||
|
// })
|
||||||
|
// const CoderRootVersionUpdate = Loadable({
|
||||||
|
// loader: () => import('./version/New'),
|
||||||
|
// loading: Loading,
|
||||||
|
// })
|
||||||
const Diff = Loadable({
|
const Diff = Loadable({
|
||||||
loader: () => import('./Diff'),
|
loader: () => import('./Diff'),
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
|
@ -83,8 +84,8 @@ class CoderRootIndex extends Component{
|
||||||
}
|
}
|
||||||
render(){
|
render(){
|
||||||
return(
|
return(
|
||||||
<div>
|
<div className="coderSubPage">
|
||||||
<Top {...this.props} {...this.state}/>
|
{/* <Top {...this.props} {...this.state}/> */}
|
||||||
<Switch {...this.props}>
|
<Switch {...this.props}>
|
||||||
{/* 新建文件 */}
|
{/* 新建文件 */}
|
||||||
<Route path="/:owner/:projectsId/:branch/newfile/:path"
|
<Route path="/:owner/:projectsId/:branch/newfile/:path"
|
||||||
|
@ -117,7 +118,7 @@ class CoderRootIndex extends Component{
|
||||||
() => (<CoderRootCommit {...this.props} {...this.state} commit_class="main" getTopCount={this.getTopCount} />)
|
() => (<CoderRootCommit {...this.props} {...this.state} commit_class="main" getTopCount={this.getTopCount} />)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
<Route path="/:owner/:projectsId/releases/:versionId/update"
|
{/* <Route path="/:owner/:projectsId/releases/:versionId/update"
|
||||||
render={
|
render={
|
||||||
(props) => (<CoderRootVersionUpdate {...this.props} {...this.state} {...props} />)
|
(props) => (<CoderRootVersionUpdate {...this.props} {...this.state} {...props} />)
|
||||||
}
|
}
|
||||||
|
@ -126,7 +127,7 @@ class CoderRootIndex extends Component{
|
||||||
render={
|
render={
|
||||||
() => (<CoderRootVersionNew {...this.props} {...this.state} />)
|
() => (<CoderRootVersionNew {...this.props} {...this.state} />)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route> */}
|
||||||
<Route path="/:owner/:projectsId/releases"
|
<Route path="/:owner/:projectsId/releases"
|
||||||
render={
|
render={
|
||||||
() => (<CoderRootVersion {...this.props} {...this.state} />)
|
() => (<CoderRootVersion {...this.props} {...this.state} />)
|
||||||
|
|
|
@ -1,35 +1,55 @@
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { Button ,Spin } from "antd";
|
import { Button ,Spin } from "antd";
|
||||||
import { truncateCommitId } from '../common/util';
|
import { timeFormat, truncateCommitId } from '../common/util';
|
||||||
import { getImageUrl } from 'educoder';
|
import { getImageUrl } from 'educoder';
|
||||||
import Files from '../Merge/Files';
|
import Files from '../Merge/Files';
|
||||||
|
import Tree from "./img/tree.png";
|
||||||
import User from "../Component/User";
|
import User from "../Component/User";
|
||||||
import Keys from "../Component/Keys";
|
|
||||||
|
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
|
||||||
const Infos = styled.div`
|
const Infos = styled.div`
|
||||||
border: 1px solid #dddddd;
|
border: 1px solid #FAFCFF;
|
||||||
margin-bottom:15px;
|
margin-bottom:15px;
|
||||||
& .commitinfos {
|
& .commitinfos {
|
||||||
background-color: #f1f8ff;
|
background-color: #f1f8ff;
|
||||||
border-bottom: 1px solid #ddd;
|
border: 1px solid rgba(42, 97, 255, 0.23);
|
||||||
padding: 20px;
|
border-radius: 3px 3px 0px 0px;
|
||||||
|
padding: 10px 20px 10px 16px;
|
||||||
|
& .f-wrap-between{
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
& .task-hide{
|
||||||
|
width: 65rem;
|
||||||
|
overflow:hidden;
|
||||||
|
white-space:normal;
|
||||||
|
word-break:break-all;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333333;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
& > .f-wrap-between {
|
& > .f-wrap-between {
|
||||||
padding: 10px 20px;
|
padding: 14px 20px 14px 16px;
|
||||||
|
border-radius: 3px 3px 0px 0px;
|
||||||
|
border: 1px solid #D0D0D0;
|
||||||
|
.df{
|
||||||
|
align-items: center;
|
||||||
|
& .underline:hover{
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
//提交详情页
|
||||||
export default ({ match , history }) => {
|
export default (props) => {
|
||||||
|
const {match , history } = props;
|
||||||
const [data, setData] = useState({undefined});
|
const [data, setData] = useState({undefined});
|
||||||
const [commit, setCommit] = useState(undefined);
|
const [commit, setCommit] = useState(undefined);
|
||||||
const [parents, setParents] = useState(undefined);
|
const [parents, setParents] = useState(undefined);
|
||||||
const [committer, setCommitter] = useState(undefined);
|
const [committer, setCommitter] = useState(undefined);
|
||||||
const [isSpin, setIsSpin] = useState(true);
|
const [isSpin, setIsSpin] = useState(true);
|
||||||
|
|
||||||
const { sha , projectsId, owner } = match.params;
|
const { sha , projectsId, owner } = match.params;
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (projectsId && owner && sha) {
|
if (projectsId && owner && sha) {
|
||||||
|
@ -43,6 +63,7 @@ export default ({ match , history }) => {
|
||||||
setParents(result.data.parents);
|
setParents(result.data.parents);
|
||||||
setCommitter(result.data.committer || (result.data.commit && result.data.commit.committer));
|
setCommitter(result.data.committer || (result.data.commit && result.data.commit.committer));
|
||||||
setIsSpin(false);
|
setIsSpin(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
|
@ -56,29 +77,42 @@ export default ({ match , history }) => {
|
||||||
<Infos>
|
<Infos>
|
||||||
<div className="commitinfos">
|
<div className="commitinfos">
|
||||||
<div className="f-wrap-between">
|
<div className="f-wrap-between">
|
||||||
{commit && commit.message &&
|
<div>
|
||||||
<pre className="task-hide" style={{marginBottom:"0px",height:"28px",whiteSpace:"pre-wrap"}}>{commit.message}</pre>
|
{commit && commit.message &&
|
||||||
}
|
<pre className="task-hide">{commit.message}</pre>
|
||||||
<Button type="primary" onClick={()=>{history.push(`/${owner}/${projectsId}/tree/${truncateCommitId(sha)}`)}} className="ml30">浏览代码</Button>
|
}
|
||||||
|
<Link to={`/${owner}/${projectsId}/tree/${data.branch}`}><i className="iconfont icon-fenzhi2 font-18"></i>{data.branch}</Link>
|
||||||
|
</div>
|
||||||
|
<Button type="primary" onClick={()=>{history.push(`/${owner}/${projectsId}/tree/${truncateCommitId(sha)}`)}} className="btnblue" style={{height:"36px"}}>浏览文件</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="f-wrap-between" style={{ alignItems: "center" }}>
|
<div className="f-wrap-between" style={{ alignItems: "center" }}>
|
||||||
<ul className="df">
|
<ul className="df">
|
||||||
<User
|
<User
|
||||||
url={(committer && getImageUrl(`/${committer.image_url}`))|| "https://dss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3025493530,1989042357&fm=26&gp=0.jpg"}
|
id = {committer && committer.id}
|
||||||
|
url={(committer && getImageUrl(`/${committer.image_url}`))}
|
||||||
name={committer && committer.name}
|
name={committer && committer.name}
|
||||||
|
login={committer && committer.login}
|
||||||
/>
|
/>
|
||||||
{committer && committer.time_from_now && <li className="ml20 mt2">{committer.time_from_now}</li>}
|
{commit && commit.timestamp && <li className="ml4">提交于{timeFormat(commit.timestamp)}</li>}
|
||||||
</ul>
|
</ul>
|
||||||
<li className="df">
|
<li className="df">
|
||||||
{
|
{
|
||||||
parents && parents.length > 0 && parents.map((item,key)=>{
|
parents && parents.length > 0 && parents.map((item,key)=>{
|
||||||
return(
|
return(
|
||||||
<Keys title="父节点" value={truncateCommitId(item.sha)} key={key} className="mr20"></Keys>
|
<div className="ml40 f-wrap-alignCenter">
|
||||||
|
<label className="mr8">父节点</label>
|
||||||
|
<img src={Tree} alt="sha" width={"16px"} className="mr4"/>
|
||||||
|
<Link to={`/${owner}/${projectsId}/commits/${truncateCommitId(`${item.sha}`)}/${data.branch}`} className="underline">{truncateCommitId(item.sha)}</Link>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
<Keys title="当前节点" value={truncateCommitId(sha)}></Keys>
|
<div className="ml40 f-wrap-alignCenter">
|
||||||
|
<label className="mr8">当前节点</label>
|
||||||
|
<img src={Tree} alt="sha" width={"16px"} className="mr4"/>
|
||||||
|
<span>{truncateCommitId(sha)}</span>
|
||||||
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</div>
|
</div>
|
||||||
</Infos>
|
</Infos>
|
||||||
|
@ -87,6 +121,7 @@ export default ({ match , history }) => {
|
||||||
data={data}
|
data={data}
|
||||||
owner={owner}
|
owner={owner}
|
||||||
projectsId={projectsId}
|
projectsId={projectsId}
|
||||||
|
parentsSha={parents && parents.length > 0 && parents[0].sha}
|
||||||
/>
|
/>
|
||||||
</Spin>
|
</Spin>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -189,13 +189,13 @@
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
padding-bottom: 2px;
|
padding-bottom: 2px;
|
||||||
a{
|
a{
|
||||||
margin: 0px 17px 0px 0px;
|
margin: 0px 17px 10px 0px;
|
||||||
img{
|
img{
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
width: 40px;
|
width: 40px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
}
|
}
|
||||||
&:nth-child(6){
|
&:nth-child(5){
|
||||||
margin-right: 0px;
|
margin-right: 0px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -253,7 +253,7 @@
|
||||||
background-color: #FAFCFF;
|
background-color: #FAFCFF;
|
||||||
.ellipsistxt{
|
.ellipsistxt{
|
||||||
margin-top: 6px;
|
margin-top: 6px;
|
||||||
cursor: pointer;
|
// cursor: pointer;
|
||||||
#ptxt{
|
#ptxt{
|
||||||
margin-bottom: 0px;
|
margin-bottom: 0px;
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
|
@ -402,6 +402,16 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background: #FAFBFC;
|
background: #FAFBFC;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
.ant-dropdown-menu-item{
|
||||||
|
border-radius: 8px;
|
||||||
|
text-align: left!important;
|
||||||
|
a{
|
||||||
|
width: 350px;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
}
|
||||||
border: 1px solid #D0D0D0;
|
border: 1px solid #D0D0D0;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
|
@ -447,4 +457,28 @@
|
||||||
.ant-anchor-ink::before{
|
.ant-anchor-ink::before{
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
.coderSubPage{
|
||||||
|
width: 1200px;
|
||||||
|
margin:0px auto;
|
||||||
|
}
|
||||||
|
.griditemAnchor{
|
||||||
|
margin-left: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
.ant-anchor{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 10px 20px;
|
||||||
|
}
|
||||||
|
.griditemCate{
|
||||||
|
color: #333;
|
||||||
|
font-size: 16px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
.catelogue{
|
||||||
|
margin-left: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
Binary file not shown.
After Width: | Height: | Size: 631 B |
Binary file not shown.
After Width: | Height: | Size: 590 B |
|
@ -575,6 +575,9 @@
|
||||||
border:1px solid #ddd;
|
border:1px solid #ddd;
|
||||||
margin-top: 18px;
|
margin-top: 18px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
.ant-anchor-wrapper{
|
||||||
|
overflow: unset!important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.commonBox .commonBox-title{
|
.commonBox .commonBox-title{
|
||||||
padding:0px 20px;
|
padding:0px 20px;
|
||||||
|
@ -719,12 +722,76 @@ a.color-grey-ccc:hover{
|
||||||
padding:0px 30px;
|
padding:0px 30px;
|
||||||
min-height: 400px;
|
min-height: 400px;
|
||||||
}
|
}
|
||||||
.commitList > div{
|
|
||||||
border-bottom: 1px solid #EEEEEE;
|
.main{
|
||||||
padding:16px 0px;
|
margin: 30px auto;
|
||||||
}
|
.ant-timeline{
|
||||||
.commitList > div:last-child{
|
margin-top: 28px;
|
||||||
border-bottom: none;
|
.commitList-item{
|
||||||
|
position: relative;
|
||||||
|
padding: 20px 20px;
|
||||||
|
background: #FAFCFF;
|
||||||
|
border: 1px solid rgba(42, 97, 255, 0.23);
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-left: 16px;
|
||||||
|
align-items: center;
|
||||||
|
&:after,&:before{
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
left: -10px;
|
||||||
|
top: 10px;
|
||||||
|
border-top: 6px solid transparent;
|
||||||
|
border-bottom: 6px solid transparent;
|
||||||
|
border-right: 10px solid rgba(42, 97, 255, 0.23);
|
||||||
|
}
|
||||||
|
&:after{
|
||||||
|
left: -8px;
|
||||||
|
border-right: 10px solid #FAFCFF;
|
||||||
|
&:hover{
|
||||||
|
border-right: 10px solid #EEF6FF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&:hover{
|
||||||
|
background: #EEF6FF;
|
||||||
|
border: 1px solid rgba(42, 97, 255, 0.58);
|
||||||
|
&:after{
|
||||||
|
border-right: 10px solid #EEF6FF;
|
||||||
|
}
|
||||||
|
&:before{
|
||||||
|
border-right: 10px solid rgba(42, 97, 255, 0.58);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.treecopy-cont{
|
||||||
|
padding: 4px 15px;
|
||||||
|
}
|
||||||
|
.btn-83{
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ant-timeline-item{
|
||||||
|
padding: 8px 0 20px;
|
||||||
|
}
|
||||||
|
.ant-timeline-item-tail{
|
||||||
|
height: calc(100% - 20px);
|
||||||
|
border-left: 2px solid #EEEEEE;
|
||||||
|
top: 12px;
|
||||||
|
&:after{
|
||||||
|
content: ' ';
|
||||||
|
height: 0;
|
||||||
|
position: absolute;
|
||||||
|
width: 0;
|
||||||
|
border: 7px solid transparent;
|
||||||
|
border-top-color: #EEEEEE;
|
||||||
|
top: 100%;
|
||||||
|
left: 50%;
|
||||||
|
margin-left: -8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ant-timeline-item-head-custom{
|
||||||
|
top:20px;
|
||||||
|
padding: 0 1px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,7 @@ function DetailBanner({ history,list , owner , projectsId , isManager , url , pa
|
||||||
</li>
|
</li>
|
||||||
:""
|
:""
|
||||||
}
|
}
|
||||||
{
|
{/* {
|
||||||
item.menu_name === "resources" &&
|
item.menu_name === "resources" &&
|
||||||
<li className={pathname==="source" ? "active" : ""}>
|
<li className={pathname==="source" ? "active" : ""}>
|
||||||
<Link to={{ pathname: `/${owner}/${projectsId}/source`, state }}>
|
<Link to={{ pathname: `/${owner}/${projectsId}/source`, state }}>
|
||||||
|
@ -95,7 +95,7 @@ function DetailBanner({ history,list , owner , projectsId , isManager , url , pa
|
||||||
{projectDetail && projectDetail.source_count ? <span className="num">{projectDetail.source_count}</span> :""}
|
{projectDetail && projectDetail.source_count ? <span className="num">{projectDetail.source_count}</span> :""}
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
}
|
} */}
|
||||||
{
|
{
|
||||||
item.menu_name === "versions" &&
|
item.menu_name === "versions" &&
|
||||||
<li className={pathname==="milestones" ? "active" : ""}>
|
<li className={pathname==="milestones" ? "active" : ""}>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React , { useState , useEffect } from 'react';
|
import React , { useState } from 'react';
|
||||||
import { Anchor , Input } from 'antd';
|
import { Anchor , Input } from 'antd';
|
||||||
import './sub.scss';
|
import './sub.scss';
|
||||||
import { Base64 } from 'js-base64';
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
const { Link } = Anchor;
|
const { Link } = Anchor;
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ function ReadmeCatelogue({ menuList , hash }) {
|
||||||
function changeValue(e) {
|
function changeValue(e) {
|
||||||
setValue(e.target.value);
|
setValue(e.target.value);
|
||||||
if(e.target.value){
|
if(e.target.value){
|
||||||
let m = menuList.filter(i=>i.text.indexOf(e.target.value)>-1);
|
let m = menuList.filter(i=>i.text.toLowerCase().indexOf(e.target.value.toLowerCase())>-1);
|
||||||
setMenu(m);
|
setMenu(m);
|
||||||
}else{
|
}else{
|
||||||
setMenu(menuList);
|
setMenu(menuList);
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
import'./sub.scss'
|
||||||
|
|
||||||
|
function SubMenu({tab,owner,projectsId}) {
|
||||||
|
return(
|
||||||
|
<ul className="subMenu">
|
||||||
|
<Link to={`/${owner}/${projectsId}/tags`} className={tab==="tags"?"active":""}>标签</Link>
|
||||||
|
<Link to={`/${owner}/${projectsId}/releases`} className={tab==="releases"?"active":""}>发行版</Link>
|
||||||
|
</ul>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default SubMenu;
|
|
@ -64,4 +64,28 @@
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
.subMenu{
|
||||||
|
display: flex;
|
||||||
|
padding-top: 30px;
|
||||||
|
a{
|
||||||
|
width: 83px;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 30px;
|
||||||
|
height: 32px;
|
||||||
|
color: #333333!important;
|
||||||
|
text-align: center;
|
||||||
|
border: 1px solid #D0D0D0;
|
||||||
|
border-radius: 0px 4px 4px 0px;
|
||||||
|
background: rgba(250, 251, 252, 0);
|
||||||
|
&:first-child{
|
||||||
|
border-right: none;
|
||||||
|
border-radius: 4px 0px 0px 4px;
|
||||||
|
}
|
||||||
|
&.active{
|
||||||
|
background-color: #466AFF;
|
||||||
|
color: #fff!important;
|
||||||
|
border-color: #466AFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,105 @@
|
||||||
|
import React,{ useEffect , useState } from 'react';
|
||||||
|
import SubMenu from '../sub/SubMenu';
|
||||||
|
import { Table , Tooltip } from 'antd';
|
||||||
|
import axios from 'axios';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
import { truncateCommitId } from '../../common/util';
|
||||||
|
import './Index.scss';
|
||||||
|
import Tree from '../img/tree.png'
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
|
|
||||||
|
function Tags(props) {
|
||||||
|
|
||||||
|
const [ source , setSource ] = useState([]);
|
||||||
|
|
||||||
|
const { projectsId , owner } = props.match.params;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (projectsId) {
|
||||||
|
const url = `/${owner}/${projectsId}/tags.json`;
|
||||||
|
axios.get(url).then((result) => {
|
||||||
|
if (result) {
|
||||||
|
setSource(result.data);
|
||||||
|
}
|
||||||
|
}).catch(error => {})
|
||||||
|
}
|
||||||
|
}, [owner, projectsId]);
|
||||||
|
|
||||||
|
const columns=[
|
||||||
|
{
|
||||||
|
title:"标签名",
|
||||||
|
dataIndex:"name",
|
||||||
|
key:1,
|
||||||
|
ellipsis:true,
|
||||||
|
render:(txt,item)=>{
|
||||||
|
return <Link className="hover" to={`/${owner}/${projectsId}/tree/${item.name}`} >{item.name}</Link>
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title:"创建时间",
|
||||||
|
dataIndex:"time_ago",
|
||||||
|
key:2,
|
||||||
|
ellipsis:true,
|
||||||
|
render:(txt,item)=>{
|
||||||
|
return (
|
||||||
|
<span className="color-grey-3">
|
||||||
|
<Link className="mr3" style={{fontWeight:"500"}} to={`/${item.commit && item.commit.login}`} >{item.commit && item.commit.name}</Link>
|
||||||
|
<span>创建于{txt}</span>
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title:"提交ID",
|
||||||
|
dataIndex:"id",
|
||||||
|
key:3,
|
||||||
|
ellipsis:true,
|
||||||
|
render:(txt,item)=>{
|
||||||
|
return (
|
||||||
|
<Tooltip placement="top" title={`最后提交日期:${item.created_at_unix ? moment(item.created_at_unix*1000).format('YYYY-MM-DD'):''}`}>
|
||||||
|
<img src={Tree} alt="提交ID" width="22px" className="mr4"/>
|
||||||
|
<Link className="hover color-blue" to={`/${owner}/${projectsId}/commits/${truncateCommitId(`${item.id}`)}`}>{truncateCommitId(item.id)}</Link>
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title:"描述信息",
|
||||||
|
dataIndex:"message",
|
||||||
|
key:4,
|
||||||
|
ellipsis:true,
|
||||||
|
render:(txt,item)=>{
|
||||||
|
return item.message || "--"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title:"下载",
|
||||||
|
dataIndex:"stage_type",
|
||||||
|
key:5,
|
||||||
|
ellipsis:true,
|
||||||
|
align:"center",
|
||||||
|
width:"181px",
|
||||||
|
render:(txt,item)=>{
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<a href={`${item.tarball_url}`} download className="btn-83">
|
||||||
|
<i className="iconfont icon-xiazai-icon font-16 mr5"></i>TAR
|
||||||
|
</a>
|
||||||
|
<a href={`${item.zipball_url}`} download className="btn-83">
|
||||||
|
<i className="iconfont icon-xiazai-icon font-16 mr5"></i>ZIP
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
return(
|
||||||
|
<div>
|
||||||
|
<SubMenu tab={"tags"} projectsId={projectsId} owner={owner}/>
|
||||||
|
<Table className="tagTable" dataSource={source} columns={columns} pagination={false}></Table>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default Tags;
|
|
@ -0,0 +1,31 @@
|
||||||
|
.tagTable{
|
||||||
|
margin-top: 30px;
|
||||||
|
thead{
|
||||||
|
tr th{
|
||||||
|
background-color: #fff;
|
||||||
|
padding:5px 0px;
|
||||||
|
.ant-table-column-title{
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tbody{
|
||||||
|
tr{
|
||||||
|
&:hover td{
|
||||||
|
background-color: #fff!important;
|
||||||
|
}
|
||||||
|
td{
|
||||||
|
padding:0px;
|
||||||
|
height: 69px;
|
||||||
|
line-height: 69px;
|
||||||
|
}
|
||||||
|
&:last-child{
|
||||||
|
td{
|
||||||
|
border-bottom: none!important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,114 @@
|
||||||
|
import React , { useEffect , useState } from 'react';
|
||||||
|
import CopyTool from '../../Component/CopyTool';
|
||||||
|
import { truncateCommitId } from '../../common/util';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
import { getImageUrl } from 'educoder';
|
||||||
|
import { Dropdown , Menu , Spin } from 'antd';
|
||||||
|
import './Index.scss';
|
||||||
|
|
||||||
|
import Tree from '../img/tree.png';
|
||||||
|
import Axios from 'axios';
|
||||||
|
|
||||||
|
function turnbar(str){
|
||||||
|
if(str && str.length>0 && str.indexOf("/")>-1){
|
||||||
|
return str.replaceAll('/','%2F');
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
function Index(props) {
|
||||||
|
const [ list , setList ] = useState([]);
|
||||||
|
const [ isSpin , setIsSpin ] = useState(true);
|
||||||
|
|
||||||
|
const { projectsId , owner } = props.match.params;
|
||||||
|
const { isManager , isDeveloper , projectDetail } = props;
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
getList();
|
||||||
|
},[])
|
||||||
|
|
||||||
|
|
||||||
|
const menu =(zip_url,tar_url)=> (
|
||||||
|
<Menu>
|
||||||
|
<Menu.Item key={'0'}><a href={zip_url}>ZIP</a></Menu.Item>
|
||||||
|
<Menu.Item key={'1'}><a href={tar_url}>TAR.GZ</a></Menu.Item>
|
||||||
|
</Menu>
|
||||||
|
)
|
||||||
|
|
||||||
|
function getList() {
|
||||||
|
const url = `/${owner}/${projectsId}/branches_slice.json`;
|
||||||
|
Axios.get(url).then(result=>{
|
||||||
|
if(result){
|
||||||
|
setList(result.data);
|
||||||
|
}
|
||||||
|
setIsSpin(false);
|
||||||
|
}).catch(error=>{setIsSpin(false);})
|
||||||
|
}
|
||||||
|
|
||||||
|
return(
|
||||||
|
<Spin spinning={isSpin}>
|
||||||
|
<div style={{paddingTop:"10px",minHeight:"400px"}}>
|
||||||
|
{
|
||||||
|
list && list.length>0 && list.map((item,key)=>{
|
||||||
|
return(
|
||||||
|
<React.Fragment>
|
||||||
|
<p className="branchSort">{item.branch_type === "default" ? "默认分支" : item.branch_type==="protected"?"保护分支":"其它分支"}</p>
|
||||||
|
{
|
||||||
|
item.list && item.list.length>0 &&
|
||||||
|
<ul className="treeUl">
|
||||||
|
{
|
||||||
|
item.list.map((i,k)=>{
|
||||||
|
let last_commit = i.last_commit;
|
||||||
|
return(
|
||||||
|
<li>
|
||||||
|
<div className="treeinfo">
|
||||||
|
<Link to={`/${owner}/${projectsId}/tree/${turnbar(i.name)}`} className="task-hide">{i.name}</Link>
|
||||||
|
<div>
|
||||||
|
{
|
||||||
|
last_commit && last_commit.committer && last_commit.committer.id?
|
||||||
|
<Link to={`/${ last_commit.committer.login}`}>
|
||||||
|
<img style={{borderRadius:"50%"}} src={getImageUrl(`/${ last_commit.committer.image_url}`)} alt=""/>
|
||||||
|
<span className="mr3 color-grey-3" style={{fontWeight:"500"}}>{last_commit && last_commit.committer && last_commit.committer.name}</span>
|
||||||
|
</Link>
|
||||||
|
:
|
||||||
|
<React.Fragment>
|
||||||
|
<img style={{borderRadius:"50%"}} src={getImageUrl(`/${ last_commit.committer.image_url}`)} alt=""/>
|
||||||
|
<span className="mr3 color-grey-3" style={{fontWeight:"500"}}>{last_commit && last_commit.committer && last_commit.committer.name}</span>
|
||||||
|
</React.Fragment>
|
||||||
|
}
|
||||||
|
<span className="color-grey-3">更新于{last_commit && last_commit.time_from_now}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="treecopy">
|
||||||
|
<div>
|
||||||
|
<span>
|
||||||
|
<img src={Tree} alt="sha" width={"16px"}/>
|
||||||
|
<Link to={`/${owner}/${projectsId}/commits/${truncateCommitId(last_commit && last_commit.sha)}`}>{truncateCommitId(last_commit && last_commit.sha)}</Link>
|
||||||
|
<input type="text" id={`value${key}${k}`} value={`${truncateCommitId(last_commit && last_commit.sha)}`}/>
|
||||||
|
</span>
|
||||||
|
<CopyTool beforeText="复制commit id" afterText="复制成功" inputId={`value${key}${k}`}/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="treeabout">
|
||||||
|
{
|
||||||
|
(isManager || isDeveloper) && (projectDetail && projectDetail.type!==2) &&
|
||||||
|
<Link to={`/${owner}/${projectsId}/pulls/new/${i.name}`} className="btn-83">+ 合并请求</Link>
|
||||||
|
}
|
||||||
|
<Dropdown overlay={menu(i.zip_url,i.tar_url)} trigger={['click']} placement="bottomRight">
|
||||||
|
<a className="btn-83 ml15">下载<i className="iconfont icon-sanjiaoxing-down font-14"></i></a>
|
||||||
|
</Dropdown>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
}
|
||||||
|
</React.Fragment>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</Spin>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default Index;
|
|
@ -0,0 +1,96 @@
|
||||||
|
.branchSort{
|
||||||
|
font-weight: 500;
|
||||||
|
color: #333333;
|
||||||
|
font-size: 15px;
|
||||||
|
height: 20px;
|
||||||
|
line-height: 20px;
|
||||||
|
padding-left: 10px;
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-bottom: 6px!important;
|
||||||
|
}
|
||||||
|
.treeUl{
|
||||||
|
background: #FAFCFF;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid rgba(42, 97, 255, 0.23);
|
||||||
|
li{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 12px 20px;
|
||||||
|
border-bottom: 1px solid rgba(42, 97, 255, 0.23);
|
||||||
|
&:last-child{
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
.treeinfo{
|
||||||
|
max-width: 399px;
|
||||||
|
flex:1;
|
||||||
|
flex-direction: column;
|
||||||
|
a:hover{
|
||||||
|
span{
|
||||||
|
color: #466AFF!important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
img{
|
||||||
|
height: 20px;
|
||||||
|
width: 20px;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.treeabout{
|
||||||
|
flex:1;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.treecopy{
|
||||||
|
flex:1;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
&>div{
|
||||||
|
height: 32px;
|
||||||
|
background: #FAFBFC;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #D0D0D0;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
&>span{
|
||||||
|
padding:0px 15px;
|
||||||
|
border-right: 1px solid rgba(153, 153, 153, 0.4);
|
||||||
|
height: 100%;
|
||||||
|
img{
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
a{
|
||||||
|
color: #466AFF;
|
||||||
|
&:hover{
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&>i{
|
||||||
|
margin:0px 12px;
|
||||||
|
color: #333!important;
|
||||||
|
}
|
||||||
|
input{
|
||||||
|
position: absolute;
|
||||||
|
z-index: 0;
|
||||||
|
opacity: 0;
|
||||||
|
top: 32px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.new-conmmit{
|
||||||
|
width: 30px;
|
||||||
|
height: 18px;
|
||||||
|
line-height: 18px;
|
||||||
|
display: block;
|
||||||
|
background: #FF6832;
|
||||||
|
color: white;
|
||||||
|
font-size: 12px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
.icon-a-yuanquan2x{
|
||||||
|
color: #466AFF;
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { Button } from 'antd';
|
||||||
|
import React from 'react';
|
||||||
|
import './version.scss';
|
||||||
|
|
||||||
|
function Empty({operation,addFunc}) {
|
||||||
|
return(
|
||||||
|
<div className="emptyPanel color-grey-3">
|
||||||
|
<i className="iconfont icon-banbenicon font-50 color-grey-3" style={{height:"50px",lineHeight:"50px",marginBottom:"13px"}}></i>
|
||||||
|
<span className="weight font-26 mb15">这里暂未发布过任何版本</span>
|
||||||
|
<span className="weight400" style={{textAlign:"center",lineHeight:"20px"}}>发行版功能基于仓库中的历史标记<br/>建议使用类似 V1.0 的版本标记作为发布点</span>
|
||||||
|
<div className="operation">
|
||||||
|
{
|
||||||
|
operation ?
|
||||||
|
<Button type={"primary"} onClick={addFunc} className="btnblue" style={{width:"118px",height:"36px"}}>发布新版本</Button>
|
||||||
|
:
|
||||||
|
<span className="color-grey-3 weight font-16">该项目暂时没有发布版本</span>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default Empty;
|
|
@ -0,0 +1,41 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Switch , Route } from 'react-router';
|
||||||
|
import Loadable from 'react-loadable';
|
||||||
|
import Loading from '../../../Loading';
|
||||||
|
import SubMenu from '../sub/SubMenu';
|
||||||
|
import "./version.scss";
|
||||||
|
|
||||||
|
const CoderRootVersion = Loadable({
|
||||||
|
loader: () => import('./version'),
|
||||||
|
loading: Loading,
|
||||||
|
})
|
||||||
|
const CoderRootVersionNew = Loadable({
|
||||||
|
loader: () => import('./New'),
|
||||||
|
loading: Loading,
|
||||||
|
})
|
||||||
|
function Index(props) {
|
||||||
|
const { projectsId , owner } = props.match.params;
|
||||||
|
return(
|
||||||
|
<div>
|
||||||
|
<SubMenu tab={"releases"} projectsId={projectsId} owner={owner}/>
|
||||||
|
<Switch>
|
||||||
|
<Route path="/:owner/:projectsId/releases/:versionId/update"
|
||||||
|
render={
|
||||||
|
(p) => (<CoderRootVersionNew {...props} {...p} />)
|
||||||
|
}
|
||||||
|
></Route>
|
||||||
|
<Route path="/:owner/:projectsId/releases/new"
|
||||||
|
render={
|
||||||
|
(p) => (<CoderRootVersionNew {...props} {...p} />)
|
||||||
|
}
|
||||||
|
></Route>
|
||||||
|
<Route path="/:owner/:projectsId/releases"
|
||||||
|
render={
|
||||||
|
(p) => (<CoderRootVersion {...props} {...p} />)
|
||||||
|
}
|
||||||
|
></Route>
|
||||||
|
</Switch>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default Index;
|
|
@ -0,0 +1,266 @@
|
||||||
|
import React, { useState, useEffect, forwardRef } from "react";
|
||||||
|
import styled from "styled-components";
|
||||||
|
import { AutoComplete , Input, Checkbox, Button, Form } from "antd";
|
||||||
|
import SelectBranch from '../../Branch/Select';
|
||||||
|
|
||||||
|
import Editor from "../../../modules/tpm/challengesnew/tpm-md-editor";
|
||||||
|
import Upload from "../../Upload/Index";
|
||||||
|
import Attachments from "../../Upload/attachment";
|
||||||
|
import axios from "axios";
|
||||||
|
import "./version.scss";
|
||||||
|
import { trim } from "lodash";
|
||||||
|
|
||||||
|
const { Option } = AutoComplete;
|
||||||
|
|
||||||
|
const Span = styled.span`
|
||||||
|
margin: 0px 15px;
|
||||||
|
color: #bbb;
|
||||||
|
line-height: 35px;
|
||||||
|
font-size:16px;
|
||||||
|
font-weight:400;
|
||||||
|
color:#666;
|
||||||
|
`;
|
||||||
|
export default Form.create()(
|
||||||
|
forwardRef(
|
||||||
|
(
|
||||||
|
{ form, projectDetail , match, showNotification, history },
|
||||||
|
ref
|
||||||
|
) => {
|
||||||
|
const { getFieldDecorator, validateFields, setFieldsValue } = form;
|
||||||
|
const [tagList, setTagList] = useState(undefined);
|
||||||
|
const [desc, setDesc] = useState(null);
|
||||||
|
const [branch, setBranch ] = useState(null);
|
||||||
|
const [fileList, setFileList] = useState(undefined);
|
||||||
|
const [attachment, setAttachment] = useState(undefined);
|
||||||
|
const [options , setOptions] = useState(undefined);
|
||||||
|
const stable = history && history.location && history.location.state.stable;
|
||||||
|
const { projectsId, versionId , owner } = match.params;
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
if(projectDetail && projectDetail.default_branch){
|
||||||
|
setBranch(projectDetail.default_branch);
|
||||||
|
}
|
||||||
|
},[projectDetail])
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (versionId) {
|
||||||
|
const url = `/${owner}/${projectsId}/releases/${versionId}/edit.json`;
|
||||||
|
axios.get(url).then(result => {
|
||||||
|
if (result) {
|
||||||
|
setFieldsValue(result.data);
|
||||||
|
setDesc(result.data.body);
|
||||||
|
setAttachment(result.data.attachments);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [versionId]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (projectsId) {
|
||||||
|
const url = `/${owner}/${projectsId}/tags.json`;
|
||||||
|
axios
|
||||||
|
.get(url,{params:{
|
||||||
|
limit:1000
|
||||||
|
}})
|
||||||
|
.then(result => {
|
||||||
|
if (result) {
|
||||||
|
setTagList(result.data);
|
||||||
|
setOptions(renderTagList(result.data));
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [projectsId]);
|
||||||
|
|
||||||
|
function renderTagList(list) {
|
||||||
|
if (list) {
|
||||||
|
let array = list.map((item, key) => {
|
||||||
|
return (
|
||||||
|
<Option key={key} value={item.name}>
|
||||||
|
{item.name}
|
||||||
|
</Option>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
return array || undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function submit() {
|
||||||
|
validateFields((err, value) => {
|
||||||
|
if(err)return;
|
||||||
|
if (versionId) {
|
||||||
|
let url = `/${owner}/${projectsId}/releases/${versionId}.json`;
|
||||||
|
axios
|
||||||
|
.put(url, {
|
||||||
|
...value,
|
||||||
|
body: desc,
|
||||||
|
attachment_ids: fileList,
|
||||||
|
target_commitish:branch
|
||||||
|
})
|
||||||
|
.then(result => {
|
||||||
|
if (result) {
|
||||||
|
showNotification("版本修改成功!");
|
||||||
|
history.push(`/${owner}/${projectsId}/releases`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
let url = `/${owner}/${projectsId}/releases.json`;
|
||||||
|
axios.post(url, {
|
||||||
|
...value,
|
||||||
|
body: desc,
|
||||||
|
attachment_ids: fileList
|
||||||
|
})
|
||||||
|
.then(result => {
|
||||||
|
if (result) {
|
||||||
|
showNotification("版本发布成功!");
|
||||||
|
history.push(`/${owner}/${projectsId}/releases`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// 输入标签名
|
||||||
|
function changeAuto(value){
|
||||||
|
let l = tagList.filter(item=>item.name.indexOf(value) > -1);
|
||||||
|
setOptions(renderTagList(l));
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeBranch(params) {
|
||||||
|
setBranch(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="df pt15">
|
||||||
|
<Form className="versionForm">
|
||||||
|
<div className="itemInline">
|
||||||
|
<Form.Item>
|
||||||
|
{getFieldDecorator("tag_name",
|
||||||
|
{ rules:[
|
||||||
|
{ required: true, message: "请输入获取或选择一个标签" },
|
||||||
|
{ validator: (rule,val,callback) =>{
|
||||||
|
if(val.length>30 || val.indexOf(' ')>0 || val.match(/^\s+$/) || trim(val).length!=val.length){
|
||||||
|
callback('无效的标签名称,请参考右侧建议命名标签并确认长度在1~30个字符之间');
|
||||||
|
}else{
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}}],
|
||||||
|
validateFirst: true
|
||||||
|
})(
|
||||||
|
<AutoComplete
|
||||||
|
placeholder="标记一个版本"
|
||||||
|
onChange={changeAuto}
|
||||||
|
style={{ width: "200px" }}
|
||||||
|
>
|
||||||
|
{options}
|
||||||
|
</AutoComplete>
|
||||||
|
)}
|
||||||
|
</Form.Item>
|
||||||
|
<Span>@</Span>
|
||||||
|
<SelectBranch
|
||||||
|
repo_id={projectDetail && projectDetail.repo_id}
|
||||||
|
projectsId={projectsId}
|
||||||
|
branch={branch}
|
||||||
|
changeBranch={changeBranch}
|
||||||
|
owner={owner}
|
||||||
|
history={history}
|
||||||
|
tagflag={false}
|
||||||
|
branchList={projectDetail && projectDetail.branches && projectDetail.branches.list}
|
||||||
|
></SelectBranch>
|
||||||
|
<p className="font-12 color-grey-6 weight400">选择一个已经存在的标签,或者在发布时新建一个标签</p>
|
||||||
|
</div>
|
||||||
|
<Form.Item className="pt20">
|
||||||
|
{getFieldDecorator("name",
|
||||||
|
{ rules:[
|
||||||
|
{ required: true, message: "请输入发行版的标题" },
|
||||||
|
{ validator: (rule,val,callback) =>{
|
||||||
|
if(val.length>50){
|
||||||
|
callback('标题长度在1~50个字符之间');
|
||||||
|
}else{
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}}],
|
||||||
|
validateFirst: true
|
||||||
|
})(
|
||||||
|
<Input placeholder="发行版的标题" />
|
||||||
|
)}
|
||||||
|
</Form.Item>
|
||||||
|
<Editor
|
||||||
|
placeholder={"描述此发行版"}
|
||||||
|
height={200}
|
||||||
|
mdID={`version-comments-description`}
|
||||||
|
initValue={desc}
|
||||||
|
onChange={setDesc}
|
||||||
|
noStorage={true}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="mt5 dragBox">
|
||||||
|
<Upload
|
||||||
|
className="versionStyle"
|
||||||
|
isComplete={true}
|
||||||
|
load={setFileList}
|
||||||
|
icon={
|
||||||
|
<i className="iconfont icon-shangchuanicon dragIcon" />
|
||||||
|
}
|
||||||
|
size={100}
|
||||||
|
showNotification={showNotification}
|
||||||
|
/>
|
||||||
|
{versionId && attachment && attachment.length > 0 ? (
|
||||||
|
<Attachments
|
||||||
|
attachments={attachment}
|
||||||
|
showNotification={showNotification}
|
||||||
|
canDelete={true}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<Form.Item className="prerelease">
|
||||||
|
{getFieldDecorator("prerelease",
|
||||||
|
{ rules:[],
|
||||||
|
validateFirst: true
|
||||||
|
})(
|
||||||
|
<Checkbox defaultChecked={!stable}>这是一个预览版本</Checkbox>
|
||||||
|
)}
|
||||||
|
</Form.Item>
|
||||||
|
<p className="pt20" style={{borderTop:"1px solid #eee"}}>
|
||||||
|
<Button onClick={submit} type="primary" className="mr30 btnblue">
|
||||||
|
{versionId ? "保存" : "创建"}发行版
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={() =>history.push(`/${owner}/${projectsId}/releases`)} className="btngrey"
|
||||||
|
>取消</Button>
|
||||||
|
</p>
|
||||||
|
</Form>
|
||||||
|
<div className="versionTips">
|
||||||
|
<div className="infosTip">
|
||||||
|
<p className="font-16 mb14 weight">标签命名建议</p>
|
||||||
|
<p className="mb15">
|
||||||
|
通常的做法是在版本名称前加上字母 v 前缀, v1.0 或者 v2.3.4。
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
如果标签不适合在生产环境下使用,请在版本名称后添加预发行版本。例如:v0.2-alpha
|
||||||
|
或者 v5.9-beta.3。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="infosTip">
|
||||||
|
<p className="font-16 mb14 weight">语义化版本</p>
|
||||||
|
<p>
|
||||||
|
如果你是第一次发布版本,我们强烈建议你阅读<a href='https://semver.org/lang/zh-CN' target='_blank' className="color-blue">语义化版本</a>。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="infosTip">
|
||||||
|
<p className="font-16 mb14 weight">附件大小说明</p>
|
||||||
|
<p>
|
||||||
|
单个附件不能超过 100M(GVP 项目200M),每个仓库总附件不可超过
|
||||||
|
1G(推荐项目不可超过 5G;GVP 项目不可超过
|
||||||
|
20G)。附件总容量统计包括仓库附件和发行版附件。
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
|
@ -0,0 +1,150 @@
|
||||||
|
import React, { useEffect , useState } from "react";
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
import { Spin , Button } from 'antd';
|
||||||
|
import { getImageUrl } from 'educoder';
|
||||||
|
import {truncateCommitId} from '../../common/util';
|
||||||
|
import Empty from './Empty';
|
||||||
|
import './version.scss';
|
||||||
|
import axios from 'axios';
|
||||||
|
import Tree from '../img/tree-black.png';
|
||||||
|
import RenderHtml from '../../../components/render-html';
|
||||||
|
import User from "../../Component/User";
|
||||||
|
|
||||||
|
function version(props) {
|
||||||
|
const [ data , setData ] = useState(undefined);
|
||||||
|
const [ releases , setReleases ] = useState(undefined);
|
||||||
|
const [ isSpin , setIsSpin ] = useState(true);
|
||||||
|
const { projectsId ,owner } = props.match.params;
|
||||||
|
const { isManager, isDeveloper, location , user } = props;
|
||||||
|
const type = props.projectDetail && props.projectDetail.type;
|
||||||
|
const turnFromNew = location && location.query && location.query.turnFromNew;
|
||||||
|
const current_user_login = user && user.login;
|
||||||
|
useEffect(()=>{
|
||||||
|
getIssueList();
|
||||||
|
},[])
|
||||||
|
// 获取列表数据
|
||||||
|
function getIssueList(){
|
||||||
|
const url = `/${owner}/${projectsId}/releases.json`;
|
||||||
|
axios.get(url).then((result) => {
|
||||||
|
if (result) {
|
||||||
|
setData(result.data);
|
||||||
|
const { releases = [] } = result.data;
|
||||||
|
//默认第一个展开(body参数)
|
||||||
|
releases.length && (releases[0].bodyshow = true);
|
||||||
|
setReleases(result.data.releases);
|
||||||
|
setIsSpin(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}).catch((error) => {
|
||||||
|
console.log(error);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 显示版本描述
|
||||||
|
function showBody(key,flag){
|
||||||
|
var lists = releases.concat();
|
||||||
|
lists[key].bodyshow = !flag ? true : false;
|
||||||
|
lists.splice();
|
||||||
|
setReleases(lists);
|
||||||
|
}
|
||||||
|
//删除
|
||||||
|
function deleteRelease(releaseId) {
|
||||||
|
if(releaseId){
|
||||||
|
axios.delete(`/${owner}/${projectsId}/releases/${releaseId}.json`).then((result)=>{
|
||||||
|
if(result){
|
||||||
|
getIssueList();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function release(item,key){
|
||||||
|
return (
|
||||||
|
<div className="versionInfo" key={key}>
|
||||||
|
<span className="versionInfo_left">
|
||||||
|
<span className={`${item.draft === "稳定" ?"versionTag green":"versionTag orange"}`}>{item.draft}</span>
|
||||||
|
<span className="color-grey-3 mt15 font-12">
|
||||||
|
<i className="iconfont icon-biaoqianicon mr3 font-14"></i>
|
||||||
|
<Link className="hover" to={`/${owner}/${projectsId}/tree/${item.tag_name}`} >{item.tag_name}</Link>
|
||||||
|
</span>
|
||||||
|
<span className="color-grey-3 font-12">
|
||||||
|
<img src={Tree} width="16px" color="#333333" className="mr3"/>
|
||||||
|
<Link className="hover" to={`/${owner}/${projectsId}/commits/${truncateCommitId(`${item.sha}`)}`}>{truncateCommitId(item.sha)}</Link>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<div className="versionInfo_right">
|
||||||
|
<div className="versionName">
|
||||||
|
<Link to={`/${owner}/${projectsId}/tree/${item.tag_name}`} className="task-hide color-blue hover font-18">{item.name}</Link>
|
||||||
|
<span>
|
||||||
|
{data && data.user_admin_permission && type !== 2 && <Link to={{pathname:`/${owner}/${projectsId}/releases/${item.version_id}/update`,state:{"stable":item.draft==="稳定"}}} className="ml15"><i className="iconfont icon-a-bianji1 font-16 color-grey-6"></i></Link>}
|
||||||
|
{data && data.user_admin_permission && type !== 2 && <i className ="iconfont icon-shanchuicon1 font-16 ml15" onClick={()=>{deleteRelease(item.version_id)}}></i>}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span className="color-grey-3 mb15 version-user">
|
||||||
|
<i className={`${item.bodyshow ? "iconfont icon-sanjiaoxing-down color-grey-8 mr3 font-14":"iconfont icon-triangle color-grey-8 mr3 font-14"}`} onClick={()=>showBody(key,item.bodyshow)}></i>
|
||||||
|
<User
|
||||||
|
id={item.id}
|
||||||
|
url={(item.image_url && getImageUrl(`/${item.image_url}`)) || "https://dss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3025493530,1989042357&fm=26&gp=0.jpg"}
|
||||||
|
name={item.user_name}
|
||||||
|
login={item.user_login}
|
||||||
|
/>
|
||||||
|
<span className="ml5">发布于{item.created_at}</span>
|
||||||
|
</span>
|
||||||
|
{
|
||||||
|
item.bodyshow &&
|
||||||
|
<div className="body-show">
|
||||||
|
<RenderHtml className="break_word_comments imageLayerParent" value={item.body || ''} url={props.history.location}/>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
<RenderHtml />
|
||||||
|
<p className="versionFile">
|
||||||
|
{/* 发行版附件下载 */}
|
||||||
|
{item.attachments && item.attachments.map((item)=>{
|
||||||
|
return(<a href={item.url}><i className="iconfont icon-wenjian7 font-14 mr10 color-grey-3"></i>下载 {item.title}</a>)
|
||||||
|
})}
|
||||||
|
{/* 发行版下载包 */}
|
||||||
|
<a href={item.tarball_url}><i className="iconfont icon-wenjian7 font-14 mr10 color-grey-3"></i>下载 {item.tag_name}.TAR.gz</a>
|
||||||
|
<a href={item.zipball_url}><i className="iconfont icon-wenjian7 font-14 mr10 color-grey-3"></i>下载 {item.tag_name}.ZIP</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
function renderList(releases){
|
||||||
|
if (releases && releases.length > 0) {
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
{
|
||||||
|
data && data.user_admin_permission && type !== 2 &&
|
||||||
|
<div className="addReleaseBtn">
|
||||||
|
<Button type={"primary"} onClick={addFunc} className="btnblue" style={{height:"36px"}}>发布新版本</Button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
<div>
|
||||||
|
{!turnFromNew ? releases.map((item, key) => release(item,key)) : release(releases[0],0)}
|
||||||
|
</div>
|
||||||
|
</React.Fragment>
|
||||||
|
)
|
||||||
|
} else if (releases && releases.length === 0) {
|
||||||
|
return (
|
||||||
|
<Empty
|
||||||
|
operation={data && data.user_admin_permission && type !== 2}
|
||||||
|
addFunc={addFunc}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addFunc(){
|
||||||
|
props.history.push({pathname:`/${owner}/${projectsId}/releases/new`,state:{stable:true}});
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="releaseIndex">
|
||||||
|
<div className="releasesVersion">
|
||||||
|
<Spin spinning={isSpin}>
|
||||||
|
{renderList(releases)}
|
||||||
|
</Spin>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default version;
|
|
@ -0,0 +1,357 @@
|
||||||
|
.topWrapper {
|
||||||
|
padding: 20px 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
border-bottom: 1px solid #EEEEEE;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.topWrapper_btn_new {
|
||||||
|
background: #fff;
|
||||||
|
color: #5091FF!important;
|
||||||
|
padding:0px 12px;
|
||||||
|
text-align: center;
|
||||||
|
height: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border:1px solid #5091FF;
|
||||||
|
}
|
||||||
|
.versionInfo{
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.versionInfo_left{
|
||||||
|
display: flex;
|
||||||
|
width: 182px;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-end;
|
||||||
|
padding-right: 15px;
|
||||||
|
&>.color-grey-3{
|
||||||
|
max-width: 10rem;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.versionInfo_right{
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
border-left: 1px solid #eee;
|
||||||
|
position: relative;
|
||||||
|
padding: 0px 30px 60px 24px;
|
||||||
|
&::before{
|
||||||
|
position: absolute;
|
||||||
|
left: -4px;
|
||||||
|
top:0px;
|
||||||
|
content: '';
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
background-color: #466AFF;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
.sendAuthorImg{
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
.body-show{
|
||||||
|
padding: 5px 10px 10px 10px;
|
||||||
|
}
|
||||||
|
& .version-user>a>span{
|
||||||
|
display: inline-block;
|
||||||
|
& img{
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.versionTag{
|
||||||
|
display: inline;
|
||||||
|
padding:0px 9px;
|
||||||
|
color: #fff;
|
||||||
|
position: relative;
|
||||||
|
margin-top: -8px;
|
||||||
|
height: 22px;
|
||||||
|
line-height: 20px;
|
||||||
|
border-radius: 4px;
|
||||||
|
&::before{
|
||||||
|
position: absolute;
|
||||||
|
content: "";
|
||||||
|
width: 0;
|
||||||
|
height: 0px;
|
||||||
|
border-left: 4px solid #cccccc;
|
||||||
|
border-top: 4px solid transparent;
|
||||||
|
border-bottom: 4px solid transparent;
|
||||||
|
border-right: 4px solid transparent;
|
||||||
|
z-index: 9;
|
||||||
|
top: 6px;
|
||||||
|
right: -9px;
|
||||||
|
}
|
||||||
|
&:after{
|
||||||
|
width: 0px;
|
||||||
|
height: 0px;
|
||||||
|
top:6px;
|
||||||
|
right: -7px;
|
||||||
|
position: absolute;
|
||||||
|
border-left:4px solid #fff;
|
||||||
|
border-top:4px solid transparent;
|
||||||
|
border-bottom:4px solid transparent;
|
||||||
|
border-right:4px solid transparent;
|
||||||
|
content:'';
|
||||||
|
z-index:10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.versionFile{
|
||||||
|
margin-top: 5px;
|
||||||
|
padding-top: 20px;
|
||||||
|
border-top: 1px solid #eee;
|
||||||
|
// width: 100%;
|
||||||
|
a{
|
||||||
|
display: block;
|
||||||
|
color: #333;
|
||||||
|
font-weight: 400;
|
||||||
|
height: 20px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.versionTag.yellow{
|
||||||
|
border: 1px solid #FBBC06;
|
||||||
|
color: #FBBC06;
|
||||||
|
&::before{
|
||||||
|
border-left-color: #FBBC06;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.versionTag.green{
|
||||||
|
border: 1px solid #2DB44D;
|
||||||
|
color: #2DB44D;
|
||||||
|
&::before{
|
||||||
|
border-left-color: #2DB44D;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.versionTag.orange{
|
||||||
|
border: 1px solid #FF6E23;
|
||||||
|
color: #FF6E23;
|
||||||
|
&::before{
|
||||||
|
border-left-color: #FF6E23;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.addReleaseBtn{
|
||||||
|
text-align: right;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
.versionName{
|
||||||
|
font-size: 16px;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
height: 18px;
|
||||||
|
line-height: 18px;
|
||||||
|
margin-top: -5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.versionmilepostleft{
|
||||||
|
padding: 15px;
|
||||||
|
margin-right: 50px;
|
||||||
|
width: 80%;
|
||||||
|
}
|
||||||
|
.topWrapper_btn_close {
|
||||||
|
background: #504b4b;
|
||||||
|
color: #FFFFFF!important;
|
||||||
|
padding:0px 12px;
|
||||||
|
text-align: center;
|
||||||
|
height: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.topWrapper_btn_delete {
|
||||||
|
background: #da1010;
|
||||||
|
color: #FFFFFF!important;
|
||||||
|
padding:0px 12px;
|
||||||
|
text-align: center;
|
||||||
|
height: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.versionrighe{
|
||||||
|
flex: 2;
|
||||||
|
}
|
||||||
|
.versionleft{
|
||||||
|
flex: 1;
|
||||||
|
text-align: right;
|
||||||
|
display: flex;
|
||||||
|
justify-content: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* .version_line{
|
||||||
|
display: flex;
|
||||||
|
height: 30px;
|
||||||
|
margin: auto;
|
||||||
|
border-left:1px solid #eee;
|
||||||
|
} */
|
||||||
|
.version_line_one{
|
||||||
|
display: flex;
|
||||||
|
height: 45px;
|
||||||
|
margin: auto;
|
||||||
|
border-left:1px solid #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.version_line_tpw{
|
||||||
|
display: flex;
|
||||||
|
height: 80px;
|
||||||
|
margin: auto;
|
||||||
|
border-left:1px solid #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.versiondiv{
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
.verwinth{
|
||||||
|
width: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*开启中 关闭中*/
|
||||||
|
.opendversionetail{
|
||||||
|
display: inline-block;
|
||||||
|
background: #21ba45;
|
||||||
|
color: #ffffff!important;
|
||||||
|
padding:0px 5px;
|
||||||
|
text-align: center;
|
||||||
|
height: 25px;
|
||||||
|
/*width: 110px;*/
|
||||||
|
border-radius: 4px;
|
||||||
|
line-height: 25px;
|
||||||
|
}
|
||||||
|
.closedversionetail{
|
||||||
|
display: inline-block;
|
||||||
|
background: #e60b0b;
|
||||||
|
color: #ffffff!important;
|
||||||
|
padding:0px 5px;
|
||||||
|
text-align: center;
|
||||||
|
height: 25px;
|
||||||
|
/*width: 110px;*/
|
||||||
|
border-radius: 4px;
|
||||||
|
line-height: 25px;
|
||||||
|
}
|
||||||
|
.versionrectangle {
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
border-radius: 100%;
|
||||||
|
margin-top: 15px;
|
||||||
|
margin-left: -4px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
background: rgb(83, 81, 81);
|
||||||
|
}
|
||||||
|
.ver-middle{
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
/* new */
|
||||||
|
.versionForm{
|
||||||
|
flex:1;
|
||||||
|
padding-right: 40px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
.ant-select-auto-complete.ant-select .ant-input:hover,.ant-input:hover {
|
||||||
|
border-color: rgba(153, 153, 153, 0.8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.versionTips{
|
||||||
|
width:268px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.infosTip{
|
||||||
|
border-bottom: 1px solid #EEEEEE;
|
||||||
|
color: #333;
|
||||||
|
padding-bottom: 26px;
|
||||||
|
margin-bottom: 26px;
|
||||||
|
font-weight: 400;
|
||||||
|
text-align: justify;
|
||||||
|
&:last-child{
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.dragBox{
|
||||||
|
background: rgba(153, 153, 153, 0.04);
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px dashed #d9d9d9;
|
||||||
|
padding:20px;
|
||||||
|
.versionStyle{
|
||||||
|
border: none!important;
|
||||||
|
padding-bottom:20px;
|
||||||
|
.dragIcon{
|
||||||
|
font-size: 40px!important;
|
||||||
|
color: #666!important;
|
||||||
|
line-height: 40px;
|
||||||
|
height: 40px;
|
||||||
|
margin-bottom: 14px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ant-upload-list-item:hover .ant-upload-list-item-info {
|
||||||
|
background-color: rgba(239, 244, 255, 1);
|
||||||
|
}
|
||||||
|
.ant-upload-list-item-info{
|
||||||
|
padding:0px 20px 0px 8px;
|
||||||
|
&>span{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.set-ant-row .ant-row{
|
||||||
|
display: flex;
|
||||||
|
height: 20px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
.itemInline{
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
position: relative;
|
||||||
|
&>p{
|
||||||
|
position: absolute;
|
||||||
|
bottom: -5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.itemInline .ant-row{
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
.prerelease{
|
||||||
|
padding-top: 20px;
|
||||||
|
.ant-form-item-control{
|
||||||
|
height: 20px;
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.releaseIndex{
|
||||||
|
margin: 30px auto;
|
||||||
|
width: 1200px;
|
||||||
|
}
|
||||||
|
.emptyPanel{
|
||||||
|
width: 100%;
|
||||||
|
background: #FAFCFF;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid rgba(42, 97, 255, 0.23);
|
||||||
|
min-height: 418px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
.operation{
|
||||||
|
width: 400px;
|
||||||
|
border-top: 1px solid #eee;
|
||||||
|
padding-top: 34px;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ant-form-item-control{
|
||||||
|
line-height: initial;
|
||||||
|
}
|
|
@ -1,17 +1,20 @@
|
||||||
import React ,{useEffect,useState } from 'react';
|
import React ,{useEffect,useRef,useState } from 'react';
|
||||||
import { truncateCommitId } from '../common/util';
|
import { truncateCommitId } from '../common/util';
|
||||||
import { AlignCenter , FlexAJ } from '../Component/layout';
|
import { AlignCenter , FlexAJ } from '../Component/layout';
|
||||||
import { Button } from 'antd';
|
import { Button, Tooltip,Progress, Popover, Anchor } from 'antd';
|
||||||
import './merge.css';
|
import './merge.css';
|
||||||
|
import './Index.scss';
|
||||||
|
|
||||||
function Files({data,history,owner,projectsId}){
|
function Files({ data,history,owner,projectsId , parentsSha }){
|
||||||
const [ files , setFiles ] = useState(data && data.files);
|
const [ files , setFiles ] = useState(data && data.files);
|
||||||
|
const [ copyfileTipTitle, setCopyfileTipTitle] = useState("复制文件路径");
|
||||||
|
const [ isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
if(data){
|
if(data){
|
||||||
setFiles(data.files);
|
setFiles(data.files);
|
||||||
}
|
}
|
||||||
},[data])
|
},[data]);
|
||||||
|
|
||||||
function showDown(flag,index,isBin){
|
function showDown(flag,index,isBin){
|
||||||
if(!isBin){
|
if(!isBin){
|
||||||
|
@ -22,35 +25,83 @@ function Files({data,history,owner,projectsId}){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function copyFileName(fileName){
|
||||||
|
var copyCont = document.createElement('input');
|
||||||
|
copyCont.defaultValue = fileName;
|
||||||
|
document.body.appendChild(copyCont);
|
||||||
|
copyCont.select(); // 选择对象
|
||||||
|
document.execCommand("Copy"); // 执行浏览器复制命令
|
||||||
|
copyCont.className = 'copyCont';
|
||||||
|
copyCont.style.display='none';
|
||||||
|
setCopyfileTipTitle("复制成功");
|
||||||
|
}
|
||||||
|
|
||||||
|
const folderOpen = (
|
||||||
|
<div className="folders">
|
||||||
|
<div className="folderList">
|
||||||
|
{files && files.map((item, key) => {
|
||||||
|
return (
|
||||||
|
<a href={`#value${key}`}>
|
||||||
|
<FlexAJ className="filesInfo" key={key} onClick={() => {item.flag && showDown(item.flag, key, item.isBin);setIsOpen(false);}}>
|
||||||
|
<AlignCenter>
|
||||||
|
<i className="iconfont icon-wenjianicon mr4"></i>
|
||||||
|
<span className="cursor-pointer" data-clipboard-text={item.name}>{item.name}</span>
|
||||||
|
</AlignCenter>
|
||||||
|
<div className="see-file">
|
||||||
|
<Tooltip placement="top" title={`${item.addition+item.deletion}处更改${item.addition + item.deletion > 0 && ":"}${item.addition>0?item.addition+"处添加":""}${item.addition>0 && item.deletion>0 ?"和":""}${item.deletion>0?item.deletion+"处删除":""}`}>
|
||||||
|
<Progress showInfo = {false} strokeColor = "#2DB44D" size="small" percent={item.addition/(item.addition+item.deletion)*100} />
|
||||||
|
{item.addition >0 && <span className="color-green ml10">+{item.addition}</span>}
|
||||||
|
{item.deletion >0 && <span className="color-red ml10">-{item.deletion}</span>}
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
</FlexAJ>
|
||||||
|
</a>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
return(
|
return(
|
||||||
<div>
|
<div>
|
||||||
<AlignCenter className="color-grey-9 pb10" style={{borderBottom:"1px solid #eee"}}>
|
<AlignCenter className="color-grey-9" style={{position:'relative'}}>
|
||||||
<i className="iconfont icon-sanjiaoxing-down mr5"></i>
|
<div onClick={()=>{setIsOpen(!isOpen)}}>
|
||||||
<span>
|
<i className={`iconfont mr5 ${isOpen? "font-18 icon-sanjiaoxing-down":"font-16 icon-triangle"}`}></i>
|
||||||
共有<span className="color-grey-3"> {data && data.files_count} 个文件被更改</span>,包括
|
<span className="color-grey-6 update-file-count">
|
||||||
|
共有<span className="color-grey-3"> {data && data.files_count} 个文件 </span>被更改,包括
|
||||||
{ data && data.total_addition ? <span className="color-green"> {data && data.total_addition} 次插入</span>:"" }
|
{ data && data.total_addition ? <span className="color-green"> {data && data.total_addition} 次插入</span>:"" }
|
||||||
{ data && data.total_addition && data.total_deletion ? " 和 ":""}
|
{ data && data.total_addition && data.total_deletion ? " 和 ":""}
|
||||||
{ data && data.total_deletion ? <span className="color-red"> {data && data.total_deletion} 次删除</span>:""}
|
{ data && data.total_deletion ? <span className="color-red"> {data && data.total_deletion} 次删除</span>:""}
|
||||||
</span>
|
</span>
|
||||||
|
</div>
|
||||||
|
{isOpen && folderOpen}
|
||||||
</AlignCenter>
|
</AlignCenter>
|
||||||
{
|
{
|
||||||
files && files.length>0 &&
|
files && files.length>0 &&
|
||||||
<div>
|
<div className="fileList">
|
||||||
{
|
{
|
||||||
files.map((item,key)=>{
|
files.map((item,key)=>{
|
||||||
return(
|
return(
|
||||||
<div className="files" key={key}>
|
<div className="files" key={key}>
|
||||||
<FlexAJ className="filesInfo" style={{cursor:item.isBin ? "default":"pointer"}} onClick={()=>showDown(item.flag,key,item.isBin)}>
|
<a id= {`value${key}`} className="anchorPoint"></a>
|
||||||
|
<FlexAJ className="filesInfo">
|
||||||
<AlignCenter>
|
<AlignCenter>
|
||||||
{!item.isBin ? <i className={!item.flag?"iconfont icon-xiajiantou font-16 mr15 color-grey-9":"iconfont icon-youjiantou font-16 mr15 color-grey-9"}></i>:""}
|
{!item.isBin ? <i className={!item.flag?"iconfont icon-sanjiaoxing-down color-grey-9 mt4":"iconfont icon-triangle font-15 color-grey-9"} onClick={()=>showDown(item.flag,key,item.isBin)}></i>:""}
|
||||||
<i className="iconfont icon-wenjia font-16 mr8 color-grey-9"></i>
|
<span className="cursor-pointer" data-clipboard-text={item.name} onClick={()=>showDown(item.flag,key,item.isBin)}>{item.name}</span>
|
||||||
<span>{item.name}</span>
|
<Tooltip
|
||||||
|
title={copyfileTipTitle}
|
||||||
|
onVisibleChange={()=>setCopyfileTipTitle("复制文件路径")}
|
||||||
|
>
|
||||||
|
<i className="iconfont icon-fuzhiicon ml6" onClick={()=>copyFileName(item.name)}></i>
|
||||||
|
</Tooltip>
|
||||||
</AlignCenter>
|
</AlignCenter>
|
||||||
<span>
|
<div className="see-file">
|
||||||
<Button className="mr20" onClick={()=>{history.push(`/${owner}/${projectsId}/tree/${truncateCommitId(item.sha)}/${item.name}`)}}>查看文件</Button>
|
<Tooltip placement="top" title={`${item.addition + item.deletion}处更改${item.addition + item.deletion > 0 && ":"} ${item.addition > 0 ? item.addition + "处添加" : ""}${item.addition > 0 && item.deletion > 0 ? "和" : ""}${item.deletion > 0 ? item.deletion + "处删除" : ""}`}>
|
||||||
<span className="color-green">+{item.addition}</span>
|
<Progress showInfo = {false} strokeColor = "#2DB44D" size="small" percent={item.addition/(item.addition+item.deletion)*100} />
|
||||||
<span className="color-red ml20">-{item.deletion}</span>
|
<span className="ml10">{item.addition+item.deletion}处</span>
|
||||||
</span>
|
</Tooltip>
|
||||||
|
<span className="see-file-btn" onClick={()=>{history.push(`/${owner}/${projectsId}${item.isDeleted ? `/commits/${truncateCommitId(parentsSha)}`:`/tree/${truncateCommitId(item.sha)}/${item.name}`}`)}}>查看文件</span>
|
||||||
|
</div>
|
||||||
</FlexAJ>
|
</FlexAJ>
|
||||||
{
|
{
|
||||||
item.sections && item.sections.length >= 1 && !item.flag &&
|
item.sections && item.sections.length >= 1 && !item.flag &&
|
||||||
|
|
|
@ -18,4 +18,86 @@
|
||||||
.pr_tags_closed{
|
.pr_tags_closed{
|
||||||
border:1px solid #FA6400;
|
border:1px solid #FA6400;
|
||||||
color: #FA6400;
|
color: #FA6400;
|
||||||
|
}
|
||||||
|
.update-file-count{
|
||||||
|
cursor: pointer;
|
||||||
|
& .color-grey-3{
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.fileList{
|
||||||
|
.sc-bxivhb{
|
||||||
|
width: 55rem;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: normal;
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
.see-file{
|
||||||
|
width: 14rem;
|
||||||
|
.ml10{
|
||||||
|
display: inline-block;
|
||||||
|
width: 4.5rem;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
span{
|
||||||
|
width: 7%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.anchorPoint{
|
||||||
|
position: relative;
|
||||||
|
top: -5rem;
|
||||||
|
display: block;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.filesInfo{
|
||||||
|
background: #FAFCFF;
|
||||||
|
border-color:rgba(42, 97, 255, 0.23);
|
||||||
|
.ant-progress-line {
|
||||||
|
width: 5rem;
|
||||||
|
}
|
||||||
|
.ant-progress-inner{
|
||||||
|
background-color: #D14A4A;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.folders,.ant-anchor{
|
||||||
|
margin-left: 0;
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
.folders{
|
||||||
|
position: absolute;
|
||||||
|
z-index: 2;
|
||||||
|
left: 0px;
|
||||||
|
top: 37px;
|
||||||
|
color: #333333;
|
||||||
|
width: 75rem;
|
||||||
|
box-shadow: 0px 4px 8px 2px rgba(212, 212, 212, 0.5);
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid rgba(153, 153, 153, 0.32);
|
||||||
|
.ant-anchor-link-active > .ant-anchor-link-title {
|
||||||
|
color: #466AFF;
|
||||||
|
}
|
||||||
|
.ant-anchor-link {
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
.folderList{
|
||||||
|
max-height: 275px;
|
||||||
|
overflow:auto;
|
||||||
|
.files{
|
||||||
|
border: 0px;
|
||||||
|
}
|
||||||
|
.filesInfo {
|
||||||
|
padding: 10px 18px 10px 15px;
|
||||||
|
height: 55px;
|
||||||
|
background: #FFF;
|
||||||
|
border-bottom: 1px solid #EEEEEE;
|
||||||
|
&:hover{
|
||||||
|
background: #F3F4F6;
|
||||||
|
}
|
||||||
|
.color-green,.color-red{
|
||||||
|
width: 3%;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -152,13 +152,23 @@ form .ant-cascader-picker, form .ant-select {
|
||||||
margin-top: 15px;
|
margin-top: 15px;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
}
|
}
|
||||||
|
.see-file-btn{
|
||||||
|
color: #466AFF;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
.filesInfo{
|
.filesInfo{
|
||||||
padding:10px 15px;
|
padding:10px 15px;
|
||||||
background-color: #fafafa;
|
background-color: #fafafa;
|
||||||
}
|
}
|
||||||
|
.filesInfo .cursor-pointer{
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
.filesContent{
|
.filesContent{
|
||||||
border-top: 1px solid #ddd;
|
border-top: 1px solid #ddd;
|
||||||
}
|
}
|
||||||
|
.icon-fuzhiicon:hover{
|
||||||
|
color: #466AFF;
|
||||||
|
}
|
||||||
.linesContent{
|
.linesContent{
|
||||||
display: flex;
|
display: flex;
|
||||||
min-height: 30px;
|
min-height: 30px;
|
||||||
|
|
|
@ -65,16 +65,18 @@ class Index extends Component {
|
||||||
<FileLanguage language={language} select_language={this.select_language}></FileLanguage>
|
<FileLanguage language={language} select_language={this.select_language}></FileLanguage>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Meditor
|
<div className="editorBorder">
|
||||||
{...this.props}
|
<Meditor
|
||||||
{...this.state}
|
{...this.props}
|
||||||
filepath={`${file_path}`}
|
{...this.state}
|
||||||
language = {language}
|
filepath={`${file_path}`}
|
||||||
content={undefined}
|
language = {language}
|
||||||
readOnly={false}
|
content={undefined}
|
||||||
editorType="new"
|
readOnly={false}
|
||||||
descName={filename && `Add ${filename}`}
|
editorType="new"
|
||||||
></Meditor>
|
descName={filename && `Add ${filename}`}
|
||||||
|
></Meditor>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
|
|
|
@ -8,7 +8,13 @@
|
||||||
border: 1px solid #d9d9d9!important;
|
border: 1px solid #d9d9d9!important;
|
||||||
border-right: none!important;
|
border-right: none!important;
|
||||||
}
|
}
|
||||||
|
.editorBorder .editorBorderBox{
|
||||||
|
border:1px solid #eee;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
.editorBorder .editorBorderSubmitBox{
|
||||||
|
padding:20px 0px!important;
|
||||||
|
}
|
||||||
.userScrew{
|
.userScrew{
|
||||||
margin:20px 0px;
|
margin:20px 0px;
|
||||||
border:1px solid #f4f4f4;
|
border:1px solid #f4f4f4;
|
||||||
|
@ -39,7 +45,7 @@
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
.ant-input-group .ant-input:focus{
|
.ant-input-group .ant-input:focus{
|
||||||
border-right: 1px solid #d9d9d9!important;
|
border-right: 1px solid rgba(70, 106, 255, 1)!important;
|
||||||
}
|
}
|
||||||
.ant-btn-primary.grey{
|
.ant-btn-primary.grey{
|
||||||
border:1px solid #BBBBBB;
|
border:1px solid #BBBBBB;
|
||||||
|
|
|
@ -10,6 +10,7 @@ class m_editor extends Component {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
editorValue: this.props.content,
|
editorValue: this.props.content,
|
||||||
|
prevHeight:0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
componentDidUpdate=(prevProps)=>{
|
componentDidUpdate=(prevProps)=>{
|
||||||
|
@ -41,42 +42,81 @@ class m_editor extends Component {
|
||||||
folding: true,
|
folding: true,
|
||||||
foldingStrategy: "indentation", // 代码可分小段折叠
|
foldingStrategy: "indentation", // 代码可分小段折叠
|
||||||
automaticLayout: true, // 自适应布局
|
automaticLayout: true, // 自适应布局
|
||||||
// overviewRulerBorder: false, // 不要滚动条的边框
|
overviewRulerBorder: false, // 不要滚动条的边框
|
||||||
// scrollBeyondLastLine: false, // 取消代码后面一大段空白
|
scrollBeyondLastLine: false, // 取消代码后面一大段空白
|
||||||
minimap: {
|
minimap: {
|
||||||
// 不要小地图
|
// 不要小地图
|
||||||
enabled: false,
|
enabled: false,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleEditorMount = (editor, monaco) => {
|
||||||
|
editor.onDidChangeModelDecorations(() => {
|
||||||
|
requestAnimationFrame(updateEditorHeight); // folding
|
||||||
|
});
|
||||||
|
|
||||||
|
const updateEditorHeight = () => {
|
||||||
|
const editorElement = editor.getDomNode();
|
||||||
|
|
||||||
|
if (!editorElement) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const padding = 40;
|
||||||
|
|
||||||
|
const lineHeight = editor.getOption(
|
||||||
|
monaco.editor.EditorOption.lineHeight
|
||||||
|
);
|
||||||
|
|
||||||
|
const lineCount = editor.getModel().getLineCount() || 1;
|
||||||
|
let height =
|
||||||
|
editor.getTopForLineNumber(lineCount + 1) +
|
||||||
|
lineHeight +
|
||||||
|
padding ;
|
||||||
|
|
||||||
|
if(height<400){height = 400;}
|
||||||
|
|
||||||
|
if (this.state.prevHeight !== height) {
|
||||||
|
this.setState({
|
||||||
|
prevHeight:height
|
||||||
|
})
|
||||||
|
// setPrevHeight(height);
|
||||||
|
editorElement.style.height = `${height}px`;
|
||||||
|
editor.layout();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
updateEditorHeight(); // typing
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<div>
|
<div className="editorBorderBox">
|
||||||
<div className="branchTable" style={{border:"1px solid #eee"}}>
|
<Editor
|
||||||
<Editor
|
language={language ? language : "plaintext"}
|
||||||
height="400px"
|
theme={"vs-grey"}
|
||||||
language={language ? language : "plaintext"}
|
placeholder="请输入内容"
|
||||||
theme={"vs-grey"}
|
value={editorValue}
|
||||||
placeholder="请输入内容"
|
options={editor_options}
|
||||||
value={editorValue}
|
onChange={this.changeEditor}
|
||||||
options={editor_options}
|
editorWillMount={this.editorWillMount}
|
||||||
onChange={this.changeEditor}
|
editorDidMount={handleEditorMount}
|
||||||
editorWillMount={this.editorWillMount}
|
/>
|
||||||
/>
|
</div>
|
||||||
</div>
|
{!readOnly && (
|
||||||
{!readOnly && (
|
<div className="editorBorderSubmitBox" style={{marginTop:"20px",padding:"20px"}}>
|
||||||
<div style={{marginTop:"20px",padding:"20px"}}>
|
<UserSubmitComponent
|
||||||
<UserSubmitComponent
|
{...this.props}
|
||||||
{...this.props}
|
{...this.state}
|
||||||
{...this.state}
|
filepath={`${this.props.filepath}`}
|
||||||
filepath={`${this.props.filepath}`}
|
content={editorValue}
|
||||||
content={editorValue}
|
editor_type={editorType}
|
||||||
editor_type={editorType}
|
currentBranch={currentBranch}
|
||||||
currentBranch={currentBranch}
|
descName={descName}
|
||||||
descName={descName}
|
></UserSubmitComponent>
|
||||||
></UserSubmitComponent>
|
</div>
|
||||||
</div>
|
)}
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ const menu = [
|
||||||
{name:"合并请求",index:"pulls"},
|
{name:"合并请求",index:"pulls"},
|
||||||
{name:"Wiki",index:"wiki"},
|
{name:"Wiki",index:"wiki"},
|
||||||
{name:"工作流(beta版)",index:"devops"},
|
{name:"工作流(beta版)",index:"devops"},
|
||||||
{name:"资源库",index:"resources"},
|
// {name:"资源库",index:"resources"},
|
||||||
{name:"里程碑",index:"versions"},
|
{name:"里程碑",index:"versions"},
|
||||||
{name:"动态",index:"activity"},
|
{name:"动态",index:"activity"},
|
||||||
]
|
]
|
||||||
|
|
|
@ -87,7 +87,7 @@ export default Form.create()(
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
<Input
|
<Input
|
||||||
addonBefore={`https://`+ port ? `${hostname}:${port}/organize`:`${hostname}/organize`}
|
addonBefore={port ? `${hostname}:${port}/`:`https://${hostname}/`}
|
||||||
placeholder="组织账号" maxLength={100}
|
placeholder="组织账号" maxLength={100}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -122,7 +122,7 @@ export default Form.create()(
|
||||||
validator:checkname
|
validator:checkname
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
<Input placeholder="请输入组织账号" maxLength={100} disabled/>,true
|
<Input placeholder="请输入组织账号" disabled/>,true
|
||||||
)}
|
)}
|
||||||
{helper(
|
{helper(
|
||||||
"组织名称:",
|
"组织名称:",
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
import { Upload, Icon , Button } from 'antd';
|
import { Upload, Icon , Button } from 'antd';
|
||||||
import { getUploadActionUrl, appendFileSizeToUploadFileAll } from 'educoder';
|
import { getUploadActionUrl, appendFileSizeToUploadFileAll } from 'educoder';
|
||||||
import { AlignCenter } from '../Component/layout';
|
|
||||||
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
const { Dragger } = Upload;
|
const { Dragger } = Upload;
|
||||||
|
@ -64,7 +63,6 @@ class Index extends Component {
|
||||||
changeIsComplete && changeIsComplete(true);
|
changeIsComplete && changeIsComplete(true);
|
||||||
if (info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') {
|
if (info.file.status === 'uploading' || info.file.status === 'done' || info.file.status === 'removed') {
|
||||||
let fileList = info.fileList;
|
let fileList = info.fileList;
|
||||||
|
|
||||||
this.setState({ fileList: appendFileSizeToUploadFileAll(fileList) });
|
this.setState({ fileList: appendFileSizeToUploadFileAll(fileList) });
|
||||||
this.fileIdList(fileList);
|
this.fileIdList(fileList);
|
||||||
}
|
}
|
||||||
|
@ -111,7 +109,7 @@ class Index extends Component {
|
||||||
:
|
:
|
||||||
<Dragger {...upload} className={className}>
|
<Dragger {...upload} className={className}>
|
||||||
{icon || <Icon type="inbox" />}
|
{icon || <Icon type="inbox" />}
|
||||||
<p className="ant-upload-text font-14">拖动文件或<span className="color-blue">点击此处上传</span></p>
|
<p className="ant-upload-text font-16 color-grey-3">拖动文件或点击此处上传</p>
|
||||||
</Dragger>
|
</Dragger>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
|
|
||||||
1.请求URL: https://code.ihub.org.cn/api/v1/mirrors/create.json
|
|
||||||
|
|
||||||
2.请求方式: POST
|
|
||||||
|
|
||||||
3.参数:
|
|
||||||
|
|
||||||
{
|
|
||||||
"image_url": "xxx.git", #必填,且后缀必为.git,
|
|
||||||
"language": "Ruby", #必填,如数据库不存在,则会创建新的记录
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
4. 返回值: {
|
|
||||||
"status": 1,
|
|
||||||
"message": "同步成功,项目ID===1806"
|
|
||||||
}
|
|
||||||
|
|
||||||
5. 返回值说明: 仅有当有返回值,且返回值的status 的值为1, 才是创建成功,其余均为创建失败
|
|
||||||
|
|
||||||
|
|
|
@ -1,278 +0,0 @@
|
||||||
import React, { useState, useEffect, useCallback, forwardRef } from "react";
|
|
||||||
import styled from "styled-components";
|
|
||||||
import { AutoComplete, Select, Input, Checkbox, Button, Form } from "antd";
|
|
||||||
|
|
||||||
import Editor from "../../modules/tpm/challengesnew/tpm-md-editor";
|
|
||||||
import Upload from "../Upload/Index";
|
|
||||||
import Attachments from "../Upload/attachment";
|
|
||||||
import axios from "axios";
|
|
||||||
import "./version.css";
|
|
||||||
import UploadImg from "../Images/upload.png";
|
|
||||||
import { getBranch } from '../GetData/getData';
|
|
||||||
|
|
||||||
const { Option } = AutoComplete;
|
|
||||||
|
|
||||||
export default Form.create()(
|
|
||||||
forwardRef(
|
|
||||||
(
|
|
||||||
{ form, projectDetail , match, showNotification, history },
|
|
||||||
ref
|
|
||||||
) => {
|
|
||||||
const { getFieldDecorator, validateFields, setFieldsValue } = form;
|
|
||||||
const [tagList, setTagList] = useState(undefined);
|
|
||||||
const [branchList, setBranchList] = useState(undefined);
|
|
||||||
const [desc, setDesc] = useState(null);
|
|
||||||
const [fileList, setFileList] = useState(undefined);
|
|
||||||
const [attachment, setAttachment] = useState(undefined);
|
|
||||||
const [options , setOptions] = useState(undefined);
|
|
||||||
|
|
||||||
|
|
||||||
const repo_id = projectDetail && projectDetail.repo_id;
|
|
||||||
const { projectsId, versionId , owner } = match.params;
|
|
||||||
useEffect(()=>{
|
|
||||||
getBranchs(projectsId,owner);
|
|
||||||
},[projectsId])
|
|
||||||
|
|
||||||
async function getBranchs(id,owner){
|
|
||||||
let result = await getBranch(id,owner);
|
|
||||||
setBranchList(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
const Span = styled.span`
|
|
||||||
margin: 0px 15px;
|
|
||||||
color: #bbb;
|
|
||||||
line-height: 35px;
|
|
||||||
`;
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (versionId) {
|
|
||||||
const url = `/${owner}/${projectsId}/releases/${versionId}/edit.json`;
|
|
||||||
axios.get(url).then(result => {
|
|
||||||
if (result) {
|
|
||||||
setFieldsValue(result.data);
|
|
||||||
setDesc(result.data.body);
|
|
||||||
setAttachment(result.data.attachments);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, [versionId]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (projectsId) {
|
|
||||||
const url = `/${owner}/${projectsId}/tags.json`;
|
|
||||||
axios
|
|
||||||
.get(url,{params:{
|
|
||||||
limit:1000
|
|
||||||
}})
|
|
||||||
.then(result => {
|
|
||||||
if (result) {
|
|
||||||
setTagList(result.data);
|
|
||||||
setOptions(renderTagList(result.data));
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, [projectsId]);
|
|
||||||
|
|
||||||
function renderTagList(list) {
|
|
||||||
if (list) {
|
|
||||||
let array = list.map((item, key) => {
|
|
||||||
return (
|
|
||||||
<Option key={key} value={item.name}>
|
|
||||||
{item.name}
|
|
||||||
</Option>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
return array || undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function submit() {
|
|
||||||
validateFields((err, value) => {
|
|
||||||
if(err)return;
|
|
||||||
if (versionId) {
|
|
||||||
let url = `/${owner}/${projectsId}/releases/${versionId}.json`;
|
|
||||||
axios
|
|
||||||
.put(url, {
|
|
||||||
...value,
|
|
||||||
body: desc,
|
|
||||||
attachment_ids: fileList
|
|
||||||
})
|
|
||||||
.then(result => {
|
|
||||||
if (result) {
|
|
||||||
showNotification("版本修改成功!");
|
|
||||||
history.push(`/${owner}/${projectsId}/releases`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
let url = `/${owner}/${projectsId}/releases.json`;
|
|
||||||
axios.post(url, {
|
|
||||||
...value,
|
|
||||||
body: desc,
|
|
||||||
attachment_ids: fileList
|
|
||||||
})
|
|
||||||
.then(result => {
|
|
||||||
if (result) {
|
|
||||||
showNotification("版本发布成功!");
|
|
||||||
history.push(`/${owner}/${projectsId}/releases`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const helper = useCallback(
|
|
||||||
(label, name, rules, widget, isRequired = true) => (
|
|
||||||
<React.Fragment>
|
|
||||||
<span required={isRequired}>{label}</span>
|
|
||||||
<Form.Item>
|
|
||||||
{getFieldDecorator(name, { rules, validateFirst: true })(widget)}
|
|
||||||
</Form.Item>
|
|
||||||
</React.Fragment>
|
|
||||||
),
|
|
||||||
[]
|
|
||||||
);
|
|
||||||
// 输入标签名
|
|
||||||
function changeAuto(value){
|
|
||||||
let l = tagList.filter(item=>item.name.indexOf(value) > -1);
|
|
||||||
setOptions(renderTagList(l));
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<div className="main df">
|
|
||||||
<Form className="versionForm">
|
|
||||||
<div>
|
|
||||||
<p className="font-16 color-grey-3 mb15">{versionId?"编辑":"创建"}发行版</p>
|
|
||||||
<div>
|
|
||||||
<div className="itemInline">
|
|
||||||
{helper(
|
|
||||||
"",
|
|
||||||
"tag_name",
|
|
||||||
[{ required: true, message: "请输入获取或选择一个标签" }],
|
|
||||||
<AutoComplete
|
|
||||||
placeholder="标记一个版本"
|
|
||||||
onChange={changeAuto}
|
|
||||||
style={{ width: "200px" }}
|
|
||||||
>
|
|
||||||
{options}
|
|
||||||
</AutoComplete>
|
|
||||||
)}
|
|
||||||
<Span>@</Span>
|
|
||||||
{helper(
|
|
||||||
"",
|
|
||||||
"target_commitish",
|
|
||||||
[{ required: true, message: "请选择一个分支" }],
|
|
||||||
<Select
|
|
||||||
placeholder="请选择一个分支"
|
|
||||||
style={{ width: "200px" }}
|
|
||||||
showArrow={false}
|
|
||||||
>
|
|
||||||
{renderTagList(branchList)}
|
|
||||||
</Select>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<p className="font-13 color-grey-8">
|
|
||||||
选择一个已经存在的标签,或者在发布时新建一个标签
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="pt20">
|
|
||||||
{helper(
|
|
||||||
"",
|
|
||||||
"name",
|
|
||||||
[{ required: true, message: "请输入发行版的标题" }],
|
|
||||||
<Input placeholder="发行版的标题" />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<Editor
|
|
||||||
placeholder={"描述此发行版"}
|
|
||||||
height={200}
|
|
||||||
mdID={`version-comments-description`}
|
|
||||||
initValue={desc}
|
|
||||||
onChange={setDesc}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="set-ant-row">
|
|
||||||
{helper(
|
|
||||||
"",
|
|
||||||
"prerelease",
|
|
||||||
[],
|
|
||||||
<Checkbox>这是一个预览版本</Checkbox>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<Upload
|
|
||||||
className="versionStyle"
|
|
||||||
isComplete={true}
|
|
||||||
load={setFileList}
|
|
||||||
icon={
|
|
||||||
<img
|
|
||||||
src={UploadImg}
|
|
||||||
width="58"
|
|
||||||
alt=""
|
|
||||||
style={{ marginBottom: 15 }}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
size={100}
|
|
||||||
showNotification={showNotification}
|
|
||||||
/>
|
|
||||||
{versionId && attachment && attachment.length > 0 ? (
|
|
||||||
<Attachments
|
|
||||||
attachments={attachment}
|
|
||||||
showNotification={showNotification}
|
|
||||||
canDelete={true}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
""
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<p className="pt20">
|
|
||||||
<Button onClick={submit} type="primary" className="mr30">
|
|
||||||
{versionId ? "保存" : "创建"}发行版
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
onClick={() =>
|
|
||||||
history.push(`/${owner}/${projectsId}/releases`)
|
|
||||||
}
|
|
||||||
style={{
|
|
||||||
backgroundColor: "rgba(187,187,187,1)",
|
|
||||||
color: "#fff"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
取消
|
|
||||||
</Button>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</Form>
|
|
||||||
<div className="versionTips">
|
|
||||||
<div className="infosTip">
|
|
||||||
<p className="font-16 mb15">标签命名建议</p>
|
|
||||||
<p className="mb15">
|
|
||||||
通常的做法是在版本名称前加上字母 v 前缀, v1.0 或者 v2.3.4。
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
如果标签不适合在生产环境下使用,请在版本名称后添加预发行版本。例如:v0.2-alpha
|
|
||||||
或者 v5.9-beta.3。
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="infosTip">
|
|
||||||
<p className="font-16 mb15">语义化版本</p>
|
|
||||||
<p className="mb15">
|
|
||||||
如果你是第一次发布版本,我们强烈建议你阅读语义化版本。
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="infosTip">
|
|
||||||
<p className="font-16 mb15">附件大小说明</p>
|
|
||||||
<p className="mb15">
|
|
||||||
单个附件不能超过 100M(GVP 项目200M),每个仓库总附件不可超过
|
|
||||||
1G(推荐项目不可超过 5G;GVP 项目不可超过
|
|
||||||
20G)。附件总容量统计包括仓库附件和发行版附件。
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
|
@ -1,205 +0,0 @@
|
||||||
.topWrapper {
|
|
||||||
padding: 20px 0;
|
|
||||||
box-sizing: border-box;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
border-bottom: 1px solid #EEEEEE;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.topWrapper_btn_new {
|
|
||||||
background: #fff;
|
|
||||||
color: #5091FF!important;
|
|
||||||
padding:0px 12px;
|
|
||||||
text-align: center;
|
|
||||||
height: 32px;
|
|
||||||
line-height: 32px;
|
|
||||||
border-radius: 4px;
|
|
||||||
border:1px solid #5091FF;
|
|
||||||
}
|
|
||||||
.versionInfo{
|
|
||||||
display: flex;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.versionInfo_left{
|
|
||||||
display: flex;
|
|
||||||
width: 30%;
|
|
||||||
padding-top: 20px;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: flex-end;
|
|
||||||
padding-right: 15px;
|
|
||||||
}
|
|
||||||
.versionInfo_right{
|
|
||||||
flex: 1;
|
|
||||||
padding: 20px 0px 20px 15px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: flex-start;
|
|
||||||
border-left: 1px solid #eee;
|
|
||||||
}
|
|
||||||
.versionTag{
|
|
||||||
display: inline;
|
|
||||||
border-radius: 2px;
|
|
||||||
padding:2px 12px;
|
|
||||||
font-size: 12px;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
.versionTag.yellow{
|
|
||||||
background-color: #FBBC06;
|
|
||||||
}
|
|
||||||
.versionTag.green{
|
|
||||||
background-color: #20BA45;
|
|
||||||
}
|
|
||||||
.versionTag.orange{
|
|
||||||
background-color: #F2711D;
|
|
||||||
}
|
|
||||||
.versionName{
|
|
||||||
font-size: 16px;
|
|
||||||
color: #333;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-end;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.versionName::before{
|
|
||||||
position: absolute;
|
|
||||||
left: -19px;
|
|
||||||
top:8px;
|
|
||||||
content: '';
|
|
||||||
width: 8px;
|
|
||||||
height: 8px;
|
|
||||||
background-color: #5091FF;
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.versionmilepostleft{
|
|
||||||
padding: 15px;
|
|
||||||
margin-right: 50px;
|
|
||||||
width: 80%;
|
|
||||||
}
|
|
||||||
.topWrapper_btn_close {
|
|
||||||
background: #504b4b;
|
|
||||||
color: #FFFFFF!important;
|
|
||||||
padding:0px 12px;
|
|
||||||
text-align: center;
|
|
||||||
height: 32px;
|
|
||||||
line-height: 32px;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.topWrapper_btn_delete {
|
|
||||||
background: #da1010;
|
|
||||||
color: #FFFFFF!important;
|
|
||||||
padding:0px 12px;
|
|
||||||
text-align: center;
|
|
||||||
height: 32px;
|
|
||||||
line-height: 32px;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.versionrighe{
|
|
||||||
flex: 2;
|
|
||||||
}
|
|
||||||
.versionleft{
|
|
||||||
flex: 1;
|
|
||||||
text-align: right;
|
|
||||||
display: flex;
|
|
||||||
justify-content: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* .version_line{
|
|
||||||
display: flex;
|
|
||||||
height: 30px;
|
|
||||||
margin: auto;
|
|
||||||
border-left:1px solid #eee;
|
|
||||||
} */
|
|
||||||
.version_line_one{
|
|
||||||
display: flex;
|
|
||||||
height: 45px;
|
|
||||||
margin: auto;
|
|
||||||
border-left:1px solid #eee;
|
|
||||||
}
|
|
||||||
|
|
||||||
.version_line_tpw{
|
|
||||||
display: flex;
|
|
||||||
height: 80px;
|
|
||||||
margin: auto;
|
|
||||||
border-left:1px solid #eee;
|
|
||||||
}
|
|
||||||
|
|
||||||
.versiondiv{
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
.verwinth{
|
|
||||||
width: 80%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*开启中 关闭中*/
|
|
||||||
.opendversionetail{
|
|
||||||
display: inline-block;
|
|
||||||
background: #21ba45;
|
|
||||||
color: #ffffff!important;
|
|
||||||
padding:0px 5px;
|
|
||||||
text-align: center;
|
|
||||||
height: 25px;
|
|
||||||
/*width: 110px;*/
|
|
||||||
border-radius: 4px;
|
|
||||||
line-height: 25px;
|
|
||||||
}
|
|
||||||
.closedversionetail{
|
|
||||||
display: inline-block;
|
|
||||||
background: #e60b0b;
|
|
||||||
color: #ffffff!important;
|
|
||||||
padding:0px 5px;
|
|
||||||
text-align: center;
|
|
||||||
height: 25px;
|
|
||||||
/*width: 110px;*/
|
|
||||||
border-radius: 4px;
|
|
||||||
line-height: 25px;
|
|
||||||
}
|
|
||||||
.versionrectangle {
|
|
||||||
width: 8px;
|
|
||||||
height: 8px;
|
|
||||||
border-radius: 100%;
|
|
||||||
margin-top: 15px;
|
|
||||||
margin-left: -4px;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
background: rgb(83, 81, 81);
|
|
||||||
}
|
|
||||||
.ver-middle{
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
/* new */
|
|
||||||
.versionForm{
|
|
||||||
flex:1;
|
|
||||||
padding-right: 30px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
.versionTips{
|
|
||||||
width:30%;
|
|
||||||
padding-left: 15px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
.infosTip{
|
|
||||||
padding:20px;
|
|
||||||
background-color: #F1F8FF;
|
|
||||||
margin-bottom: 22px;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
.versionStyle{
|
|
||||||
height: 200px!important;
|
|
||||||
border: 1px dashed rgba(80,145,255,1)!important;
|
|
||||||
}
|
|
||||||
.set-ant-row .ant-row{
|
|
||||||
display: flex;
|
|
||||||
height: 20px;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.itemInline{
|
|
||||||
display: flex;
|
|
||||||
align-item: center;
|
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
|
||||||
.itemInline .ant-row{
|
|
||||||
margin-bottom: 0px;
|
|
||||||
}
|
|
|
@ -1,128 +0,0 @@
|
||||||
import React, { Component } from "react";
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import { Spin } from 'antd';
|
|
||||||
import NoneData from '../Nodata';
|
|
||||||
import './version.css';
|
|
||||||
import axios from 'axios';
|
|
||||||
import RenderHtml from '../../components/render-html';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* issue_chosen:下拉的筛选列表,
|
|
||||||
* data:列表接口返回的所有数据,
|
|
||||||
* issues:列表数组,
|
|
||||||
* isSpin:加载中,
|
|
||||||
*/
|
|
||||||
class version extends Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
issue_chosen: undefined,
|
|
||||||
data: undefined,
|
|
||||||
releases:undefined,
|
|
||||||
issues: undefined,
|
|
||||||
isSpin: true,
|
|
||||||
search: undefined,
|
|
||||||
search_count: undefined,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount = () => {
|
|
||||||
this.getIssueList();
|
|
||||||
}
|
|
||||||
// 获取列表数据
|
|
||||||
getIssueList = () => {
|
|
||||||
const { projectsId, owner } = this.props.match.params;
|
|
||||||
const url = `/${owner}/${projectsId}/releases.json`;
|
|
||||||
axios.get(url).then((result) => {
|
|
||||||
if (result) {
|
|
||||||
this.setState({
|
|
||||||
data: result.data,
|
|
||||||
releases:result.data.releases,
|
|
||||||
issues: result.data.issues,
|
|
||||||
isSpin: false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
console.log(error);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 显示版本描述
|
|
||||||
showBody=(key,flag)=>{
|
|
||||||
let { releases } = this.state;
|
|
||||||
releases[key].bodyshow = !flag;
|
|
||||||
this.setState({
|
|
||||||
releases
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
renderList = (releases) => {
|
|
||||||
const { projectsId , owner } = this.props.match.params;
|
|
||||||
const { isManager , isDeveloper } = this.props;
|
|
||||||
const type = this.props.projectDetail && this.props.projectDetail.type;
|
|
||||||
|
|
||||||
if (releases && releases.length > 0) {
|
|
||||||
return (
|
|
||||||
releases.map((item, key) => {
|
|
||||||
return (
|
|
||||||
<div className="versionInfo" key={key}>
|
|
||||||
<span className="versionInfo_left">
|
|
||||||
<span className={`${item.draft === "稳定" ?"versionTag green":"versionTag yellow"}`}>{item.draft}</span>
|
|
||||||
<span className="mt10">{item.created_at}</span>
|
|
||||||
<span className="color-grey-8">
|
|
||||||
<i className="iconfont icon-biaoqian3 mr3 font-14"></i>
|
|
||||||
{item.tag_name}
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
<div className="versionInfo_right">
|
|
||||||
<span className="versionName">
|
|
||||||
<span className="task-hide">{item.name}</span>
|
|
||||||
{
|
|
||||||
(isManager || isDeveloper) && type !==2 &&
|
|
||||||
<Link to={`/${owner}/${projectsId}/releases/${item.version_id}/update`} className="color-blue ml3 font-12">(编辑)</Link>
|
|
||||||
}
|
|
||||||
</span>
|
|
||||||
<span className="color-grey-3">
|
|
||||||
<i className={`${item.bodyshow ? "iconfont icon-sanjiaoxing-down color-grey-8 mr3 font-14":"iconfont icon-triangle color-grey-8 mr3 font-14"}`} onClick={()=>this.showBody(key,item.bodyshow)}></i>
|
|
||||||
{item.user_name}:<span className="color-grey-8">发布了这个版本,并在发布后提交给{item.target_commitish}</span>
|
|
||||||
</span>
|
|
||||||
{
|
|
||||||
item.bodyshow && <RenderHtml className="break_word_comments imageLayerParent" value={item.body} url={this.props.history.location}/>
|
|
||||||
}
|
|
||||||
<RenderHtml />
|
|
||||||
<p className="mt10 pl3">
|
|
||||||
<a href={item.tarball_url} style={{color:"#4CC1DA"}} className="mr30"><i className="iconfont icon-TAR font-18 mr5"></i>TAR</a>
|
|
||||||
<a href={item.zipball_url} style={{color:"#28BD6C"}}><i className="iconfont icon-ZIP font-18 mr5"></i>ZIP</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
)
|
|
||||||
} else if (releases && releases.length === 0) {
|
|
||||||
return ( <NoneData _html="暂时还没有相关数据!" /> )
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { projectsId ,owner } = this.props.match.params;
|
|
||||||
const { data , releases , isSpin } = this.state;
|
|
||||||
const type = this.props.projectDetail && this.props.projectDetail.type;
|
|
||||||
return (
|
|
||||||
<div className="main" style={{padding:"0px"}}>
|
|
||||||
<div className="topWrapper" style={{padding:"15px 20px"}}>
|
|
||||||
<span className="font-18 color-grey-3">版本发布</span>
|
|
||||||
{
|
|
||||||
data && data.user_permission && type !== 2 ?
|
|
||||||
<Link to={`/${owner}/${projectsId}/releases/new`} className="topWrapper_btn_new">+ 发布新版</Link>
|
|
||||||
: ''
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
<div className="releasesVersion">
|
|
||||||
<Spin spinning={isSpin}><div>{this.renderList(releases)}</div></Spin>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export default version;
|
|
|
@ -6,3 +6,11 @@ export function truncateCommitId(str) {
|
||||||
return str
|
return str
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 秒数转2021-9-29 01:01
|
||||||
|
export function timeFormat(SecondsStr){
|
||||||
|
const time = new Date(SecondsStr*1000);
|
||||||
|
const hour = time.getHours()<10?"0".concat(time.getHours()):time.getHours();
|
||||||
|
const minutes = time.getMinutes()<10?"0".concat(time.getMinutes()):time.getMinutes();
|
||||||
|
return time.getFullYear()+"-"+(time.getMonth()+1)+"-"+time.getDate()+" "+hour+":"+minutes;
|
||||||
|
}
|
|
@ -88,14 +88,23 @@ ul,ol,dl{
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
&>span, & a:link, a:visited{
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
&>span{
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.commitDesc{
|
.commitDesc{
|
||||||
flex:1;
|
flex:1;
|
||||||
margin-left:20px;
|
line-height:20px;
|
||||||
font-size:16px;
|
|
||||||
color:#333;
|
|
||||||
line-height:26px;
|
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
|
width: 49rem;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: normal;
|
||||||
|
&:hover{
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.normalBox{
|
.normalBox{
|
||||||
|
@ -143,7 +152,7 @@ form.ant-form{
|
||||||
}
|
}
|
||||||
form{
|
form{
|
||||||
.ant-row.ant-form-item{
|
.ant-row.ant-form-item{
|
||||||
margin-bottom: 15px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@media screen and (max-width: 1000px){
|
@media screen and (max-width: 1000px){
|
||||||
|
@ -285,4 +294,50 @@ form{
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
.btn-83{
|
||||||
|
width: 83px;
|
||||||
|
height: 32px;
|
||||||
|
line-height: 30px;
|
||||||
|
text-align: center;
|
||||||
|
background: #FAFBFC;
|
||||||
|
border: 1px solid #D0D0D0;
|
||||||
|
display: inline-block;
|
||||||
|
border-radius: 5px;
|
||||||
|
font-weight: 500;
|
||||||
|
color: #333333!important;
|
||||||
|
margin-right: 15px;
|
||||||
|
&:hover{
|
||||||
|
background: #F3F4F6;
|
||||||
|
color: #333333!important;
|
||||||
|
}
|
||||||
|
&:active{
|
||||||
|
background: #D0D0D0;
|
||||||
|
color: #333333!important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.shadow:hover{
|
||||||
|
background: #eeeff1;
|
||||||
|
border-bottom-left-radius: 4px;
|
||||||
|
border-top-left-radius: 4px;
|
||||||
|
}
|
||||||
|
a.hover:hover{
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
button.ant-btn-primary.btnblue{
|
||||||
|
background-color:rgba(70, 106, 255, 1);
|
||||||
|
border-color:rgba(70, 106, 255, 1);
|
||||||
|
&:hover{
|
||||||
|
background-color:rgba(70, 106, 255, 0.85);
|
||||||
|
border-color:rgba(70, 106, 255, 0.85);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
button.btngrey{
|
||||||
|
background-color:#FFFFFF;
|
||||||
|
border-color:#D0D0D0;
|
||||||
|
color: #666666;
|
||||||
|
&:hover,&:focus{
|
||||||
|
border-color:rgba(153, 153, 153, 0.5);
|
||||||
|
color: #666666;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -30,11 +30,11 @@
|
||||||
|
|
||||||
.ant-upload-list-item-info .anticon-loading,
|
.ant-upload-list-item-info .anticon-loading,
|
||||||
.ant-upload-list-item-info .anticon-paper-clip {
|
.ant-upload-list-item-info .anticon-paper-clip {
|
||||||
color: #29bd8b !important;
|
color: rgba(102, 102, 102, 1) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.anticon anticon-paper-clip {
|
.anticon anticon-paper-clip {
|
||||||
color: #29bd8b !important;
|
color: rgba(102, 102, 102, 1) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.MuiModal-root-15 {
|
.MuiModal-root-15 {
|
||||||
|
|
|
@ -53,8 +53,6 @@ class CompetitionContentspdfpeopledata extends Component {
|
||||||
let url = `/users/accounts/${id}.json`;
|
let url = `/users/accounts/${id}.json`;
|
||||||
axios.get(url).then((result) => {
|
axios.get(url).then((result) => {
|
||||||
if (result.data) {
|
if (result.data) {
|
||||||
console.log("GetuseridApi");
|
|
||||||
console.log(result.data);
|
|
||||||
this.setState({
|
this.setState({
|
||||||
userdata:result.data
|
userdata:result.data
|
||||||
})
|
})
|
||||||
|
|
|
@ -938,7 +938,7 @@ body #root {
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-input:focus {
|
.ant-input:focus {
|
||||||
border: 1px solid #d9d9d9 !important;
|
border: 1px solid rgba(70, 106, 255, 1) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 公用的文字按钮:蓝、白、灰 */
|
/* 公用的文字按钮:蓝、白、灰 */
|
||||||
|
@ -1423,7 +1423,7 @@ samp {
|
||||||
}
|
}
|
||||||
|
|
||||||
.newcourses .ant-select-selection--single:hover {
|
.newcourses .ant-select-selection--single:hover {
|
||||||
border: 1px solid #d9d9d9 !important;
|
border: 1px solid rgba(70, 106, 255, 1) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pd20 {
|
.pd20 {
|
||||||
|
@ -1528,9 +1528,6 @@ samp {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.exerciselist .ant-input {
|
|
||||||
border: 1px solid #d9d9d9 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.exercisetime .ant-form-explain {
|
.exercisetime .ant-form-explain {
|
||||||
margin-left: 107px;
|
margin-left: 107px;
|
||||||
|
@ -1689,18 +1686,12 @@ samp {
|
||||||
height: 40px;
|
height: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-input-affix-wrapper:hover .ant-input:not(.ant-input-disabled) {
|
|
||||||
border: 1px solid #d9d9d9 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ant-input-affix-wrapper .ant-input-prefix,
|
.ant-input-affix-wrapper .ant-input-prefix,
|
||||||
.ant-input-affix-wrapper .ant-input-suffix {
|
.ant-input-affix-wrapper .ant-input-suffix {
|
||||||
background: #fafafa !important;
|
background: #fafafa !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ant-input:hover {
|
|
||||||
border: 1px solid #d9d9d9 !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ant-input:focus {
|
.ant-input:focus {
|
||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
|
|
|
@ -11,9 +11,6 @@
|
||||||
.ant-input-affix-wrapper:hover .ant-input:not(.ant-input-disabled){
|
.ant-input-affix-wrapper:hover .ant-input:not(.ant-input-disabled){
|
||||||
border:1px solid #d9d9d9!important;
|
border:1px solid #d9d9d9!important;
|
||||||
}
|
}
|
||||||
.ant-input:hover{
|
|
||||||
border:1px solid #d9d9d9!important;
|
|
||||||
}
|
|
||||||
.ant-input:focus{
|
.ant-input:focus{
|
||||||
box-shadow:none!important;
|
box-shadow:none!important;
|
||||||
background-color: #fff!important;
|
background-color: #fff!important;
|
||||||
|
|
|
@ -163,7 +163,6 @@ body>.-task-title {
|
||||||
outline: 0;
|
outline: 0;
|
||||||
-webkit-box-shadow: 0 0 0 2px transparent;
|
-webkit-box-shadow: 0 0 0 2px transparent;
|
||||||
box-shadow: 0 0 0 2px transparent;
|
box-shadow: 0 0 0 2px transparent;
|
||||||
border: 1px solid #d9d9d9;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.HeaderSearch .ant-input-search .ant-input::-webkit-input-placeholder {
|
.HeaderSearch .ant-input-search .ant-input::-webkit-input-placeholder {
|
||||||
|
|
Loading…
Reference in New Issue