Compare commits
No commits in common. "pre_develop" and "v3.1.5" have entirely different histories.
pre_develo
...
v3.1.5
File diff suppressed because it is too large
Load Diff
|
@ -1,2 +0,0 @@
|
||||||
{
|
|
||||||
}
|
|
|
@ -3425,9 +3425,9 @@
|
||||||
"integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw=="
|
"integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw=="
|
||||||
},
|
},
|
||||||
"clipboard": {
|
"clipboard": {
|
||||||
"version": "2.0.8",
|
"version": "2.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.6.tgz",
|
||||||
"integrity": "sha512-Y6WO0unAIQp5bLmk1zdThRhgJt/x3ks6f30s3oE3H1mgIEU33XyQjEf8gsf6DxC7NPX8Y1SsNWjUjL/ywLnnbQ==",
|
"integrity": "sha512-g5zbiixBRk/wyKakSwCKd7vQXDjFnAMGHoEyBogG/bw9kTD9GvdAvaoRR1ALcEzt3pVKxZR0pViekPMIS0QyGg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"good-listener": "^1.2.2",
|
"good-listener": "^1.2.2",
|
||||||
"select": "^1.1.2",
|
"select": "^1.1.2",
|
||||||
|
@ -3875,52 +3875,6 @@
|
||||||
"warning": "^4.0.3"
|
"warning": "^4.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"cross-env": {
|
|
||||||
"version": "7.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz",
|
|
||||||
"integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==",
|
|
||||||
"requires": {
|
|
||||||
"cross-spawn": "^7.0.1"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"cross-spawn": {
|
|
||||||
"version": "7.0.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
|
|
||||||
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
|
|
||||||
"requires": {
|
|
||||||
"path-key": "^3.1.0",
|
|
||||||
"shebang-command": "^2.0.0",
|
|
||||||
"which": "^2.0.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"path-key": {
|
|
||||||
"version": "3.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
|
|
||||||
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="
|
|
||||||
},
|
|
||||||
"shebang-command": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
|
|
||||||
"requires": {
|
|
||||||
"shebang-regex": "^3.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"shebang-regex": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
|
|
||||||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="
|
|
||||||
},
|
|
||||||
"which": {
|
|
||||||
"version": "2.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
|
||||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
|
||||||
"requires": {
|
|
||||||
"isexe": "^2.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"cross-fetch": {
|
"cross-fetch": {
|
||||||
"version": "3.1.4",
|
"version": "3.1.4",
|
||||||
"resolved": "https://registry.nlark.com/cross-fetch/download/cross-fetch-3.1.4.tgz",
|
"resolved": "https://registry.nlark.com/cross-fetch/download/cross-fetch-3.1.4.tgz",
|
||||||
|
@ -4931,7 +4885,7 @@
|
||||||
},
|
},
|
||||||
"dom-closest": {
|
"dom-closest": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npm.taobao.org/dom-closest/download/dom-closest-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/dom-closest/-/dom-closest-0.2.0.tgz",
|
||||||
"integrity": "sha1-69n5HRvyLo1vR3h2u80+yQIWwM8=",
|
"integrity": "sha1-69n5HRvyLo1vR3h2u80+yQIWwM8=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"dom-matches": ">=1.0.1"
|
"dom-matches": ">=1.0.1"
|
||||||
|
@ -4975,7 +4929,7 @@
|
||||||
},
|
},
|
||||||
"dom-matches": {
|
"dom-matches": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npm.taobao.org/dom-matches/download/dom-matches-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/dom-matches/-/dom-matches-2.0.0.tgz",
|
||||||
"integrity": "sha1-0nKLQWqHUzmA6wibhI0lPPI6dYw="
|
"integrity": "sha1-0nKLQWqHUzmA6wibhI0lPPI6dYw="
|
||||||
},
|
},
|
||||||
"dom-scroll-into-view": {
|
"dom-scroll-into-view": {
|
||||||
|
@ -5233,7 +5187,7 @@
|
||||||
},
|
},
|
||||||
"enquire.js": {
|
"enquire.js": {
|
||||||
"version": "2.1.6",
|
"version": "2.1.6",
|
||||||
"resolved": "https://registry.npm.taobao.org/enquire.js/download/enquire.js-2.1.6.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fenquire.js%2Fdownload%2Fenquire.js-2.1.6.tgz",
|
"resolved": "https://registry.npmjs.org/enquire.js/-/enquire.js-2.1.6.tgz",
|
||||||
"integrity": "sha1-PoeAybi4NQhMP2DhZtvDwqPImBQ="
|
"integrity": "sha1-PoeAybi4NQhMP2DhZtvDwqPImBQ="
|
||||||
},
|
},
|
||||||
"entities": {
|
"entities": {
|
||||||
|
@ -5752,7 +5706,7 @@
|
||||||
},
|
},
|
||||||
"eventlistener": {
|
"eventlistener": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"resolved": "https://registry.npm.taobao.org/eventlistener/download/eventlistener-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/eventlistener/-/eventlistener-0.0.1.tgz",
|
||||||
"integrity": "sha1-7Suqu4UiJ68rz4iRUscsY8pTLrg="
|
"integrity": "sha1-7Suqu4UiJ68rz4iRUscsY8pTLrg="
|
||||||
},
|
},
|
||||||
"events": {
|
"events": {
|
||||||
|
@ -8086,7 +8040,7 @@
|
||||||
},
|
},
|
||||||
"hammerjs": {
|
"hammerjs": {
|
||||||
"version": "2.0.8",
|
"version": "2.0.8",
|
||||||
"resolved": "https://registry.npm.taobao.org/hammerjs/download/hammerjs-2.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz",
|
||||||
"integrity": "sha1-BO93hiz/K7edMPdpIJWTAiK/YPE="
|
"integrity": "sha1-BO93hiz/K7edMPdpIJWTAiK/YPE="
|
||||||
},
|
},
|
||||||
"handle-thing": {
|
"handle-thing": {
|
||||||
|
@ -8927,7 +8881,7 @@
|
||||||
},
|
},
|
||||||
"immutable": {
|
"immutable": {
|
||||||
"version": "3.7.6",
|
"version": "3.7.6",
|
||||||
"resolved": "https://registry.npm.taobao.org/immutable/download/immutable-3.7.6.tgz",
|
"resolved": "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz",
|
||||||
"integrity": "sha1-E7TTyxK++hVIKib+Gy665kAHHks="
|
"integrity": "sha1-E7TTyxK++hVIKib+Gy665kAHHks="
|
||||||
},
|
},
|
||||||
"import-fresh": {
|
"import-fresh": {
|
||||||
|
@ -10532,7 +10486,7 @@
|
||||||
},
|
},
|
||||||
"lodash.throttle": {
|
"lodash.throttle": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npm.taobao.org/lodash.throttle/download/lodash.throttle-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
|
||||||
"integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ="
|
"integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ="
|
||||||
},
|
},
|
||||||
"lodash.uniq": {
|
"lodash.uniq": {
|
||||||
|
@ -16632,11 +16586,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"save-dev": {
|
|
||||||
"version": "0.0.1-security",
|
|
||||||
"resolved": "https://registry.npmjs.org/save-dev/-/save-dev-0.0.1-security.tgz",
|
|
||||||
"integrity": "sha512-k6knZTDNK8PKKbIqnvxiOveJinuw2LcQjqDoaorZWP9M5AR2EPsnpDeSbeoZZ0pHr5ze1uoaKdK8NBGQrJ34Uw=="
|
|
||||||
},
|
|
||||||
"sax": {
|
"sax": {
|
||||||
"version": "1.2.4",
|
"version": "1.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
|
||||||
|
|
|
@ -22,11 +22,10 @@
|
||||||
"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.8",
|
"clipboard": "^2.0.6",
|
||||||
"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",
|
||||||
"cross-env": "^7.0.3",
|
|
||||||
"css-loader": "^3.5.2",
|
"css-loader": "^3.5.2",
|
||||||
"dompurify": "^2.0.15",
|
"dompurify": "^2.0.15",
|
||||||
"dotenv": "4.0.0",
|
"dotenv": "4.0.0",
|
||||||
|
@ -104,7 +103,6 @@
|
||||||
"redux-thunk": "2.3.0",
|
"redux-thunk": "2.3.0",
|
||||||
"rsuite": "^4.3.4",
|
"rsuite": "^4.3.4",
|
||||||
"sass-loader": "7.3.1",
|
"sass-loader": "7.3.1",
|
||||||
"save-dev": "0.0.1-security",
|
|
||||||
"scroll-into-view": "^1.14.2",
|
"scroll-into-view": "^1.14.2",
|
||||||
"showdown": "^1.9.1",
|
"showdown": "^1.9.1",
|
||||||
"showdown-katex": "^0.8.0",
|
"showdown-katex": "^0.8.0",
|
||||||
|
@ -124,8 +122,8 @@
|
||||||
},
|
},
|
||||||
"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": "NODE_ENV=production 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",
|
"test-build": "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",
|
||||||
|
@ -195,7 +193,6 @@
|
||||||
"babel-core": "^6.26.0",
|
"babel-core": "^6.26.0",
|
||||||
"babel-plugin-import": "^1.13.0",
|
"babel-plugin-import": "^1.13.0",
|
||||||
"babel-plugin-transform-runtime": "^6.23.0",
|
"babel-plugin-transform-runtime": "^6.23.0",
|
||||||
"babel-polyfill": "^6.26.0",
|
|
||||||
"babel-preset-es2015": "^6.24.1",
|
"babel-preset-es2015": "^6.24.1",
|
||||||
"babel-preset-react": "^6.24.1",
|
"babel-preset-react": "^6.24.1",
|
||||||
"babel-preset-stage-2": "^6.24.1",
|
"babel-preset-stage-2": "^6.24.1",
|
||||||
|
|
|
@ -114,6 +114,14 @@ a:visited {
|
||||||
color: #898989;
|
color: #898989;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: #FF7500;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover.fa {
|
||||||
|
color: #FF7500;
|
||||||
|
}
|
||||||
|
|
||||||
input,
|
input,
|
||||||
textarea,
|
textarea,
|
||||||
select {
|
select {
|
||||||
|
|
|
@ -97,6 +97,10 @@ a:visited {
|
||||||
color: #05101a;
|
color: #05101a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: #459be5;
|
||||||
|
}
|
||||||
|
|
||||||
ol,
|
ol,
|
||||||
ul,
|
ul,
|
||||||
li {
|
li {
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
@charset "utf-8";
|
|
||||||
/* 头部 */
|
/* 头部 */
|
||||||
.header {
|
.header {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -1272,7 +1271,7 @@ html body {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
line-height: 2.0;
|
line-height: 2.0;
|
||||||
background: #fafafa;
|
background: #fafafa;
|
||||||
font-family: "Microsoft YaHei", "SimSun";
|
font-family: "微软雅黑", "宋体";
|
||||||
color: #05101a;
|
color: #05101a;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -1308,7 +1307,6 @@ td,
|
||||||
span {
|
span {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin-bottom: 0px!important;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
table,
|
table,
|
||||||
|
@ -1365,6 +1363,10 @@ a:visited {
|
||||||
color: #05101a;
|
color: #05101a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: #459be5;
|
||||||
|
}
|
||||||
|
|
||||||
ol,
|
ol,
|
||||||
ul,
|
ul,
|
||||||
li {
|
li {
|
||||||
|
@ -1471,7 +1473,7 @@ a.edu-txt-w80,
|
||||||
|
|
||||||
/*隐藏*/
|
/*隐藏*/
|
||||||
.none {
|
.none {
|
||||||
display: none!important;
|
display: none
|
||||||
}
|
}
|
||||||
|
|
||||||
.block {
|
.block {
|
||||||
|
@ -1520,15 +1522,7 @@ 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;
|
||||||
}
|
}
|
||||||
|
@ -1548,9 +1542,6 @@ 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;
|
||||||
|
@ -1572,9 +1563,6 @@ 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;
|
||||||
}
|
}
|
||||||
|
@ -1760,14 +1748,6 @@ a.decoration {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mb12 {
|
|
||||||
margin-bottom: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mb13 {
|
|
||||||
margin-bottom: 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mb14 {
|
.mb14 {
|
||||||
margin-bottom: 14px;
|
margin-bottom: 14px;
|
||||||
}
|
}
|
||||||
|
@ -2456,11 +2436,7 @@ a.hoverLine:hover{
|
||||||
|
|
||||||
|
|
||||||
.color-grey-9 {
|
.color-grey-9 {
|
||||||
color: #999 !important;
|
color: #999999 !important;
|
||||||
}
|
|
||||||
|
|
||||||
a:hover{
|
|
||||||
color: #466AFF !important;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.color-grey-98 {
|
.color-grey-98 {
|
||||||
|
@ -2495,23 +2471,33 @@ a:hover{
|
||||||
a.color-grey-name:hover,
|
a.color-grey-name:hover,
|
||||||
a.color-dark:hover,
|
a.color-dark:hover,
|
||||||
a.color-grey-6:hover,
|
a.color-grey-6:hover,
|
||||||
a.color-grey-3:hover,a.color-ooo:hover {
|
a.color-grey-3:hover {
|
||||||
color: #2A61FF !important;
|
color: #4cacff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.color-grey-9:hover,
|
||||||
|
a.color-grey-8:hover,
|
||||||
|
a.color-grey-c:hover {
|
||||||
|
color: #111C24 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*蓝色*/
|
/*蓝色*/
|
||||||
.color-blue {
|
.color-blue {
|
||||||
color: #2A61FF !important;
|
color: #4CACFF !important;
|
||||||
}
|
|
||||||
.color-blue-file {
|
|
||||||
color: #4598FA!important;
|
|
||||||
}
|
}
|
||||||
/* 绿色 */
|
/* 绿色 */
|
||||||
|
.color-green-file{
|
||||||
|
color: #28BD6C;
|
||||||
|
}
|
||||||
/*主*/
|
/*主*/
|
||||||
.color-blue_4C {
|
.color-blue_4C {
|
||||||
color: #4CACFF !important;
|
color: #4CACFF !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
a.color-blue:hover,
|
||||||
|
a.color-blue_4C:hover {
|
||||||
|
color: #459BE6 !important;
|
||||||
|
}
|
||||||
|
|
||||||
/*橙色*/
|
/*橙色*/
|
||||||
.color-orange {
|
.color-orange {
|
||||||
|
|
|
@ -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=1632964996877') format('woff2'),
|
src: url('iconfont.woff2?t=1630632852475') format('woff2'),
|
||||||
url('iconfont.woff?t=1632964996877') format('woff'),
|
url('iconfont.woff?t=1630632852475') format('woff'),
|
||||||
url('iconfont.ttf?t=1632964996877') format('truetype');
|
url('iconfont.ttf?t=1630632852475') format('truetype');
|
||||||
}
|
}
|
||||||
|
|
||||||
.iconfont {
|
.iconfont {
|
||||||
|
@ -13,82 +13,6 @@
|
||||||
-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 {
|
|
||||||
content: "\e8da";
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-icon:before {
|
|
||||||
content: "\e8ce";
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-tar:before {
|
|
||||||
content: "\e8cf";
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-a-fuzhi2:before {
|
|
||||||
content: "\e8d0";
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-fujian1:before {
|
|
||||||
content: "\e8d1";
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-a-bianji1:before {
|
|
||||||
content: "\e8d2";
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-banbenicon:before {
|
|
||||||
content: "\e8d3";
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-shanchuicon2:before {
|
|
||||||
content: "\e8d4";
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-a-lajitong_icon3x:before {
|
|
||||||
content: "\e8d5";
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-xialaanniu2:before {
|
|
||||||
content: "\e8d6";
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-xiazai-icon:before {
|
|
||||||
content: "\e8d7";
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-master_icon1:before {
|
|
||||||
content: "\e8d8";
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-shangchuanicon:before {
|
|
||||||
content: "\e8d9";
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-gerenziliao1:before {
|
.icon-gerenziliao1:before {
|
||||||
content: "\e8c7";
|
content: "\e8c7";
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -5,139 +5,6 @@
|
||||||
"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",
|
|
||||||
"name": "项目标签",
|
|
||||||
"font_class": "xiangmubiaoqian",
|
|
||||||
"unicode": "e8da",
|
|
||||||
"unicode_decimal": 59610
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"icon_id": "24368060",
|
|
||||||
"name": "icon",
|
|
||||||
"font_class": "icon",
|
|
||||||
"unicode": "e8ce",
|
|
||||||
"unicode_decimal": 59598
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"icon_id": "24368061",
|
|
||||||
"name": "tar",
|
|
||||||
"font_class": "tar",
|
|
||||||
"unicode": "e8cf",
|
|
||||||
"unicode_decimal": 59599
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"icon_id": "24289113",
|
|
||||||
"name": "复制 (2)",
|
|
||||||
"font_class": "a-fuzhi2",
|
|
||||||
"unicode": "e8d0",
|
|
||||||
"unicode_decimal": 59600
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"icon_id": "24289114",
|
|
||||||
"name": "附件",
|
|
||||||
"font_class": "fujian1",
|
|
||||||
"unicode": "e8d1",
|
|
||||||
"unicode_decimal": 59601
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"icon_id": "24289115",
|
|
||||||
"name": "编 辑",
|
|
||||||
"font_class": "a-bianji1",
|
|
||||||
"unicode": "e8d2",
|
|
||||||
"unicode_decimal": 59602
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"icon_id": "24289116",
|
|
||||||
"name": "版本icon",
|
|
||||||
"font_class": "banbenicon",
|
|
||||||
"unicode": "e8d3",
|
|
||||||
"unicode_decimal": 59603
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"icon_id": "24289117",
|
|
||||||
"name": "删除icon",
|
|
||||||
"font_class": "shanchuicon2",
|
|
||||||
"unicode": "e8d4",
|
|
||||||
"unicode_decimal": 59604
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"icon_id": "24289118",
|
|
||||||
"name": "垃圾桶_icon@3x",
|
|
||||||
"font_class": "a-lajitong_icon3x",
|
|
||||||
"unicode": "e8d5",
|
|
||||||
"unicode_decimal": 59605
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"icon_id": "24289119",
|
|
||||||
"name": "下拉按钮",
|
|
||||||
"font_class": "xialaanniu2",
|
|
||||||
"unicode": "e8d6",
|
|
||||||
"unicode_decimal": 59606
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"icon_id": "24289120",
|
|
||||||
"name": "下载-icon",
|
|
||||||
"font_class": "xiazai-icon",
|
|
||||||
"unicode": "e8d7",
|
|
||||||
"unicode_decimal": 59607
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"icon_id": "24289121",
|
|
||||||
"name": "master_icon",
|
|
||||||
"font_class": "master_icon1",
|
|
||||||
"unicode": "e8d8",
|
|
||||||
"unicode_decimal": 59608
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"icon_id": "24289122",
|
|
||||||
"name": "上传icon",
|
|
||||||
"font_class": "shangchuanicon",
|
|
||||||
"unicode": "e8d9",
|
|
||||||
"unicode_decimal": 59609
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"icon_id": "24059956",
|
"icon_id": "24059956",
|
||||||
"name": "个人资料",
|
"name": "个人资料",
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -3319,9 +3319,9 @@
|
||||||
text = text.replace(emailReg, function ($1, $2, $3, $4) {
|
text = text.replace(emailReg, function ($1, $2, $3, $4) {
|
||||||
return $1.replace(/@/g, "_#_@_#_");
|
return $1.replace(/@/g, "_#_@_#_");
|
||||||
});
|
});
|
||||||
// " + editormd.urls.atLinkBase + "" + $2 + "
|
|
||||||
text = text.replace(atLinkReg, function ($1, $2) {
|
text = text.replace(atLinkReg, function ($1, $2) {
|
||||||
return "<span title=\"@" + $2 + "\" class=\"at-link\"> " + $1 + " </span>";
|
return "<a href=\"" + editormd.urls.atLinkBase + "" + $2 + "\" title=\"@" + $2 + "\" class=\"at-link\">" + $1 + "</a>";
|
||||||
}).replace(/_#_@_#_/g, "@");
|
}).replace(/_#_@_#_/g, "@");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
24
src/App.js
24
src/App.js
|
@ -19,7 +19,7 @@ import moment from 'moment'
|
||||||
import { MuiThemeProvider, createMuiTheme } from 'material-ui/styles';
|
import { MuiThemeProvider, createMuiTheme } from 'material-ui/styles';
|
||||||
import SiderBar from './forge/Component/SiderBar'
|
import SiderBar from './forge/Component/SiderBar'
|
||||||
|
|
||||||
import { SnackbarHOC } from 'educoder';
|
import { SnackbarHOC } from 'educoder'
|
||||||
import { initAxiosInterceptors } from './AppConfig'
|
import { initAxiosInterceptors } from './AppConfig'
|
||||||
import { Provider } from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
import configureStore from './redux/stores/configureStore';
|
import configureStore from './redux/stores/configureStore';
|
||||||
|
@ -39,11 +39,6 @@ const Projects = Loadable({
|
||||||
loader: () => import('./forge/Index'),
|
loader: () => import('./forge/Index'),
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
})
|
})
|
||||||
// forge项目详情
|
|
||||||
const ProjectDetail = Loadable({
|
|
||||||
loader: () => import("./forge/Main/DetailAdaptor"),
|
|
||||||
loading: Loading,
|
|
||||||
});
|
|
||||||
//forge安全设置
|
//forge安全设置
|
||||||
const Security = Loadable({
|
const Security = Loadable({
|
||||||
loader: () => import('./forge/SecuritySetting/Index'),
|
loader: () => import('./forge/SecuritySetting/Index'),
|
||||||
|
@ -97,13 +92,8 @@ const ProjectIndex = Loadable({
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
});
|
});
|
||||||
|
|
||||||
// const CreateMerge = Loadable({
|
|
||||||
// loader: () => import('./forge/Merge/NewMerge'),
|
|
||||||
// loading: Loading,
|
|
||||||
// })
|
|
||||||
|
|
||||||
// 此处仅维护前端可能的一级路由,不用进行项目或者组织判断的字段。
|
// 此处仅维护前端可能的一级路由,不用进行项目或者组织判断的字段。
|
||||||
const keyWord = ["explore", "settings", "setting", "mulan", "wiki", "issues", "setting", "trending", "code", "projects", "pulls", "mine", "login", "register", "email", "export", "nopage", "404", "403", "500", "501", "search", "organize"];
|
const keyWord = ["explore", "settings", "setting", "CCF", "mulan", "wiki", "issues", "setting", "trending", "code", "projects", "pulls", "mine", "login", "register", "email", "export", "nopage", "404", "403", "500", "501", "search"];
|
||||||
|
|
||||||
class App extends Component {
|
class App extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -278,13 +268,6 @@ class App extends Component {
|
||||||
}
|
}
|
||||||
} />
|
} />
|
||||||
|
|
||||||
{/* 项目PR */}
|
|
||||||
<Route path="/:owner/:projectsId/compare"
|
|
||||||
render={
|
|
||||||
(props) => (<ProjectDetail {...this.props} {...props} {...this.state} />)
|
|
||||||
}
|
|
||||||
></Route>
|
|
||||||
|
|
||||||
{/*项目*/}
|
{/*项目*/}
|
||||||
<Route
|
<Route
|
||||||
path={"/:owner/:projectId/devops/:opsId/detail"}
|
path={"/:owner/:projectId/devops/:opsId/detail"}
|
||||||
|
@ -365,7 +348,7 @@ class App extends Component {
|
||||||
return (<OrganizeIndex {...props} {...this.props} {...this.state} />)
|
return (<OrganizeIndex {...props} {...this.props} {...this.state} />)
|
||||||
}
|
}
|
||||||
}>
|
}>
|
||||||
</Route> : pathType === '404' ? <Route component={Shixunnopage} />:
|
</Route> : pathType === '404' ? <Route path="/" component={Shixunnopage} /> :
|
||||||
<Route exact path="/"
|
<Route exact path="/"
|
||||||
render={
|
render={
|
||||||
(props) => (
|
(props) => (
|
||||||
|
@ -377,7 +360,6 @@ class App extends Component {
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
// <Route path="/" component={Loading} />
|
// <Route path="/" component={Loading} />
|
||||||
// <Route path="/" component={Shixunnopage} />
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -11,9 +11,9 @@ broadcastChannelOnmessage('refreshPage', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
function locationurl(list) {
|
function locationurl(list) {
|
||||||
if (window.location.port !== "3007") {
|
// if (window.location.port !== "3007") {
|
||||||
window.location.href = list
|
window.location.href = list
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
// TODO 开发期多个身份切换
|
// TODO 开发期多个身份切换
|
||||||
let debugType = ""
|
let debugType = ""
|
||||||
|
@ -86,7 +86,7 @@ export function initAxiosInterceptors(props) {
|
||||||
|
|
||||||
if (response.data.status === 404) {
|
if (response.data.status === 404) {
|
||||||
let responseURL = response.request ? response.request.responseURL:'';
|
let responseURL = response.request ? response.request.responseURL:'';
|
||||||
if (responseURL.indexOf('/api/users/') === -1 && responseURL.indexOf('/api/organizations/') === -1 ) {
|
if (responseURL.indexOf('/api/users/') === -1 && responseURL.indexOf('/api/organizations/') === -1 && responseURL.indexOf('/api/owners/') === -1) {
|
||||||
locationurl('/nopage');
|
locationurl('/nopage');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -218,7 +218,7 @@ a:hover {
|
||||||
}
|
}
|
||||||
|
|
||||||
.color-blue {
|
.color-blue {
|
||||||
color: #2A61FF;
|
color: #4CACFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
.color-huang {
|
.color-huang {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -18,23 +18,6 @@ export function getImageUrl(path) {
|
||||||
return `${path}`;
|
return `${path}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function numFormat(num, digits){
|
|
||||||
let d = digits || 1;
|
|
||||||
var si = [
|
|
||||||
{ value: 1, symbol: "" },
|
|
||||||
{ value: 1E3, symbol: "k" },
|
|
||||||
{ value: 1E4, symbol: "W" }
|
|
||||||
];
|
|
||||||
var rx = /\.0+$|(\.[0-9]*[1-9])0+$/;
|
|
||||||
var i;
|
|
||||||
for (i = si.length - 1; i > 0; i--) {
|
|
||||||
if (num >= si[i].value) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (num / si[i].value).toFixed(d).replace(rx, "$1") + si[i].symbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getImage(path) {
|
export function getImage(path) {
|
||||||
// https://www.educoder.net
|
// https://www.educoder.net
|
||||||
// https://testbdweb.trustie.net
|
// https://testbdweb.trustie.net
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
// export { default as OrderStateUtil } from '../routes/Order/components/OrderStateUtil';
|
// export { default as OrderStateUtil } from '../routes/Order/components/OrderStateUtil';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
getUploadLogoActionUrl as getUploadLogoActionUrl,numFormat as numFormat,
|
getUploadLogoActionUrl as getUploadLogoActionUrl,
|
||||||
getImageUrl as getImageUrl,getImage as getImage, getmyUrl as getmyUrl, getRandomNumber as getRandomNumber, getUrl as getUrl, publicSearchs as publicSearchs, getRandomcode as getRandomcode, getUrlmys as getUrlmys, getUrl2 as getUrl2, setImagesUrl as setImagesUrl
|
getImageUrl as getImageUrl,getImage as getImage, getmyUrl as getmyUrl, getRandomNumber as getRandomNumber, getUrl as getUrl, publicSearchs as publicSearchs, getRandomcode as getRandomcode, getUrlmys as getUrlmys, getUrl2 as getUrl2, setImagesUrl as setImagesUrl
|
||||||
, getUploadActionUrl as getUploadActionUrl, getUploadActionUrltwo as getUploadActionUrltwo, getUploadActionUrlthree as getUploadActionUrlthree, getUploadActionUrlOfAuth as getUploadActionUrlOfAuth
|
, getUploadActionUrl as getUploadActionUrl, getUploadActionUrltwo as getUploadActionUrltwo, getUploadActionUrlthree as getUploadActionUrlthree, getUploadActionUrlOfAuth as getUploadActionUrlOfAuth
|
||||||
, getTaskUrlById as getTaskUrlById, TEST_HOST, htmlEncode as htmlEncode, getupload_git_file as getupload_git_file, getcdnImageUrl as getcdnImageUrl
|
, getTaskUrlById as getTaskUrlById, TEST_HOST, htmlEncode as htmlEncode, getupload_git_file as getupload_git_file, getcdnImageUrl as getcdnImageUrl
|
||||||
|
|
|
@ -10,10 +10,6 @@ import ActivityItem from './ActivityItem';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
const LIMIT = 15;
|
const LIMIT = 15;
|
||||||
const ARRAY = [
|
const ARRAY = [
|
||||||
{
|
|
||||||
id:"",
|
|
||||||
name:'全部'
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
id:1,
|
id:1,
|
||||||
name:'1天'
|
name:'1天'
|
||||||
|
@ -36,15 +32,10 @@ class Activity extends Component{
|
||||||
constructor(props){
|
constructor(props){
|
||||||
super(props);
|
super(props);
|
||||||
this.state={
|
this.state={
|
||||||
time:undefined,
|
time:'30',
|
||||||
type:undefined,
|
type:undefined,
|
||||||
state:undefined,
|
state:undefined,
|
||||||
page:1,
|
page:1,
|
||||||
pr_count:undefined,
|
|
||||||
new_pr_count:undefined,
|
|
||||||
close_issues_count:undefined,
|
|
||||||
open_issues_count:undefined,
|
|
||||||
pr_all_count:undefined,issues_count:undefined,
|
|
||||||
|
|
||||||
data:undefined,
|
data:undefined,
|
||||||
project_trends:undefined,
|
project_trends:undefined,
|
||||||
|
@ -72,15 +63,8 @@ class Activity extends Component{
|
||||||
this.setState({
|
this.setState({
|
||||||
data:result.data,
|
data:result.data,
|
||||||
project_trends:result.data.project_trends,
|
project_trends:result.data.project_trends,
|
||||||
isSpin:false,
|
isSpin:false
|
||||||
pr_count:result.data.pr_count,
|
|
||||||
new_pr_count:result.data.new_pr_count,
|
|
||||||
close_issues_count:result.data.close_issues_count,
|
|
||||||
open_issues_count:result.data.open_issues_count,
|
|
||||||
pr_all_count:result.data.pr_all_count,
|
|
||||||
issues_count:result.data.issues_count,
|
|
||||||
})
|
})
|
||||||
window.scrollTo(0,0);
|
|
||||||
}
|
}
|
||||||
}).catch(error=>{
|
}).catch(error=>{
|
||||||
console.log(error);
|
console.log(error);
|
||||||
|
@ -90,19 +74,19 @@ class Activity extends Component{
|
||||||
// 切换周期
|
// 切换周期
|
||||||
changeTime=(e)=>{
|
changeTime=(e)=>{
|
||||||
this.setState({
|
this.setState({
|
||||||
time:e.key ==="item_0"?undefined:e.key,
|
time:e.key,
|
||||||
isSpin:true
|
isSpin:true
|
||||||
})
|
})
|
||||||
const { type,status,page } = this.state;
|
const { type,status,page } = this.state;
|
||||||
this.getInfo(e.key ==="item_0"?undefined:e.key,type,status,page);
|
this.getInfo(e.key,type,status,page);
|
||||||
}
|
}
|
||||||
//筛选
|
//筛选
|
||||||
changeTrends=(type,status)=>{
|
changeTrends=(type,status)=>{
|
||||||
this.setState({
|
this.setState({
|
||||||
type,status,page:1
|
type,status
|
||||||
})
|
})
|
||||||
const {time}=this.state;
|
const {time,page}=this.state;
|
||||||
this.getInfo(time,type,status,1);
|
this.getInfo(time,type,status,page);
|
||||||
}
|
}
|
||||||
// 分页
|
// 分页
|
||||||
ChangePage=(page)=>{
|
ChangePage=(page)=>{
|
||||||
|
@ -124,14 +108,12 @@ class Activity extends Component{
|
||||||
</Menu>
|
</Menu>
|
||||||
)
|
)
|
||||||
render(){
|
render(){
|
||||||
const { time , data , page , project_trends , isSpin , pr_count , new_pr_count , close_issues_count , open_issues_count , pr_all_count ,issues_count } = this.state;
|
const { time , data , page , project_trends , isSpin } = this.state;
|
||||||
let name = time ? ARRAY.filter(item=>item.id === parseInt(time)) :[{name:"全部"}];
|
|
||||||
|
|
||||||
const first_per = pr_all_count > 0 ? `${parseFloat(pr_count/pr_all_count).toFixed(2)*100}%` :"50%";
|
|
||||||
const second_per =pr_all_count > 0 ? `${parseFloat(new_pr_count/pr_all_count).toFixed(2)*100}%` :"50%";
|
|
||||||
const third_per =issues_count > 0 ?`${parseFloat(close_issues_count/issues_count).toFixed(2)*100}%` :"50%";
|
|
||||||
const fourth_per =issues_count > 0 ?`${parseFloat(open_issues_count/issues_count).toFixed(2)*100}%` :"50%";
|
|
||||||
|
|
||||||
|
let name = time && ARRAY.filter(item=>item.id === parseInt(time)) ;
|
||||||
|
const second_per = (parseInt(data && data.close_issues_count)/parseInt(data && data.issues_count)*100)+'%';
|
||||||
|
const third_per = (parseInt(data && data.close_issues_count)/parseInt(data && data.issues_count)*100)+'%';
|
||||||
|
const fourth_per = (parseInt(data && data.open_issues_count)/parseInt(data && data.issues_count)*100)+'%';
|
||||||
return(
|
return(
|
||||||
<div className="main">
|
<div className="main">
|
||||||
|
|
||||||
|
@ -140,7 +122,7 @@ class Activity extends Component{
|
||||||
<div className="orderInfo">
|
<div className="orderInfo">
|
||||||
<div>
|
<div>
|
||||||
<div className="percentLine prPercent">
|
<div className="percentLine prPercent">
|
||||||
<p className="percent_purple" style={{width:first_per}}></p>
|
<p className="percent_purple" style={{width:'100%'}}></p>
|
||||||
<p className="percent_green resetStyle" style={{width:`${second_per}`}}></p>
|
<p className="percent_green resetStyle" style={{width:`${second_per}`}}></p>
|
||||||
</div>
|
</div>
|
||||||
<span>{data && data.pr_all_count}合并请求</span>
|
<span>{data && data.pr_all_count}合并请求</span>
|
||||||
|
@ -150,25 +132,25 @@ class Activity extends Component{
|
||||||
<p className="percent_red" style={{width:`${third_per}`}}></p>
|
<p className="percent_red" style={{width:`${third_per}`}}></p>
|
||||||
<p className="percent_green" style={{width:`${fourth_per}`}}></p>
|
<p className="percent_green" style={{width:`${fourth_per}`}}></p>
|
||||||
</div>
|
</div>
|
||||||
<span>{data && data.issues_count}易修</span>
|
<span>{data && data.issues_count}任务</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ul className="percentBox">
|
<ul className="percentBox">
|
||||||
<li>
|
<li>
|
||||||
<span className="purple">{data && data.pr_count}</span>
|
<span className="purple">{data && data.pr_count}</span>
|
||||||
<span className="change" onClick={()=>this.changeTrends("PullRequest","delay")}>已处理的合并请求</span>
|
<span className="change" onClick={()=>this.changeTrends("PullRequest","close")}>已处理的合并请求</span>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<span className="green">{data && data.new_pr_count}</span>
|
<span className="green">{data && data.new_pr_count}</span>
|
||||||
<span className="change" onClick={()=>this.changeTrends("PullRequest","not_delay")}>未处理的合并请求</span>
|
<span className="change" onClick={()=>this.changeTrends("PullRequest","create")}>未处理的合并请求</span>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<span className="red">{data && data.close_issues_count}</span>
|
<span className="red">{data && data.close_issues_count}</span>
|
||||||
<span className="change" onClick={()=>this.changeTrends("Issue","delay")}>已关闭的易修</span>
|
<span className="change" onClick={()=>this.changeTrends("Issue","close")}>已关闭的任务</span>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<span className="green">{data && data.open_issues_count}</span>
|
<span className="green">{data && data.open_issues_count}</span>
|
||||||
<span className="change" onClick={()=>this.changeTrends("Issue","not_delay")}>未处理的易修</span>
|
<span className="change" onClick={()=>this.changeTrends("Issue","create")}>未处理的任务</span>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -27,7 +27,7 @@ class ActivityItem extends Component {
|
||||||
:
|
:
|
||||||
// 如果是合并请求
|
// 如果是合并请求
|
||||||
<p className="itemLine">
|
<p className="itemLine">
|
||||||
<Link to={`/${owner}/${projectsId}/pulls/${item.trend_id}`} className="color-blue font-16">{item.name}</Link>
|
<Link to={`/${owner}/${projectsId}/pulls/${item.trend_id}/Messagecount`} className="color-blue font-16">{item.name}</Link>
|
||||||
<span className="activity_type">{item.trend_type}</span>
|
<span className="activity_type">{item.trend_type}</span>
|
||||||
</p >
|
</p >
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ function CloneAddress({http_url , ssh_url , zip_url , tar_url}) {
|
||||||
const [ key , setKey ] = useState("HTTP");
|
const [ key , setKey ] = useState("HTTP");
|
||||||
return (
|
return (
|
||||||
<div className="downMenu">
|
<div className="downMenu">
|
||||||
<div style={{borderBottom:"1px solid #eee"}}>
|
<div style={{padding:"10px 20px 20px 20px",borderBottom:"1px solid #eee"}}>
|
||||||
<Menu className="urlMenu" selectedKeys={[key]} mode={"horizontal"}>
|
<Menu className="urlMenu" selectedKeys={[key]} mode={"horizontal"}>
|
||||||
<Menu.Item key="HTTP" onClick={(e)=>{setKey(e.key)}}>HTTP</Menu.Item>
|
<Menu.Item key="HTTP" onClick={(e)=>{setKey(e.key)}}>HTTP</Menu.Item>
|
||||||
<Menu.Item key="SSH" onClick={(e)=>{setKey(e.key)}}>SSH</Menu.Item>
|
<Menu.Item key="SSH" onClick={(e)=>{setKey(e.key)}}>SSH</Menu.Item>
|
||||||
|
|
|
@ -1,65 +1,116 @@
|
||||||
import React , { useState , useEffect , useRef } from 'react';
|
import React , { useState , useEffect } from 'react';
|
||||||
import { Dropdown} from 'antd';
|
import { Popover , Input , Spin } from 'antd';
|
||||||
import './branch.scss';
|
import './branch.scss';
|
||||||
import SelectOverlay from './SelectOverlay';
|
import { getBranch , getTag } from '../GetData/getData';
|
||||||
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 [ inputValue , setInputValue] = useState(undefined);
|
||||||
|
const [ nav , setNav ] = useState(0);
|
||||||
|
const [ isSpin , setIsSpin ] = useState(true);
|
||||||
|
const [ flag , setFlag ] = useState(false);
|
||||||
|
|
||||||
const refFa = useRef(null);
|
const [ data , setData ] = useState(undefined);
|
||||||
const refBox = useRef(null);
|
const [ datas , setDatas ] = useState(undefined);
|
||||||
|
|
||||||
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) {
|
useEffect(()=>{
|
||||||
setVisible(false);
|
document.body.addEventListener('click', e => {
|
||||||
changeBranch(params);
|
let name = e.target.className;
|
||||||
|
let turn = name === "ant-input OptionsInput" || name === "navli active"|| name === "navli" || name === "padding10 bor-bottom-greyE";
|
||||||
|
if(turn){
|
||||||
|
return;
|
||||||
|
}else{
|
||||||
|
setFlag(false);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
if(branchList){
|
||||||
|
setData(branchList);
|
||||||
|
setDatas(branchList);
|
||||||
|
setIsSpin(false);
|
||||||
|
}
|
||||||
|
},[branchList])
|
||||||
|
|
||||||
|
|
||||||
|
async function getBranchs(id,owner){
|
||||||
|
let result = await getBranch(id,owner);
|
||||||
|
setData(result);
|
||||||
|
setDatas(result);
|
||||||
|
setIsSpin(false);
|
||||||
|
}
|
||||||
|
async function getTags(id,owner){
|
||||||
|
let result = await getTag(id,owner);
|
||||||
|
setData(result);
|
||||||
|
setDatas(result);
|
||||||
|
setIsSpin(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function changeInputValue(e){
|
||||||
|
setInputValue(e.target.value);
|
||||||
|
let filter = e.target.value ? data && data.length>0 && data.filter(item=>item.name.indexOf(e.target.value)>-1) : data;
|
||||||
|
setDatas(filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeNav(nav){
|
||||||
|
setNav(nav);
|
||||||
|
setIsSpin(true);
|
||||||
|
if(nav === 0){
|
||||||
|
getBranchs(projectsId,owner);
|
||||||
|
}else{
|
||||||
|
getTags(projectsId,owner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function chooseitem(value){
|
||||||
|
// setShowValue(value);
|
||||||
|
changeBranch(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const menu = (
|
const menu = (
|
||||||
<div ref={refFa}>
|
<div>
|
||||||
<SelectOverlay
|
<div className="padding10 bor-bottom-greyE">
|
||||||
visible={visible}
|
<Input
|
||||||
changeBranch={ChangeB}
|
placeholder="请输入分支或标签名称搜索"
|
||||||
tagflag={tagflag}
|
autocomplete="off" className="OptionsInput" value={inputValue}
|
||||||
projectsId={projectsId}
|
onChange={changeInputValue} style={{width:"220px"}}
|
||||||
owner={owner}
|
/>
|
||||||
branchList={branchList}
|
<ul className="navUl">
|
||||||
/>
|
<li className={nav === 0?"navli active":"navli"} onClick={()=>changeNav(0)}><i className="iconfont icon-fenzhi1 font-14 mr3"></i>分支列表</li>
|
||||||
|
{ tagflag && <li className={nav === 1?"navli active":"navli"} onClick={()=>changeNav(1)}><i className="iconfont icon-biaoqian3 font-14 mr3"></i>标签列表</li> }
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<Spin spinning={isSpin}>
|
||||||
|
<ul className="OptionsUl" id="ul-btn">
|
||||||
|
{
|
||||||
|
datas && datas.length>0 ?
|
||||||
|
datas.map((item,key)=>{
|
||||||
|
return(
|
||||||
|
<li key={key} onClick={()=>chooseitem(item.name)}><a className="task-hide ulALink">{item.name}</a></li>
|
||||||
|
)
|
||||||
|
}):
|
||||||
|
<p className="listTips">暂无{inputValue}{nav === 0 ?"分支":"标签"}~</p>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
</Spin>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
return(
|
return(
|
||||||
<Dropdown placement='bottomLeft' visible={visible} overlay={menu} overlayClassName="branch-tagBox-list" trigger={['click']} >
|
<Popover placement='bottomLeft' visible={flag} content={menu} onClick={()=>setFlag(!flag)} overlayClassName="branch-tagBox-list">
|
||||||
<div className="branch-tagBox" ref={refBox} onClick={()=>setVisible(visible ? false : true)}>
|
<div className="branch-tagBox">
|
||||||
{/* {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",minWidth:"45px",maxWidth:"270px"}}>
|
<a className="ant-dropdown-link">
|
||||||
{showValue}
|
{showValue}
|
||||||
</span>
|
</a>
|
||||||
<i className="showtag iconfont icon-sanjiaoxing-down font-15 color-grey-9 mr5 ml5 mt1" />
|
<i className="showtag iconfont icon-xiajiantou font-14 color-grey-9 mr8" />
|
||||||
</div>
|
</div>
|
||||||
</Dropdown>
|
</Popover>
|
||||||
)
|
)
|
||||||
})
|
})
|
|
@ -1,90 +0,0 @@
|
||||||
import React , { useState , useEffect } from 'react';
|
|
||||||
import { Input , Spin , Menu } from 'antd';
|
|
||||||
import { getBranch , getTag } from '../GetData/getData';
|
|
||||||
|
|
||||||
function SelectOverlay({ changeBranch , tagflag , projectsId , owner , visible }) {
|
|
||||||
const [ inputValue , setInputValue] = useState(undefined);
|
|
||||||
const [ nav , setNav ] = useState(0);
|
|
||||||
const [ isSpin , setIsSpin ] = useState(true);
|
|
||||||
|
|
||||||
const [ data , setData ] = useState(undefined);
|
|
||||||
const [ datas , setDatas ] = useState(undefined);
|
|
||||||
const [ keys ,setKeys] = useState("branch");
|
|
||||||
|
|
||||||
useEffect(()=>{
|
|
||||||
if(visible){
|
|
||||||
setKeys("branch");
|
|
||||||
getBranchs(projectsId,owner);
|
|
||||||
setIsSpin(true);
|
|
||||||
}
|
|
||||||
},[visible])
|
|
||||||
|
|
||||||
async function getBranchs(id,owner){
|
|
||||||
let result = await getBranch(id,owner);
|
|
||||||
setData(result);
|
|
||||||
setDatas(result);
|
|
||||||
setIsSpin(false);
|
|
||||||
}
|
|
||||||
async function getTags(id,owner){
|
|
||||||
let result = await getTag(id,owner);
|
|
||||||
setData(result);
|
|
||||||
setDatas(result);
|
|
||||||
setIsSpin(false);
|
|
||||||
}
|
|
||||||
function chooseitem(value){
|
|
||||||
changeBranch(value);
|
|
||||||
}
|
|
||||||
function changeInputValue(e){
|
|
||||||
setInputValue(e.target.value);
|
|
||||||
let filter = e.target.value ? data && data.length>0 && data.filter(item=>item.name.indexOf(e.target.value)>-1) : data;
|
|
||||||
setDatas(filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
function changeNav(e){
|
|
||||||
setKeys(e.key);
|
|
||||||
setIsSpin(true);
|
|
||||||
if(e.key === "branch"){
|
|
||||||
getBranchs(projectsId,owner);
|
|
||||||
setNav(0);
|
|
||||||
}else{
|
|
||||||
getTags(projectsId,owner);
|
|
||||||
setNav(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return(
|
|
||||||
<div className="overlayBranch">
|
|
||||||
<div className="padding15" style={{paddingBottom:"0px"}}>
|
|
||||||
<Input
|
|
||||||
prefix={<i className="iconfont icon-sousuo_icon1 font-14"></i>}
|
|
||||||
placeholder={`请输入分支${tagflag ? "或标签" :""}名称搜索`}
|
|
||||||
autocomplete="off" className="OptionsInput"
|
|
||||||
value={inputValue}
|
|
||||||
onChange={changeInputValue}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<Menu mode="horizontal" className="navUl" selectedKeys={[keys]} onClick={changeNav}>
|
|
||||||
<Menu.Item key={"branch"}>分支</Menu.Item>
|
|
||||||
{ tagflag && <Menu.Item key={"tag"}>标签</Menu.Item> }
|
|
||||||
</Menu>
|
|
||||||
<Spin spinning={isSpin}>
|
|
||||||
<ul className="OptionsUl" id="ul-btn">
|
|
||||||
{
|
|
||||||
datas && datas.length>0 &&
|
|
||||||
datas.map((item,key)=>{
|
|
||||||
return(
|
|
||||||
<li key={key} onClick={()=>chooseitem(item.name)}><a className="task-hide ulALink">{item.name}</a></li>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
{
|
|
||||||
datas && datas.length === 0 &&
|
|
||||||
<p className="listTips">暂无{inputValue}{nav === 0 ?"分支":"标签"}~</p>
|
|
||||||
}
|
|
||||||
</ul>
|
|
||||||
</Spin>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export default SelectOverlay;
|
|
|
@ -23,16 +23,14 @@
|
||||||
max-height: 300px;
|
max-height: 300px;
|
||||||
}
|
}
|
||||||
.OptionsUl{
|
.OptionsUl{
|
||||||
min-height: 50px;
|
|
||||||
max-height: 220px;
|
max-height: 220px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
.OptionsUl li{
|
.OptionsUl li{
|
||||||
height: 30px;
|
height: 35px;
|
||||||
line-height: 30px;
|
line-height: 35px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding:0px 20px;
|
padding:0px 10px;
|
||||||
margin:5px 0px;
|
|
||||||
}
|
}
|
||||||
.OptionsUl li:hover{
|
.OptionsUl li:hover{
|
||||||
background-color: #F0F0F0;
|
background-color: #F0F0F0;
|
||||||
|
@ -47,56 +45,38 @@
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
.branch-tagBox{
|
.branch-tagBox{
|
||||||
border:1px solid #D0D0D0;
|
border:1px solid #eee;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
height: 32px;
|
height: 40px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
min-width: 104px;
|
min-width: 140px;
|
||||||
}
|
}
|
||||||
.branch-tagBox:hover{
|
.branch-tagBox-list .ant-popover-arrow{
|
||||||
background-color: #F3F4F6;
|
display: none;
|
||||||
}
|
}
|
||||||
.branch-tagBox-list{
|
.branch-tagBox-list.ant-popover.ant-popover-placement-bottom{
|
||||||
background: #FFFFFF;
|
padding-top:0px;
|
||||||
box-shadow: 0px 4px 8px 2px rgba(212, 212, 212, 0.5);
|
|
||||||
border-radius: 4px;
|
|
||||||
.ant-popover-arrow{
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
&.ant-popover.ant-popover-placement-bottom{
|
|
||||||
padding-top:0px;
|
|
||||||
}
|
|
||||||
.branch-tagBox .ant-dropdown-link{
|
|
||||||
display: block;
|
|
||||||
flex:1;
|
|
||||||
max-width: 105px;
|
|
||||||
}
|
|
||||||
.ant-popover-inner-content{
|
|
||||||
padding:0px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.overlayBranch{
|
.branch-tagBox .ant-dropdown-link{
|
||||||
width: 325px;
|
display: block;
|
||||||
.navUl{
|
flex:1;
|
||||||
margin-top: 8px;
|
}
|
||||||
height: 30px;
|
.branch-tagBox-list .ant-popover-inner-content{
|
||||||
line-height: 30px;
|
padding:0px;
|
||||||
li{
|
}
|
||||||
height: 30px;
|
.navUl{
|
||||||
line-height: 30px;
|
display: flex;
|
||||||
padding:0px 5px;
|
justify-content: space-between;
|
||||||
margin-left: 20px!important;
|
align-items: center;
|
||||||
&.ant-menu-item-selected{
|
margin-top: 5px;
|
||||||
border-color:#466aff!important;
|
}
|
||||||
color:#466aff!important;
|
.navUl li{
|
||||||
}
|
cursor: pointer;
|
||||||
&.ant-menu-item-active{
|
}
|
||||||
border-color:transparent ;
|
.navUl li.active{
|
||||||
}
|
color:#5091FF;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.listTips{
|
.listTips{
|
||||||
padding:20px 0px;
|
padding:20px 0px;
|
||||||
|
@ -106,7 +86,6 @@
|
||||||
.urlMenu{
|
.urlMenu{
|
||||||
line-height: 30px;
|
line-height: 30px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
padding:15px 20px 0px 20px;
|
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
li.ant-menu-item{
|
li.ant-menu-item{
|
||||||
height: 30px;
|
height: 30px;
|
||||||
|
@ -117,7 +96,7 @@
|
||||||
color: #333;
|
color: #333;
|
||||||
}
|
}
|
||||||
&.ant-menu-item-selected{
|
&.ant-menu-item-selected{
|
||||||
border-color:#466aff!important;
|
border-color:#1890ff!important;
|
||||||
}
|
}
|
||||||
&.ant-menu-item-active{
|
&.ant-menu-item-active{
|
||||||
border-color:transparent ;
|
border-color:transparent ;
|
||||||
|
|
|
@ -113,14 +113,7 @@ li.ant-menu-item{
|
||||||
z-index: 10000;
|
z-index: 10000;
|
||||||
}
|
}
|
||||||
.laterest{
|
.laterest{
|
||||||
background-color: #EF3131;
|
color: #05690d;
|
||||||
color: #fff;
|
|
||||||
font-size: 12px;
|
|
||||||
margin-left: 10px;
|
|
||||||
padding:0px 5px;
|
|
||||||
border-radius: 2px;
|
|
||||||
height: 18px;
|
|
||||||
line-height: 18px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 1800px){
|
@media screen and (max-width: 1800px){
|
||||||
|
@ -162,112 +155,41 @@ li.ant-menu-item{
|
||||||
margin:0px 20px!important;
|
margin:0px 20px!important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.hoverA{
|
|
||||||
display:flex;
|
|
||||||
align-items: center;
|
|
||||||
max-width: 78px;
|
|
||||||
&:hover a{
|
|
||||||
color:#2A61FF !important ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.menuPanels{
|
.menuPanels{
|
||||||
width: 295px;
|
width: 240px;
|
||||||
.leftline{
|
height: 180px;
|
||||||
position: relative;
|
|
||||||
color: #666;
|
|
||||||
height: 16px;
|
|
||||||
margin-left: 14px;
|
|
||||||
font-size: 12px;
|
|
||||||
&::before{
|
|
||||||
position: absolute;
|
|
||||||
left: -7px;
|
|
||||||
top:3px;
|
|
||||||
height: 12px;
|
|
||||||
width: 1px;
|
|
||||||
background-color: #999;
|
|
||||||
content: "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.ant-btn{
|
|
||||||
height: 36px;
|
|
||||||
line-height: 34px;
|
|
||||||
width: 83px;
|
|
||||||
text-align: center;
|
|
||||||
padding:0px ;
|
|
||||||
font-weight: 500;
|
|
||||||
font-size: 14px;
|
|
||||||
&.currentBtn{
|
|
||||||
cursor: default;
|
|
||||||
color: #333;
|
|
||||||
&:hover{
|
|
||||||
color: #333;
|
|
||||||
border-color: #d0d0d0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.ant-btn-default{
|
|
||||||
color: #333;
|
|
||||||
border-color: #d0d0d0;
|
|
||||||
&:hover{
|
|
||||||
background: #F3F4F6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.ant-btn{
|
|
||||||
width: 102px;
|
|
||||||
height: 32px;
|
|
||||||
line-height: 30px;
|
|
||||||
}
|
|
||||||
.ant-btn-primary{
|
|
||||||
color: #fff;
|
|
||||||
background-color: #466AFF;
|
|
||||||
border:none;
|
|
||||||
&:hover{
|
|
||||||
background-color: rgba(70,106,255,0.85);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.focusPanelHeadInfo{
|
|
||||||
padding:14px 16px;
|
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
}
|
|
||||||
.ant-popover-content,.ant-popover-inner{
|
.ant-popover-content,.ant-popover-inner{
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
.ant-popover-inner-content{
|
|
||||||
padding:0px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.halfs{
|
.halfs{
|
||||||
margin-top: 24px;
|
margin-top: 24px;
|
||||||
padding:24px 0px 0px 0px;
|
padding:24px 0px 0px 0px;
|
||||||
border-top: 1px solid #e8e8e8;
|
border-top: 1px solid #e8e8e8;
|
||||||
}
|
.attrPerson{
|
||||||
.aboutSubTitle{
|
padding-bottom: 24px;
|
||||||
display: flex;
|
}
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
.menuMaininfos{
|
|
||||||
padding:10px 16px 14px;
|
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
}
|
}
|
||||||
.menuinfos{
|
.menuinfos{
|
||||||
padding:10px 20px 16px;
|
padding:15px 0px;
|
||||||
&>a{
|
&>a{
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
border-right: 1px solid #eee;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
& >span:first-child{
|
& >span:first-child{
|
||||||
font-size: 16px;
|
font-size: 18px;
|
||||||
font-weight: 500;
|
font-weight: 400;
|
||||||
color: #333;
|
color: #333;
|
||||||
line-height: 22px;
|
|
||||||
}
|
}
|
||||||
& >span:last-child{
|
& >span:last-child{
|
||||||
color: #666;
|
color: #666;
|
||||||
font-weight: 400;
|
}
|
||||||
line-height: 20px;
|
&:last-child{
|
||||||
margin-top: 6px;
|
border-right: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { AlignCenter , FlexAJ } from '../Component/layout';
|
import { AlignCenter , FlexAJ } from '../Component/layout';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { Popover , Spin , Button } from 'antd';
|
import { Popover , Spin } from 'antd';
|
||||||
import { getImageUrl } from 'educoder';
|
import { getImageUrl } from 'educoder';
|
||||||
import './Component.scss';
|
import './Component.scss';
|
||||||
import { getUser } from '../GetData/getData';
|
import { getUser } from '../GetData/getData';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
function Contributors({contributors,owner,projectsId,currentLogin}){
|
function Contributors({contributors,owner,projectsId}){
|
||||||
const [ menuList ,setMenuList ]= useState([]);
|
const [ menuList ,setMenuList ]= useState([]);
|
||||||
const [ list , setList ]= useState(undefined);
|
const [ list , setList ]= useState(undefined);
|
||||||
const [ total , setTotal ]= useState(0);
|
const [ total , setTotal ]= useState(0);
|
||||||
|
@ -46,60 +46,46 @@ function Contributors({contributors,owner,projectsId,currentLogin}){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function renderOrganize(list) {
|
|
||||||
let str = "";
|
|
||||||
list.map(i=>{
|
|
||||||
str = str+i.name + "、";
|
|
||||||
})
|
|
||||||
return str && str.substr(0,str.length - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
function setMenusFunc(data){
|
function setMenusFunc(data){
|
||||||
if(data){
|
if(data){
|
||||||
let ele = (
|
let ele = (
|
||||||
<Spin spinning={isSpin}>
|
<Spin spinning={isSpin}>
|
||||||
<FlexAJ className="menuMaininfos">
|
<FlexAJ>
|
||||||
<AlignCenter>
|
<AlignCenter>
|
||||||
<Link to={`/${data.login}`}><img src={getImageUrl(`/${data.image_url}`)} alt="" className="radius" width="38px" height="38px"/></Link>
|
<Link to={`/${data.login}`}><img src={getImageUrl(`/${data.image_url}`)} alt="" className="radius" width="38px" height="38px"/></Link>
|
||||||
|
<Link to={`/${data.login}`} className="ml10">{data.name}</Link>
|
||||||
<div className="ml10">
|
|
||||||
<Link to={`/${data.login}`}>{data.name}</Link>
|
|
||||||
{ data.location && <span className="leftline">{data.location}</span> }
|
|
||||||
{
|
|
||||||
data.organizations && data.organizations.length>0&&
|
|
||||||
<p className="task-hide" style={{maxWidth:"215px"}}>
|
|
||||||
所属组织:{renderOrganize(data.organizations)}
|
|
||||||
</p>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</AlignCenter>
|
</AlignCenter>
|
||||||
|
{
|
||||||
|
data.is_watch ? <a className="color-grey-9" onClick={()=>FocusFunc(false,data.login)}>取消关注</a>:<a className="color-blue" onClick={()=>FocusFunc(true,data.login)}>关注</a>
|
||||||
|
}
|
||||||
</FlexAJ>
|
</FlexAJ>
|
||||||
<AlignCenter className="menuinfos">
|
<AlignCenter className="menuinfos">
|
||||||
<Link to={`/${data.login}/projects`}>
|
<a href={data.projects_url}>
|
||||||
<span>{data.projects_count}</span>
|
<span>{data.projects_count}</span>
|
||||||
<span>项目数</span>
|
<span>项目数</span>
|
||||||
</Link>
|
</a>
|
||||||
<Link to={`/${data.login}/followers`}>
|
<a href={data.followers_url}>
|
||||||
<span>{data.followers_count}</span>
|
<span>{data.followers_count}</span>
|
||||||
<span>粉丝数</span>
|
<span>粉丝数</span>
|
||||||
</Link>
|
</a>
|
||||||
<Link to={`/${data.login}/following`}>
|
<a href={data.following_url}>
|
||||||
<span>{data.following_count}</span>
|
<span>{data.following_count}</span>
|
||||||
<span>关注数</span>
|
<span>关注数</span>
|
||||||
</Link>
|
</a>
|
||||||
</AlignCenter>
|
</AlignCenter>
|
||||||
<div className={"pb20"} style={{display:"flex",justifyContent:'center'}}>
|
{
|
||||||
{
|
data.organizations && data.organizations.length > 0 ?
|
||||||
currentLogin && (currentLogin === data.login)
|
<AlignCenter className="font-12 pt4 pb4">
|
||||||
?
|
<span>所属组织:</span>
|
||||||
<Button className="currentBtn">当前用户</Button>
|
<div className="task-hide flex1">
|
||||||
:
|
{renderArray(data.organizations)}
|
||||||
data.is_watch ?
|
</div>
|
||||||
<Button type={"default"} onClick={()=>FocusFunc(false,data.login)}>已关注</Button>
|
</AlignCenter>
|
||||||
:
|
:""
|
||||||
<Button type={"primary"} onClick={()=>FocusFunc(true,data.login)}>关注TA</Button>
|
}
|
||||||
}
|
{
|
||||||
</div>
|
data.location && <AlignCenter className="font-12 pt4 pb4"><span>所在地址:</span><span className="ml5">{data.location}</span></AlignCenter>
|
||||||
|
}
|
||||||
</Spin>
|
</Spin>
|
||||||
)
|
)
|
||||||
setMenu(ele);
|
setMenu(ele);
|
||||||
|
@ -149,10 +135,10 @@ function Contributors({contributors,owner,projectsId,currentLogin}){
|
||||||
|
|
||||||
return(
|
return(
|
||||||
<div className="halfs">
|
<div className="halfs">
|
||||||
<Link to={`/${owner}/${projectsId}/contribute`} className="font-16 color-ooo hoverA">
|
<FlexAJ>
|
||||||
<span>贡献者</span>
|
<AlignCenter><span className="font-16 color-grey-6">贡献者</span>{ contributors && contributors.total_count > 0 && <span className="infoCount">{contributors.total_count}</span>}</AlignCenter>
|
||||||
{ contributors && contributors.total_count > 0 && <span className="infoCount">{contributors.total_count}</span>}
|
<Link className="font-12 color-grey-9" to={`/${owner}/${projectsId}/contribute`}>全部</Link>
|
||||||
</Link>
|
</FlexAJ>
|
||||||
<div className="attrPerson" onMouseLeave={()=>setVisibleFunc(false)}>
|
<div className="attrPerson" onMouseLeave={()=>setVisibleFunc(false)}>
|
||||||
{
|
{
|
||||||
total > 0 ?
|
total > 0 ?
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React, { useState, useCallback, memo } from 'react';
|
||||||
import { Tooltip } from 'antd';
|
import { Tooltip } from 'antd';
|
||||||
|
|
||||||
CopyTool.defaultProps = {
|
CopyTool.defaultProps = {
|
||||||
beforeText: '复制链接', //浮动过去显示的文字
|
beforeText: '复制', //浮动过去显示的文字
|
||||||
afterText: '复制成功', //点击后显示的文字
|
afterText: '复制成功', //点击后显示的文字
|
||||||
className: '', //传给svg的class
|
className: '', //传给svg的class
|
||||||
inputId: 'copyText', //要复制的文本的ID
|
inputId: 'copyText', //要复制的文本的ID
|
||||||
|
@ -26,7 +26,6 @@ function CopyTool({ beforeText, afterText, className , inputId , timeOut }) {
|
||||||
if (document.execCommand('copy')) {
|
if (document.execCommand('copy')) {
|
||||||
document.execCommand('copy');
|
document.execCommand('copy');
|
||||||
}
|
}
|
||||||
document.getSelection().removeAllRanges();
|
|
||||||
|
|
||||||
setTitle(afterText);
|
setTitle(afterText);
|
||||||
if(timeOut){
|
if(timeOut){
|
||||||
|
|
|
@ -25,7 +25,7 @@ function LanguagePower({languages}){
|
||||||
}
|
}
|
||||||
return(
|
return(
|
||||||
<div>
|
<div>
|
||||||
<p className="font-16 color-ooo aboutSubTitle">开发语言</p>
|
<p className="font-16 color-grey-6">开发语言</p>
|
||||||
<div className="progress">
|
<div className="progress">
|
||||||
{
|
{
|
||||||
array && array.map((item,key)=>{
|
array && array.map((item,key)=>{
|
||||||
|
|
|
@ -1,125 +0,0 @@
|
||||||
/* eslint-disable react/jsx-no-duplicate-props */
|
|
||||||
import React, { useState } from 'react';
|
|
||||||
import * as ReactDOM from 'react-dom';
|
|
||||||
import { Modal, Button } from 'antd';
|
|
||||||
import './index.scss';
|
|
||||||
|
|
||||||
// 函数式调用删除、通知等模态框
|
|
||||||
|
|
||||||
InitModal.defaultProps = {
|
|
||||||
okText: '确认', //确定按钮的文字
|
|
||||||
cancelText: '取消', //取消按钮的文字
|
|
||||||
className: '', //传入的模态框类名
|
|
||||||
inputId: 'copyText', //要复制的文本的ID
|
|
||||||
onCancel:()=>{}, //取消的回调
|
|
||||||
onOk:()=>{}, //确认的回调
|
|
||||||
title:'提示', //模态框名字
|
|
||||||
contentTitle:'', //内容标题
|
|
||||||
content:'', //详细内容
|
|
||||||
afterClose:()=>{}, //关闭模态框以后的回调
|
|
||||||
};
|
|
||||||
|
|
||||||
// 使用函数调用删除组件
|
|
||||||
export default function DelModal(props) {
|
|
||||||
renderModal({ ...props, type: 'delete' })
|
|
||||||
}
|
|
||||||
|
|
||||||
// 使用函数调用选择模态框组件
|
|
||||||
export function Confirm(props) {
|
|
||||||
renderModal({ ...props, type: 'confirm' })
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderModal(props) {
|
|
||||||
const { type, afterClose } = props;
|
|
||||||
const div = document.createElement('div');
|
|
||||||
document.body.appendChild(div);
|
|
||||||
|
|
||||||
function destroy() {
|
|
||||||
afterClose && afterClose();
|
|
||||||
const unmountResult = ReactDOM.unmountComponentAtNode(div);
|
|
||||||
if (unmountResult && div.parentNode) {
|
|
||||||
div.parentNode.removeChild(div);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function modalType(type) {
|
|
||||||
if (type === 'delete') {
|
|
||||||
return <InitModal
|
|
||||||
title="删除"
|
|
||||||
contentTitle="确定要删除吗?"
|
|
||||||
okText="确认删除"
|
|
||||||
{...props}
|
|
||||||
|
|
||||||
afterClose={destroy}
|
|
||||||
contentTitle={<React.Fragment>
|
|
||||||
<i className="red-circle iconfont icon-shanchu_tc_icon mr3"></i>
|
|
||||||
{props.contentTitle}
|
|
||||||
</React.Fragment>}
|
|
||||||
/>
|
|
||||||
} else if (type === 'confirm') {
|
|
||||||
return <InitModal title="选择" afterClose={destroy} {...props} />
|
|
||||||
} else {
|
|
||||||
return <InitModal title="选择" afterClose={destroy} {...props} />
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function render() {
|
|
||||||
setTimeout(() => {
|
|
||||||
ReactDOM.render(
|
|
||||||
modalType(type),
|
|
||||||
div,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
render();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 选择模态框组件
|
|
||||||
function InitModal({
|
|
||||||
onCancel,
|
|
||||||
onOk,
|
|
||||||
title,
|
|
||||||
contentTitle,
|
|
||||||
content,
|
|
||||||
okText,
|
|
||||||
cancelText,
|
|
||||||
afterClose,
|
|
||||||
className,
|
|
||||||
}) {
|
|
||||||
|
|
||||||
const [visible, setVisible] = useState(true);
|
|
||||||
|
|
||||||
function onCancelModal() {
|
|
||||||
setVisible(false);
|
|
||||||
onCancel && onCancel()
|
|
||||||
}
|
|
||||||
|
|
||||||
function onSuccess() {
|
|
||||||
setVisible(false);
|
|
||||||
onOk && onOk();
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Modal
|
|
||||||
visible={visible}
|
|
||||||
onCancel={onCancelModal}
|
|
||||||
afterClose={afterClose}
|
|
||||||
title={title}
|
|
||||||
className={`myself-modal ${className}`}
|
|
||||||
centered
|
|
||||||
footer={[
|
|
||||||
<Button type="default" key="back" onClick={onCancelModal}>
|
|
||||||
{cancelText}
|
|
||||||
</Button>,
|
|
||||||
<Button className="foot-submit" key="submit" onClick={onSuccess}>
|
|
||||||
{okText}
|
|
||||||
</Button>,
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
{contentTitle && <p className="content-title">{contentTitle}</p>}
|
|
||||||
<p className="content-descibe">{content}</p>
|
|
||||||
</div>
|
|
||||||
</Modal>
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -1,63 +0,0 @@
|
||||||
.myself-modal {
|
|
||||||
.ant-modal-header {
|
|
||||||
padding: 9px 24px;
|
|
||||||
background: #f8f8f8;
|
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
}
|
|
||||||
.ant-modal-title {
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
.ant-modal-close {
|
|
||||||
top: 0px !important;
|
|
||||||
}
|
|
||||||
.ant-modal-close-x {
|
|
||||||
font-size: 24px;
|
|
||||||
}
|
|
||||||
.ant-modal-body {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
.content-title {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
margin: 2rem 0 1rem !important;
|
|
||||||
font-size: 16px;
|
|
||||||
color: #333;
|
|
||||||
letter-spacing: 0;
|
|
||||||
line-height: 29px;
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
.red-circle {
|
|
||||||
align-self: flex-start;
|
|
||||||
color: #ca0002;
|
|
||||||
font-size: 1.5rem !important;
|
|
||||||
}
|
|
||||||
.content-descibe {
|
|
||||||
font-size: 14px;
|
|
||||||
color: #666;
|
|
||||||
line-height: 33px;
|
|
||||||
font-weight: 400;
|
|
||||||
}
|
|
||||||
.ant-modal-footer {
|
|
||||||
padding: 2rem 0;
|
|
||||||
text-align: center;
|
|
||||||
border: 0;
|
|
||||||
.ant-btn {
|
|
||||||
width: 6rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.foot-submit {
|
|
||||||
margin-left: 3rem;
|
|
||||||
color: #df0002;
|
|
||||||
&:hover {
|
|
||||||
border-color: #df0002;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.ant-btn-default:hover,
|
|
||||||
.ant-btn-default:active,
|
|
||||||
.ant-btn-default:focus {
|
|
||||||
background: #f3f4f6;
|
|
||||||
color: #333;
|
|
||||||
border-color: #d0d0d0;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,90 +0,0 @@
|
||||||
.systemBox{
|
|
||||||
.ant-modal-body{
|
|
||||||
padding:1px 0px 0px 0px;
|
|
||||||
.sysBox{
|
|
||||||
background-image: url('./bg.png');
|
|
||||||
background-repeat: no-repeat;
|
|
||||||
background-size: 100% 334px;
|
|
||||||
margin-top: -55px;
|
|
||||||
}
|
|
||||||
.sysnoticeBox{
|
|
||||||
width: 100%;
|
|
||||||
padding:80px 0px 34px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
width: 780px;
|
|
||||||
margin: 0px auto;
|
|
||||||
p.ntitle{
|
|
||||||
height: 33px;
|
|
||||||
font-size: 24px;
|
|
||||||
font-weight: 500;
|
|
||||||
color: #31FFF7;
|
|
||||||
line-height: 33px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
p.nSubtitle{
|
|
||||||
height: 25px;
|
|
||||||
line-height: 25px;
|
|
||||||
font-size: 18px;
|
|
||||||
font-weight: 500;
|
|
||||||
color: #FFFFFF;
|
|
||||||
margin-top: 60px;
|
|
||||||
padding-left: 20px;
|
|
||||||
}
|
|
||||||
.markdown-body{
|
|
||||||
box-shadow: 0px 0px 17px rgba(0,0,0,0.2);
|
|
||||||
border-radius: 4px;
|
|
||||||
margin-top: 17px!important;
|
|
||||||
}
|
|
||||||
.nContent{
|
|
||||||
padding:20px 34px;
|
|
||||||
background-color: #fff;
|
|
||||||
line-height: 30px;
|
|
||||||
font-size: 15px;
|
|
||||||
font-weight: 400;
|
|
||||||
color: #333;
|
|
||||||
.realmName{
|
|
||||||
margin-top: 20px;
|
|
||||||
display: flex;
|
|
||||||
ul{
|
|
||||||
width: 50%;
|
|
||||||
padding-left: 0px!important;
|
|
||||||
li{
|
|
||||||
font-size: 15px;
|
|
||||||
font-weight: 500;
|
|
||||||
line-height: 32px;
|
|
||||||
text-align: left;
|
|
||||||
color: #000;
|
|
||||||
list-style-type: none!important;
|
|
||||||
&:first-child{
|
|
||||||
color: #E65714;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.nSubdesc{
|
|
||||||
font-size: 15px;
|
|
||||||
font-weight: 400;
|
|
||||||
color: #000000;
|
|
||||||
line-height: 31px;
|
|
||||||
margin-top: 20px;
|
|
||||||
}
|
|
||||||
.nInfo{
|
|
||||||
font-size: 14px;
|
|
||||||
font-weight: 400;
|
|
||||||
color: #333333;
|
|
||||||
text-align: right;
|
|
||||||
margin-top: 25px;
|
|
||||||
p{
|
|
||||||
height: 20px;
|
|
||||||
line-height: 20px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.nBtn{
|
|
||||||
text-align: center;
|
|
||||||
margin-top: 33px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,76 +0,0 @@
|
||||||
import React , { useEffect , useState } from 'react';
|
|
||||||
import { Modal , Button } from 'antd';
|
|
||||||
import './Index.scss';
|
|
||||||
import '../../css/index.scss';
|
|
||||||
import RenderHtml from '../../../components/render-html';
|
|
||||||
import cookie from 'react-cookies';
|
|
||||||
|
|
||||||
function SystemNotice({system_notification,history}){
|
|
||||||
const [ visible , setVisible ] = useState(false);
|
|
||||||
|
|
||||||
useEffect(()=>{
|
|
||||||
if(system_notification && !cookie.load('notice_stage')){
|
|
||||||
setVisible(true);
|
|
||||||
}
|
|
||||||
},[system_notification,history.location])
|
|
||||||
|
|
||||||
function sureContinue() {
|
|
||||||
cookie.remove('notice_stage');
|
|
||||||
|
|
||||||
let inFifteenMinutes = new Date(new Date().getTime() + 24 * 3600 * 1000);//一天
|
|
||||||
// let inFifteenMinutes = new Date(new Date().getTime() + 60 * 1000);//一分钟
|
|
||||||
cookie.save('notice_stage', true,{ expires: inFifteenMinutes,path:"/" });
|
|
||||||
|
|
||||||
setVisible(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Modal
|
|
||||||
visible = {visible}
|
|
||||||
width="1000px"
|
|
||||||
footer={false}
|
|
||||||
title={false}
|
|
||||||
centered={true}
|
|
||||||
closable={false}
|
|
||||||
wrapClassName={'systemBox'}
|
|
||||||
>
|
|
||||||
<div className="sysBox">
|
|
||||||
<div className="sysnoticeBox">
|
|
||||||
<p className="ntitle">{system_notification && system_notification.subject}</p>
|
|
||||||
<p className="nSubtitle">{system_notification && system_notification.sub_subject}</p>
|
|
||||||
{/* <div className="nContent">
|
|
||||||
<div className="nMaindesc">
|
|
||||||
为了给用户提供更加稳定、优质的服务,我们即将对平台门户首页、平台名称、平台域名进行一次全面升级与变更。原平台名称:Trustie(中文名:确实)将于2021年10月xx日统一更改为Gitlink(中文名:确实开源)。届时平台域名将统一进行更换,更换规则如下
|
|
||||||
</div>
|
|
||||||
<div className="realmName">
|
|
||||||
<ul>
|
|
||||||
<li>原域名:</li>
|
|
||||||
<li>官网顶级域名https://www.trustie.net</li>
|
|
||||||
<li>版本库子域名https://forgeplus.trustie.net</li>
|
|
||||||
<li>论坛子域名https://forum.trustie.net/forums</li>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li>更换后域名:</li>
|
|
||||||
<li>官网顶级域名https://www.gitlink.org.cn</li>
|
|
||||||
<li>版本库子域名https://www.git.gitlink.org.cn</li>
|
|
||||||
<li>论坛子域名https://forum.gitlink.org.cn</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div className="nSubdesc">
|
|
||||||
自2021年10月xx日起,旧域名将停止访问。因平台名称与域名变更给您带来的不便,我们深表歉意!非常感谢您一直以来对本平台的信任与支持,我们将一如既往地为您提供优质的服务。 特此通知!
|
|
||||||
</div>
|
|
||||||
<div className="nInfo">
|
|
||||||
<p>Gitlink运营团队</p>
|
|
||||||
<p>2021年10月xx日</p>
|
|
||||||
</div>
|
|
||||||
</div> */}
|
|
||||||
<RenderHtml className="break_word_comments imageLayerParent" value={system_notification && system_notification.content} url={history.location}/>
|
|
||||||
<div className="nBtn">
|
|
||||||
<Button type="primary" className="btnblue" onClick={sureContinue}>确认并继续</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Modal>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export default SystemNotice;
|
|
Binary file not shown.
Before Width: | Height: | Size: 280 KiB |
|
@ -1,35 +1,38 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { AlignTop } from '../Component/layout';
|
import { AlignCenter , AlignTop , FlexAJ } from '../Component/layout';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
function Releases({ owner, projectsId, releaseVersions, distribution }) {
|
function Releases({owner,projectsId,releaseVersions , baseOperate , projectType}){
|
||||||
|
|
||||||
return(
|
return(
|
||||||
<div>
|
<div>
|
||||||
<Link to={`/${owner}/${projectsId}/releases`} className="font-16 color-ooo hoverA">
|
<FlexAJ>
|
||||||
<span>发行版</span>
|
<AlignCenter><span className="font-16 color-grey-6">发行版</span>
|
||||||
{ releaseVersions && releaseVersions.total_count > 0 && <span className="infoCount">{releaseVersions.total_count}</span>}
|
{ releaseVersions && releaseVersions.total_count > 0 && <span className="infoCount">{releaseVersions.total_count}</span>}
|
||||||
</Link>
|
</AlignCenter>
|
||||||
|
{ (releaseVersions && releaseVersions.total_count > 0) || projectType ===2 ?
|
||||||
|
<Link className="font-12 color-grey-9" to={`/${owner}/${projectsId}/releases`}>全部</Link>
|
||||||
|
:
|
||||||
|
baseOperate && <Link className="font-12 color-blue" to={`/${owner}/${projectsId}/releases/new`}>新建</Link>
|
||||||
|
}
|
||||||
|
</FlexAJ>
|
||||||
{
|
{
|
||||||
releaseVersions && releaseVersions.total_count>0 ?
|
releaseVersions && releaseVersions.total_count>0 ?
|
||||||
releaseVersions.list.map((item,key)=>{
|
releaseVersions.list.map((item,key)=>{
|
||||||
return(
|
return(
|
||||||
key === 0 &&<AlignTop className="mt10">
|
key === 0 &&<AlignTop className="mt10">
|
||||||
|
<i className="iconfont icon-biaoqian3 color-grey-6 font-18 mr10"></i>
|
||||||
<div>
|
<div>
|
||||||
<p className="font-16 color-grey-6" style={{display:'flex',alignItems:'center'}}>
|
<p className="font-16 color-grey-6">
|
||||||
{/* 如果是点击最新则发行版列表页只展示最新的一个 */}
|
<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-9 font-13">{item.created_at}</p>
|
||||||
</div>
|
</div>
|
||||||
</AlignTop>
|
</AlignTop>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
:
|
:""
|
||||||
<div className="mt8">
|
|
||||||
您暂未发布任何版本
|
|
||||||
{distribution && <Link className="color-blue ml20" to={{pathname:`/${owner}/${projectsId}/releases/new`,state:{stable:true}}}>创建新版本</Link>}
|
|
||||||
</div>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,9 +2,9 @@ import React from 'react';
|
||||||
import {Popover} from 'antd';
|
import {Popover} from 'antd';
|
||||||
import './Component.scss';
|
import './Component.scss';
|
||||||
|
|
||||||
export default (({menu , children, overlayClassName})=>{
|
export default (({menu , children})=>{
|
||||||
return(
|
return(
|
||||||
<Popover content={menu} trigger={['click']} placement='bottom' overlayClassName={overlayClassName}>
|
<Popover content={menu} trigger={['click']} placement='bottom'>
|
||||||
{children}
|
{children}
|
||||||
</Popover>
|
</Popover>
|
||||||
)
|
)
|
||||||
|
|
|
@ -5,7 +5,6 @@ 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)=>{setEventValue(e)}}>
|
<Select mode="multiple" allowClear value={eventValue} dropdownClassName="chooseCon" style={{width:"180px",marginLeft:"10px"}} onChange={(e)=>{console.log(e);setEventValue(e)}}>
|
||||||
{
|
{
|
||||||
EVENT.map((item,key)=>{
|
EVENT.map((item,key)=>{
|
||||||
return(
|
return(
|
||||||
|
|
|
@ -24,6 +24,7 @@ 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,
|
||||||
|
@ -138,10 +139,12 @@ 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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -46,11 +46,14 @@ function DivertModal({form , visible , onSuccess , onCancel,owner,repo}){
|
||||||
Axios.post(url,{
|
Axios.post(url,{
|
||||||
...values
|
...values
|
||||||
}).then(result=>{
|
}).then(result=>{
|
||||||
if(result && result.data.id){
|
if(result){
|
||||||
onSuccess(result.data && result.data.owner);
|
if(result.data.status === 0){
|
||||||
}else{
|
onSuccess(result.data && result.data.owner);
|
||||||
onSuccess();
|
}else{
|
||||||
|
onSuccess();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}).catch(error=>{})
|
}).catch(error=>{})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,108 +0,0 @@
|
||||||
import React, { Component } from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { Icon } from 'antd';
|
|
||||||
import _ from 'lodash';
|
|
||||||
import Nodata from '../Nodata';
|
|
||||||
|
|
||||||
|
|
||||||
class PullRefresh extends Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
}
|
|
||||||
this.pullRef = {};
|
|
||||||
// 节流
|
|
||||||
this.onScrollList = _.throttle(this.handleScroll, 200, {
|
|
||||||
leading: false,
|
|
||||||
trailing: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
let dom = document.querySelector('.pull-refresh-wrap');
|
|
||||||
dom && dom.addEventListener('scroll', this.onScrollList);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
let dom = document.querySelector('.pull-refresh-wrap');
|
|
||||||
dom && dom.removeEventListener('scroll', this.onScrollList)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
handleScroll = () => {
|
|
||||||
if (this.props.count < this.props.pageSize) return;
|
|
||||||
if (this.props.type === 1 || this.props.type === 2) return;
|
|
||||||
const wrap = this.pullRef;
|
|
||||||
const currentScroll = wrap.scrollTop + wrap.clientHeight
|
|
||||||
|
|
||||||
// 触底
|
|
||||||
if (currentScroll >= (wrap.scrollHeight - 200)) {
|
|
||||||
this.loadData()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
handleLoadClick = () => {
|
|
||||||
this.loadData();
|
|
||||||
}
|
|
||||||
|
|
||||||
loadData = () => {
|
|
||||||
this.props.onPullRefresh()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
renderLoading() {
|
|
||||||
switch (this.props.type) {
|
|
||||||
case 0: // 加载更多
|
|
||||||
return <div className='text-center' onClick={this.handleLoadClick}>显示更多</div>
|
|
||||||
case 1: // 加载中
|
|
||||||
return (
|
|
||||||
<div className='text-center'>
|
|
||||||
<Icon type="loading" />
|
|
||||||
<span className='text-center'>加载中...</span>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
case 2: // 无样式
|
|
||||||
return <div className='text-center'>没有更多了</div>
|
|
||||||
default:
|
|
||||||
return <div className='text-center'>没有更多了</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { className, count, children } = this.props;
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={`pull-refresh-wrap ${className}`}
|
|
||||||
ref={dom => { this.pullRef = dom }}
|
|
||||||
>
|
|
||||||
|
|
||||||
{children}
|
|
||||||
|
|
||||||
{
|
|
||||||
count < 1 && <Nodata _html="暂无未读消息"/>
|
|
||||||
}
|
|
||||||
|
|
||||||
{/* 大于分页数据才显示loading */}
|
|
||||||
{/* {this.props.count >= this.props.pageSize ? this.renderLoading() : null} */}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PullRefresh.propTypes = {
|
|
||||||
className: PropTypes.string,
|
|
||||||
children: PropTypes.any,
|
|
||||||
onPullRefresh: PropTypes.func.isRequired,
|
|
||||||
type: PropTypes.oneOf([0, 1, 2]),
|
|
||||||
count: PropTypes.number.isRequired,
|
|
||||||
pageSize: PropTypes.number.isRequired,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export default PullRefresh
|
|
|
@ -19,7 +19,7 @@ function Footer(){
|
||||||
|
|
||||||
return(
|
return(
|
||||||
<div>
|
<div>
|
||||||
<div style={{height:"543px"}}></div>
|
<div style={{height:"497px"}}></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">
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React, { Component } from 'react';
|
||||||
import AccountProfile from "../../modules/user/AccountProfile";
|
import AccountProfile from "../../modules/user/AccountProfile";
|
||||||
import { getImageUrl } from 'educoder'
|
import { getImageUrl } from 'educoder'
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { Input , notification , Dropdown ,Popover, Menu,Badge, Button } from 'antd';
|
import { Input , notification , Dropdown , Menu } from 'antd';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
import LoginDialog from '../../modules/login/LoginDialog';
|
import LoginDialog from '../../modules/login/LoginDialog';
|
||||||
|
@ -13,7 +13,6 @@ import '../../modules/tpm/TPMIndex.css';
|
||||||
import CheckProfile from '../Component/ProfileModal/Profile';
|
import CheckProfile from '../Component/ProfileModal/Profile';
|
||||||
|
|
||||||
import './header.scss';
|
import './header.scss';
|
||||||
import NoticeContent from './NoticeContent';
|
|
||||||
const $ = window.$
|
const $ = window.$
|
||||||
// TODO 这部分脚本从公共脚本中直接调用
|
// TODO 这部分脚本从公共脚本中直接调用
|
||||||
const { Search } = Input;
|
const { Search } = Input;
|
||||||
|
@ -48,7 +47,6 @@ class NewHeader extends Component {
|
||||||
settings: null,
|
settings: null,
|
||||||
visiblemyss: false,
|
visiblemyss: false,
|
||||||
openSearch:false,
|
openSearch:false,
|
||||||
visible:false, //浮动消息框展示控制
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
@ -94,6 +92,9 @@ class NewHeader extends Component {
|
||||||
this.setState({
|
this.setState({
|
||||||
user: newProps.user
|
user: newProps.user
|
||||||
})
|
})
|
||||||
|
if (newProps.Headertop !== undefined) {
|
||||||
|
old_url = newProps.Headertop.old_url
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
educoderlogin = () => {
|
educoderlogin = () => {
|
||||||
|
@ -120,6 +121,7 @@ class NewHeader extends Component {
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
HideAddcoursestypess = (i) => {
|
HideAddcoursestypess = (i) => {
|
||||||
|
console.log("调用了");
|
||||||
this.setState({
|
this.setState({
|
||||||
Addcoursestypes: false,
|
Addcoursestypes: false,
|
||||||
mydisplay: true,
|
mydisplay: true,
|
||||||
|
@ -253,7 +255,6 @@ class NewHeader extends Component {
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
renderMenu=(personal)=>{
|
renderMenu=(personal)=>{
|
||||||
const { current_user } = this.props;
|
const { current_user } = this.props;
|
||||||
return(
|
return(
|
||||||
|
@ -268,18 +269,14 @@ 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>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
handleVisibleChange = visible => {
|
|
||||||
this.setState({ visible });
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { match ,resetUserInfo ,showNotification} = this.props;
|
const { match} = this.props;
|
||||||
let current_user = this.props.user;
|
let current_user = this.props.user;
|
||||||
let {
|
let {
|
||||||
AccountProfiletype,
|
AccountProfiletype,
|
||||||
|
@ -288,7 +285,6 @@ class NewHeader extends Component {
|
||||||
headtypesonClickbool,
|
headtypesonClickbool,
|
||||||
headtypess,
|
headtypess,
|
||||||
settings,
|
settings,
|
||||||
visible,
|
|
||||||
} = this.state;
|
} = this.state;
|
||||||
/*用户名称 用户头像url*/
|
/*用户名称 用户头像url*/
|
||||||
let activeIndex = false;
|
let activeIndex = false;
|
||||||
|
@ -367,6 +363,7 @@ class NewHeader extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
let search_url = settings && settings.common && settings.common.search;
|
let search_url = settings && settings.common && settings.common.search;
|
||||||
|
let notice_url = settings && settings.common && settings.common.notice;
|
||||||
return (
|
return (
|
||||||
<div className="newHeaders" id="nHeader">
|
<div className="newHeaders" id="nHeader">
|
||||||
<div className="headerContent">
|
<div className="headerContent">
|
||||||
|
@ -398,7 +395,7 @@ class NewHeader extends Component {
|
||||||
{
|
{
|
||||||
settings.navbar && settings.navbar.map((item, key) => {
|
settings.navbar && settings.navbar.map((item, key) => {
|
||||||
var new_link = item.link;
|
var new_link = item.link;
|
||||||
var user_login = current_user && current_user.login;
|
var user_login = this.props.user && this.props.user.login;
|
||||||
var is_hidden = item.hidden
|
var is_hidden = item.hidden
|
||||||
if (new_link && (new_link.indexOf("courses") > -1 || new_link.indexOf("contests") > -1)) {
|
if (new_link && (new_link.indexOf("courses") > -1 || new_link.indexOf("contests") > -1)) {
|
||||||
if (user_login) {
|
if (user_login) {
|
||||||
|
@ -429,30 +426,25 @@ class NewHeader extends Component {
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<div className="head-right">
|
<div className="head-right">
|
||||||
|
{/* {search_url ? this.SearchInput(openSearch,search_url):""} */}
|
||||||
{ search_url && <HeadSearch {...this.props}/>}
|
{ search_url && <HeadSearch {...this.props}/>}
|
||||||
{
|
{
|
||||||
current_user && (current_user.main_site || current_user.login) && (settings && settings.add && settings.add.length>0)?
|
current_user && (current_user.main_site || current_user.login) && (settings && settings.add && settings.add.length>0)?
|
||||||
<Dropdown overlay={this.addMenu(settings && settings.add)} placement="bottomRight">
|
<Dropdown overlay={this.addMenu(settings && settings.add)} placement="bottomRight">
|
||||||
<i className="iconfont icon-tianjiafangda color-grey-6 ml30 mr15"></i>
|
<i className="iconfont icon-tianjiafangda color-grey-6 ml30"></i>
|
||||||
</Dropdown>:""
|
</Dropdown>:""
|
||||||
}
|
}
|
||||||
|
|
||||||
{ (settings && settings.common && settings.common.notice) && (current_user && current_user.login)?
|
{this.props.user && this.props.user.login && notice_url ?
|
||||||
<Popover
|
<div className="ml30 edu-menu-panel">
|
||||||
overlayClassName="notice-popover"
|
{user && user.login &&
|
||||||
placement={`bottomRight`}
|
<a href={`${notice_url}`} style={{ position: 'relative' }}>
|
||||||
content={<NoticeContent visible={visible} current_user={current_user} showNotification={showNotification} resetUserInfo={resetUserInfo}/>}
|
<i className="iconfont icon-xiaoxilingdang color-grey-6"></i>
|
||||||
visible={visible}
|
<span className="newslight" style={{ display: this.props.Headertop === undefined ? "none" : this.props.Headertop.new_message === true ? "block" : "none" }}>
|
||||||
onVisibleChange={this.handleVisibleChange}
|
</span>
|
||||||
destroyTooltipOnHide
|
</a>
|
||||||
>
|
}
|
||||||
<Link to={"/settings/notice"} className="message-icon">
|
</div>:""
|
||||||
{current_user && <Badge count={current_user.message_unread_total}>
|
|
||||||
<i className="iconfont icon-xiaoxilingdang color-grey-6 ml15 mr15"></i>
|
|
||||||
</Badge>}
|
|
||||||
</Link>
|
|
||||||
</Popover>
|
|
||||||
: ""
|
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
{!user || (user && !user.login) ?
|
{!user || (user && !user.login) ?
|
||||||
|
|
|
@ -1,262 +0,0 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
|
||||||
import { Badge, Menu } from 'antd';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import axios from 'axios';
|
|
||||||
import AppPullRefresh from './AppPullRefresh';
|
|
||||||
import { noticeSourceType } from '../common/static';
|
|
||||||
import './header.scss';
|
|
||||||
import '../SecuritySetting/notice/manager/Index.scss';
|
|
||||||
import '../SecuritySetting/Index.scss';
|
|
||||||
import '../SecuritySetting/notice/myNotice/Index.scss';
|
|
||||||
|
|
||||||
|
|
||||||
function NoticeContent({ visible, showNotification, resetUserInfo, current_user: { login } }) {
|
|
||||||
const [initialize, setInitialize] = useState(true);
|
|
||||||
const [noticeType, setNoticeType] = useState("notification");
|
|
||||||
const [letterUnreadCount, setLetterUnreadCount] = useState(0);//未读私信数量
|
|
||||||
|
|
||||||
const [noticeUnreadCount, setNoticeUnreadCount] = useState(0);//未读系统通知数量
|
|
||||||
const [noticePage, setNoticePage] = useState(0);
|
|
||||||
const [noticeUnreadList, setNoticeUnreadList] = useState([]);//未读系统通知列表
|
|
||||||
|
|
||||||
const [atUnreadCount, setAtUnreadCount] = useState();//未读@我数量
|
|
||||||
const [atPage, setAtPage] = useState(0);
|
|
||||||
const [atUnreadList, setAtUnreadList] = useState([]);//未读@我列表
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
resetUserInfo();
|
|
||||||
}, [noticeUnreadCount,atUnreadCount]);
|
|
||||||
|
|
||||||
useEffect(()=>{
|
|
||||||
setNoticePage(0);
|
|
||||||
setAtPage(0);
|
|
||||||
},[visible])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const params = {
|
|
||||||
type: noticeType,
|
|
||||||
limit: 10,
|
|
||||||
page: noticeType === "notification" ? noticePage : noticeType === "atme" ? atPage : "",
|
|
||||||
status: 1,
|
|
||||||
}
|
|
||||||
getMessageList(params);
|
|
||||||
}, [noticePage, atPage]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const params = {
|
|
||||||
type: noticeType,
|
|
||||||
limit: 10,
|
|
||||||
page: 0,
|
|
||||||
status: 1,
|
|
||||||
};
|
|
||||||
if (initialize) {
|
|
||||||
params.type = "atme"
|
|
||||||
}
|
|
||||||
visible && getMessageList(params);
|
|
||||||
}, [visible]);
|
|
||||||
|
|
||||||
|
|
||||||
function getMessageList(params) {
|
|
||||||
axios.get(`/users/${login}/messages.json`, {
|
|
||||||
params: params,
|
|
||||||
}).then((response) => {
|
|
||||||
if (response && response.data) {
|
|
||||||
setNoticeUnreadCount(response.data.unread_notification);
|
|
||||||
setAtUnreadCount(response.data.unread_atme);
|
|
||||||
if (params.type === "notification") {
|
|
||||||
let list = response.data.messages;
|
|
||||||
if (params.page !== 0) {
|
|
||||||
list = [...noticeUnreadList, ...list];
|
|
||||||
}
|
|
||||||
setNoticeUnreadList(list);
|
|
||||||
if (initialize) {
|
|
||||||
// 如果是第一次加载,根据数据量判断是否切换tab栏
|
|
||||||
setInitialize(false);
|
|
||||||
if (response.data.unread_notification === 0 && response.data.unread_atme !== 0) {
|
|
||||||
setNoticeType("atme");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (params.type === "atme") {
|
|
||||||
let list = response.data.messages;
|
|
||||||
if (params.page !== 0) {
|
|
||||||
list = [...atUnreadList, ...list];
|
|
||||||
}
|
|
||||||
setAtUnreadList(list);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
function readAll() {
|
|
||||||
axios.post(`/users/${login}/messages/read.json`, {
|
|
||||||
type: noticeType,
|
|
||||||
ids: [-1]
|
|
||||||
}).then((response) => {
|
|
||||||
let data = response.data;
|
|
||||||
if (!data) return;
|
|
||||||
if (data.status === 0) {
|
|
||||||
changeReadMarkAll(noticeType);
|
|
||||||
} else {
|
|
||||||
showNotification(data.message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function changeReadMarkAll(noticeType) {
|
|
||||||
if (noticeType === "notification") {
|
|
||||||
let list = noticeUnreadList.slice();
|
|
||||||
list.forEach(item => {
|
|
||||||
item.status = 2;
|
|
||||||
})
|
|
||||||
setNoticeUnreadList(list);
|
|
||||||
setNoticeUnreadCount(0);
|
|
||||||
} else if (noticeType === "atme") {
|
|
||||||
let list = atUnreadList.slice();
|
|
||||||
list.forEach(item => {
|
|
||||||
item.status = 2;
|
|
||||||
})
|
|
||||||
setAtUnreadList(list);
|
|
||||||
setAtUnreadCount(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// const [letter_unread_list, setLetter_unread_list] = useState([
|
|
||||||
// {
|
|
||||||
// id: 122,
|
|
||||||
// read: 0, //是否已读,0未读,1已读
|
|
||||||
// send_name: "蒋宇航", //消息发送人
|
|
||||||
// send_login: "jiangYuHang", //消息发送人的login,前端根据这个跳转到消息内页
|
|
||||||
// content: "私信内容", //最近一条未读消息的内容
|
|
||||||
// create_time: "2019-03-04 18:08", //发送时间
|
|
||||||
// },
|
|
||||||
// ]);
|
|
||||||
|
|
||||||
function readItem(item) {
|
|
||||||
axios.post(`/users/${login}/messages/read.json`, {
|
|
||||||
type: noticeType,
|
|
||||||
ids: [item.id]
|
|
||||||
}).then((response) => {
|
|
||||||
let data = response.data;
|
|
||||||
if (!data) return;
|
|
||||||
if (data.status === 0) {
|
|
||||||
changeReadMark(item);
|
|
||||||
item.notification_url && window.open(item.notification_url);
|
|
||||||
} else {
|
|
||||||
showNotification(data.message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function changeReadMark(item) {
|
|
||||||
if (item.type === "notification") {
|
|
||||||
let list = noticeUnreadList.slice();
|
|
||||||
let index = noticeUnreadList.indexOf(item);
|
|
||||||
list[index].status = 2;
|
|
||||||
setNoticeUnreadList(list);
|
|
||||||
if (noticeUnreadCount > 0) {
|
|
||||||
setNoticeUnreadCount(noticeUnreadCount - 1);
|
|
||||||
}
|
|
||||||
} else if (item.type === "atme") {
|
|
||||||
let list = atUnreadList.slice();
|
|
||||||
let index = atUnreadList.indexOf(item);
|
|
||||||
list[index].status = 2;
|
|
||||||
setAtUnreadList(list);
|
|
||||||
if (atUnreadCount > 0) {
|
|
||||||
setAtUnreadCount(atUnreadCount - 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="messageHoverDiv notice01">
|
|
||||||
<div className="sshHead hoverNotice-head">
|
|
||||||
<Menu mode="horizontal" selectedKeys={noticeType} onClick={(e) => setNoticeType(e.key)}>
|
|
||||||
<Menu.Item key="notification"><Badge count={noticeUnreadCount}>系统通知</Badge></Menu.Item>
|
|
||||||
{/* <Menu.Item key="1" id="item-private"><Badge count={letterUnreadCount}>私信</Badge></Menu.Item> */}
|
|
||||||
<Menu.Item key="atme"><Badge count={atUnreadCount}>@我</Badge></Menu.Item>
|
|
||||||
</Menu>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* 系统通知 */}
|
|
||||||
{noticeType === "notification" && <AppPullRefresh
|
|
||||||
className='hoverNotice-body' // 外部添加className加以区分
|
|
||||||
onPullRefresh={() => { setNoticePage(noticePage + 1); }} //触发加载ajax的function
|
|
||||||
// type={2} // 传送加载组件的状态
|
|
||||||
count={noticeUnreadList.length} // 数据当前的总数量
|
|
||||||
pageSize={10} //
|
|
||||||
>
|
|
||||||
{
|
|
||||||
noticeUnreadList.map(item => {
|
|
||||||
return (
|
|
||||||
<div key={item.id + Math.random()} className="noticeCont-back" onClick={() => { readItem(item) }}>
|
|
||||||
<div className={`noticeCont ${item.notification_url?'pointer':''}`}>
|
|
||||||
<span style={{ visibility: item.status === 1 ? 'visible' : 'hidden' }}>
|
|
||||||
<Badge color="#FA2020" />
|
|
||||||
</span>
|
|
||||||
<i className={"iconfont " + noticeSourceType[item.source]}></i>
|
|
||||||
<div className="noticeCont-text">
|
|
||||||
<span className="content-span notice-cont-span" dangerouslySetInnerHTML={{ __html: item.content }}></span>
|
|
||||||
<span className="timeSpan">{item.time_ago}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</AppPullRefresh>
|
|
||||||
}
|
|
||||||
|
|
||||||
{/* @我 */}
|
|
||||||
{noticeType === "atme" && <AppPullRefresh
|
|
||||||
className='hoverNotice-body' // 外部添加className加以区分
|
|
||||||
onPullRefresh={() => { setAtPage(atPage + 1); }} //触发加载ajax的function
|
|
||||||
// type={1} // 传送加载组件的状态
|
|
||||||
count={atUnreadList.length} // 数据当前的总数量
|
|
||||||
pageSize={10} //
|
|
||||||
>
|
|
||||||
{atUnreadList.map(item => {
|
|
||||||
return (
|
|
||||||
<div key={item.id + Math.random()} className="noticeCont-back" onClick={() => { readItem(item) }}>
|
|
||||||
<div className="noticeCont">
|
|
||||||
<span style={{ visibility: item.status === 1 ? 'visible' : 'hidden' }}>
|
|
||||||
<Badge color="#FA2020" />
|
|
||||||
</span>
|
|
||||||
<div className="noticeCont-text">
|
|
||||||
<span className="content-span atme-cont-span" dangerouslySetInnerHTML={{ __html: "<b>" + (item.sender ? item.sender.name : '') + "</b> " + item.content + " 中@我" }}></span>
|
|
||||||
<span className="timeSpan">{item.time_ago}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</AppPullRefresh>
|
|
||||||
}
|
|
||||||
|
|
||||||
{/* 私信 */}
|
|
||||||
{/* {noticeType === "1" ? letter_unread_list.length > 0 ? letter_unread_list.map(item => {
|
|
||||||
return (
|
|
||||||
<div className="noticeCont-back">
|
|
||||||
<div className="noticeCont" style={{ height: item.content.length >= 30 && item.content.length <= 34 ? '65px' : "" }}>
|
|
||||||
<Badge color="#FA2020" />
|
|
||||||
<div className="noticeCont-text">
|
|
||||||
<span>{item.send_name}:</span>
|
|
||||||
<span className="boldSpan" dangerouslySetInnerHTML={{ __html: item.content.length >= 50 ? item.content.substr(0, 50) + "..." : item.content }}></span>
|
|
||||||
<span className="timeSpan">{item.create_time ? timeAgo(item.create_time) : "刚刚"}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}) : "暂无数据" : ""} */}
|
|
||||||
<div className="hoverNotice-buttom">
|
|
||||||
<Link to={{pathname:"/settings/notice",query:{noticeType:noticeType}}}>全部消息</Link>
|
|
||||||
{noticeUnreadCount > 0 && noticeType === "notification" && <a onClick={readAll}>所有系统消息一键已读</a>}
|
|
||||||
{atUnreadCount > 0 && noticeType === "atme" && <a onClick={readAll}>所有@我一键已读</a>}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export default NoticeContent;
|
|
|
@ -24,9 +24,8 @@
|
||||||
width: 34px;
|
width: 34px;
|
||||||
height: 34px;
|
height: 34px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
margin-left: 15px;
|
margin-left: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.currentMenu{
|
.currentMenu{
|
||||||
width: 120px;
|
width: 120px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
@ -128,138 +127,3 @@
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 右上角小铃铛单独样式
|
|
||||||
.notice-popover{
|
|
||||||
//popover小尖尖
|
|
||||||
.ant-popover-arrow{
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
//popover框
|
|
||||||
.ant-popover-inner-content {
|
|
||||||
width: 386px;
|
|
||||||
height: 446px;
|
|
||||||
box-shadow: 0px 4px 8px 2px rgba(212, 212, 212, 0.5);
|
|
||||||
border-radius: 4px;
|
|
||||||
margin-top: -10px;
|
|
||||||
padding: 12px 1px 12px 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.messageHoverDiv .ant-menu-item{
|
|
||||||
margin-right: 24px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hoverNotice-head{
|
|
||||||
margin-left: 18px;
|
|
||||||
|
|
||||||
& .ant-badge{
|
|
||||||
font-size: 14px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
&>.ant-menu-horizontal {
|
|
||||||
border-bottom: 1px solid #e8e8e8 !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.hoverNotice-body{
|
|
||||||
height: 342px;
|
|
||||||
overflow-y: scroll;
|
|
||||||
|
|
||||||
& b{
|
|
||||||
font-weight: 400;
|
|
||||||
text-shadow: 0.5px 0 0 #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.none_panels{
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.message-icon{
|
|
||||||
position: relative;
|
|
||||||
.ant-scroll-number{
|
|
||||||
right:12px;
|
|
||||||
padding: 0 0px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.hoverNotice-buttom{
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
padding: 12px 18px;
|
|
||||||
a{
|
|
||||||
color: #466AFF;
|
|
||||||
&:hover{
|
|
||||||
opacity:0.85;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.noticeCont-back{
|
|
||||||
.pointer{
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
&:hover{
|
|
||||||
background: #F3F4F6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.noticeCont{
|
|
||||||
display: flex;
|
|
||||||
margin: 0 16px 0 18px;
|
|
||||||
padding: 12px 0 10px 0;
|
|
||||||
line-height: 24px;
|
|
||||||
border-bottom: 1px solid #EEEEEE;
|
|
||||||
cursor: default;
|
|
||||||
i{
|
|
||||||
font-size: 14px !important;
|
|
||||||
margin-right: 6px;
|
|
||||||
color: #333333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.boldSpan{
|
|
||||||
font-weight: 400;
|
|
||||||
text-shadow: 0.5px 0 0 #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
.noticeCont-text{
|
|
||||||
display: flex;
|
|
||||||
color:#333333;
|
|
||||||
flex:auto;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
& .content-span{
|
|
||||||
word-break: break-all;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
display: -webkit-box;
|
|
||||||
-webkit-box-orient: vertical;
|
|
||||||
-webkit-line-clamp: 2;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
& .atme-cont-span{
|
|
||||||
width: 272px;
|
|
||||||
}
|
|
||||||
|
|
||||||
& .notice-cont-span{
|
|
||||||
width: 255px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.timeSpan{
|
|
||||||
font-size: 12px;
|
|
||||||
color: #666666;
|
|
||||||
}
|
|
||||||
|
|
||||||
.at-name{
|
|
||||||
margin-right: 12px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-center{
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
|
@ -1,9 +1,8 @@
|
||||||
import React , { useEffect , useState } from 'react';
|
import React , { useEffect , useState } from 'react';
|
||||||
import { WhiteBack , Box , LongWidth , ShortWidth , Gap , AlignCenter , FlexAJ } from '../Component/layout';
|
import { WhiteBack , Box , LongWidth , ShortWidth , Gap , AlignCenter , FlexAJ } from '../Component/layout';
|
||||||
import { Dropdown , Menu , Divider , Spin, Button , Typography } from 'antd';
|
import { Dropdown , Menu , Divider , Spin, Button } from 'antd';
|
||||||
import { getImageUrl } from "educoder";
|
import { getImageUrl } from "educoder";
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { truncateCommitId } from "../common/util";
|
|
||||||
import CloneAddress from '../Branch/CloneAddress';
|
import CloneAddress from '../Branch/CloneAddress';
|
||||||
|
|
||||||
import SelectBranch from '../Branch/Select';
|
import SelectBranch from '../Branch/Select';
|
||||||
|
@ -22,11 +21,10 @@ import UpdateDescModal from './sub/UpdateDescModal';
|
||||||
import Nodata from '../Nodata';
|
import Nodata from '../Nodata';
|
||||||
import Invite from './sub/Invite';
|
import Invite from './sub/Invite';
|
||||||
import CheckProfile from '../Component/ProfileModal/Profile';
|
import CheckProfile from '../Component/ProfileModal/Profile';
|
||||||
import RenderHtml from '../../components/render-html';
|
|
||||||
/**
|
/**
|
||||||
* projectDetail.type:0是托管项目,1是镜像项目,2是同步镜像项目(为2时不支持在线创建、在线上传、在线修改、在线删除、创建合并请求等功能)
|
* projectDetail.type:0是托管项目,1是镜像项目,2是同步镜像项目(为2时不支持在线创建、在线上传、在线修改、在线删除、创建合并请求等功能)
|
||||||
*/
|
*/
|
||||||
const { Paragraph } = Typography;
|
|
||||||
function turnbar(str){
|
function turnbar(str){
|
||||||
if(str && str.length>0 && str.indexOf("/")>-1){
|
if(str && str.length>0 && str.indexOf("/")>-1){
|
||||||
return str.replaceAll('/','%2F');
|
return str.replaceAll('/','%2F');
|
||||||
|
@ -68,7 +66,6 @@ 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;
|
||||||
|
@ -76,8 +73,7 @@ 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(()=>{
|
||||||
|
@ -122,47 +118,14 @@ 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);
|
||||||
|
@ -182,10 +145,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);
|
console.log("dddd:",result.data.entries);
|
||||||
}
|
}
|
||||||
setTimeout(function(){setIsSpin(false);},500);
|
setTimeout(function(){setIsSpin(false);},500);
|
||||||
}).catch(error=>{setIsSpin(false);})
|
}).catch(error=>{setIsSpin(false);})
|
||||||
|
@ -197,7 +160,7 @@ function CoderDepot(props){
|
||||||
let ele = document.getElementById("ptxt");
|
let ele = document.getElementById("ptxt");
|
||||||
if(ele){
|
if(ele){
|
||||||
let h = ele.offsetHeight;
|
let h = ele.offsetHeight;
|
||||||
if( h > 35 ) setHideBtn(true);
|
if( h > 18 ) setHideBtn(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},[projectDetail,lastCommit])
|
},[projectDetail,lastCommit])
|
||||||
|
@ -218,18 +181,15 @@ 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);
|
||||||
}
|
}
|
||||||
|
@ -249,7 +209,7 @@ function CoderDepot(props){
|
||||||
let b = branchName || defaultBranch;
|
let b = branchName || defaultBranch;
|
||||||
let checkvalue = turnbar(b);
|
let checkvalue = turnbar(b);
|
||||||
return (
|
return (
|
||||||
<Menu className="fileMenu">
|
<Menu>
|
||||||
<Menu.Item>
|
<Menu.Item>
|
||||||
<CheckProfile {...props} sureFunc={()=>urlLink(`/${owner}/${projectsId}/${checkvalue}/uploadfile${treeValue === undefined ? "" : `/${treeValue}`}`)}>上传文件</CheckProfile>
|
<CheckProfile {...props} sureFunc={()=>urlLink(`/${owner}/${projectsId}/${checkvalue}/uploadfile${treeValue === undefined ? "" : `/${treeValue}`}`)}>上传文件</CheckProfile>
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
|
@ -341,10 +301,8 @@ 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 = current_user && current_user.login && issuesFlag;
|
const baseOperate = projectDetail && projectDetail.permission && projectDetail.permission !=="Reporter";
|
||||||
const baseOperate = projectDetail && projectDetail.permission && projectDetail.permission !=="Reporter" && projectDetail.type !== 2 && pullsFlag;
|
|
||||||
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));
|
||||||
|
|
||||||
return(
|
return(
|
||||||
<WhiteBack>
|
<WhiteBack>
|
||||||
<UpdateDescModal desc={desc} website={website} lesson_url={lesson_url} visible={openModal} onCancel={()=>setOpenModal(false)} onOk={okUpdate}/>
|
<UpdateDescModal desc={desc} website={website} lesson_url={lesson_url} visible={openModal} onCancel={()=>setOpenModal(false)} onOk={okUpdate}/>
|
||||||
|
@ -363,7 +321,7 @@ function CoderDepot(props){
|
||||||
list = {mainFlag ? dirInfo : undefined}
|
list = {mainFlag ? dirInfo : undefined}
|
||||||
/>
|
/>
|
||||||
<div className="drawerBtn" onClick={()=>setVisible(true)}>
|
<div className="drawerBtn" onClick={()=>setVisible(true)}>
|
||||||
<i className="iconfont icon-zuohuaicon font-14"></i>
|
<i className="iconfont icon-youjiantou font-16"></i>
|
||||||
<span>目录</span>
|
<span>目录</span>
|
||||||
</div>
|
</div>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
|
@ -376,7 +334,7 @@ function CoderDepot(props){
|
||||||
<div className="panelmenu">
|
<div className="panelmenu">
|
||||||
<FlexAJ>
|
<FlexAJ>
|
||||||
<AlignCenter>
|
<AlignCenter>
|
||||||
<div className="mr30">
|
<div className="mr20">
|
||||||
{
|
{
|
||||||
props && props.platform ?
|
props && props.platform ?
|
||||||
<SelectBranch
|
<SelectBranch
|
||||||
|
@ -392,61 +350,41 @@ function CoderDepot(props){
|
||||||
<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">
|
||||||
treeValuePath && treeValuePath.length > 0 ?
|
<Link to={`/${owner}/${projectsId}/branches`} className="color-grey-9">
|
||||||
<Path
|
<i className="iconfont icon-fenzhi2 font-18 color-grey-9 mr3"></i>
|
||||||
identifier={projectDetail && projectDetail.identifier}
|
<span className="color-grey-6 mr3">{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="color-grey-9">
|
||||||
/>
|
<i className="iconfont icon-biaoqian3 font-16 color-grey-9 mr3"></i>
|
||||||
:
|
<span className="color-grey-6 mr3">{projectDetail && projectDetail.tags && projectDetail.tags.total_count}个</span>标签
|
||||||
<React.Fragment>
|
</Link>
|
||||||
<AlignCenter className="mr20">
|
</AlignCenter>
|
||||||
<Link to={`/${owner}/${projectsId}/branches`} className="iconBtn">
|
|
||||||
<i className="iconfont icon-master_icon font-16"></i>
|
|
||||||
<span>分支</span>
|
|
||||||
<span>{projectDetail && projectDetail.branches_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_count}</span>
|
|
||||||
</Link>
|
|
||||||
</AlignCenter>
|
|
||||||
</React.Fragment>
|
|
||||||
}
|
|
||||||
</AlignCenter>
|
</AlignCenter>
|
||||||
<AlignCenter className="depotBtn">
|
<AlignCenter>
|
||||||
{
|
{
|
||||||
(baseOperate || baseOper) &&
|
baseOperate && ((projectDetail.type !== 2 && pullsFlag) || issuesFlag )&&
|
||||||
<div className="addOptionBtn">
|
<div className="mr20 addOptionBtn">
|
||||||
{
|
{
|
||||||
baseOperate &&
|
projectDetail.type !== 2 && pullsFlag &&
|
||||||
<CheckProfile {...props} sureFunc={()=>urlLink(`/${owner}/${projectsId}/compare/master...${branchName || defaultBranch}`)} >+ 合并请求</CheckProfile>
|
<CheckProfile {...props} sureFunc={()=>urlLink(`/${owner}/${projectsId}/pulls/new`)} >+ 合并请求</CheckProfile>
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
baseOper &&
|
issuesFlag &&
|
||||||
<CheckProfile {...props} sureFunc={()=>urlLink(`/${owner}/${projectsId}/issues/new`)} >+ 易修</CheckProfile>
|
<CheckProfile {...props} sureFunc={()=>urlLink(`/${owner}/${projectsId}/issues/new`)} >+ 任务</CheckProfile>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
{ fileOperate &&
|
{ fileOperate &&
|
||||||
<Dropdown
|
<Dropdown overlay={fileMenu()} className="mr20" trigger={['click']}>
|
||||||
overlay={fileMenu()}
|
<Button type="default">文件 <i className="iconfont icon-sanjiaoxing-down ml3 font-14 color-grey-9"></i></Button>
|
||||||
className="mr10"
|
|
||||||
trigger={['click']}
|
|
||||||
getPopupContainer={document.parentNode}
|
|
||||||
>
|
|
||||||
<a>文件 <i className="iconfont icon-sanjiaoxing-down ml3 font-14 color-grey-6 mr-5"></i></a>
|
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
}
|
}
|
||||||
|
|
||||||
<Dropdown overlay={downloadMenu} placement="bottomRight" trigger={['click']}>
|
<Dropdown overlay={downloadMenu} placement="bottomRight" trigger={['click']}>
|
||||||
<Button type={'primary'}>下载 <i className="iconfont icon-sanjiaoxing-down ml3 font-14 color-white mr-3"></i></Button>
|
<Button type={'primary'}>下载 <i className="iconfont icon-sanjiaoxing-down ml3 font-14 color-white"></i></Button>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
</AlignCenter>
|
</AlignCenter>
|
||||||
</FlexAJ>
|
</FlexAJ>
|
||||||
|
@ -458,20 +396,27 @@ function CoderDepot(props){
|
||||||
<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 className={hideBtn && hide ? "ellipsistxt hidetxt" :"ellipsistxt"}>
|
<div className={hideBtn && hide ? "ellipsistxt hidetxt" :"ellipsistxt"}>
|
||||||
<pre id="ptxt"><Link to={`/${owner}/${projectsId}/commits/${truncateCommitId(lastCommit.sha)}`}><RenderHtml value={lastCommit.message}/></Link></pre>
|
<pre id="ptxt">{lastCommit && lastCommit.message}</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> }
|
||||||
|
|
||||||
<span className="ml20 color-grey-6 font-12 mt3">{lastCommit.time_from_now}</span>
|
<span className="ml12 color-grey-9 mt3">{lastCommit && lastCommit.time_from_now}</span>
|
||||||
{
|
{ commitCount ? <Link to={`/${owner}/${projectsId}/commits/branch/${turnbar(branchName || defaultBranch)}`} className="ml12 color-grey-9">
|
||||||
commitCount ?
|
<i className="iconfont icon-tijiao mr3 font-17 color-grey-9"></i>{commitCount}次提交
|
||||||
<Link to={`/${owner}/${projectsId}/commits/branch/${turnbar(branchName || defaultBranch)}`} className="ml20 color-grey-3"style={{height:"28px",lineHeight:"28px"}}>
|
</Link>:"" }
|
||||||
<i className="iconfont icon-tijiaoicon mr3 font-16"></i><span style={{fontWeight:"500"}}>{commitCount}次提交</span>
|
|
||||||
</Link>:""
|
|
||||||
}
|
|
||||||
</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)=>{
|
||||||
|
@ -505,80 +450,81 @@ function CoderDepot(props){
|
||||||
(dirInfo && dirInfo.length === 0) && !fileInfo ? <Nodata _html="暂未发现文件"/> :""
|
(dirInfo && dirInfo.length === 0) && !fileInfo ? <Nodata _html="暂未发现文件"/> :""
|
||||||
}
|
}
|
||||||
{/* readme文件显示(显示文件详情时不显示readme文件) */}
|
{/* readme文件显示(显示文件详情时不显示readme文件) */}
|
||||||
{ (readme && readme.content) ? <ReadMe ChangeFile={ChangeFile} readme={readme} operate={props && (props.isManager || props.isDeveloper) && projectDetail.type !==2 } history={props.history} /> :"" }
|
{ dirInfo && (readme && readme.content) ? <ReadMe ChangeFile={ChangeFile} readme={readme} operate={props && (props.isManager || props.isDeveloper) && projectDetail.type !==2 } history={props.history} /> :"" }
|
||||||
</div>
|
</div>
|
||||||
</LongWidth>
|
</LongWidth>
|
||||||
{
|
{
|
||||||
(!(treeValuePath && treeValuePath.length > 0) && !fileInfo) &&
|
!fileInfo &&
|
||||||
<ShortWidth>
|
<ShortWidth>
|
||||||
<Gap style={{paddingLeft:"30px"}}>
|
<Gap style={{paddingLeft:"30px"}}>
|
||||||
<div className="panelmenu">
|
<div className="panelmenu">
|
||||||
<FlexAJ className="font-18 color-ooo mb20" style={{lineHeight:"28px"}}>关于
|
<FlexAJ className="font-18 color-grey-6 mb20" style={{lineHeight:"28px"}}>简介
|
||||||
{
|
{
|
||||||
projectDetail.permission && (projectDetail.permission==="Admin" || projectDetail.permission==="Owner" || projectDetail.permission==="Manager") &&
|
projectDetail.permission && (projectDetail.permission==="Admin" || projectDetail.permission==="Owner" || projectDetail.permission==="Manager") &&
|
||||||
<i onClick={()=>setOpenModal(true)} className="iconfont icon-a-shezhi color-grey-9 font-15"></i>
|
<i onClick={()=>setOpenModal(true)} className="iconfont icon-anquanshezhi color-grey-9 font-15"></i>
|
||||||
}
|
}
|
||||||
</FlexAJ>
|
</FlexAJ>
|
||||||
{desc && <p className="font-14 color-grey-3 mb15 task-hide-2" style={{lineHeight:"24px",WebkitLineClamp:"4",textAlign:"justify",wordBreak:"break-all"}}>{desc}</p>}
|
{desc && <p className="font-14 color-grey-9 mb15 task-hide-2" style={{lineHeight:"22px",WebkitLineClamp:"4",textAlign:"justify",wordBreak:"break-all"}}>{desc}</p>}
|
||||||
{
|
{
|
||||||
website &&
|
website &&
|
||||||
<div className="color-grey-6 df pinfos mb5">
|
<p className="color-grey-6 df">
|
||||||
<i className="iconfont icon-lianjie2 font-15 mr10"></i>
|
<i className="iconfont icon-lianjie2 font-15 mr10 color-grey-9"></i>
|
||||||
<a href={website} target="_blank" style={{wordBreak:"break-all",lineHeight:"20px",marginTop:"5px",textDecoration:"underline"}}>{website}</a>
|
<a href={website} className="color-grey-6" target="_blank" style={{wordBreak:"break-all",lineHeight:"20px",marginTop:"5px",textDecoration:"underline"}}>{website}</a>
|
||||||
</div>
|
</p>
|
||||||
}
|
}
|
||||||
<div className="pinfos mb5">
|
<p>
|
||||||
<i className="iconfont icon-zishuwenjian_icon font-15 mr10"></i>
|
<i className="iconfont icon-wenjian4 font-15 mr10 color-grey-9"></i>
|
||||||
<a href="#readme">README.md</a>
|
<a href="#readme" className="color-grey-6">README.md</a>
|
||||||
</div>
|
</p>
|
||||||
<div className="color-grey-6 mb5">
|
<p className="color-grey-6">
|
||||||
<i className="iconfont icon-neicunicon font-15 mr10"></i>
|
<i className="iconfont icon-dataBase font-15 mr10 color-grey-6"></i>
|
||||||
<span>{projectDetail && projectDetail.size}</span>
|
<span>{projectDetail && projectDetail.size}</span>
|
||||||
</div>
|
</p>
|
||||||
{
|
{
|
||||||
projectDetail && projectDetail.license_name &&
|
projectDetail && projectDetail.license_name &&
|
||||||
<div className="pinfos">
|
<p className="color-grey-6">
|
||||||
<i className="iconfont icon-xieyiicon font-16 mr10"></i>
|
<i className="iconfont icon-tianping font-16 mr10 color-grey-3"></i>
|
||||||
<Link to={`/${owner}/${projectsId}/tree/${branchName || defaultBranch}/LICENSE`} className="color-grey-6">{projectDetail.license_name}</Link>
|
<span>{projectDetail.license_name}</span>
|
||||||
</div>
|
</p>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
{
|
{
|
||||||
inviteCode &&
|
inviteCode &&
|
||||||
<div>
|
<div>
|
||||||
<Divider />
|
<Divider />
|
||||||
<Invite code={inviteCode}/>
|
<Invite code={inviteCode} className={"detailsCode"}/>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
lesson_url &&
|
lesson_url &&
|
||||||
<div>
|
<div>
|
||||||
<Divider />
|
<Divider />
|
||||||
<p className="font-16 color-ooo">实践课程</p>
|
<p className="font-16 color-grey-6">实践课程</p>
|
||||||
<a href={lesson_url} target="_blank" className="color-grey-6" style={{textDecoration:"underline",wordBreak:"break-all"}}>{lesson_url}</a>
|
<a href={lesson_url} target="_blank" className="color-grey-6" style={{textDecoration:"underline",wordBreak:"break-all"}}>{lesson_url}</a>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
{/* 发布 */}
|
{/* 发布 */}
|
||||||
{
|
{
|
||||||
releaseVersions &&
|
projectDetail && projectDetail.release_versions &&
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Divider />
|
<Divider />
|
||||||
<Releases
|
<Releases
|
||||||
owner={owner}
|
owner={owner}
|
||||||
projectsId={projectsId}
|
projectsId={projectsId}
|
||||||
releaseVersions={releaseVersions}
|
releaseVersions={projectDetail.release_versions}
|
||||||
history={props.history}
|
history={props.history}
|
||||||
distribution={distribution}
|
baseOperate={baseOperate}
|
||||||
|
projectType={projectDetail.type}
|
||||||
/>
|
/>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
}
|
}
|
||||||
{/* 贡献者 */}
|
{/* 贡献者 */}
|
||||||
{
|
{
|
||||||
projectDetail && projectDetail.contributors && projectDetail.contributors.total_count >0 &&
|
projectDetail && projectDetail.contributors && projectDetail.contributors.length >0 &&
|
||||||
<Contributors contributors={projectDetail.contributors} owner={owner} projectsId={projectsId} />
|
<Contributors contributors={projectDetail && projectDetail.contributors} owner={owner} projectsId={projectsId} />
|
||||||
}
|
}
|
||||||
{/* 语言 */}
|
{/* 语言 */}
|
||||||
{ projectDetail && projectDetail.languages &&
|
{ projectDetail && projectDetail.languages && projectDetail.languages.length >0 &&
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Divider />
|
<Divider />
|
||||||
<LanguagePower languages={projectDetail.languages}/>
|
<LanguagePower languages={projectDetail.languages}/>
|
||||||
|
|
|
@ -4,8 +4,8 @@ import { truncateCommitId } from '../common/util';
|
||||||
|
|
||||||
const typeIco = {
|
const typeIco = {
|
||||||
"submodule":"icon-file-submodule font-17",
|
"submodule":"icon-file-submodule font-17",
|
||||||
"file":'icon-wenjian6 font-15 color-blue-file',
|
"file":'icon-wenjia font-15',
|
||||||
"dir":"icon-wenjianjia4 font-15 color-blue_4C"
|
"dir":"icon-wenjianjia1 font-15"
|
||||||
}
|
}
|
||||||
|
|
||||||
function CoderDepotCatalogue({item , goToSubRoot , owner , projectsId }){
|
function CoderDepotCatalogue({item , goToSubRoot , owner , projectsId }){
|
||||||
|
@ -13,7 +13,7 @@ function CoderDepotCatalogue({item , goToSubRoot , owner , projectsId }){
|
||||||
<li>
|
<li>
|
||||||
<span>
|
<span>
|
||||||
<a onClick={()=>goToSubRoot(item.path,item.type,item.name)} className={item.type === "submodule" && "submoduleStyle"}>
|
<a onClick={()=>goToSubRoot(item.path,item.type,item.name)} className={item.type === "submodule" && "submoduleStyle"}>
|
||||||
<i className={`iconfont ${typeIco[`${item.type}`]} mr8`}></i>{item.name}
|
<i className={`iconfont ${typeIco[`${item.type}`]} color-green-file mr5`}></i>{item.name}
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
<span title="init project">
|
<span title="init project">
|
||||||
|
@ -21,7 +21,7 @@ function CoderDepotCatalogue({item , goToSubRoot , owner , projectsId }){
|
||||||
{item.commit && item.commit.message}
|
{item.commit && item.commit.message}
|
||||||
</Link>
|
</Link>
|
||||||
</span>
|
</span>
|
||||||
<span title={item.commit && item.commit.created_at}>{item.commit && item.commit.time_from_now}</span>
|
<span>{item.commit && item.commit.time_from_now}</span>
|
||||||
</li>
|
</li>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { result } from 'lodash';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import RenderHtml from '../../components/render-html';
|
import RenderHtml from '../../components/render-html';
|
||||||
import { AlignCenter } from '../Component/layout';
|
import { AlignCenter } from '../Component/layout';
|
||||||
import { Dropdown , Anchor , Spin } from 'antd';
|
import { Dropdown , Menu , Spin } from 'antd';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
import ReadmeCatelogue from './sub/ReadmeCatelogue';
|
|
||||||
const $ = window.$;
|
const $ = window.$;
|
||||||
|
|
||||||
function CoderDepotReadme({ operate , history , readme , ChangeFile }){
|
function CoderDepotReadme({ operate , history , readme , ChangeFile }){
|
||||||
|
@ -24,45 +23,49 @@ function CoderDepotReadme({ operate , history , readme , ChangeFile }){
|
||||||
const anchor = el.id;
|
const anchor = el.id;
|
||||||
const level = el.tagName.replace("H", "");
|
const level = el.tagName.replace("H", "");
|
||||||
const href = `#${anchor}`;
|
const href = `#${anchor}`;
|
||||||
return { href:`${href}`,text:el.textContent , level:level }
|
return { href:`${path}${href}`,text:el.textContent , level:level }
|
||||||
});
|
});
|
||||||
setMenuList(items);
|
setMenuList(items);
|
||||||
},[content])
|
},[content])
|
||||||
|
|
||||||
function menu(){
|
function menu(){
|
||||||
if(menuList && menuList.length > 0){
|
if(menuList && menuList.length > 0){
|
||||||
|
let hash = history.location.hash;
|
||||||
return(
|
return(
|
||||||
<ReadmeCatelogue menuList={menuList} hash={history.location.hash}/>
|
<Menu className="menuslist">
|
||||||
|
{
|
||||||
|
menuList.map((item,key)=>{
|
||||||
|
return(
|
||||||
|
<Menu.Item key={item.id} className={decodeURI(hash).indexOf(item.text)>-1 ?"active":""}><Link to={`${item.href}`} style={{paddingLeft:`${item.level *10}px`}} title={item.text}>{item.text}</Link></Menu.Item>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</Menu>
|
||||||
)
|
)
|
||||||
}else{
|
}else{
|
||||||
return <Spin />
|
return <Spin />
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return(
|
return(
|
||||||
<div className="commonBox readBox" id="readme">
|
<div className="commonBox" id="readme">
|
||||||
<Anchor offsetTop={70} targetOffset={160}>
|
<div className="commonBox-title boxTitle">
|
||||||
<div className="commonBox-title boxTitle">
|
<AlignCenter>
|
||||||
<AlignCenter>
|
<Dropdown overlay={menu()}>
|
||||||
<Dropdown overlay={menu()} trigger={['hover']} overlayClassName="menuslist">
|
<span className="catelogue">
|
||||||
<span className="catelogue">
|
<i className="iconfont icon-zhangjie1 font-14 mr5"></i>
|
||||||
<i className="iconfont icon-muluicon font-12 mr5"></i>
|
<span>目录</span>
|
||||||
<span>目录</span>
|
</span>
|
||||||
</span>
|
</Dropdown>
|
||||||
</Dropdown>
|
<span className="commonBox-title-read">README.md</span>
|
||||||
|
</AlignCenter>
|
||||||
<span className="commonBox-title-read"><a href="#readme ">README.md</a></span>
|
{
|
||||||
|
operate ?
|
||||||
</AlignCenter>
|
<a className="ml20 pull-right" onClick={() =>ChangeFile(readme && readme.path, false)}>
|
||||||
{
|
<i className="iconfont icon-bianji6 font-16 color-blue"></i>
|
||||||
operate ?
|
</a>
|
||||||
<a className="ml20 pull-right" onClick={() =>ChangeFile(readme && readme.path, false)}>
|
:""
|
||||||
<i className="iconfont icon-a-bianji font-17 color-grey-6"></i>
|
}
|
||||||
</a>
|
</div>
|
||||||
:""
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</Anchor>
|
|
||||||
{
|
{
|
||||||
content &&
|
content &&
|
||||||
<div className="commonBox-info">
|
<div className="commonBox-info">
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
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.css';
|
||||||
|
|
||||||
|
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,19 +1,13 @@
|
||||||
import React , { Component } from 'react';
|
import React , { Component } from 'react';
|
||||||
import { Spin , Pagination, Timeline } from 'antd';
|
import { Spin , Pagination } from 'antd';
|
||||||
import { getImageUrl } from 'educoder';
|
import { getImageUrl } from 'educoder';
|
||||||
import { truncateCommitId ,timeFormat } from '../common/util';
|
import { truncateCommitId } 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 RenderHtml from '../../components/render-html.jsx';
|
|
||||||
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){
|
||||||
|
@ -21,16 +15,14 @@ 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:10,
|
limit:20,
|
||||||
page: 1,
|
page:1,
|
||||||
isSpining:false,
|
isSpining:false,
|
||||||
branchList:undefined
|
branchList:undefined
|
||||||
}
|
}
|
||||||
|
@ -58,34 +50,20 @@ 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 { limit } = this.state;
|
const { page , 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 , realPage , limit );
|
this.getCommitList( branchName , page , 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,{
|
||||||
|
@ -108,8 +86,7 @@ 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({
|
||||||
|
@ -128,9 +105,10 @@ class CoderRootCommit extends Component{
|
||||||
}
|
}
|
||||||
|
|
||||||
ChangePage=(page)=>{
|
ChangePage=(page)=>{
|
||||||
this.props.history.push({pathname: this.props.history.location.pathname,search: `page=${page}`})
|
const { branchName } = this.props.match.params;
|
||||||
|
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;
|
||||||
|
@ -151,50 +129,46 @@ class CoderRootCommit extends Component{
|
||||||
></SelectBranch>
|
></SelectBranch>
|
||||||
</div>
|
</div>
|
||||||
<Spin spinning={isSpining}>
|
<Spin spinning={isSpining}>
|
||||||
<Timeline className="commitList">
|
<div className="commonBox">
|
||||||
{
|
<div className="commonBox-title">
|
||||||
commitDatas && commitDatas.length > 0 && commitDatas.map((item,k)=>{
|
<div className="f-wrap-between" style={{alignItems:"center"}}>
|
||||||
return(
|
<span className="font-16">{dataCount}次提交代码({branch})</span>
|
||||||
<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>
|
||||||
<div>
|
<div className="commitList">
|
||||||
<AlignTop>
|
{
|
||||||
<div className="commitDesc"><Link to={`/${owner}/${projectsId}/commits/${truncateCommitId(`${item.sha}`)}`} className="font-14 color-grey-3 font-bd"><RenderHtml value={item.message}/></Link></div>
|
commitDatas && commitDatas.length > 0 && commitDatas.map((item,k)=>{
|
||||||
</AlignTop>
|
return(
|
||||||
<p className="f-wrap-alignCenter mt15 pb5">
|
<div key={k}>
|
||||||
<User
|
<AlignTop>
|
||||||
id={item.id}
|
<Link to={`/${owner}/${projectsId}/commits/${truncateCommitId(`${item.sha}`)}`} className="commitKey" style={{marginLeft:0,marginTop:"3px"}}>{truncateCommitId(`${item.sha}`)}</Link>
|
||||||
url={(item.image_url && getImageUrl(`/${item.image_url}`)) || "https://dss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3025493530,1989042357&fm=26&gp=0.jpg"}
|
<Link to={`/${owner}/${projectsId}/commits/${truncateCommitId(`${item.sha}`)}`} className="commitDesc">{item.message}</Link>
|
||||||
name={item.name}
|
</AlignTop>
|
||||||
login={item.login}
|
<p className="f-wrap-alignCenter mt15">
|
||||||
/>
|
{
|
||||||
{item.timestamp && <label className="font-14 color-grey-3 ml3">提交于 {timeFormat(item.timestamp)}</label>}
|
item.id ?
|
||||||
</p>
|
<Link to={`/${item.login}`} className="show-user-link">
|
||||||
</div>
|
{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 className="treecopy">
|
</Link>:
|
||||||
<div>
|
<span className="show-user-link">
|
||||||
<span className="treecopy-cont shadow">
|
{item.image_url?<img src={getImageUrl(`/${item.image_url}`)} alt="" width="28px" height="28px" className="mr15 radius"/>:""}
|
||||||
<img src={Tree} alt="sha" width={"16px"}/>
|
<label className="font-14 color-grey-6" style={{verticalAlign:'middle'}}>{item.name ?`${item.name}:`:""}提交于 {item.time_from_now}</label>
|
||||||
<Link to={`/${owner}/${projectsId}/commits/${truncateCommitId(`${item.sha}`)}`}>{truncateCommitId(`${item.sha}`)}</Link>
|
</span>
|
||||||
<input type="text" id={`value${k}`} value={`${truncateCommitId(`${item.sha}`)}`}/>
|
}
|
||||||
</span>
|
|
||||||
<CopyTool beforeText="复制commit id" afterText="复制成功" inputId={`value${k}`}/>
|
</p>
|
||||||
</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="暂无数据"/>}
|
||||||
{commitDatas && commitDatas.length === 0 && <Nodata _html="暂无数据"/>}
|
</div>
|
||||||
</Timeline>
|
</div>
|
||||||
{
|
{
|
||||||
dataCount > limit ?
|
dataCount > limit ?
|
||||||
<div className="edu-txt-center pt30 mb30">
|
<div className="edu-txt-center pt30 mb30">
|
||||||
<Pagination simple current={page} total={dataCount} pageSize={limit} onChange={this.ChangePage}></Pagination>
|
<Pagination simple defaultCurrent={page} total={dataCount} pageSize={limit} onChange={this.ChangePage}></Pagination>
|
||||||
</div>
|
</div>
|
||||||
:""
|
:""
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
import { Popconfirm , Select , Dropdown , Spin , Anchor } from "antd";
|
import { Popconfirm , Select } from "antd";
|
||||||
import "./list.scss";
|
import "./list.css";
|
||||||
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,
|
||||||
|
@ -21,13 +19,11 @@ 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
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount = () => {
|
componentDidMount = () => {
|
||||||
window.scrollTo(0, 0);
|
|
||||||
const { detail , mdFlag } = this.props;
|
const { detail , mdFlag } = this.props;
|
||||||
this.setState({
|
this.setState({
|
||||||
value: detail.content,
|
value: detail.content,
|
||||||
|
@ -173,31 +169,6 @@ 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,
|
||||||
|
@ -215,88 +186,79 @@ class CoderRootFileDetail extends Component {
|
||||||
const Option = Select.Option;
|
const Option = Select.Option;
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Anchor className="griditemAnchor" offsetTop={70}>
|
<div className="grid-item branchTitle">
|
||||||
<div className="griditemCate">
|
<div className="grid-item">
|
||||||
{
|
<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>
|
||||||
{
|
}
|
||||||
type !==2 &&
|
</span>:""
|
||||||
<a onClick={() => this.EditFile(false)} className="ml20">
|
}
|
||||||
<i className="iconfont icon-bianji1 font-15 color-grey-6"></i>
|
</span>
|
||||||
</a>
|
) : (
|
||||||
}
|
<React.Fragment>
|
||||||
</span>:""
|
<Select
|
||||||
}
|
showSearch={true}
|
||||||
</span>
|
placeholder={"请选择文本语言"}
|
||||||
) : (
|
style={{ width: 200 }}
|
||||||
<React.Fragment>
|
value={language}
|
||||||
<Select
|
onChange={this.select_language}
|
||||||
showSearch={true}
|
>
|
||||||
placeholder={"请选择文本语言"}
|
<Option value={undefined}>请选择文本语言</Option>
|
||||||
style={{ width: 200 }}
|
{languages &&
|
||||||
value={language}
|
languages.map((item, key) => {
|
||||||
onChange={this.select_language}
|
return (
|
||||||
>
|
<Option value={item} key={key}>
|
||||||
<Option value={undefined}>请选择文本语言</Option>
|
{item}
|
||||||
{languages &&
|
</Option>
|
||||||
languages.map((item, key) => {
|
);
|
||||||
return (
|
})}
|
||||||
<Option value={item} key={key}>
|
</Select>
|
||||||
{item}
|
<button
|
||||||
</Option>
|
type="button"
|
||||||
);
|
className="ant-btn ant-btn-sm ml20"
|
||||||
})}
|
onClick={() => this.EditFile(true)}
|
||||||
</Select>
|
>
|
||||||
<button
|
<span>取 消</span>
|
||||||
type="button"
|
</button>
|
||||||
className="ant-btn ant-btn-sm ml20"
|
</React.Fragment>
|
||||||
onClick={() => this.EditFile(true)}
|
)}
|
||||||
>
|
{
|
||||||
<span>取 消</span>
|
type !==2 &&
|
||||||
</button>
|
<Popconfirm
|
||||||
</React.Fragment>
|
title="确认删除这个文件?"
|
||||||
)}
|
className="ml20"
|
||||||
{
|
okText="确定"
|
||||||
type !==2 &&
|
cancelText="取消"
|
||||||
<Popconfirm
|
onConfirm={this.deleteFile}
|
||||||
title="确认删除这个文件?"
|
>
|
||||||
className="ml20"
|
<a>
|
||||||
okText="确定"
|
<i className="iconfont icon-shanchu font-15 color-grey-6"></i>
|
||||||
cancelText="取消"
|
</a>
|
||||||
onConfirm={this.deleteFile}
|
</Popconfirm>
|
||||||
>
|
}
|
||||||
<a>
|
|
||||||
<i className="iconfont icon-shanchu font-15 color-grey-6"></i>
|
|
||||||
</a>
|
|
||||||
</Popconfirm>
|
|
||||||
}
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
</Anchor>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{detail.image_type ? (
|
{detail.image_type ? (
|
||||||
<div className="edu-txt-center pt20 pb20">
|
<div className="edu-txt-center pt20 pb20">
|
||||||
|
@ -310,7 +272,7 @@ class CoderRootFileDetail extends Component {
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
md && readOnly ?
|
md && readOnly ?
|
||||||
<div className="files-md" id="files-md">
|
<div className="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,9 @@
|
||||||
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 './Index.scss';
|
import axios from 'axios';
|
||||||
|
|
||||||
const FileNew = Loadable({
|
const FileNew = Loadable({
|
||||||
loader: () => import('../Newfile/Index'),
|
loader: () => import('../Newfile/Index'),
|
||||||
|
@ -18,25 +18,25 @@ const CoderRootCommit = Loadable({
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
})
|
})
|
||||||
const CoderRootBranch = Loadable({
|
const CoderRootBranch = Loadable({
|
||||||
loader: () => import('./tree/Index'),
|
loader: () => import('./CoderRootBranch'),
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
})
|
})
|
||||||
const CoderRootTag = Loadable({
|
const CoderRootTag = Loadable({
|
||||||
loader: () => import('./tag/Index'),
|
loader: () => import('./CoderRootTag'),
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
})
|
})
|
||||||
const CoderRootVersion = Loadable({
|
const CoderRootVersion = Loadable({
|
||||||
loader: () => import('./version/Index'),
|
loader: () => import('../Version/version'),
|
||||||
|
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,
|
||||||
|
@ -50,41 +50,41 @@ class CoderRootIndex extends Component{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// componentDidMount=()=>{
|
componentDidMount=()=>{
|
||||||
// this.Init();
|
this.Init();
|
||||||
// }
|
}
|
||||||
// componentDidUpdate=(prevProps)=>{
|
componentDidUpdate=(prevProps)=>{
|
||||||
// const { location } = this.props;
|
const { location } = this.props;
|
||||||
// const prevlocation = prevProps && prevProps.location;
|
const prevlocation = prevProps && prevProps.location;
|
||||||
// if (location !== prevlocation) {
|
if (location !== prevlocation) {
|
||||||
// this.Init();
|
this.Init();
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
|
|
||||||
// Init=()=>{
|
Init=()=>{
|
||||||
// const { branchName } = this.props.match.params;
|
const { branchName } = this.props.match.params;
|
||||||
// const { defaultBranch } = this.props;
|
const { defaultBranch } = this.props;
|
||||||
// this.getTopCount(branchName || defaultBranch);
|
this.getTopCount(branchName || defaultBranch);
|
||||||
// }
|
}
|
||||||
|
|
||||||
// 获取<Top />组件里要显示的数据
|
// 获取<Top />组件里要显示的数据
|
||||||
// getTopCount=(branch)=>{
|
getTopCount=(branch)=>{
|
||||||
// const { projectsId , owner } = this.props.match.params;
|
const { projectsId , owner } = this.props.match.params;
|
||||||
// const url = `/${owner}/${projectsId}/top_counts.json`;
|
const url = `/${owner}/${projectsId}/top_counts.json`;
|
||||||
// axios.get(url,{params:{
|
axios.get(url,{params:{
|
||||||
// ref:branch
|
ref:branch
|
||||||
// }}).then(result=>{
|
}}).then(result=>{
|
||||||
// if(result){
|
if(result){
|
||||||
// this.setState({
|
this.setState({
|
||||||
// coderCount:result.data
|
coderCount:result.data
|
||||||
// })
|
})
|
||||||
// }
|
}
|
||||||
// }).catch(error=>{console.log(error);})
|
}).catch(error=>{console.log(error);})
|
||||||
// }
|
}
|
||||||
render(){
|
render(){
|
||||||
return(
|
return(
|
||||||
<div className="coderSubPage">
|
<div>
|
||||||
{/* <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"
|
||||||
|
@ -99,12 +99,12 @@ class CoderRootIndex extends Component{
|
||||||
></Route>
|
></Route>
|
||||||
<Route path="/:owner/:projectsId/:branch/newfile"
|
<Route path="/:owner/:projectsId/:branch/newfile"
|
||||||
render={
|
render={
|
||||||
(props) => (<FileNew {...this.props} {...props} {...this.state} />)
|
(props) => (<FileNew {...this.props} {...props} {...this.state} getTopCount={this.getTopCount} />)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
<Route path="/:owner/:projectsId/commits/branch/:branchName"
|
<Route path="/:owner/:projectsId/commits/branch/:branchName"
|
||||||
render={
|
render={
|
||||||
() => (<CoderRootCommit {...this.props} {...this.state} commit_class="main" />)
|
() => (<CoderRootCommit {...this.props} {...this.state} commit_class="main" getTopCount={this.getTopCount} />)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
<Route path="/:owner/:projectsId/commits/:sha"
|
<Route path="/:owner/:projectsId/commits/:sha"
|
||||||
|
@ -114,10 +114,10 @@ class CoderRootIndex extends Component{
|
||||||
></Route>
|
></Route>
|
||||||
<Route path="/:owner/:projectsId/commits"
|
<Route path="/:owner/:projectsId/commits"
|
||||||
render={
|
render={
|
||||||
() => (<CoderRootCommit {...this.props} {...this.state} commit_class="main" />)
|
() => (<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 +126,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} />)
|
||||||
|
|
|
@ -34,7 +34,7 @@ export default (( props, { projectDetail }) => {
|
||||||
<div className="div_table">
|
<div className="div_table">
|
||||||
<ul className="ul_thead">
|
<ul className="ul_thead">
|
||||||
<li>
|
<li>
|
||||||
<span className="flex1">标记名</span>
|
<span className="flex1">标签名</span>
|
||||||
<span>提交信息</span>
|
<span>提交信息</span>
|
||||||
<span className="ul_tbody_forth">下载</span>
|
<span className="ul_tbody_forth">下载</span>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { Spin, Tooltip } from 'antd';
|
import { Spin, Tooltip, Button } from 'antd';
|
||||||
import { Link, Route, Switch } from 'react-router-dom';
|
import { Link, Route, Switch } from 'react-router-dom';
|
||||||
import { Content, AlignTop } from '../Component/layout';
|
import { Content, AlignTop } from '../Component/layout';
|
||||||
import DetailBanner from './sub/DetailBanner';
|
import DetailBanner from './sub/DetailBanner';
|
||||||
import '../css/index.scss'
|
import '../css/index.scss'
|
||||||
import './list.scss';
|
import './list.css';
|
||||||
|
|
||||||
import { ImageLayerOfCommentHOC } from "../../modules/page/layers/ImageLayerOfCommentHOC";
|
|
||||||
|
|
||||||
|
|
||||||
import Loadable from 'react-loadable';
|
import Loadable from 'react-loadable';
|
||||||
import Loading from '../../Loading';
|
import Loading from '../../Loading';
|
||||||
|
@ -70,7 +67,7 @@ const MergeIndexDetail = Loadable({
|
||||||
})
|
})
|
||||||
|
|
||||||
const CreateMerge = Loadable({
|
const CreateMerge = Loadable({
|
||||||
loader: () => import('../Merge/CreateMerge'),
|
loader: () => import('../Merge/NewMerge'),
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -145,14 +142,12 @@ const WikiEdit = Loadable({
|
||||||
function checkPathname(projectsId, owner, pathname) {
|
function checkPathname(projectsId, owner, pathname) {
|
||||||
let name = "";
|
let name = "";
|
||||||
if (pathname && pathname !== `/${owner}/${projectsId}`) {
|
if (pathname && pathname !== `/${owner}/${projectsId}`) {
|
||||||
let url = pathname.split(`/${owner}/${projectsId}`)[1] || "";
|
let url = pathname.split(`/${owner}/${projectsId}`)[1];
|
||||||
if (url.indexOf("/about") > -1) {
|
if (url.indexOf("/about") > -1) {
|
||||||
name = "about"
|
name = "about"
|
||||||
} else if (url.indexOf("/issues") > -1 || url.indexOf("Milepost") > 0) {
|
} else if (url.indexOf("/issues") > -1 || url.indexOf("Milepost") > 0) {
|
||||||
name = "issues";
|
name = "issues";
|
||||||
} else if (url.indexOf("/pulls") > -1 || url.indexOf("/compare") > -1) {
|
} else if (url.indexOf("/pulls") > -1) {
|
||||||
// /pulls,合并请求除新建合并请求外,
|
|
||||||
// /compare,新建合并请求
|
|
||||||
name = "pulls"
|
name = "pulls"
|
||||||
} else if (url.indexOf("/milestones") > -1) {
|
} else if (url.indexOf("/milestones") > -1) {
|
||||||
name = "milestones"
|
name = "milestones"
|
||||||
|
@ -257,11 +252,7 @@ class Detail extends Component {
|
||||||
open_devops: flag
|
open_devops: flag
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
/**
|
canvasChannel = () => {
|
||||||
*
|
|
||||||
* @param {*} deleteFlag :同步镜像需要提示成功,且未成功的情况下不需要删除项目
|
|
||||||
*/
|
|
||||||
canvasChannel = (deleteFlag) => {
|
|
||||||
const name = window.location.hostname === "localhost" ? "testforgeplus.trustie.net" : window.location.hostname;
|
const name = window.location.hostname === "localhost" ? "testforgeplus.trustie.net" : window.location.hostname;
|
||||||
const actioncable = require("actioncable");
|
const actioncable = require("actioncable");
|
||||||
var project = this.state.project;
|
var project = this.state.project;
|
||||||
|
@ -278,15 +269,10 @@ class Detail extends Component {
|
||||||
console.log(`###### ---received data--- ######`);
|
console.log(`###### ---received data--- ######`);
|
||||||
console.log(data);
|
console.log(data);
|
||||||
if (data) {
|
if (data) {
|
||||||
if(deleteFlag){
|
if ( data.project && data.project.mirror_status === 2) {
|
||||||
this.props.showNotification("镜像同步成功!");
|
this.deleteProjectBack();
|
||||||
window.location.reload();
|
|
||||||
}else{
|
|
||||||
if (data.project && data.project.mirror_status === 2) {
|
|
||||||
this.deleteProjectBack();
|
|
||||||
}
|
|
||||||
this.getDetail();
|
|
||||||
}
|
}
|
||||||
|
this.getDetail();
|
||||||
this.setState({
|
this.setState({
|
||||||
firstSync: false,
|
firstSync: false,
|
||||||
secondSync: false
|
secondSync: false
|
||||||
|
@ -320,9 +306,6 @@ class Detail extends Component {
|
||||||
const url = `/${owner}/${projectsId}/detail.json`;
|
const url = `/${owner}/${projectsId}/detail.json`;
|
||||||
axios.get(url).then((result) => {
|
axios.get(url).then((result) => {
|
||||||
if (result && result.data) {
|
if (result && result.data) {
|
||||||
if (result.data.status === 404) {
|
|
||||||
this.props.history.push('/nopage');
|
|
||||||
}
|
|
||||||
this.setState({
|
this.setState({
|
||||||
projectDetail: result.data,
|
projectDetail: result.data,
|
||||||
project_id: result.data.project_id,
|
project_id: result.data.project_id,
|
||||||
|
@ -442,10 +425,8 @@ class Detail extends Component {
|
||||||
const url = `/${owner}/${projectsId}/sync_mirror.json`;
|
const url = `/${owner}/${projectsId}/sync_mirror.json`;
|
||||||
axios.post(url).then(result => {
|
axios.post(url).then(result => {
|
||||||
if (result && result.data && result.data.status === 0) {
|
if (result && result.data && result.data.status === 0) {
|
||||||
this.setState({
|
this.props.showNotification("镜像同步成功!");
|
||||||
secondSync:true
|
this.getProject(2);
|
||||||
})
|
|
||||||
this.canvasChannel(true);
|
|
||||||
} else {
|
} else {
|
||||||
this.props.showNotification("镜像同步失败!");
|
this.props.showNotification("镜像同步失败!");
|
||||||
}
|
}
|
||||||
|
@ -490,7 +471,7 @@ class Detail extends Component {
|
||||||
<div>
|
<div>
|
||||||
<div className="detailHeader-wrapper">
|
<div className="detailHeader-wrapper">
|
||||||
<div className="normal">
|
<div className="normal">
|
||||||
<AlignTop style={{ padding: "18px 0px 10px", justifyContent: "space-between" }}>
|
<AlignTop style={{ padding: "20px 0px 10px", justifyContent: "space-between" }}>
|
||||||
<div>
|
<div>
|
||||||
<AlignTop>
|
<AlignTop>
|
||||||
<div className="projectallName">
|
<div className="projectallName">
|
||||||
|
@ -508,6 +489,11 @@ class Detail extends Component {
|
||||||
this.textFunc(projectDetail.forked_from_project_id, projectDetail.fork_info)
|
this.textFunc(projectDetail.forked_from_project_id, projectDetail.fork_info)
|
||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
projectDetail && projectDetail.type && projectDetail.type !== 0 ?
|
||||||
|
<span className="color-grey-9">镜像自 <a className="color-grey-6" target="_blank" href={projectDetail.mirror_url}>{projectDetail.mirror_url}</a></span>
|
||||||
|
: ""
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
@ -518,7 +504,7 @@ class Detail extends Component {
|
||||||
((current_user && current_user.admin) || isManager) && (projectDetail && projectDetail.type && projectDetail.type === 2) ?
|
((current_user && current_user.admin) || isManager) && (projectDetail && projectDetail.type && projectDetail.type === 2) ?
|
||||||
<a className="synchronism ml30" onClick={this.synchronismMirror}>同步镜像</a> : ""
|
<a className="synchronism ml30" onClick={this.synchronismMirror}>同步镜像</a> : ""
|
||||||
}
|
}
|
||||||
<span className="detail_tag_btn">
|
<Button className="detail_tag_btn">
|
||||||
<a className="detail_tag_btn_name" style={{ cursor: platform ? "pointer" : "default" }} onClick={() => this.focusFunc(watched)}>
|
<a className="detail_tag_btn_name" style={{ cursor: platform ? "pointer" : "default" }} onClick={() => this.focusFunc(watched)}>
|
||||||
<i className={watched ? "iconfont icon-shixing color-orange font-16 mr3" : "iconfont icon-kongxing color-grey-9 font-16 mr3"}></i>
|
<i className={watched ? "iconfont icon-shixing color-orange font-16 mr3" : "iconfont icon-kongxing color-grey-9 font-16 mr3"}></i>
|
||||||
<span>{watched ? '取消关注' : '关注'}</span>
|
<span>{watched ? '取消关注' : '关注'}</span>
|
||||||
|
@ -526,15 +512,15 @@ class Detail extends Component {
|
||||||
{
|
{
|
||||||
watchers_count > 0 ?
|
watchers_count > 0 ?
|
||||||
platform ?
|
platform ?
|
||||||
<Link className="detail_tag_btn_count" style={{ color: `#666` }} to={platform ? { pathname: `/${owner}/${projectsId}/following`, state } : ""}>
|
<Link className="detail_tag_btn_count" style={{ color: `${watched ? "#2878FF" : "#666"}` }} to={platform ? { pathname: `/${owner}/${projectsId}/following`, state } : ""}>
|
||||||
{watchers_count}
|
{watchers_count}
|
||||||
</Link>
|
</Link>
|
||||||
:
|
:
|
||||||
<span className="detail_tag_btn_count">{watchers_count}</span>
|
<span className="detail_tag_btn_count">{watchers_count}</span>
|
||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
</span>
|
</Button>
|
||||||
<span className="detail_tag_btn">
|
<Button className="detail_tag_btn">
|
||||||
<a className="detail_tag_btn_name" style={{ cursor: platform ? "pointer" : "default" }} onClick={() => this.pariseFunc(praised)}>
|
<a className="detail_tag_btn_name" style={{ cursor: platform ? "pointer" : "default" }} onClick={() => this.pariseFunc(praised)}>
|
||||||
<i className={praised ? "iconfont icon-weibiaoti105 color-orange font-14 mr3" : "iconfont icon-guanzhu color-grey-9 font-14 mr3"}></i>
|
<i className={praised ? "iconfont icon-weibiaoti105 color-orange font-14 mr3" : "iconfont icon-guanzhu color-grey-9 font-14 mr3"}></i>
|
||||||
<span>{praised ? '取消点赞' : '点赞'}</span>
|
<span>{praised ? '取消点赞' : '点赞'}</span>
|
||||||
|
@ -542,17 +528,17 @@ class Detail extends Component {
|
||||||
{
|
{
|
||||||
praises_count > 0 ?
|
praises_count > 0 ?
|
||||||
platform ?
|
platform ?
|
||||||
<Link className="detail_tag_btn_count" style={{ color: `#666` }} to={{ pathname: `/${owner}/${projectsId}/stargazers`, state }}>
|
<Link className="detail_tag_btn_count" style={{ color: `${praised ? "#2878FF" : "#666"}` }} to={{ pathname: `/${owner}/${projectsId}/stargazers`, state }}>
|
||||||
{praises_count}
|
{praises_count}
|
||||||
</Link> :
|
</Link> :
|
||||||
<span className="detail_tag_btn_count">{praises_count}</span>
|
<span className="detail_tag_btn_count">{praises_count}</span>
|
||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
</span>
|
</Button>
|
||||||
<span className="detail_tag_btn" loading={forkSpin}>
|
<Button className="detail_tag_btn" loading={forkSpin}>
|
||||||
<Tooltip title="复刻是fork的中文名,即复制代码仓库" placement="bottom">
|
<Tooltip title="复刻是fork的中文名,即复制代码仓库" placement="bottom">
|
||||||
<a className="detail_tag_btn_name" style={{ cursor: platform ? "pointer" : "default" }} onClick={this.forkFunc}>
|
<a className="detail_tag_btn_name" style={{ cursor: platform ? "pointer" : "default" }} onClick={this.forkFunc}>
|
||||||
<i className="iconfont icon-fork color-grey-9 mr3 font-16"></i><span>复刻(Fork)</span>
|
<i className="iconfont icon-fork color-grey-9 mr3"></i>复刻
|
||||||
</a>
|
</a>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
{
|
{
|
||||||
|
@ -565,7 +551,7 @@ class Detail extends Component {
|
||||||
<span className="detail_tag_btn_count">{forked_count}</span>
|
<span className="detail_tag_btn_count">{forked_count}</span>
|
||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
</span>
|
</Button>
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
@ -681,19 +667,18 @@ class Detail extends Component {
|
||||||
(props) => (<OrderNew {...this.props} {...props} {...this.state} {...common} />)
|
(props) => (<OrderNew {...this.props} {...props} {...this.state} {...common} />)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
{/* 修改详情 updatedetail*/}
|
{/* 修改详情 */}
|
||||||
<Route path="/:owner/:projectsId/issues/:orderId/:operateName"
|
<Route path="/:owner/:projectsId/issues/:orderId/updatedetail"
|
||||||
render={
|
render={
|
||||||
(props) => (<OrderupdateDetail {...this.props} {...props} {...this.state} {...common} />)
|
(props) => (<OrderupdateDetail {...this.props} {...props} {...this.state} {...common} />)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
{/* 复制详情 copyetail*/}
|
{/* 复制详情 */}
|
||||||
<Route path="/:owner/:projectsId/issues/:orderId/copyetail"
|
<Route path="/:owner/:projectsId/issues/:orderId/copyetail"
|
||||||
render={
|
render={
|
||||||
(props) => (<OrderupdateDetail {...this.props} {...props} {...this.state} {...common} />)
|
(props) => (<OrdercopyDetail {...this.props} {...props} {...this.state} {...common} />)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
|
|
||||||
{/* 任务详情 */}
|
{/* 任务详情 */}
|
||||||
<Route path="/:owner/:projectsId/issues/:orderId"
|
<Route path="/:owner/:projectsId/issues/:orderId"
|
||||||
render={
|
render={
|
||||||
|
@ -713,32 +698,22 @@ class Detail extends Component {
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
{/* 新建合并请求 */}
|
{/* 新建合并请求 */}
|
||||||
{/* <Route path="/:owner/:projectsId/compare/:branch"
|
<Route path="/:owner/:projectsId/pulls/new/:branch"
|
||||||
render={
|
|
||||||
(props) => (<CreateMerge {...this.props} {...props} {...this.state} {...common} is_fork={true} />)
|
|
||||||
}
|
|
||||||
></Route> */}
|
|
||||||
<Route path="/:owner/:projectsId/compare"
|
|
||||||
render={
|
render={
|
||||||
(props) => (<CreateMerge {...this.props} {...props} {...this.state} {...common} is_fork={true} />)
|
(props) => (<CreateMerge {...this.props} {...props} {...this.state} {...common} is_fork={true} />)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
<Route path="/:owner/:projectsId/pulls/:mergeId/edit"
|
<Route path="/:owner/:projectsId/pulls/new"
|
||||||
|
render={
|
||||||
|
(props) => (<CreateMerge {...this.props} {...props} {...this.state} {...common} is_fork={true} />)
|
||||||
|
}
|
||||||
|
></Route>
|
||||||
|
<Route path="/:owner/:projectsId/pulls/:mergeId/UpdateMerge"
|
||||||
render={
|
render={
|
||||||
(props) => (<UpdateMerge {...this.props} {...props} {...this.state} {...common} />)
|
(props) => (<UpdateMerge {...this.props} {...props} {...this.state} {...common} />)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
<Route path="/:owner/:projectsId/pulls/:mergeId"
|
<Route path="/:owner/:projectsId/pulls/:mergeId/Messagecount"
|
||||||
render={
|
|
||||||
(props) => (<MessageCount {...this.props} {...props} {...this.state} {...common} />)
|
|
||||||
}
|
|
||||||
></Route>
|
|
||||||
<Route path="/:owner/:projectsId/pulls/:mergeId/commits"
|
|
||||||
render={
|
|
||||||
(props) => (<MessageCount {...this.props} {...props} {...this.state} {...common} />)
|
|
||||||
}
|
|
||||||
></Route>
|
|
||||||
<Route path="/:owner/:projectsId/pulls/:mergeId/files"
|
|
||||||
render={
|
render={
|
||||||
(props) => (<MessageCount {...this.props} {...props} {...this.state} {...common} />)
|
(props) => (<MessageCount {...this.props} {...props} {...this.state} {...common} />)
|
||||||
}
|
}
|
||||||
|
@ -805,7 +780,4 @@ class Detail extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ImageLayerOfCommentHOC({
|
export default Detail;
|
||||||
imgSelector: ".imageLayerParent img, .imageLayerParent .imageTarget",
|
|
||||||
parentSelector: ".newContainer",
|
|
||||||
})(Detail);
|
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { Route, Switch } from "react-router-dom";
|
|
||||||
import { withRouter } from "react-router";
|
|
||||||
import Loadable from "react-loadable";
|
|
||||||
import Loading from "../../Loading";
|
|
||||||
import { SnackbarHOC } from "educoder";
|
|
||||||
import { CNotificationHOC } from "../../modules/courses/common/CNotificationHOC";
|
|
||||||
import { TPMIndexHOC } from "../../modules/tpm/TPMIndexHOC";
|
|
||||||
|
|
||||||
// forge项目详情
|
|
||||||
const ProjectDetail = Loadable({
|
|
||||||
loader: () => import("../Main/Detail"),
|
|
||||||
loading: Loading,
|
|
||||||
});
|
|
||||||
export default withRouter(
|
|
||||||
(CNotificationHOC()(SnackbarHOC()(TPMIndexHOC((props) => {
|
|
||||||
return (
|
|
||||||
<Switch>
|
|
||||||
<Route
|
|
||||||
path="/:owner/:projectsId"
|
|
||||||
render={(p) => (
|
|
||||||
<ProjectDetail {...props} {...p} />
|
|
||||||
)}
|
|
||||||
></Route>
|
|
||||||
</Switch>
|
|
||||||
)
|
|
||||||
}))))
|
|
||||||
)
|
|
|
@ -1,65 +1,35 @@
|
||||||
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 { timeFormat, truncateCommitId } from '../common/util';
|
import { 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 RenderHtml from "../../components/render-html";
|
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 #FAFCFF;
|
border: 1px solid #dddddd;
|
||||||
margin-bottom:15px;
|
margin-bottom:15px;
|
||||||
& .commitinfos {
|
& .commitinfos {
|
||||||
background-color: #f1f8ff;
|
background-color: #f1f8ff;
|
||||||
border: 1px solid rgba(42, 97, 255, 0.23);
|
border-bottom: 1px solid #ddd;
|
||||||
border-radius: 3px 3px 0px 0px;
|
padding: 20px;
|
||||||
padding: 10px 20px 10px 16px;
|
|
||||||
& .markdown-body table{
|
|
||||||
background: #f1f8ff;
|
|
||||||
}
|
|
||||||
& .btnblue{
|
|
||||||
margin-top: 12px;
|
|
||||||
}
|
|
||||||
& .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: 14px 20px 14px 16px;
|
padding: 10px 20px;
|
||||||
border-radius: 3px 3px 0px 0px;
|
|
||||||
border: 1px solid #D0D0D0;
|
|
||||||
.df{
|
|
||||||
align-items: center;
|
|
||||||
& .underline:hover{
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
function turnbar(str){
|
|
||||||
if(str && str.length>0 && str.indexOf("/")>-1){
|
export default ({ match , history }) => {
|
||||||
return str.replaceAll('/','%2F');
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
//提交详情页
|
|
||||||
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) {
|
||||||
|
@ -73,7 +43,6 @@ export default (props) => {
|
||||||
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 => {
|
||||||
|
@ -87,42 +56,29 @@ export default (props) => {
|
||||||
<Infos>
|
<Infos>
|
||||||
<div className="commitinfos">
|
<div className="commitinfos">
|
||||||
<div className="f-wrap-between">
|
<div className="f-wrap-between">
|
||||||
<div>
|
{commit && commit.message &&
|
||||||
{commit && commit.message &&
|
<pre className="task-hide" style={{marginBottom:"0px",height:"28px",whiteSpace:"pre-wrap"}}>{commit.message}</pre>
|
||||||
<RenderHtml className="task-hide" value={commit.message}/>
|
}
|
||||||
}
|
<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
|
||||||
id = {committer && committer.id}
|
url={(committer && getImageUrl(`/${committer.image_url}`))|| "https://dss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3025493530,1989042357&fm=26&gp=0.jpg"}
|
||||||
url={(committer && getImageUrl(`/${committer.image_url}`))}
|
|
||||||
name={committer && committer.name}
|
name={committer && committer.name}
|
||||||
login={committer && committer.login}
|
|
||||||
/>
|
/>
|
||||||
{commit && commit.timestamp && <li className="ml4">提交于{timeFormat(commit.timestamp)}</li>}
|
{committer && committer.time_from_now && <li className="ml20 mt2">{committer.time_from_now}</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(
|
||||||
<div className="ml40 f-wrap-alignCenter">
|
<Keys title="父节点" value={truncateCommitId(item.sha)} key={key} className="mr20"></Keys>
|
||||||
<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>
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
<div className="ml40 f-wrap-alignCenter">
|
<Keys title="当前节点" value={truncateCommitId(sha)}></Keys>
|
||||||
<label className="mr8">当前节点</label>
|
|
||||||
<img src={Tree} alt="sha" width={"16px"} className="mr4"/>
|
|
||||||
<span>{truncateCommitId(sha)}</span>
|
|
||||||
</div>
|
|
||||||
</li>
|
</li>
|
||||||
</div>
|
</div>
|
||||||
</Infos>
|
</Infos>
|
||||||
|
@ -131,7 +87,6 @@ export default (props) => {
|
||||||
data={data}
|
data={data}
|
||||||
owner={owner}
|
owner={owner}
|
||||||
projectsId={projectsId}
|
projectsId={projectsId}
|
||||||
parentsSha={parents && parents.length > 0 && parents[0].sha}
|
|
||||||
/>
|
/>
|
||||||
</Spin>
|
</Spin>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { getImageUrl } from 'educoder';
|
||||||
import "slick-carousel/slick/slick.css";
|
import "slick-carousel/slick/slick.css";
|
||||||
import "slick-carousel/slick/slick-theme.css";
|
import "slick-carousel/slick/slick-theme.css";
|
||||||
import '../css/index.scss'
|
import '../css/index.scss'
|
||||||
import './list.scss';
|
import './list.css';
|
||||||
import './Index.scss';
|
import './Index.scss';
|
||||||
import ListItem from './IndexItem'
|
import ListItem from './IndexItem'
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
@ -255,14 +255,14 @@ class Index extends Component {
|
||||||
|
|
||||||
newItem = ()=>{
|
newItem = ()=>{
|
||||||
return(
|
return(
|
||||||
<ul>
|
<Menu>
|
||||||
<li>
|
<Menu.Item key="created_mirror">
|
||||||
<CheckProfile {...this.props} sureFunc={()=>{this.props.history.push('/projects/deposit/new')}}>新建项目</CheckProfile>
|
<CheckProfile {...this.props} sureFunc={()=>{this.props.history.push('/projects/mirror/new')}}>新建镜像项目</CheckProfile>
|
||||||
</li>
|
</Menu.Item>
|
||||||
<li>
|
<Menu.Item key="created_deposit">
|
||||||
<CheckProfile {...this.props} sureFunc={()=>{this.props.history.push('/projects/mirror/new')}}>导入项目</CheckProfile>
|
<CheckProfile {...this.props} sureFunc={()=>{this.props.history.push('/projects/deposit/new')}}>新建托管项目</CheckProfile>
|
||||||
</li>
|
</Menu.Item>
|
||||||
</ul>
|
</Menu>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,13 +392,7 @@ class Index extends Component {
|
||||||
<div>
|
<div>
|
||||||
{
|
{
|
||||||
current_user && current_user.login &&
|
current_user && current_user.login &&
|
||||||
<Popover
|
<Popover content={this.newItem()} trigger={["click"]} placement='bottom' className="mr50">
|
||||||
overlayClassName="newPopUl"
|
|
||||||
content={this.newItem()}
|
|
||||||
trigger={["click"]}
|
|
||||||
placement='bottom'
|
|
||||||
className="mr50"
|
|
||||||
>
|
|
||||||
<a className="ant-dropdown-link">
|
<a className="ant-dropdown-link">
|
||||||
<span className="color-blue font-16"><img src={img_new} alt="" width="13px" /> 新建</span>
|
<span className="color-blue font-16"><img src={img_new} alt="" width="13px" /> 新建</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -13,21 +13,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.iconBtn{
|
|
||||||
i{
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
span{
|
|
||||||
margin-left: 4px;
|
|
||||||
color: #333!important;
|
|
||||||
&:last-child{
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&:hover span,&:hover i{
|
|
||||||
color: #466AFF!important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* recommandProjects */
|
/* recommandProjects */
|
||||||
.recommandProjects.slick-slider{
|
.recommandProjects.slick-slider{
|
||||||
width: 1230px;
|
width: 1230px;
|
||||||
|
@ -123,94 +108,63 @@
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
.panelmenu{
|
.panelmenu{
|
||||||
padding-top:30px;
|
padding-top:30px;
|
||||||
.depotBtn{
|
|
||||||
.mr-5{
|
|
||||||
margin-right: -5px;
|
|
||||||
}
|
|
||||||
.ant-btn{
|
|
||||||
height: 32px;
|
|
||||||
line-height: 32px;
|
|
||||||
width: 83px;
|
|
||||||
text-align: center;
|
|
||||||
padding:0px ;
|
|
||||||
font-weight: 500;
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
.ant-btn-default{
|
|
||||||
color: #333;
|
|
||||||
border-color: #d0d0d0;
|
|
||||||
&:hover{
|
|
||||||
background: #F3F4F6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.ant-btn-primary{
|
|
||||||
color: #fff;
|
|
||||||
background-color: #466AFF;
|
|
||||||
border: none;
|
|
||||||
&:hover{
|
|
||||||
background-color: rgba(70,106,255,0.85);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.depotBtn,.addOptionBtn{
|
.addOptionBtn{
|
||||||
|
height: 32px;
|
||||||
|
line-height: 30px;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
border:1px solid #d9d9d9;
|
||||||
|
border-radius: 2px;
|
||||||
a{
|
a{
|
||||||
color: #333!important;
|
padding:0px 13px;
|
||||||
font-weight: 500!important;
|
color: rgba(0, 0, 0, 0.65);
|
||||||
border-radius: 5px;
|
cursor: pointer;
|
||||||
width: 83px;
|
}
|
||||||
height: 32px;
|
& > a:first-child{
|
||||||
line-height: 30px;
|
border-right: 1px solid #d9d9d9;
|
||||||
background: #fff;
|
}
|
||||||
border: 1px solid #D0D0D0;
|
& > a:last-child{
|
||||||
margin-right: 10px;
|
border-right: none;
|
||||||
text-align: center;
|
|
||||||
&:hover,&:active{
|
|
||||||
background: #F3F4F6;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.infoCount{
|
.infoCount{
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 24px;
|
padding:0px 5px;
|
||||||
text-align: center;
|
height: 16px;
|
||||||
height: 24px;
|
line-height: 16px;
|
||||||
line-height: 24px;
|
background-color: #eee;
|
||||||
background-color:rgba(153, 153, 153, 0.13);;
|
color:#999;
|
||||||
color:#666;
|
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
margin-left: 6px;
|
margin-left: 10px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
.attrPerson{
|
.attrPerson{
|
||||||
padding-top: 12px;
|
padding-top: 15px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
padding-bottom: 2px;
|
|
||||||
a{
|
a{
|
||||||
margin: 0px 17px 10px 0px;
|
margin: 10px 10px 0px 0px;
|
||||||
img{
|
img{
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
width: 40px;
|
width: 35px;
|
||||||
height: 40px;
|
height: 35px;
|
||||||
}
|
}
|
||||||
&:nth-child(5n){
|
&:nth-child(6){
|
||||||
margin-right: 0px;
|
margin-right: 0px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.progress{
|
.progress{
|
||||||
display: flex;
|
display: flex;
|
||||||
border-radius: 2px;
|
border-radius: 10px;
|
||||||
height: 11px;
|
height: 7px;
|
||||||
margin-top: 12px;
|
margin-top: 12px;
|
||||||
span{
|
span{
|
||||||
&:first-child{
|
&:first-child{
|
||||||
border-radius: 2px 0px 0px 2px;
|
border-radius: 10px 0px 0px 10px;
|
||||||
}
|
}
|
||||||
&:last-child{
|
&:last-child{
|
||||||
border-radius: 0px 2px 2px 0px;
|
border-radius: 0px 10px 10px 0px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -224,17 +178,16 @@
|
||||||
height: 8px;
|
height: 8px;
|
||||||
width: 8px;
|
width: 8px;
|
||||||
left: 0px;
|
left: 0px;
|
||||||
top:8px;
|
top:10px
|
||||||
}
|
}
|
||||||
&>span{
|
&>span{
|
||||||
padding-left: 15px;
|
padding-left: 15px;
|
||||||
position: relative;
|
position: relative;
|
||||||
min-width: 33.5%;
|
min-width: 33.5%;
|
||||||
font-size: 12px;
|
|
||||||
font-weight: 400;
|
|
||||||
color: #666;
|
|
||||||
span{
|
span{
|
||||||
|
color: #666;
|
||||||
&:last-child{
|
&:last-child{
|
||||||
|
color: #999;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -242,24 +195,18 @@
|
||||||
}
|
}
|
||||||
.listtable{
|
.listtable{
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
|
border:1px solid #d9d9d9;
|
||||||
|
border-radius: 4px;
|
||||||
.listtablehead{
|
.listtablehead{
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
border-bottom: 1px solid #d9d9d9;
|
border-bottom: 1px solid #d9d9d9;
|
||||||
padding:12px 20px 11px;
|
padding:7px 20px;
|
||||||
border-radius: 4px 4px 0px 0px;
|
border-radius: 4px 4px 0px 0px;
|
||||||
border: 1px solid rgba(42, 97, 255, 0.23);
|
background-color: #FAFBFC;
|
||||||
background-color: #FAFCFF;
|
|
||||||
.ellipsistxt{
|
.ellipsistxt{
|
||||||
&:hover .markdown-body{
|
margin-top: 6px;
|
||||||
color: #466AFF;
|
|
||||||
& a{
|
|
||||||
color: #466AFF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
margin-top: 2px;
|
|
||||||
// cursor: pointer;
|
|
||||||
#ptxt{
|
#ptxt{
|
||||||
margin-bottom: 0px;
|
margin-bottom: 0px;
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
|
@ -269,27 +216,6 @@
|
||||||
white-space:-pre-wrap; /* Opera 4-6 */
|
white-space:-pre-wrap; /* Opera 4-6 */
|
||||||
white-space:-o-pre-wrap; /* Opera 7 */
|
white-space:-o-pre-wrap; /* Opera 7 */
|
||||||
word-wrap:break-word;
|
word-wrap:break-word;
|
||||||
.markdown-body{
|
|
||||||
line-height: 10px;
|
|
||||||
font-size: 14px;
|
|
||||||
& p {
|
|
||||||
margin: 1px 0px 0px !important;
|
|
||||||
font-size: 14px !important;
|
|
||||||
}
|
|
||||||
& ol,ul{
|
|
||||||
padding-bottom: 3px;
|
|
||||||
& li{
|
|
||||||
min-height: 18px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
& table{
|
|
||||||
line-height: 1;
|
|
||||||
background: #FAFCFF;
|
|
||||||
}
|
|
||||||
&:first-child {
|
|
||||||
margin-top: -1px !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
margin-left: 13px;
|
margin-left: 13px;
|
||||||
line-height:18px;
|
line-height:18px;
|
||||||
|
@ -297,41 +223,36 @@
|
||||||
width: 0;
|
width: 0;
|
||||||
color: #666;
|
color: #666;
|
||||||
&.hidetxt{
|
&.hidetxt{
|
||||||
height: 24px;
|
height: 18px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
padding-right:8px;
|
padding-right:8px;
|
||||||
// &::after{
|
&::after{
|
||||||
// position: absolute;
|
position: absolute;
|
||||||
// right: 0px;
|
right: 0px;
|
||||||
// bottom: 0px;
|
bottom: 0px;
|
||||||
// content:"...";
|
content:"...";
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.ellipsis{
|
.ellipsis{
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
height: 16px;
|
background-color: #c1c1c1;
|
||||||
background: rgba(153, 153, 153, 0.2);
|
|
||||||
border-radius: 2px;
|
|
||||||
padding:0px 4px;
|
padding:0px 4px;
|
||||||
height: 14px;
|
height: 14px;
|
||||||
line-height: 14px;
|
line-height: 14px;
|
||||||
margin-top: 9px;
|
margin-top: 9px;
|
||||||
i{
|
i{
|
||||||
font-size: 15px!important;
|
font-size: 15px!important;
|
||||||
color: #333;
|
color: #fff;
|
||||||
height: 14px;
|
height: 14px;
|
||||||
line-height: 14px;
|
line-height: 14px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.listtablebody{
|
.listtablebody{
|
||||||
border-radius:0px 0px 4px 4px ;
|
|
||||||
border: 1px solid #D0D0D0;
|
|
||||||
border-top: none;
|
|
||||||
li.listtablepath{
|
li.listtablepath{
|
||||||
a{color: #40a9ff;}
|
a{color: #40a9ff;}
|
||||||
p{
|
p{
|
||||||
|
@ -339,15 +260,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
& > li{
|
& > li{
|
||||||
height: 38px;
|
height: 42px;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
border-bottom: 1px solid #d9d9d9;
|
border-bottom: 1px solid #d9d9d9;
|
||||||
padding:0px 20px 0px 24px;
|
padding:0px 20px 0px 24px;
|
||||||
&:hover{
|
|
||||||
background-color: #F3F4F6;
|
|
||||||
}
|
|
||||||
& > span:first-child{
|
& > span:first-child{
|
||||||
width: 30%;
|
width: 30%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@ -374,10 +292,8 @@
|
||||||
.drawerBtn{
|
.drawerBtn{
|
||||||
position: fixed;
|
position: fixed;
|
||||||
left: -13px;
|
left: -13px;
|
||||||
width: 33px;
|
border:1px solid rgb(207,205,223);
|
||||||
background: #FFFFFF;
|
width: 34px;
|
||||||
box-shadow: 0px 0px 8px 3px rgba(0, 0, 0, 0.09);
|
|
||||||
border: 1px solid #666666;
|
|
||||||
border-radius: 0px 12px 12px 0px;
|
border-radius: 0px 12px 12px 0px;
|
||||||
height: 70px;
|
height: 70px;
|
||||||
top:50%;
|
top:50%;
|
||||||
|
@ -385,49 +301,36 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: flex-end;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding-left: 7px;
|
|
||||||
&:hover{
|
&:hover{
|
||||||
box-shadow: 0px 0px 8px 3px rgba(0, 0, 0, 0.09);
|
box-shadow: 1px 0px 7px rgba(0,0,0,0.1);
|
||||||
}
|
}
|
||||||
span{
|
span{
|
||||||
writing-mode: vertical-lr;
|
writing-mode: vertical-lr;
|
||||||
color: #333;
|
color: #202429;
|
||||||
width: 25px;
|
width: 25px;
|
||||||
font-size: 14px;
|
|
||||||
}
|
}
|
||||||
i{
|
i{
|
||||||
color: #333;
|
color: #24292e;
|
||||||
height: 14px;
|
height: 18px;
|
||||||
line-height: 14px;
|
line-height: 18px;
|
||||||
width: 14px;
|
width: 18px;
|
||||||
margin-left: 2px;
|
|
||||||
margin-bottom: 3px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.downMenu{
|
.downMenu{
|
||||||
width: 329px;
|
width: 330px;
|
||||||
|
box-shadow: 0px 0px 9px rgba(134, 134, 134,0.4);
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
box-shadow: 0px 1px 8px 1px rgba(212, 212, 212, 0.5);
|
.ant-menu-vertical .ant-menu-item:hover{
|
||||||
padding-bottom: 14px;
|
background-color: #e6f7ff;
|
||||||
.ant-menu-item{
|
|
||||||
height: 50px;
|
|
||||||
line-height: 50px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.fileMenu{
|
|
||||||
width: 83px;
|
|
||||||
li{
|
|
||||||
padding:6px 0px!important;
|
|
||||||
text-align: center;
|
|
||||||
width: 100%;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.catelogue{
|
.menuslist{
|
||||||
cursor: pointer;
|
max-height: 200px;
|
||||||
background: #FAFBFC;
|
overflow-y: auto;
|
||||||
|
padding:10px 15px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
.ant-dropdown-menu-item{
|
.ant-dropdown-menu-item{
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
|
@ -439,19 +342,22 @@
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
border: 1px solid #D0D0D0;
|
.ant-dropdown-menu-item.active{
|
||||||
|
background-color: #e6f7ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.catelogue{
|
||||||
|
border:1px solid rgb(211, 211, 211);
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
margin-right: 12px;
|
border-radius: 5px;
|
||||||
|
margin-right: 10px;
|
||||||
padding:0px 10px;
|
padding:0px 10px;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
line-height: 30px;
|
line-height: 30px;
|
||||||
color: #666!important;
|
color: #666!important;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
&:hover{
|
|
||||||
background-color: #F3F4F6;
|
|
||||||
}
|
|
||||||
span{
|
span{
|
||||||
margin-top: 1px;
|
margin-top: 1px;
|
||||||
}
|
}
|
||||||
|
@ -465,47 +371,3 @@
|
||||||
color: #05101a;
|
color: #05101a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.pinfos{
|
|
||||||
i,a{color: #666;}
|
|
||||||
&:hover i,&:hover a{
|
|
||||||
color: #2A61FF!important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.graph{
|
|
||||||
flex:1;
|
|
||||||
margin:0px 12px;
|
|
||||||
.ant-typography{
|
|
||||||
white-space: pre-wrap;
|
|
||||||
margin-bottom: 0px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.ant-anchor-wrapper{
|
|
||||||
padding-left: 2px!important;
|
|
||||||
.ant-anchor-ink::before{
|
|
||||||
background-color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.coderSubPage{
|
|
||||||
width: 1200px;
|
|
||||||
margin:0px auto;
|
|
||||||
}
|
|
||||||
.griditemAnchor{
|
|
||||||
margin-left: 0px!important;
|
|
||||||
padding: 0px!important;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,7 +5,7 @@ import { AlignCenter } from '../Component/layout';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import '../css/index.scss';
|
import '../css/index.scss';
|
||||||
import Nodata from '../Nodata';
|
import Nodata from '../Nodata';
|
||||||
import './list.scss';
|
import './list.css';
|
||||||
import img_parise from '../Images/parise.png';
|
import img_parise from '../Images/parise.png';
|
||||||
|
|
||||||
class IndexItem extends Component {
|
class IndexItem extends Component {
|
||||||
|
@ -41,17 +41,23 @@ class IndexItem extends Component {
|
||||||
{ !item.is_public && <span className="privateTag">私有</span> }
|
{ !item.is_public && <span className="privateTag">私有</span> }
|
||||||
{
|
{
|
||||||
item.forked_from_project_id ?
|
item.forked_from_project_id ?
|
||||||
<Tooltip title="该项目是一个fork仓库" className="ml5">
|
<span className="ml5">
|
||||||
<i className="iconfont icon-fork font-18 color-orange" />
|
<i className="iconfont icon-fork font-18 color-orange" />
|
||||||
</Tooltip>
|
</span>
|
||||||
: ""
|
: ""
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
item.type && item.type === 2 ?
|
item.type && item.type === 2 ?
|
||||||
<Tooltip title="该项目是一个同步镜像仓库" className="ml5">
|
<Tooltip title="该项目是一个镜像" className="ml5">
|
||||||
<i className="iconfont icon-banbenku font-18 color-green" />
|
<i className="iconfont icon-banbenku font-18 color-green" />
|
||||||
</Tooltip>:""
|
</Tooltip>:""
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
item.type && item.type === 1 ?
|
||||||
|
<span className="ml5">
|
||||||
|
<i className="iconfont icon-jingxiang font-18 color-green" />
|
||||||
|
</span>:""
|
||||||
|
}
|
||||||
</AlignCenter>
|
</AlignCenter>
|
||||||
<span className="p-r-tags">
|
<span className="p-r-tags">
|
||||||
{
|
{
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 631 B |
Binary file not shown.
Before Width: | Height: | Size: 590 B |
|
@ -218,92 +218,74 @@
|
||||||
}
|
}
|
||||||
/* -----------详情------------ */
|
/* -----------详情------------ */
|
||||||
.detailHeader-wrapper{
|
.detailHeader-wrapper{
|
||||||
background-color:#FBFCFF;
|
background-color:#FAFBFC;
|
||||||
border-bottom:1px solid #e2e2e2;
|
/* background: url(../Images/forgeBanner.jpg) no-repeat center; */
|
||||||
|
/* background-size:cover; */
|
||||||
}
|
}
|
||||||
.headerMenu-wrapper{
|
.headerMenu-wrapper{
|
||||||
|
font-size: 16px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
cursor: pointer;
|
}
|
||||||
li{
|
.headerMenu-wrapper li{
|
||||||
text-align: center;
|
position: relative;
|
||||||
padding:0px;
|
text-align: center;
|
||||||
margin-right: 40px;
|
height: 40px;
|
||||||
display: flex;
|
line-height: 28px;
|
||||||
& > a{
|
margin-right: 40px;
|
||||||
position: relative;
|
}
|
||||||
font-size: 14px;
|
.headerMenu-wrapper li a{
|
||||||
height: 36px;
|
color: #666;
|
||||||
line-height: 24px;
|
}
|
||||||
display: block;
|
.headerMenu-wrapper li a > img{
|
||||||
color: #000!important;
|
margin-right: 8px;
|
||||||
&> span.num{
|
}
|
||||||
line-height: 24px;
|
.headerMenu-wrapper li a > span.num{
|
||||||
margin-left: 5px;
|
height: 28px;
|
||||||
font-size: 12px;
|
line-height: 29px;
|
||||||
float: right;
|
margin-left: 8px;
|
||||||
color: #666!important;
|
font-size: 12px;
|
||||||
background-color: rgba(153, 153, 153, 0.13);;
|
color: #2878FF;
|
||||||
border-radius: 50%;
|
float: right;
|
||||||
width: 24px;
|
}
|
||||||
height: 24px;
|
.headerMenu-wrapper li.active::after{
|
||||||
}
|
position: absolute;
|
||||||
}
|
bottom:0px;
|
||||||
|
height:2px;
|
||||||
&.active a::after,&:hover a::after{
|
background-color: #5091FF;
|
||||||
position: absolute;
|
content:'';
|
||||||
bottom:0px;
|
left: 0px;
|
||||||
height:2px;
|
width:100%;
|
||||||
background-color:rgba(153, 153, 153, 0.2);
|
|
||||||
content:'';
|
|
||||||
left: 0px;
|
|
||||||
width:100%;
|
|
||||||
}
|
|
||||||
&.active span{
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
&.active a::after{
|
|
||||||
background-color: #466AFF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.detail_tag_btn{
|
.detail_tag_btn{
|
||||||
height:32px;
|
height:26px;
|
||||||
line-height: 32px;
|
line-height: 26px;
|
||||||
border-radius:5px;
|
border-radius:5px;
|
||||||
border:1px solid #D0D0D0;
|
border:1px solid #f1f1f1;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-left: 10px;
|
margin-left: 30px;
|
||||||
padding:0px;
|
padding:0px;
|
||||||
background-color:#FAFBFC;
|
background-color: transparent;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
.detail_tag_btn_name{
|
|
||||||
padding:0px 10px;
|
|
||||||
text-align: center;
|
|
||||||
height: 30px;
|
|
||||||
line-height: 30px;
|
|
||||||
border-radius:5px 0px 0px 5px;
|
|
||||||
&:hover
|
|
||||||
{
|
|
||||||
background-color: #F3F4F6;
|
|
||||||
}
|
|
||||||
span{
|
|
||||||
color: #333!important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.detail_tag_btn_count{
|
|
||||||
width: 42px;
|
|
||||||
text-align: center;
|
|
||||||
background: #fff;
|
|
||||||
border-radius: 0px 4px 4px 0px;
|
|
||||||
height:100%;
|
|
||||||
border-left: 1px solid #D0D0D0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.ant-tooltip {
|
.ant-tooltip {
|
||||||
max-width: fit-content!important;
|
max-width: fit-content!important;
|
||||||
}
|
}
|
||||||
|
.detail_tag_btn_name{
|
||||||
|
padding:0px 10px;
|
||||||
|
color: #666!important;
|
||||||
|
}
|
||||||
|
.detail_tag_btn_name img{
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
.detail_tag_btn_count{
|
||||||
|
padding:0px 10px;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 0px 4px 4px 0px;
|
||||||
|
font-size: 12px;
|
||||||
|
height:100%;
|
||||||
|
}
|
||||||
.files-md{
|
.files-md{
|
||||||
padding:20px;
|
padding:20px;
|
||||||
}
|
}
|
||||||
|
@ -354,7 +336,6 @@
|
||||||
|
|
||||||
|
|
||||||
.gitAddressClone{
|
.gitAddressClone{
|
||||||
margin:14px 20px!important;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -426,15 +407,14 @@
|
||||||
border-right: none;
|
border-right: none;
|
||||||
}
|
}
|
||||||
.gitAddressClone > input{
|
.gitAddressClone > input{
|
||||||
|
border:none;
|
||||||
outline: none;
|
outline: none;
|
||||||
padding: 0px 8px;
|
padding:0px 8px;
|
||||||
height: 38px;
|
height: 40px;
|
||||||
line-height: 38px;
|
line-height: 40px;
|
||||||
border: none!important;
|
border-radius: 0px;
|
||||||
border-right: 1px solid #eee!important;
|
border: 1px solid #eee;
|
||||||
border-radius: 4px 0px 0px 4px;
|
flex:1;
|
||||||
flex: 1;
|
|
||||||
max-width: 249px;
|
|
||||||
}
|
}
|
||||||
.wrap-commit-table .ant-table-small > .ant-table-content > .ant-table-body{
|
.wrap-commit-table .ant-table-small > .ant-table-content > .ant-table-body{
|
||||||
margin:0px;
|
margin:0px;
|
||||||
|
@ -519,7 +499,7 @@
|
||||||
}
|
}
|
||||||
.addFile a{
|
.addFile a{
|
||||||
display: block;
|
display: block;
|
||||||
background-color: rgba(76, 172, 255,0.8);
|
background-color: rgb(76, 172, 255,0.8);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
|
@ -534,7 +514,7 @@
|
||||||
border-left: 1px solid rgba(247, 247, 247, 0.3);
|
border-left: 1px solid rgba(247, 247, 247, 0.3);
|
||||||
}
|
}
|
||||||
.addFile a:active{
|
.addFile a:active{
|
||||||
background-color: rgba(76, 172, 255,1);
|
background-color: rgb(76, 172, 255,1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -573,11 +553,8 @@
|
||||||
}
|
}
|
||||||
.commonBox{
|
.commonBox{
|
||||||
border:1px solid #ddd;
|
border:1px solid #ddd;
|
||||||
margin-top: 18px;
|
margin-top: 30px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
.ant-anchor-wrapper{
|
|
||||||
overflow: unset!important;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.commonBox .commonBox-title{
|
.commonBox .commonBox-title{
|
||||||
padding:0px 20px;
|
padding:0px 20px;
|
||||||
|
@ -590,28 +567,14 @@
|
||||||
border-bottom: 1px solid #d9d9d9;
|
border-bottom: 1px solid #d9d9d9;
|
||||||
border-radius: 4px 4px 0px 0px;
|
border-radius: 4px 4px 0px 0px;
|
||||||
}
|
}
|
||||||
.readBox{
|
|
||||||
border:none;
|
|
||||||
&.commonBox .commonBox-info{
|
|
||||||
border:1px solid #D0D0D0;
|
|
||||||
border-top: none;
|
|
||||||
border-radius: 0px 0px 4px 4px;
|
|
||||||
padding:20px 38px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.commonBox .commonBox-title.boxTitle{
|
.commonBox .commonBox-title.boxTitle{
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
height: 55px;
|
|
||||||
line-height: 55px;
|
|
||||||
background: #FAFCFF;
|
|
||||||
border-radius: 4px 4px 0px 0px;
|
|
||||||
border: 1px solid rgba(42, 97, 255, 0.23);
|
|
||||||
}
|
}
|
||||||
.synchronism{
|
.synchronism{
|
||||||
display: block;
|
display: block;
|
||||||
height: 34px;
|
height: 26px;
|
||||||
line-height: 34px;
|
line-height: 26px;
|
||||||
padding:0px 15px;
|
padding:0px 15px;
|
||||||
color: #fff!important;
|
color: #fff!important;
|
||||||
background-color: #28BD6C;
|
background-color: #28BD6C;
|
||||||
|
@ -620,19 +583,10 @@
|
||||||
.files_info{
|
.files_info{
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.commonBox {
|
.commonBox .commonBox-info{
|
||||||
.commonBox-info{
|
padding:20px 15px;
|
||||||
padding:20px 15px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.commonBox-title-read{
|
|
||||||
vertical-align: middle;
|
|
||||||
color: #000;
|
|
||||||
font-size: 14px;
|
|
||||||
&:hover {
|
|
||||||
color: #466AFF;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
.commonBox-title-read{vertical-align: middle;color: #666;}
|
||||||
|
|
||||||
@media screen and (max-width: 370px){
|
@media screen and (max-width: 370px){
|
||||||
.p-r-tags,.p-r-btn{
|
.p-r-tags,.p-r-btn{
|
||||||
|
@ -673,7 +627,9 @@
|
||||||
.item:last-child{
|
.item:last-child{
|
||||||
border-bottom:none;
|
border-bottom:none;
|
||||||
}
|
}
|
||||||
|
.gitAddressClone{
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
.item_title small{
|
.item_title small{
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
|
@ -722,84 +678,12 @@ a.color-grey-ccc:hover{
|
||||||
padding:0px 30px;
|
padding:0px 30px;
|
||||||
min-height: 400px;
|
min-height: 400px;
|
||||||
}
|
}
|
||||||
|
.commitList > div{
|
||||||
.main{
|
border-bottom: 1px solid #EEEEEE;
|
||||||
margin: 30px auto;
|
padding:16px 0px;
|
||||||
.ant-timeline{
|
}
|
||||||
margin-top: 28px;
|
.commitList > div:last-child{
|
||||||
.commitList-item{
|
border-bottom: none;
|
||||||
position: relative;
|
|
||||||
padding: 20px 20px;
|
|
||||||
background: #FAFCFF;
|
|
||||||
border: 1px solid rgba(42, 97, 255, 0.23);
|
|
||||||
border-radius: 4px;
|
|
||||||
margin-left: 16px;
|
|
||||||
& .treecopy{
|
|
||||||
margin-top: 20px;
|
|
||||||
}
|
|
||||||
& .markdown-body table{
|
|
||||||
background: #FAFCFF;
|
|
||||||
}
|
|
||||||
&: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);
|
|
||||||
}
|
|
||||||
& .markdown-body table{
|
|
||||||
background: #EEF6FF;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -849,12 +733,3 @@ a.color-grey-ccc:hover{
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
.depotNum{
|
|
||||||
color: #666!important;
|
|
||||||
span:last-child{
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
&:hover span:last-child{
|
|
||||||
color: #2A61FF;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +1,6 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { Skeleton , Tooltip} from 'antd';
|
import { Skeleton , Tooltip} from 'antd';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { numFormat } from 'educoder';
|
|
||||||
|
|
||||||
function DetailBanner({ history,list , owner , projectsId , isManager , url , pathname , state , urlFlag , projectDetail , platform ,open_devops }){
|
function DetailBanner({ history,list , owner , projectsId , isManager , url , pathname , state , urlFlag , projectDetail , platform ,open_devops }){
|
||||||
const [ menuName , setMenuName ] = useState(undefined);
|
const [ menuName , setMenuName ] = useState(undefined);
|
||||||
|
@ -18,7 +17,7 @@ function DetailBanner({ history,list , owner , projectsId , isManager , url , pa
|
||||||
}
|
}
|
||||||
},[list]);
|
},[list]);
|
||||||
return(
|
return(
|
||||||
<div className="f-wrap-between mt25">
|
<div className="f-wrap-between mt15">
|
||||||
{
|
{
|
||||||
menuName && projectDetail ?
|
menuName && projectDetail ?
|
||||||
<ul className="headerMenu-wrapper">
|
<ul className="headerMenu-wrapper">
|
||||||
|
@ -30,39 +29,39 @@ function DetailBanner({ history,list , owner , projectsId , isManager , url , pa
|
||||||
item.menu_name === "home" &&
|
item.menu_name === "home" &&
|
||||||
<li className={pathname==="about" ? "active" : ""}>
|
<li className={pathname==="about" ? "active" : ""}>
|
||||||
<Link to={{ pathname: `/${owner}/${projectsId}/about`, state }}>
|
<Link to={{ pathname: `/${owner}/${projectsId}/about`, state }}>
|
||||||
<i className={"iconfont icon-zhuye-fill color-grey-3 mr5 font-14"}></i>
|
<i className={(pathname==="" || urlFlag) ? "iconfont icon-zhuye1 color-grey-3 mr5 font-14":"iconfont icon-zhuye1 color-grey-6 font-14 mr5"}></i>
|
||||||
<span>主页</span>
|
<span>主页</span>
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
item.menu_name === "code" &&
|
item.menu_name === "code" &&
|
||||||
<li className={(pathname==="" || urlFlag) ? "active" : ""}>
|
<li className={(pathname==="" || urlFlag) ? "active" : ""}>
|
||||||
<Link to={{ pathname: `/${owner}/${projectsId}`, state }}>
|
<Link to={{ pathname: `/${owner}/${projectsId}`, state }}>
|
||||||
<i className={"iconfont icon-daimakuicon1 color-grey-3 mr5 font-14"}></i>
|
<i className={(pathname==="" || urlFlag) ? "iconfont icon-daimaku color-grey-3 mr5 font-14":"iconfont icon-daimaku color-grey-6 font-14 mr5"}></i>
|
||||||
<span>代码库</span>
|
<span>代码库</span>
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
item.menu_name === "issues" &&
|
item.menu_name === "issues" &&
|
||||||
<li className={pathname==="issues" ? "active" : ""}>
|
<li className={pathname==="issues" ? "active" : ""}>
|
||||||
|
<Tooltip title="易修是Issue的中文名,即问题列表" placement="bottom">
|
||||||
<Link to={{ pathname: `/${owner}/${projectsId}/issues`, state }}>
|
<Link to={{ pathname: `/${owner}/${projectsId}/issues`, state }}>
|
||||||
<Tooltip title="易修是Issue的中文名,即问题列表" placement="bottom">
|
<i className={pathname==="issues" ? "iconfont icon-renwu color-grey-3 mr5 font-14":"iconfont icon-renwu color-grey-6 font-14 mr5"}></i>
|
||||||
<i className={"iconfont icon-yixiuicon1 color-grey-3 mr5 font-14"}></i>
|
<span>易修</span>
|
||||||
<span>易修(Issue)</span>
|
{projectDetail && projectDetail.issues_count ? <span className="num">{projectDetail.issues_count}</span> : ""}
|
||||||
</Tooltip>
|
|
||||||
{projectDetail && projectDetail.issues_count ? <span className="num">{numFormat(projectDetail.issues_count)}</span> : ""}
|
|
||||||
</Link>
|
</Link>
|
||||||
|
</Tooltip>
|
||||||
</li>
|
</li>
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
item.menu_name === "pulls" && projectDetail && parseInt(projectDetail.type) !== 2 && platform ?
|
item.menu_name === "pulls" && projectDetail && parseInt(projectDetail.type) !== 2 && platform ?
|
||||||
<li className={pathname==="pulls" ? "active" : ""}>
|
<li className={pathname==="pulls" ? "active" : ""}>
|
||||||
<Link to={{ pathname: `/${owner}/${projectsId}/pulls`, state }}>
|
<Link to={{ pathname: `/${owner}/${projectsId}/pulls`, state }}>
|
||||||
<i className={"iconfont icon-hebingqingqiu1 color-grey-3 mr5 font-14"}></i>
|
<i className={pathname==="pulls" ? "iconfont icon-hebingqingqiu1 color-grey-3 mr5 font-14":"iconfont icon-hebingqingqiu1 color-grey-6 font-14 mr5"}></i>
|
||||||
<span>合并请求</span>
|
<span>合并请求</span>
|
||||||
{projectDetail && projectDetail.pull_requests_count ? <span className="num">{numFormat(projectDetail.pull_requests_count)}</span> : ""}
|
{projectDetail && projectDetail.pull_requests_count ? <span className="num">{projectDetail.pull_requests_count}</span> : ""}
|
||||||
</Link>
|
</Link>
|
||||||
</li>:""
|
</li>:""
|
||||||
}
|
}
|
||||||
|
@ -70,7 +69,7 @@ function DetailBanner({ history,list , owner , projectsId , isManager , url , pa
|
||||||
item.menu_name === "wiki" &&
|
item.menu_name === "wiki" &&
|
||||||
<li className={pathname === "wiki" ? "active" : ""}>
|
<li className={pathname === "wiki" ? "active" : ""}>
|
||||||
<Link to={{ pathname: `/${owner}/${projectsId}/wiki`, state }}>
|
<Link to={{ pathname: `/${owner}/${projectsId}/wiki`, state }}>
|
||||||
<i className={"iconfont icon-a-wikiicon1 color-grey-3 mr5 font-14"}></i>
|
<i className={pathname==="wiki" ? "iconfont icon-wiki_icon color-grey-3 mr5 font-14":"iconfont icon-wiki_icon color-grey-6 font-14 mr5"}></i>
|
||||||
<span>Wiki</span>
|
<span>Wiki</span>
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
|
@ -80,29 +79,29 @@ function DetailBanner({ history,list , owner , projectsId , isManager , url , pa
|
||||||
<li className={pathname==="devops" ? "active" : ""}>
|
<li className={pathname==="devops" ? "active" : ""}>
|
||||||
{/* <Link to={{ pathname: `/${owner}/${projectsId}/devops${open_devops ? `/dispose`:""}`, state }}> */}
|
{/* <Link to={{ pathname: `/${owner}/${projectsId}/devops${open_devops ? `/dispose`:""}`, state }}> */}
|
||||||
<Link to={{ pathname: `/${owner}/${projectsId}/devops`, state:{...state,open_devops} }}>
|
<Link to={{ pathname: `/${owner}/${projectsId}/devops`, state:{...state,open_devops} }}>
|
||||||
<i className="iconfont icon-gongzuoliuicon font-13 mr5 color-grey-3"></i>工作流(beta版)
|
<i className="iconfont icon-gongzuoliu font-13 mr8"></i>工作流(beta版)
|
||||||
{projectDetail && projectDetail.ops_count ? <span>{projectDetail.ops_count}</span> : ""}
|
{projectDetail && projectDetail.ops_count ? <span>{projectDetail.ops_count}</span> : ""}
|
||||||
</Link>
|
</Link>
|
||||||
</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 }}>
|
||||||
<i className={pathname==="source" ? "iconfont icon-ziyuanpaihanghetuijian color-grey-3 mr5 font-14":"iconfont icon-ziyuanpaihanghetuijian color-grey-6 font-14 mr5"}></i>
|
// <i className={pathname==="source" ? "iconfont icon-ziyuanpaihanghetuijian color-grey-3 mr5 font-14":"iconfont icon-ziyuanpaihanghetuijian color-grey-6 font-14 mr5"}></i>
|
||||||
<span>资源库</span>
|
// <span>资源库</span>
|
||||||
{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" : ""}>
|
||||||
<Link to={{ pathname: `/${owner}/${projectsId}/milestones`, state }}>
|
<Link to={{ pathname: `/${owner}/${projectsId}/milestones`, state }}>
|
||||||
<i className={pathname==="milestones" ? "iconfont icon-lichengbeiicon color-grey-3 mr5 font-14":"iconfont icon-lichengbeiicon color-grey-6 font-14 mr5"}></i>
|
<i className={pathname==="milestones" ? "iconfont icon-lichengbei color-grey-3 mr5 font-14":"iconfont icon-lichengbei color-grey-6 font-14 mr5"}></i>
|
||||||
<span>里程碑</span>
|
<span>里程碑</span>
|
||||||
{projectDetail && projectDetail.versions_count ? <span className="num">{numFormat(projectDetail.versions_count)}</span> :""}
|
{projectDetail && projectDetail.versions_count ? <span className="num">{projectDetail.versions_count}</span> :""}
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
}
|
}
|
||||||
|
@ -110,7 +109,7 @@ function DetailBanner({ history,list , owner , projectsId , isManager , url , pa
|
||||||
item.menu_name === "activity" &&
|
item.menu_name === "activity" &&
|
||||||
<li className={pathname==="activity" ? "active" : ""}>
|
<li className={pathname==="activity" ? "active" : ""}>
|
||||||
<Link to={{ pathname: `/${owner}/${projectsId}/activity`, state }}>
|
<Link to={{ pathname: `/${owner}/${projectsId}/activity`, state }}>
|
||||||
<i className={pathname==="activity" ? "iconfont icon-dongtaiicon color-grey-3 mr5 font-14":"iconfont icon-dongtaiicon color-grey-6 font-14 mr5"}></i>
|
<i className={pathname==="activity" ? "iconfont icon-tongzhi color-grey-3 mr5 font-14":"iconfont icon-tongzhi color-grey-6 font-14 mr5"}></i>
|
||||||
<span>动态</span>
|
<span>动态</span>
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
|
@ -119,7 +118,7 @@ function DetailBanner({ history,list , owner , projectsId , isManager , url , pa
|
||||||
item.menu_name === "settings" &&
|
item.menu_name === "settings" &&
|
||||||
<li className={pathname === "settings" ? "active" : ""}>
|
<li className={pathname === "settings" ? "active" : ""}>
|
||||||
<Link to={`/${owner}/${projectsId}/settings`}>
|
<Link to={`/${owner}/${projectsId}/settings`}>
|
||||||
<i className={url && url.indexOf("/settings") > 0 ? "iconfont icon-cangkushezhiicon color-grey-3 mr5 font-14":"iconfont icon-cangkushezhiicon color-grey-6 font-14 mr5"}></i>
|
<i className={url && url.indexOf("/settings") > 0 ? "iconfont icon-cangku color-grey-3 mr5 font-14":"iconfont icon-cangku color-grey-6 font-14 mr5"}></i>
|
||||||
<span>仓库设置</span>
|
<span>仓库设置</span>
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -6,7 +6,7 @@ function Invite({code,className}) {
|
||||||
|
|
||||||
return(
|
return(
|
||||||
<div className={className}>
|
<div className={className}>
|
||||||
<span className="font-16 color-ooo">邀请码</span>
|
<span className="font-16 color-grey-6">邀请码</span>
|
||||||
<div>
|
<div>
|
||||||
<input value={code} id="devitecode" style={{width:"62px",border:"none",cursor:"default"}} readOnly/>
|
<input value={code} id="devitecode" style={{width:"62px",border:"none",cursor:"default"}} readOnly/>
|
||||||
<CopyTool timeOut={true} beforeText={<p className="edu-txt-center">可以通过邀请码邀请成员加入项目<br/>点击复制邀请码。</p>} className="ml8 font-16" inputId="devitecode"/>
|
<CopyTool timeOut={true} beforeText={<p className="edu-txt-center">可以通过邀请码邀请成员加入项目<br/>点击复制邀请码。</p>} className="ml8 font-16" inputId="devitecode"/>
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
import React , { useState } from 'react';
|
|
||||||
import { Anchor , Input } from 'antd';
|
|
||||||
import './sub.scss';
|
|
||||||
import { useEffect } from 'react';
|
|
||||||
|
|
||||||
const { Link } = Anchor;
|
|
||||||
|
|
||||||
function ReadmeCatelogue({ menuList , hash }) {
|
|
||||||
const [ goHref , setGoHref ] = useState("");
|
|
||||||
const [ value , setValue ] = useState("");
|
|
||||||
const [ menu , setMenu] = useState(menuList);
|
|
||||||
|
|
||||||
|
|
||||||
function onChange(link){
|
|
||||||
setGoHref(link);
|
|
||||||
};
|
|
||||||
|
|
||||||
function changeValue(e) {
|
|
||||||
setValue(e.target.value);
|
|
||||||
if(e.target.value){
|
|
||||||
let m = menuList.filter(i=>i.text.toLowerCase().indexOf(e.target.value.toLowerCase())>-1);
|
|
||||||
setMenu(m);
|
|
||||||
}else{
|
|
||||||
setMenu(menuList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return(
|
|
||||||
<div>
|
|
||||||
<div className="searchBox">
|
|
||||||
<Input
|
|
||||||
placeholder={"请输入关键字"}
|
|
||||||
value={value}
|
|
||||||
onChange={changeValue}
|
|
||||||
prefix={<i className="iconfont icon-sousuo_icon1 font-14"></i>}/>
|
|
||||||
</div>
|
|
||||||
{
|
|
||||||
menu && menu.length>0?
|
|
||||||
<div className="anchorBox">
|
|
||||||
<Anchor affix={false} onChange={onChange}>
|
|
||||||
{
|
|
||||||
menu.map((item,key)=>{
|
|
||||||
return(
|
|
||||||
<div style={{paddingLeft:`${item.level *10}px`}} className={goHref===item.href?"items active":"items"}>
|
|
||||||
<Link href={`#${item.text}`} title={item.text} />
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</Anchor>
|
|
||||||
</div>
|
|
||||||
:""
|
|
||||||
}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export default ReadmeCatelogue;
|
|
|
@ -1,13 +0,0 @@
|
||||||
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;
|
|
|
@ -53,7 +53,7 @@ function UpdateDescModal({form , visible , onCancel , onOk,desc,website,lesson_u
|
||||||
{getFieldDecorator("lesson_url",{
|
{getFieldDecorator("lesson_url",{
|
||||||
rules:[]
|
rules:[]
|
||||||
})(
|
})(
|
||||||
<Input placeholder="实践课程链接" />
|
<Input placeholder="实践课程链接"/>
|
||||||
)}
|
)}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
|
@ -24,68 +24,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.menuslist{
|
.detailsCode{
|
||||||
z-index: 100;
|
|
||||||
width: 297px;
|
|
||||||
background: #FFFFFF;
|
|
||||||
box-shadow: 0px 4px 8px 2px rgba(212, 212, 212, 0.5);
|
|
||||||
border-radius: 4px;
|
|
||||||
.searchBox{
|
|
||||||
padding:15px;
|
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
}
|
|
||||||
.ant-anchor-wrapper{
|
|
||||||
margin-left: 0px;
|
|
||||||
padding:5px 15px;
|
|
||||||
max-height: 255px!important;
|
|
||||||
.items{
|
|
||||||
border-radius: 4px;
|
|
||||||
margin-bottom: 5px;
|
|
||||||
cursor: pointer;
|
|
||||||
.ant-anchor-link-title{
|
|
||||||
color: #333333!important;
|
|
||||||
}
|
|
||||||
&:hover{
|
|
||||||
background-color: #F3F4F6;
|
|
||||||
}
|
|
||||||
&.active{
|
|
||||||
background-color: #2A61FF;
|
|
||||||
.ant-anchor-link-title{
|
|
||||||
color: #fff!important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.ant-anchor-link{
|
|
||||||
padding:0px;
|
|
||||||
height: 30px;
|
|
||||||
line-height: 30px;
|
|
||||||
}
|
|
||||||
.ant-anchor-ink::before{
|
|
||||||
background-color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.subMenu{
|
|
||||||
display: flex;
|
display: flex;
|
||||||
padding-top: 30px;
|
justify-content: space-between;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,138 +0,0 @@
|
||||||
import React,{ useEffect , useState } from 'react';
|
|
||||||
import SubMenu from '../sub/SubMenu';
|
|
||||||
import { Table , Tooltip , Spin } from 'antd';
|
|
||||||
import axios from 'axios';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import { truncateCommitId } from '../../common/util';
|
|
||||||
import { getImageUrl } from 'educoder';
|
|
||||||
import Nonedata from '../../Nodata';
|
|
||||||
import './Index.scss';
|
|
||||||
import Tree from '../img/tree.png'
|
|
||||||
import moment from 'moment';
|
|
||||||
|
|
||||||
function Tags(props) {
|
|
||||||
|
|
||||||
const [ source , setSource ] = useState(undefined);
|
|
||||||
const [ isSpin , setIsSpin ] = useState(true);
|
|
||||||
|
|
||||||
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);
|
|
||||||
setIsSpin(false);
|
|
||||||
}
|
|
||||||
}).catch(error => {})
|
|
||||||
}
|
|
||||||
}, [owner, projectsId]);
|
|
||||||
|
|
||||||
const columns=[
|
|
||||||
{
|
|
||||||
title:"标签名",
|
|
||||||
dataIndex:"name",
|
|
||||||
key:1,
|
|
||||||
ellipsis:true,
|
|
||||||
width:"200px",
|
|
||||||
render:(txt,item)=>{
|
|
||||||
return(
|
|
||||||
<div className="tagBranch">
|
|
||||||
<Link className="hover tagClass" to={`/${owner}/${projectsId}/tree/${item.name}`}>{item.name}</Link>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title:"创建时间",
|
|
||||||
dataIndex:"time_ago",
|
|
||||||
key:2,
|
|
||||||
ellipsis:true,
|
|
||||||
render:(txt,item)=>{
|
|
||||||
return (
|
|
||||||
<span className="color-grey-3 tagModel">
|
|
||||||
{
|
|
||||||
item.tagger &&
|
|
||||||
<Tooltip placement="top" title={item.tagger.name}>
|
|
||||||
{
|
|
||||||
item.tagger.id ?
|
|
||||||
<Link className="mr3 tagModelImg" to={`/${item.tagger.login}`} >
|
|
||||||
<img src={getImageUrl(`/${item.tagger && item.tagger.image_url}`)} alt=""/>
|
|
||||||
</Link>
|
|
||||||
:
|
|
||||||
<span className="mr3 tagModelImg" style={{cursor:"default"}}>
|
|
||||||
<img src={getImageUrl(`/${item.tagger && item.tagger.image_url}`)} alt=""/>
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
</Tooltip>
|
|
||||||
}
|
|
||||||
<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:"204px",
|
|
||||||
render:(txt,item)=>{
|
|
||||||
return (
|
|
||||||
<React.Fragment>
|
|
||||||
<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>
|
|
||||||
</React.Fragment>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
return(
|
|
||||||
<div>
|
|
||||||
<SubMenu tab={"tags"} projectsId={projectsId} owner={owner}/>
|
|
||||||
<Spin spinning={isSpin}>
|
|
||||||
<div className="tagSpin">
|
|
||||||
{
|
|
||||||
source && source.length > 0 &&
|
|
||||||
<Table
|
|
||||||
className="tagTable"
|
|
||||||
dataSource={source} columns={columns} pagination={false}></Table>
|
|
||||||
}
|
|
||||||
{
|
|
||||||
source && source.length === 0 && <Nonedata _html={'暂无数据~'}/>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</Spin>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export default Tags;
|
|
|
@ -1,58 +0,0 @@
|
||||||
.tagTable{
|
|
||||||
margin-top: 30px;
|
|
||||||
thead{
|
|
||||||
tr th{
|
|
||||||
background-color: #fff;
|
|
||||||
padding:5px 0px;
|
|
||||||
width: 172px;
|
|
||||||
.ant-table-column-title{
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: 500;
|
|
||||||
color: #333333;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tbody{
|
|
||||||
.btn-83{
|
|
||||||
margin:0px 8px;
|
|
||||||
}
|
|
||||||
tr{
|
|
||||||
&:hover td{
|
|
||||||
background-color: #fff!important;
|
|
||||||
}
|
|
||||||
td{
|
|
||||||
padding:0px;
|
|
||||||
height: 69px;
|
|
||||||
line-height: 69px;
|
|
||||||
color:#333333;
|
|
||||||
div{
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&:last-child{
|
|
||||||
td{
|
|
||||||
border-bottom: none!important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.tagSpin{
|
|
||||||
min-height: 300px;
|
|
||||||
}
|
|
||||||
.tagBranch{
|
|
||||||
padding-right: 15px;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
.tagClass{
|
|
||||||
color:#333333;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.tagModel{
|
|
||||||
font-weight: 400;
|
|
||||||
.tagModelImg img{
|
|
||||||
width: 25px;
|
|
||||||
height: 25px;
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,114 +0,0 @@
|
||||||
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}/compare/master...${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;
|
|
|
@ -1,101 +0,0 @@
|
||||||
.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{
|
|
||||||
width: 399px;
|
|
||||||
flex:1;
|
|
||||||
flex-direction: column;
|
|
||||||
&>a{
|
|
||||||
display: block;
|
|
||||||
width: 399px;
|
|
||||||
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
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;
|
|
|
@ -1,41 +0,0 @@
|
||||||
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;
|
|
|
@ -1,266 +0,0 @@
|
||||||
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>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
|
@ -1,150 +0,0 @@
|
||||||
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 { location } = props;
|
|
||||||
const type = props.projectDetail && props.projectDetail.type;
|
|
||||||
const turnFromNew = location && location.query && location.query.turnFromNew;
|
|
||||||
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}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
} else{
|
|
||||||
return (<div></div>)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
|
@ -1,357 +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: 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,448 +0,0 @@
|
||||||
import React, { Component } from 'react';
|
|
||||||
import { Input, Select, Spin, Alert } from 'antd';
|
|
||||||
import axios from 'axios';
|
|
||||||
import MergeForm from './merge_form';
|
|
||||||
import MergeFooter from './merge_footer';
|
|
||||||
|
|
||||||
import '../Order/order.css';
|
|
||||||
import './merge.css';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据url获取目标仓库、目标分支、源仓库、源分支
|
|
||||||
* 路由规则:owner/projectId/compare/merge...pullowner:pullBranch
|
|
||||||
* 可能存在的情况
|
|
||||||
* 1、代码库首页跳转,仓库相同,目标分支为默认分支,owner/projectId/compare/pullBranch
|
|
||||||
* 2、代码库分支列表,仓库相同,目标分支为默认分支,owner/projectId/compare/pullBranch
|
|
||||||
* 3、合并请求列表页(新建、无数据时的提示),仓库相同,源、目标都为默认分支,owner/projectId/compare
|
|
||||||
* 4、新建页面,切换分支、切换目标仓库、刷新页面等,存在所有可能情况
|
|
||||||
*/
|
|
||||||
function getBranchParams(pathname) {
|
|
||||||
const result = {
|
|
||||||
// 目标仓库所有者
|
|
||||||
mergeOwner: undefined,
|
|
||||||
// 目标分支
|
|
||||||
mergeBranch: 'master',
|
|
||||||
// 源仓库所有者
|
|
||||||
pullOwner: undefined,
|
|
||||||
// 源分支
|
|
||||||
pullBranch: 'master',
|
|
||||||
// 仓库名称
|
|
||||||
projectId: undefined,
|
|
||||||
};
|
|
||||||
// 去掉第一个字符/
|
|
||||||
const _pathname = pathname.slice(1);
|
|
||||||
const [ownerProject, branchUrl] = _pathname.split('/compare');
|
|
||||||
const [mergeOwner, projectId] = ownerProject.split('/');
|
|
||||||
// 同仓库时
|
|
||||||
result.mergeOwner = mergeOwner;
|
|
||||||
result.pullOwner = mergeOwner;
|
|
||||||
result.projectId = projectId;
|
|
||||||
if (branchUrl) {
|
|
||||||
// 如果存在具体的分支
|
|
||||||
const _branchUrl = branchUrl.slice(1);
|
|
||||||
if (_branchUrl.indexOf('...') > -1) {
|
|
||||||
// 存在源分支与目标分支
|
|
||||||
const [mergeBranch, pullObj] = _branchUrl.split('...');
|
|
||||||
result.mergeBranch = mergeBranch;
|
|
||||||
if (pullObj.indexOf(':') > -1) {
|
|
||||||
// 存在源仓库
|
|
||||||
const [pullOwner, pullBranch] = pullObj.split(':');
|
|
||||||
result.pullOwner = pullOwner;
|
|
||||||
result.pullBranch = pullBranch;
|
|
||||||
} else {
|
|
||||||
result.pullBranch = pullObj;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
result.pullBranch = _branchUrl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Option = Select.Option;
|
|
||||||
|
|
||||||
class CreateMerge extends Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
const { pullBranch, mergeBranch } = getBranchParams(
|
|
||||||
this.props.location.pathname
|
|
||||||
);
|
|
||||||
this.state = {
|
|
||||||
data: undefined,
|
|
||||||
pullBranches: undefined,
|
|
||||||
mergeBranches: undefined,
|
|
||||||
mergeProjects: undefined,
|
|
||||||
merge: mergeBranch || 'master',
|
|
||||||
pull: pullBranch || 'master',
|
|
||||||
id: undefined,
|
|
||||||
// isFork: false,
|
|
||||||
projects_names: undefined,
|
|
||||||
isSpin: true,
|
|
||||||
showMessage: false,
|
|
||||||
merge_head: false, // 是否向fork后的源项目发起合并请求
|
|
||||||
defaultMessage: '必须选择不同的分支',
|
|
||||||
project_id: undefined, // 当前项目的id,也即开始发送合并请求的源项目id
|
|
||||||
merge_project_user: undefined,
|
|
||||||
comparesData: undefined, //提交和文件的内容,保存compare接口返回的数据
|
|
||||||
// 比较分支时的加载效果
|
|
||||||
isCompareSpin: true,
|
|
||||||
// 是否是初次加载,用这个字段来控制提示组件和文件组件的显示、隐藏比直接用isCompareSpin交互友好些
|
|
||||||
isFirstLoading: true,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount = () => {
|
|
||||||
// 初始化时根据url获取目标仓库、分支,源仓库、分支;
|
|
||||||
// 再获取对应的仓库列表、分支列表
|
|
||||||
// 再调用比较接口
|
|
||||||
const branchParams = getBranchParams(this.props.location.pathname);
|
|
||||||
this.getMergeInfo(branchParams);
|
|
||||||
};
|
|
||||||
|
|
||||||
componentDidUpdate = (preProps) => {
|
|
||||||
// url变化触发时(切换源分支、切换目标仓库、切换目标分支;回退)
|
|
||||||
const oldPathname = preProps.location.pathname;
|
|
||||||
const newPathname = this.props.location.pathname;
|
|
||||||
if (oldPathname !== newPathname) {
|
|
||||||
const branchParams = getBranchParams(newPathname);
|
|
||||||
this.getMergeInfo(branchParams);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
//获取新建合并请求数据
|
|
||||||
getMergeInfo = (branchParams) => {
|
|
||||||
this.setState({ isSpin: true });
|
|
||||||
const { pullOwner, pullBranch, mergeOwner, mergeBranch, projectId } =
|
|
||||||
branchParams;
|
|
||||||
const url = `/${pullOwner}/${projectId}/pulls/new.json`;
|
|
||||||
axios
|
|
||||||
.get(url)
|
|
||||||
.then((result) => {
|
|
||||||
if (result) {
|
|
||||||
// 如果url上的分支不存在,取默认值master
|
|
||||||
const noMergeBranch =
|
|
||||||
(result.data.branches || []).filter(
|
|
||||||
(branch) => branch.name === mergeBranch
|
|
||||||
).length === 0;
|
|
||||||
const noPullBranch =
|
|
||||||
(result.data.branches || []).filter(
|
|
||||||
(branch) => branch.name === pullBranch
|
|
||||||
).length === 0;
|
|
||||||
this.setState({
|
|
||||||
// isFork: result.data.is_fork,
|
|
||||||
projects_names: result.data.projects_names,
|
|
||||||
mergeProjects: result.data.merge_projects,
|
|
||||||
pullBranches: result.data.branches,
|
|
||||||
mergeBranches: result.data.branches,
|
|
||||||
project_id: result.data.project_id,
|
|
||||||
id: result.data.id,
|
|
||||||
merge: mergeBranch,
|
|
||||||
pull: pullBranch,
|
|
||||||
});
|
|
||||||
|
|
||||||
//判断源分支是否存在
|
|
||||||
if(noPullBranch){
|
|
||||||
this.setState({
|
|
||||||
showMessage: true,
|
|
||||||
defaultMessage:'源分支不存在',
|
|
||||||
isCompareSpin: false,
|
|
||||||
});
|
|
||||||
}else{
|
|
||||||
if(pullOwner === mergeOwner){
|
|
||||||
if (!noMergeBranch) {
|
|
||||||
this.compareProject(true, branchParams);
|
|
||||||
} else {
|
|
||||||
this.setState({
|
|
||||||
showMessage: true,
|
|
||||||
defaultMessage:'目标分支不存在',
|
|
||||||
isCompareSpin: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
this.getBranchList(branchParams);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.setState({ isSpin: false });
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
this.setState({ isSpin: false });
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// compare接口,获取分支对比信息
|
|
||||||
compareProject = (sameProject, branchParams) => {
|
|
||||||
// const { project } = this.props;
|
|
||||||
// const { owner, projectsId } = this.props.match.params;
|
|
||||||
const { pullOwner, pullBranch, mergeOwner, mergeBranch, projectId } =
|
|
||||||
branchParams;
|
|
||||||
|
|
||||||
let url = `/${mergeOwner}/${projectId}/compare`;
|
|
||||||
if (sameProject) {
|
|
||||||
url += `/${pullBranch}...${mergeBranch}.json`;
|
|
||||||
} else {
|
|
||||||
url += `/${mergeBranch}...${pullOwner}/${projectId}:${pullBranch}.json`;
|
|
||||||
}
|
|
||||||
this.setState({ isSpin: false, isCompareSpin: true });
|
|
||||||
axios
|
|
||||||
.get(url)
|
|
||||||
.then((result) => {
|
|
||||||
if (result) {
|
|
||||||
if (result.data.status === 0) {
|
|
||||||
this.setState({
|
|
||||||
showMessage: false,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.setState({
|
|
||||||
showMessage: true,
|
|
||||||
defaultMessage: result.data.message,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this.setState({
|
|
||||||
comparesData: result.data,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this.setState({
|
|
||||||
isFirstLoading: false,
|
|
||||||
isSpin: false,
|
|
||||||
isCompareSpin: false,
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
this.setState({ isSpin: false, isCompareSpin: false });
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// 根据所有者、仓库名,获取分支列表,目前仅涉及目标仓库分支查询
|
|
||||||
getBranchList = (branchParams) => {
|
|
||||||
const { mergeOwner, projectId, mergeBranch } = branchParams;
|
|
||||||
this.setState({ isSpin: true });
|
|
||||||
const url = `/${mergeOwner}/${projectId}/pulls/get_branches.json`;
|
|
||||||
axios
|
|
||||||
.get(url)
|
|
||||||
.then((result) => {
|
|
||||||
if (result) {
|
|
||||||
const noMergeBranch =
|
|
||||||
(result.data || []).filter((branch) => branch.name === mergeBranch)
|
|
||||||
.length === 0;
|
|
||||||
this.setState({
|
|
||||||
mergeBranches: result.data,
|
|
||||||
showMessage: noMergeBranch,
|
|
||||||
defaultMessage: '目标分支不存在',
|
|
||||||
isCompareSpin: false,
|
|
||||||
});
|
|
||||||
!noMergeBranch && this.compareProject(false, branchParams);
|
|
||||||
}
|
|
||||||
this.setState({ isSpin: false });
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
this.setState({ isSpin: false });
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// 切换分支事件
|
|
||||||
selectBrach = (type, value) => {
|
|
||||||
const { pullOwner, pullBranch, mergeOwner, mergeBranch, projectId } =
|
|
||||||
getBranchParams(this.props.location.pathname);
|
|
||||||
let _url = `/${mergeOwner}/${projectId}/compare/`;
|
|
||||||
// type为pull时,pullBranch取value,否则取原有值
|
|
||||||
// type为pull时,mergeBranch取原有值,否则取value
|
|
||||||
let _pullBranch = type === 'pull' ? value : pullBranch;
|
|
||||||
let _mergeBranch = type === 'pull' ? mergeBranch : value;
|
|
||||||
if (pullOwner === mergeOwner) {
|
|
||||||
// 如果仓库相同, compare/目标分支...源分支
|
|
||||||
_url += `${_mergeBranch}...${_pullBranch}`;
|
|
||||||
} else {
|
|
||||||
// 如果仓库不同, compare/目标分支...源分支
|
|
||||||
_url += `${_mergeBranch}...${pullOwner}:${_pullBranch}`;
|
|
||||||
}
|
|
||||||
this.props.history.push(_url);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 切换仓库响应事件,目前仅目标分支可切换仓库
|
|
||||||
selectProjectName = (value) => {
|
|
||||||
const { projects_names, id } = this.state;
|
|
||||||
const { pullOwner, pullBranch } = getBranchParams(
|
|
||||||
this.props.location.pathname
|
|
||||||
);
|
|
||||||
let arr =
|
|
||||||
projects_names && projects_names.filter((item) => item.id === value);
|
|
||||||
let identifier = arr && arr[0].project_id;
|
|
||||||
let login = arr && arr[0].project_user_login;
|
|
||||||
// 目标仓库与源仓库不是一个仓库
|
|
||||||
let is_fork = parseInt(value, 10) !== parseInt(id, 10);
|
|
||||||
this.setState({
|
|
||||||
isSpin: true,
|
|
||||||
// merge_head: is_fork,
|
|
||||||
data: {
|
|
||||||
is_original: is_fork,
|
|
||||||
fork_project_id: is_fork ? id : '',
|
|
||||||
merge_user_login: is_fork
|
|
||||||
? projects_names[0].project_user_login
|
|
||||||
: undefined,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (login === pullOwner) {
|
|
||||||
// 如果切换后, 仓库与源仓库一致了
|
|
||||||
this.props.history.push(
|
|
||||||
`/${login}/${identifier}/compare/master...${pullBranch}`
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
this.props.history.push(
|
|
||||||
`/${login}/${identifier}/compare/master...${pullOwner}:${pullBranch}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// this.newMergelist(login, identifier);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 渲染分支列表
|
|
||||||
renderBrances = (list) => {
|
|
||||||
if (list && list.length > 0) {
|
|
||||||
return list.map((item, key) => {
|
|
||||||
return (
|
|
||||||
<Option key={key + 1} value={item.name}>
|
|
||||||
{item.name}
|
|
||||||
</Option>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 渲染项目列表
|
|
||||||
renderProjectNames = (list) => {
|
|
||||||
if (list && list.length > 0) {
|
|
||||||
return list.map((item, key) => {
|
|
||||||
return (
|
|
||||||
<Option key={key + 1} value={item.id}>
|
|
||||||
{item.project_name}
|
|
||||||
</Option>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 渲染html内容
|
|
||||||
withHtml = (html) => {
|
|
||||||
return <div dangerouslySetInnerHTML={{ __html: html }}></div>;
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {
|
|
||||||
data,
|
|
||||||
pullBranches,
|
|
||||||
mergeBranches,
|
|
||||||
mergeProjects,
|
|
||||||
pull,
|
|
||||||
merge,
|
|
||||||
isSpin,
|
|
||||||
isCompareSpin,
|
|
||||||
isFirstLoading,
|
|
||||||
showMessage,
|
|
||||||
defaultMessage,
|
|
||||||
projects_names,
|
|
||||||
id,
|
|
||||||
comparesData,
|
|
||||||
} = this.state;
|
|
||||||
|
|
||||||
let { project } = this.props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Spin spinning={isSpin || isCompareSpin}>
|
|
||||||
<div className="main">
|
|
||||||
<div className="merge-header width100 inline-block">
|
|
||||||
<div className="width40 pull-left">
|
|
||||||
<div className="color-grey-3 mb10 fwb">源分支:</div>
|
|
||||||
<Input.Group compact className="display-flex">
|
|
||||||
<Select
|
|
||||||
value={id}
|
|
||||||
className="hide-1 task-hide flex1"
|
|
||||||
disabled
|
|
||||||
>
|
|
||||||
{this.renderProjectNames(projects_names)}
|
|
||||||
</Select>
|
|
||||||
<Select
|
|
||||||
value={pull}
|
|
||||||
onSelect={(e) => this.selectBrach('pull', e)}
|
|
||||||
showSearch
|
|
||||||
className="merge-flex1 flex1 matchwidth"
|
|
||||||
dropdownMatchSelectWidth={false}
|
|
||||||
dropdownClassName="overlihide"
|
|
||||||
>
|
|
||||||
{this.renderBrances(pullBranches)}
|
|
||||||
</Select>
|
|
||||||
</Input.Group>
|
|
||||||
</div>
|
|
||||||
<div className="width10 pull-left text-center mt25">
|
|
||||||
<i
|
|
||||||
className={'iconfont icon-youjiang color-grey-c font-32'}
|
|
||||||
></i>
|
|
||||||
</div>
|
|
||||||
<div className="width40 pull-left">
|
|
||||||
<div>
|
|
||||||
<div className="color-grey-3 mb10 fwb">目标分支:</div>
|
|
||||||
<Input.Group compact className="display-flex">
|
|
||||||
<Select
|
|
||||||
value={project && project.id}
|
|
||||||
className="hide-1 task-hide flex1"
|
|
||||||
onSelect={(e) => this.selectProjectName(e)}
|
|
||||||
>
|
|
||||||
{this.renderProjectNames(mergeProjects)}
|
|
||||||
</Select>
|
|
||||||
<Select
|
|
||||||
value={merge}
|
|
||||||
onSelect={(e) => this.selectBrach('merge', e)}
|
|
||||||
showSearch
|
|
||||||
className="merge-flex1 flex1 matchwidth"
|
|
||||||
dropdownMatchSelectWidth={false}
|
|
||||||
dropdownClassName="overlihide"
|
|
||||||
>
|
|
||||||
{this.renderBrances(mergeBranches)}
|
|
||||||
</Select>
|
|
||||||
</Input.Group>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/* 非加载状态且有提示 */}
|
|
||||||
{!isCompareSpin && showMessage && (
|
|
||||||
<div className="mb20">
|
|
||||||
<Alert
|
|
||||||
description={this.withHtml(defaultMessage)}
|
|
||||||
type="error"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{/* 非加载状态且可以提交 */}
|
|
||||||
{!isCompareSpin && !showMessage && (
|
|
||||||
<MergeForm
|
|
||||||
{...this.props}
|
|
||||||
merge_type="new"
|
|
||||||
data={data}
|
|
||||||
merge={merge}
|
|
||||||
pull={pull}
|
|
||||||
files_count={
|
|
||||||
comparesData &&
|
|
||||||
comparesData.diff &&
|
|
||||||
comparesData.diff.files_count
|
|
||||||
}
|
|
||||||
commits_count={comparesData && comparesData.commits_count}
|
|
||||||
></MergeForm>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
{!isFirstLoading && (
|
|
||||||
<MergeFooter
|
|
||||||
{...this.props}
|
|
||||||
merge={merge}
|
|
||||||
pull={pull}
|
|
||||||
comparesData={comparesData}
|
|
||||||
></MergeFooter>
|
|
||||||
)}
|
|
||||||
</Spin>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default CreateMerge;
|
|
|
@ -1,24 +1,17 @@
|
||||||
import React ,{useEffect,useState } from 'react';
|
import React ,{useEffect,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 { Tooltip,Progress } from 'antd';
|
import { Button } from 'antd';
|
||||||
import './merge.css';
|
import './merge.css';
|
||||||
import './Index.scss';
|
|
||||||
|
|
||||||
function Files({ data,history,owner,projectsId , parentsSha }){
|
function Files({data,history,owner,projectsId}){
|
||||||
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])
|
||||||
|
|
||||||
useEffect(()=>{
|
|
||||||
document.addEventListener('click',()=>{setIsOpen(false)})
|
|
||||||
})
|
|
||||||
|
|
||||||
function showDown(flag,index,isBin){
|
function showDown(flag,index,isBin){
|
||||||
if(!isBin){
|
if(!isBin){
|
||||||
|
@ -29,86 +22,35 @@ function Files({ data,history,owner,projectsId , parentsSha }){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 onClick={(e)=>{e.nativeEvent.stopImmediatePropagation()}}>
|
<div>
|
||||||
<AlignCenter className="color-grey-9" style={{position:'relative'}}>
|
<AlignCenter className="color-grey-9 pb10" style={{borderBottom:"1px solid #eee"}}>
|
||||||
<div onClick={()=>{setIsOpen(!isOpen)}}>
|
<i className="iconfont icon-sanjiaoxing-down mr5"></i>
|
||||||
<i className={`iconfont mr5 ${isOpen? "font-18 icon-sanjiaoxing-down":"font-16 icon-triangle"}`}></i>
|
<span>
|
||||||
<span className="color-grey-6 update-file-count">
|
共有<span className="color-grey-3"> {data && data.files_count} 个文件被更改</span>,包括
|
||||||
共有<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 className="fileList">
|
<div>
|
||||||
{
|
{
|
||||||
files.map((item,key)=>{
|
files.map((item,key)=>{
|
||||||
return(
|
return(
|
||||||
<div className="files" key={key}>
|
<div className="files" key={key}>
|
||||||
<a id= {`value${key}`} className="anchorPoint"></a>
|
<FlexAJ className="filesInfo" style={{cursor:item.isBin ? "default":"pointer"}} onClick={()=>showDown(item.flag,key,item.isBin)}>
|
||||||
<FlexAJ className="filesInfo">
|
|
||||||
<AlignCenter>
|
<AlignCenter>
|
||||||
{!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>:""}
|
{!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>:""}
|
||||||
<span className="cursor-pointer" data-clipboard-text={item.name} onClick={()=>showDown(item.flag,key,item.isBin)}>{item.name}</span>
|
<i className="iconfont icon-wenjia font-16 mr8 color-grey-9"></i>
|
||||||
<Tooltip
|
<span>{item.name}</span>
|
||||||
title={copyfileTipTitle}
|
|
||||||
onVisibleChange={()=>setCopyfileTipTitle("复制文件路径")}
|
|
||||||
>
|
|
||||||
<i className="iconfont icon-fuzhiicon ml6" onClick={()=>copyFileName(item.name)}></i>
|
|
||||||
</Tooltip>
|
|
||||||
</AlignCenter>
|
</AlignCenter>
|
||||||
<div className="see-file">
|
<span>
|
||||||
<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 + "处删除" : ""}`}>
|
<Button className="mr20" onClick={()=>{history.push(`/${owner}/${projectsId}/tree/${truncateCommitId(item.sha)}/${item.name}`)}}>查看文件</Button>
|
||||||
<Progress showInfo = {false} strokeColor = "#2DB44D" size="small" percent={item.addition/(item.addition+item.deletion)*100} />
|
<span className="color-green">+{item.addition}</span>
|
||||||
<span className="ml10">{item.addition+item.deletion}处</span>
|
<span className="color-red ml20">-{item.deletion}</span>
|
||||||
</Tooltip>
|
</span>
|
||||||
{
|
|
||||||
!item.isSubmodule &&
|
|
||||||
<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 &&
|
||||||
|
|
|
@ -19,85 +19,3 @@
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -228,7 +228,7 @@ class MergeDetail extends Component {
|
||||||
<div>
|
<div>
|
||||||
{
|
{
|
||||||
data && data.issue.user_permission ?
|
data && data.issue.user_permission ?
|
||||||
<Link to={`/${owner}/${projectsId}/pulls/${mergeid}/edit`} className="color-blue fr">编辑</Link>
|
<Link to={`/${owner}/${projectsId}/pulls/${mergeid}/updatemerge`} className="color-blue fr">编辑</Link>
|
||||||
: ''
|
: ''
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -62,9 +62,9 @@ class MergeItem extends Component {
|
||||||
<p className="mb15 df" style={{ alignItems: "center" }}>
|
<p className="mb15 df" style={{ alignItems: "center" }}>
|
||||||
<i className={`iconfont icon-hebingqingqiu1 font-14 mr3 i_${status}`}></i>
|
<i className={`iconfont icon-hebingqingqiu1 font-14 mr3 i_${status}`}></i>
|
||||||
<Link
|
<Link
|
||||||
to={`/${owner}/${projectsId}/pulls/${item.pull_request_id}`}
|
to={`/${owner}/${projectsId}/pulls/${item.pull_request_id}/Messagecount`}
|
||||||
className="hide-1 font-15 color-grey-3 fwb lineh-30 mr10"
|
className="hide-1 font-15 color-grey-3 fwb lineh-30 mr10"
|
||||||
style={{ maxWidth: "600px" }}
|
style={{ maxWidth: "300px" }}
|
||||||
>
|
>
|
||||||
{item.name}
|
{item.name}
|
||||||
</Link>
|
</Link>
|
||||||
|
@ -110,7 +110,7 @@ class MergeItem extends Component {
|
||||||
<Tag className="pr-branch-tag">
|
<Tag className="pr-branch-tag">
|
||||||
<Link
|
<Link
|
||||||
to={`/${item.is_original ? item.fork_project_user : owner}/${ item.is_original ? item.fork_project_identifier : projectsId }/tree/${turnbar(item.pull_request_head)}`}
|
to={`/${item.is_original ? item.fork_project_user : owner}/${ item.is_original ? item.fork_project_identifier : projectsId }/tree/${turnbar(item.pull_request_head)}`}
|
||||||
className="maxW200px task-hide ver-middle" style={{maxWidth:"200px"}}
|
className="maxW200px hide-1 ver-middle"
|
||||||
>
|
>
|
||||||
{item.is_original
|
{item.is_original
|
||||||
? item.fork_project_user
|
? item.fork_project_user
|
||||||
|
@ -134,7 +134,7 @@ class MergeItem extends Component {
|
||||||
<Tag className="pr-branch-tag">
|
<Tag className="pr-branch-tag">
|
||||||
<Link
|
<Link
|
||||||
to={`/${owner}/${projectsId}/tree/${turnbar(item.pull_request_base)}`}
|
to={`/${owner}/${projectsId}/tree/${turnbar(item.pull_request_base)}`}
|
||||||
className="maxW200px task-hide ver-middle" style={{maxWidth:"200px"}}
|
className="maxW200px hide-1 ver-middle"
|
||||||
>
|
>
|
||||||
{/* {item.is_fork ? item.pull_request_base : `${item.author_name}:${item.pull_request_base}`} */}
|
{/* {item.is_fork ? item.pull_request_base : `${item.author_name}:${item.pull_request_base}`} */}
|
||||||
{project_author_name}:{item.pull_request_base}
|
{project_author_name}:{item.pull_request_base}
|
||||||
|
@ -175,7 +175,7 @@ class MergeItem extends Component {
|
||||||
{item.journals_count ? (
|
{item.journals_count ? (
|
||||||
<Link
|
<Link
|
||||||
className="mr5 color-grey-8"
|
className="mr5 color-grey-8"
|
||||||
to={`/${owner}/${projectsId}/pulls/${item.pull_request_id}`}
|
to={`/${owner}/${projectsId}/pulls/${item.pull_request_id}/Messagecount`}
|
||||||
>
|
>
|
||||||
<i className="iconfont icon-huifu1 font-15 mr5 ver-middle"></i>
|
<i className="iconfont icon-huifu1 font-15 mr5 ver-middle"></i>
|
||||||
{item.journals_count}
|
{item.journals_count}
|
||||||
|
@ -196,7 +196,7 @@ class MergeItem extends Component {
|
||||||
>
|
>
|
||||||
<div className="grid-item mr15 color-grey-9">
|
<div className="grid-item mr15 color-grey-9">
|
||||||
<Link
|
<Link
|
||||||
to={`/${owner}/${projectsId}/pulls/${item.pull_request_id}/edit`}
|
to={`/${owner}/${projectsId}/pulls/${item.pull_request_id}/updatemerge`}
|
||||||
className="color-grey-9"
|
className="color-grey-9"
|
||||||
>
|
>
|
||||||
<i className="iconfont icon-bianji3 font-14 mr5"></i>
|
<i className="iconfont icon-bianji3 font-14 mr5"></i>
|
||||||
|
|
|
@ -1,210 +0,0 @@
|
||||||
import React, { Component } from 'react';
|
|
||||||
import { Tabs, Spin } from 'antd';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import axios from 'axios';
|
|
||||||
|
|
||||||
import Commits from './Commits';
|
|
||||||
import Comments from '../comments/comments';
|
|
||||||
import Files from './Files';
|
|
||||||
|
|
||||||
import '../Order/order.css';
|
|
||||||
import './merge.css';
|
|
||||||
|
|
||||||
const { TabPane } = Tabs;
|
|
||||||
|
|
||||||
class MergeFooter extends Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.state = {
|
|
||||||
commitsData: [],
|
|
||||||
filesData: undefined,
|
|
||||||
isSpin: false,
|
|
||||||
activeKey: '1',
|
|
||||||
commitCount: 0,
|
|
||||||
filesCount: 0,
|
|
||||||
// 总评论数量,包含回复
|
|
||||||
commentsTotalCount: 0,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
componentDidMount() {
|
|
||||||
this.Init();
|
|
||||||
// 为父组件绑定当前,以方便调用方法
|
|
||||||
this.props.bindFootRef && this.props.bindFootRef(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
|
||||||
// 解决切换tab后浏览器回退不刷新的问题、点击tab后url变化但tab未切换的问题
|
|
||||||
const newPathname = this.props.location.pathname;
|
|
||||||
const prevPathname = prevProps.location.pathname;
|
|
||||||
if (newPathname !== prevPathname) {
|
|
||||||
this.Init(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Init = (isTabChange) => {
|
|
||||||
const { data, location, match } = this.props;
|
|
||||||
const { pathname } = location;
|
|
||||||
const { projectsId, owner, mergeId } = match.params;
|
|
||||||
|
|
||||||
let activeKey = '1';
|
|
||||||
if (pathname.indexOf('commits') > -1) {
|
|
||||||
activeKey = '2';
|
|
||||||
this.getCommit(owner, projectsId, mergeId);
|
|
||||||
} else if (pathname.indexOf('files') > -1) {
|
|
||||||
activeKey = '3';
|
|
||||||
this.getFile(owner, projectsId, mergeId);
|
|
||||||
}
|
|
||||||
if (isTabChange && activeKey === '1') {
|
|
||||||
this.refreshComment();
|
|
||||||
}
|
|
||||||
this.setState({
|
|
||||||
activeKey: activeKey,
|
|
||||||
commitCount: data && data.commits_count,
|
|
||||||
filesCount: data && data.files_count,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
bindCommentRef = (commentRef) => {
|
|
||||||
this.childComment = commentRef;
|
|
||||||
}
|
|
||||||
|
|
||||||
refreshComment = () => {
|
|
||||||
this.childComment && this.childComment.getjournalslist();
|
|
||||||
}
|
|
||||||
|
|
||||||
getCommit = (owner, projectsId, mergeId) => {
|
|
||||||
this.setState({ isSpin: true });
|
|
||||||
const url = `/${owner}/${projectsId}/pulls/${mergeId}/commits.json`;
|
|
||||||
axios
|
|
||||||
.get(url)
|
|
||||||
.then((result) => {
|
|
||||||
if (result) {
|
|
||||||
this.setState({
|
|
||||||
commitsData: result.data.commits,
|
|
||||||
commitCount: result.data.commits_count,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this.setState({ isSpin: false });
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
this.setState({ isSpin: false });
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
getFile = (owner, projectsId, mergeId) => {
|
|
||||||
this.setState({ isSpin: true });
|
|
||||||
const url = `/${owner}/${projectsId}/pulls/${mergeId}/files.json`;
|
|
||||||
axios
|
|
||||||
.get(url)
|
|
||||||
.then((result) => {
|
|
||||||
if (result) {
|
|
||||||
this.setState({
|
|
||||||
filesData: result.data,
|
|
||||||
filesCount: result.data.files_count,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this.setState({ isSpin: false });
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
this.setState({ isSpin: false });
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { projectsId, owner, mergeId } = this.props.match.params;
|
|
||||||
|
|
||||||
const { order_id, data = {} } = this.props;
|
|
||||||
const {
|
|
||||||
isSpin,
|
|
||||||
activeKey,
|
|
||||||
filesCount,
|
|
||||||
commitCount,
|
|
||||||
filesData,
|
|
||||||
commitsData = [],
|
|
||||||
} = this.state;
|
|
||||||
|
|
||||||
// 评论数量优先取Comment组件中列表接口返回的,其次取合并请求详情接口中的,都没有取默认值0
|
|
||||||
const commentsTotalCount = parseInt(
|
|
||||||
this.state.commentsTotalCount || data.comments_total_count || 0,
|
|
||||||
10
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="main mergeRequest" style={{ paddingTop: '0px' }}>
|
|
||||||
<Spin spinning={isSpin}>
|
|
||||||
<Tabs
|
|
||||||
activeKey={activeKey}
|
|
||||||
className="custom-commit-tabs"
|
|
||||||
animated={false}
|
|
||||||
>
|
|
||||||
<TabPane
|
|
||||||
tab={
|
|
||||||
<Link to={`/${owner}/${projectsId}/pulls/${mergeId}`}>
|
|
||||||
<span className="font-16">评论</span>
|
|
||||||
{commentsTotalCount > 0 && (
|
|
||||||
<span className="tabNum">{commentsTotalCount}</span>
|
|
||||||
)}
|
|
||||||
</Link>
|
|
||||||
}
|
|
||||||
key="1"
|
|
||||||
>
|
|
||||||
<Comments
|
|
||||||
order_id={order_id}
|
|
||||||
showNotification={this.props.showNotification}
|
|
||||||
only_show_content={true}
|
|
||||||
updateCommentsNum={(commentsCount) => {
|
|
||||||
this.setState({ commentsTotalCount: commentsCount || 0 });
|
|
||||||
}}
|
|
||||||
{...this.props}
|
|
||||||
bindCommentRef={this.bindCommentRef}
|
|
||||||
/>
|
|
||||||
</TabPane>
|
|
||||||
{commitCount > 0 && (
|
|
||||||
<TabPane
|
|
||||||
tab={
|
|
||||||
<Link to={`/${owner}/${projectsId}/pulls/${mergeId}/commits`}>
|
|
||||||
<span className="font-16">提交</span>
|
|
||||||
{commitCount > 0 && (
|
|
||||||
<span className="tabNum">{commitCount}</span>
|
|
||||||
)}
|
|
||||||
</Link>
|
|
||||||
}
|
|
||||||
key="2"
|
|
||||||
>
|
|
||||||
{commitsData.length > 0 && (
|
|
||||||
<Commits
|
|
||||||
{...this.props}
|
|
||||||
commits={commitsData}
|
|
||||||
projectsId={projectsId}
|
|
||||||
owner={owner}
|
|
||||||
></Commits>
|
|
||||||
)}
|
|
||||||
</TabPane>
|
|
||||||
)}
|
|
||||||
{filesCount > 0 && (
|
|
||||||
<TabPane
|
|
||||||
tab={
|
|
||||||
<Link to={`/${owner}/${projectsId}/pulls/${mergeId}/files`}>
|
|
||||||
<span className="font-16">文件</span>
|
|
||||||
{filesCount > 0 && (
|
|
||||||
<span className="tabNum">{filesCount}</span>
|
|
||||||
)}
|
|
||||||
</Link>
|
|
||||||
}
|
|
||||||
key="3"
|
|
||||||
>
|
|
||||||
<Files
|
|
||||||
{...this.props}
|
|
||||||
data={filesData}
|
|
||||||
projectsId={projectsId}
|
|
||||||
owner={owner}
|
|
||||||
/>
|
|
||||||
</TabPane>
|
|
||||||
)}
|
|
||||||
</Tabs>
|
|
||||||
</Spin>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export default MergeFooter;
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
import { Tabs } from 'antd';
|
import { Tabs } from 'antd';
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
|
import { AlignCenter } from '../Component/layout';
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { getImageUrl } from "educoder";
|
import { getImageUrl } from "educoder";
|
||||||
import {
|
import {
|
||||||
|
@ -10,6 +11,7 @@ import {
|
||||||
Dropdown,
|
Dropdown,
|
||||||
Icon,
|
Icon,
|
||||||
Menu,
|
Menu,
|
||||||
|
Select,
|
||||||
Tag,
|
Tag,
|
||||||
Button,
|
Button,
|
||||||
Alert,
|
Alert,
|
||||||
|
@ -17,8 +19,9 @@ import {
|
||||||
import "./merge.css";
|
import "./merge.css";
|
||||||
import RenderHtml from "../../components/render-html";
|
import RenderHtml from "../../components/render-html";
|
||||||
import "../Order/order.css";
|
import "../Order/order.css";
|
||||||
import MergeLinkFooter from "./MergeLinkFooter";
|
import MergeFooter from "./merge_footer";
|
||||||
|
|
||||||
|
const Option = Select.Option;
|
||||||
const TextArea = Input.TextArea;
|
const TextArea = Input.TextArea;
|
||||||
|
|
||||||
function turnbar(str){
|
function turnbar(str){
|
||||||
|
@ -58,11 +61,6 @@ class MessageCount extends Component {
|
||||||
|
|
||||||
// this.clickBody();
|
// this.clickBody();
|
||||||
};
|
};
|
||||||
|
|
||||||
bindFootRef = (footRef) => {
|
|
||||||
this.footRef = footRef;
|
|
||||||
}
|
|
||||||
|
|
||||||
clickBody=()=>{
|
clickBody=()=>{
|
||||||
document.body.addEventListener('click', e => {
|
document.body.addEventListener('click', e => {
|
||||||
let name = e.target.className;
|
let name = e.target.className;
|
||||||
|
@ -152,8 +150,6 @@ class MessageCount extends Component {
|
||||||
});
|
});
|
||||||
const { getDetail } = this.props;
|
const { getDetail } = this.props;
|
||||||
getDetail && getDetail();
|
getDetail && getDetail();
|
||||||
// 调用子组件的方法刷新评论列表
|
|
||||||
this.footRef && this.footRef.refreshComment();
|
|
||||||
} else {
|
} else {
|
||||||
this.setState({ SpinMerge: false });
|
this.setState({ SpinMerge: false });
|
||||||
}
|
}
|
||||||
|
@ -287,13 +283,13 @@ class MessageCount extends Component {
|
||||||
conflict_files && conflict_files.length>0 &&
|
conflict_files && conflict_files.length>0 &&
|
||||||
<div>
|
<div>
|
||||||
<p className="mt10 font-16 pt10" style={{borderTop:"1px solid #f9d7d5"}}>如下文件有代码冲突:</p>
|
<p className="mt10 font-16 pt10" style={{borderTop:"1px solid #f9d7d5"}}>如下文件有代码冲突:</p>
|
||||||
<div>
|
<p>
|
||||||
{
|
{
|
||||||
conflict_files.map((i,k)=>{
|
conflict_files.map((i,k)=>{
|
||||||
return <p key={k}>{i}</p>
|
return <p>{i}</p>
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
</div>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
@ -340,11 +336,11 @@ class MessageCount extends Component {
|
||||||
<div>
|
<div>
|
||||||
<div className="main">
|
<div className="main">
|
||||||
<div>
|
<div>
|
||||||
<div className="pb20 border-1f df">
|
<div className="grid-item-top pb20 border-1f">
|
||||||
<div className="flex1">
|
<div>
|
||||||
<div className="ver-middle">
|
<div className="ver-middle">
|
||||||
<span className="mr10 ver-middle">
|
<span className="mr10 ver-middle">
|
||||||
<span className="font-18 fwb" style={{wordBreak:"break-all"}}>
|
<span className="font-18 fwb">
|
||||||
{data.issue.subject}
|
{data.issue.subject}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
@ -366,9 +362,9 @@ class MessageCount extends Component {
|
||||||
<Tag className="pr-branch-tag">
|
<Tag className="pr-branch-tag">
|
||||||
<Link
|
<Link
|
||||||
to={`/${data.pull_request.is_original ? data.pull_request.fork_project_user : data.issue.project_author_name}/${data.pull_request.is_original?data.project_identifier:projectsId}/tree/${turnbar(data.pull_request && data.pull_request.head)}`}
|
to={`/${data.pull_request.is_original ? data.pull_request.fork_project_user : data.issue.project_author_name}/${data.pull_request.is_original?data.project_identifier:projectsId}/tree/${turnbar(data.pull_request && data.pull_request.head)}`}
|
||||||
className="ver-middle task-hide" style={{maxWidth:"200px"}} title={`${data.pull_request.is_original ? data.pull_request.fork_project_user : data.issue.project_author_name}: ${data.pull_request && data.pull_request.head}`}
|
className="ver-middle"
|
||||||
>
|
>
|
||||||
{data.pull_request.is_original ? data.pull_request.fork_project_user : data.issue.project_author_name}: {data.pull_request && data.pull_request.head}
|
{data.pull_request.is_original ? data.pull_request.fork_project_user : data.issue.project_author_name}: {turnbar(data.pull_request && data.pull_request.head)}
|
||||||
</Link>
|
</Link>
|
||||||
</Tag>
|
</Tag>
|
||||||
<span className="mr8 ver-middle">
|
<span className="mr8 ver-middle">
|
||||||
|
@ -381,7 +377,7 @@ class MessageCount extends Component {
|
||||||
<Tag className="pr-branch-tag">
|
<Tag className="pr-branch-tag">
|
||||||
<Link
|
<Link
|
||||||
to={`/${owner}/${projectsId}/tree/${data.pull_request.base}`}
|
to={`/${owner}/${projectsId}/tree/${data.pull_request.base}`}
|
||||||
className="ver-middle task-hide" style={{maxWidth:"200px"}} title={`${data.issue.project_author_name}:${data.pull_request.base}`}
|
className="ver-middle"
|
||||||
>
|
>
|
||||||
{data.issue.project_author_name}:{data.pull_request.base}
|
{data.issue.project_author_name}:{data.pull_request.base}
|
||||||
</Link>
|
</Link>
|
||||||
|
@ -428,7 +424,7 @@ class MessageCount extends Component {
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<span className="ml25">
|
<span className="ml25">
|
||||||
<span className="color-grey-8">标记:</span>
|
<span className="color-grey-8">标签:</span>
|
||||||
<span className="color-grey-3">
|
<span className="color-grey-3">
|
||||||
{data.issue.issue_tags &&
|
{data.issue.issue_tags &&
|
||||||
data.issue.issue_tags.length > 0
|
data.issue.issue_tags.length > 0
|
||||||
|
@ -445,13 +441,14 @@ class MessageCount extends Component {
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="ml10 text-right">
|
<div className="ml10">
|
||||||
|
<div className="mt15 text-right" style={{display:"flex",justifyContent:"flex-end"}}>
|
||||||
{operate && (
|
{operate && (
|
||||||
<Button
|
<Button
|
||||||
type="green"
|
type="green"
|
||||||
ghost
|
ghost
|
||||||
className="ml20"
|
className="ml20"
|
||||||
onClick={()=>{this.props.history.push(`/${owner}/${projectsId}/pulls/${mergeId}/edit`);}}
|
onClick={()=>{this.props.history.push(`/${owner}/${projectsId}/pulls/${mergeId}/UpdateMerge`);}}
|
||||||
>
|
>
|
||||||
编辑
|
编辑
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -468,6 +465,7 @@ class MessageCount extends Component {
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{
|
{
|
||||||
data.issue.description ?
|
data.issue.description ?
|
||||||
|
@ -545,7 +543,7 @@ class MessageCount extends Component {
|
||||||
onChange={this.changbodypr}
|
onChange={this.changbodypr}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<p
|
||||||
className="clearfix mt15"
|
className="clearfix mt15"
|
||||||
style={{ display: this.state.buttonshow }}
|
style={{ display: this.state.buttonshow }}
|
||||||
>
|
>
|
||||||
|
@ -560,19 +558,19 @@ class MessageCount extends Component {
|
||||||
取消
|
取消
|
||||||
</Button>
|
</Button>
|
||||||
</Spin>
|
</Spin>
|
||||||
</div>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</Spin>
|
</Spin>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<MergeLinkFooter
|
<MergeFooter
|
||||||
|
footer_type={true}
|
||||||
order_id={data && data.issue.id}
|
order_id={data && data.issue.id}
|
||||||
{...this.props}
|
{...this.props}
|
||||||
{...this.state}
|
{...this.state}
|
||||||
bindFootRef={this.bindFootRef}
|
></MergeFooter>
|
||||||
></MergeLinkFooter>
|
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
""
|
""
|
||||||
|
|
|
@ -6,11 +6,6 @@ import "./merge.css";
|
||||||
import MergeForm from "./merge_form";
|
import MergeForm from "./merge_form";
|
||||||
import MergeFooter from "./merge_footer";
|
import MergeFooter from "./merge_footer";
|
||||||
const Option = Select.Option;
|
const Option = Select.Option;
|
||||||
/**
|
|
||||||
* 此文件已废弃,新文件为CreateMerge.js
|
|
||||||
* 2021.10.12
|
|
||||||
*/
|
|
||||||
|
|
||||||
class NewMerge extends Component {
|
class NewMerge extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
@ -53,10 +48,8 @@ class NewMerge extends Component {
|
||||||
this.compareProject(this.state.id,pull,"master");
|
this.compareProject(this.state.id,pull,"master");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 页面销毁取消监听
|
// 页面销毁取消监听
|
||||||
componentWillUnmount () {
|
componentWillUnmount () {
|
||||||
console.log('----------destoyed---------');
|
|
||||||
window.removeEventListener('popstate', this.handleBack, false);
|
window.removeEventListener('popstate', this.handleBack, false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -67,11 +60,8 @@ class NewMerge extends Component {
|
||||||
|
|
||||||
//获取新建分支数据
|
//获取新建分支数据
|
||||||
getmergelist = (projectsId) => {
|
getmergelist = (projectsId) => {
|
||||||
this.setState({isSpin: true});
|
this.setState({isSpin: true})
|
||||||
// const { owner } = this.props.match.params;
|
const { owner } = this.props.match.params;
|
||||||
let owner =this.props.history.location.pathname.split('/')[1];
|
|
||||||
console.log('owner:'+owner);
|
|
||||||
console.log(this.props);
|
|
||||||
const url = `/${owner}/${projectsId}/pulls/new.json`;
|
const url = `/${owner}/${projectsId}/pulls/new.json`;
|
||||||
axios
|
axios
|
||||||
.get(url)
|
.get(url)
|
||||||
|
@ -115,7 +105,6 @@ class NewMerge extends Component {
|
||||||
const { author , identifier } =oldProject;
|
const { author , identifier } =oldProject;
|
||||||
url += `/${mergeBranch}...${author && author.login}/${identifier}:${localBranch}.json`;
|
url += `/${mergeBranch}...${author && author.login}/${identifier}:${localBranch}.json`;
|
||||||
}
|
}
|
||||||
this.setState({isSpin: true});
|
|
||||||
axios.get(url).then(result=>{
|
axios.get(url).then(result=>{
|
||||||
if(result){
|
if(result){
|
||||||
if (result.data.status === 0) {
|
if (result.data.status === 0) {
|
||||||
|
@ -134,9 +123,7 @@ class NewMerge extends Component {
|
||||||
comparesData:result.data
|
comparesData:result.data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}).catch(error=>{
|
}).catch(error=>{})
|
||||||
this.setState({isSpin: false});
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,7 +186,7 @@ class NewMerge extends Component {
|
||||||
// this.ischeckmerge();
|
// this.ischeckmerge();
|
||||||
let { id ,merge , pull } = this.state;
|
let { id ,merge , pull } = this.state;
|
||||||
if(type==="pull"){
|
if(type==="pull"){
|
||||||
this.props.history.push(`/${owner}/${projectsId}/compare/${pull}`)
|
this.props.history.push(`/${owner}/${projectsId}/pulls/new/${pull}`)
|
||||||
this.compareProject(id,value,merge);
|
this.compareProject(id,value,merge);
|
||||||
}else{
|
}else{
|
||||||
this.compareProject(id,pull,value);
|
this.compareProject(id,pull,value);
|
||||||
|
@ -221,7 +208,7 @@ class NewMerge extends Component {
|
||||||
merge_user_login: is_fork_id ? projects_names[0].project_user_login : undefined
|
merge_user_login: is_fork_id ? projects_names[0].project_user_login : undefined
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
this.props.history.push(`/${login}/${identifier}/compare`);
|
this.props.history.push(`/${login}/${identifier}/pulls/new`);
|
||||||
this.newMergelist(login,identifier);
|
this.newMergelist(login,identifier);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -277,9 +264,7 @@ class NewMerge extends Component {
|
||||||
show_message,
|
show_message,
|
||||||
default_message,
|
default_message,
|
||||||
merge_head,
|
merge_head,
|
||||||
projects_names,
|
projects_names,id,comparesData
|
||||||
id,
|
|
||||||
comparesData
|
|
||||||
} = this.state;
|
} = this.state;
|
||||||
|
|
||||||
const renderBrances = (list, type) => {
|
const renderBrances = (list, type) => {
|
||||||
|
@ -313,7 +298,6 @@ class NewMerge extends Component {
|
||||||
return <div dangerouslySetInnerHTML={{ __html: html }}></div>;
|
return <div dangerouslySetInnerHTML={{ __html: html }}></div>;
|
||||||
};
|
};
|
||||||
let { project } = this.props;
|
let { project } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className="main">
|
<div className="main">
|
||||||
|
|
|
@ -64,12 +64,12 @@ class UpdateMerge extends Component {
|
||||||
<div className="color-grey-3 mb10 fwb">源分支:</div>
|
<div className="color-grey-3 mb10 fwb">源分支:</div>
|
||||||
|
|
||||||
<Input.Group compact className="display-flex">
|
<Input.Group compact className="display-flex">
|
||||||
<Button className="merge-header-button flex1 maxW50 hide-1 task-hide" disabled>
|
<Button className="merge-header-button maxW50 hide-1 task-hide">
|
||||||
{data.is_original ? `${data.fork_project_user_name}/${data.fork_project_identifier}` : `${data.project_author}/${data.project_name}`}
|
{data.is_original ? `${data.fork_project_user_name}/${data.fork_project_identifier}` : `${data.project_author}/${data.project_name}`}
|
||||||
</Button>
|
</Button>
|
||||||
<Select
|
<Select
|
||||||
defaultValue={data.is_original ? `${data.fork_project_user}:${pull}` : `${pull}`}
|
defaultValue={data.is_original ? `${data.fork_project_user}:${pull}` : `${pull}`}
|
||||||
className="minW50 merge-flex1 flex1 matchwidth"
|
className="minW50 merge-flex1"
|
||||||
disabled
|
disabled
|
||||||
></Select>{" "}
|
></Select>{" "}
|
||||||
</Input.Group>{" "}
|
</Input.Group>{" "}
|
||||||
|
@ -83,12 +83,12 @@ class UpdateMerge extends Component {
|
||||||
<div>
|
<div>
|
||||||
<div className="color-grey-3 mb10 fwb"> 目标分支 : </div>{" "}
|
<div className="color-grey-3 mb10 fwb"> 目标分支 : </div>{" "}
|
||||||
<Input.Group compact className="display-flex">
|
<Input.Group compact className="display-flex">
|
||||||
<Button className="merge-header-button flex1 maxW50 hide-1 task-hide" disabled>
|
<Button className="merge-header-button maxW50 hide-1 task-hide">
|
||||||
{`${data.project_author}/${data.project_name}`}
|
{`${data.project_author}/${data.project_name}`}
|
||||||
</Button>
|
</Button>
|
||||||
<Select
|
<Select
|
||||||
defaultValue={data.is_original ? `${data.project_login}:${merge}` : `${merge}`}
|
defaultValue={data.is_original ? `${data.project_login}:${merge}` : `${merge}`}
|
||||||
className="minW50 merge-flex1 flex1 matchwidth"
|
className="minW50 merge-flex1"
|
||||||
disabled
|
disabled
|
||||||
></Select>{" "}
|
></Select>{" "}
|
||||||
</Input.Group>{" "}
|
</Input.Group>{" "}
|
||||||
|
|
|
@ -40,7 +40,6 @@ form .ant-cascader-picker, form .ant-select {
|
||||||
}
|
}
|
||||||
.merge-header-button{
|
.merge-header-button{
|
||||||
background:rgba(241,248,255,1);
|
background:rgba(241,248,255,1);
|
||||||
text-align: left;
|
|
||||||
}
|
}
|
||||||
.width70{
|
.width70{
|
||||||
width:70%;
|
width:70%;
|
||||||
|
@ -153,23 +152,13 @@ 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;
|
||||||
|
@ -210,16 +199,3 @@ form .ant-cascader-picker, form .ant-select {
|
||||||
.linesContent.add{
|
.linesContent.add{
|
||||||
background: rgba(48, 232, 132, 0.15);
|
background: rgba(48, 232, 132, 0.15);
|
||||||
}
|
}
|
||||||
|
|
||||||
.mergeRequest .folders{
|
|
||||||
/* width: 72rem; */
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.matchwidth .ant-select-selection__rendered{
|
|
||||||
width: 200px;
|
|
||||||
}
|
|
||||||
.overlihide li{
|
|
||||||
max-width: 450px;
|
|
||||||
|
|
||||||
}
|
|
|
@ -43,7 +43,7 @@ class merge extends Component {
|
||||||
//设置选择高亮
|
//设置选择高亮
|
||||||
openselect: 1,
|
openselect: 1,
|
||||||
closeselect: undefined,
|
closeselect: undefined,
|
||||||
issue_tag_ids: "标记",
|
issue_tag_ids: "标签",
|
||||||
fixed_version_ids: "里程碑",
|
fixed_version_ids: "里程碑",
|
||||||
assigned_to_ids: "审查人员",
|
assigned_to_ids: "审查人员",
|
||||||
paix: "排序",
|
paix: "排序",
|
||||||
|
@ -198,7 +198,7 @@ class merge extends Component {
|
||||||
});
|
});
|
||||||
this.setState({
|
this.setState({
|
||||||
status_type: type,
|
status_type: type,
|
||||||
issue_tag_ids: "标记",
|
issue_tag_ids: "标签",
|
||||||
fixed_version_ids: "里程碑",
|
fixed_version_ids: "里程碑",
|
||||||
assigned_to_ids: "审查人员",
|
assigned_to_ids: "审查人员",
|
||||||
paix: "排序",
|
paix: "排序",
|
||||||
|
@ -213,7 +213,7 @@ class merge extends Component {
|
||||||
|
|
||||||
checkOperation() {
|
checkOperation() {
|
||||||
const { projectsId,owner } = this.props.match.params;
|
const { projectsId,owner } = this.props.match.params;
|
||||||
this.props.history.push(`/${owner}/${projectsId}/compare/master...master`);
|
this.props.history.push(`/${owner}/${projectsId}/pulls/new`);
|
||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
const { projectsId , owner } = this.props.match.params;
|
const { projectsId , owner } = this.props.match.params;
|
||||||
|
@ -321,7 +321,7 @@ class merge extends Component {
|
||||||
className="topWrapperSelect"
|
className="topWrapperSelect"
|
||||||
overlay={this.renderMenu(
|
overlay={this.renderMenu(
|
||||||
issue_chosen && issue_chosen.issue_tag,
|
issue_chosen && issue_chosen.issue_tag,
|
||||||
"标记",
|
"标签",
|
||||||
"issue_tag_id"
|
"issue_tag_id"
|
||||||
)}
|
)}
|
||||||
trigger={["click"]}
|
trigger={["click"]}
|
||||||
|
|
|
@ -1,84 +1,169 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from "react";
|
||||||
import { Tabs } from 'antd';
|
import { Tabs, Spin } from "antd";
|
||||||
import Commits from './Commits';
|
import "../Order/order.css";
|
||||||
import Files from './Files';
|
import "./merge.css";
|
||||||
|
import Commits from "./Commits";
|
||||||
import '../Order/order.css';
|
import Comments from "../comments/comments";
|
||||||
import './merge.css';
|
import Files from "./Files";
|
||||||
|
import axios from 'axios';
|
||||||
const { TabPane } = Tabs;
|
const { TabPane } = Tabs;
|
||||||
|
|
||||||
class MergeFooter extends Component {
|
class MergeFooter extends Component {
|
||||||
constructor(props) {
|
constructor(props){
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state={
|
||||||
activeKey: '1',
|
pageData:undefined,
|
||||||
};
|
commitsData:undefined,
|
||||||
|
filesData:undefined,
|
||||||
|
isSpin:false,
|
||||||
|
activeKey:"1",
|
||||||
|
commitCount:0,
|
||||||
|
filesCount:0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
componentDidMount=()=>{
|
||||||
|
const { footer_type ,data } = this.props;
|
||||||
|
if(footer_type){
|
||||||
|
const { projectsId , owner , mergeId } = this.props.match.params;
|
||||||
|
this.getCommit(owner,projectsId,mergeId);
|
||||||
|
this.getFile(owner,projectsId,mergeId);
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
activeKey:footer_type ? "1" : "2",
|
||||||
|
commitCount:data && data.commits_count,
|
||||||
|
filesCount:data && data.files_count
|
||||||
|
})
|
||||||
|
}
|
||||||
|
componentDidUpdate=(prevProps)=>{
|
||||||
|
const { comparesData } = this.props;
|
||||||
|
const { footer_type } = this.props;
|
||||||
|
if(footer_type){
|
||||||
|
const { data } = this.props;
|
||||||
|
if(data !== prevProps.data){
|
||||||
|
this.setState({
|
||||||
|
commitCount:data && data.commits_count,
|
||||||
|
filesCount:data && data.files_count
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(comparesData !== prevProps.comparesData){
|
||||||
|
this.setState({
|
||||||
|
activeKey:footer_type ? "1" : "2"
|
||||||
|
})
|
||||||
|
this.changeTab(footer_type ? "1" : "2");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
changeTab = (index) => {
|
changeTab=(index)=>{
|
||||||
this.setState({
|
this.setState({
|
||||||
activeKey: index,
|
isSpin:true
|
||||||
});
|
})
|
||||||
};
|
this.setState({
|
||||||
|
activeKey:index
|
||||||
|
})
|
||||||
|
const { footer_type , comparesData } = this.props;
|
||||||
|
const { projectsId , owner , mergeId } = this.props.match.params;
|
||||||
|
|
||||||
|
if(footer_type){
|
||||||
|
if(index === "2"){
|
||||||
|
this.getCommit(owner,projectsId,mergeId);
|
||||||
|
}else if(index === "3"){
|
||||||
|
this.getFile(owner,projectsId,mergeId);
|
||||||
|
}else{
|
||||||
|
this.setState({
|
||||||
|
isSpin:false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
this.setState({
|
||||||
|
commitsData:comparesData.commits,
|
||||||
|
filesData:comparesData.diff,
|
||||||
|
commitCount:comparesData.commits_count,
|
||||||
|
filesCount:comparesData.diff && comparesData.diff.files_count,
|
||||||
|
isSpin:false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getCommit =(owner,projectsId,mergeId)=>{
|
||||||
|
const url = `/${owner}/${projectsId}/pulls/${mergeId}/commits.json`;
|
||||||
|
axios.get(url).then(result=>{
|
||||||
|
if(result){
|
||||||
|
this.setState({
|
||||||
|
commitsData:result.data.commits,
|
||||||
|
isSpin:false,
|
||||||
|
commitCount:result.data.commits_count
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}).catch(error=>{})
|
||||||
|
}
|
||||||
|
|
||||||
|
getFile =(owner,projectsId,mergeId)=>{
|
||||||
|
const url = `/${owner}/${projectsId}/pulls/${mergeId}/files.json`;
|
||||||
|
axios.get(url).then(result=>{
|
||||||
|
if(result){
|
||||||
|
this.setState({
|
||||||
|
filesData:result.data,
|
||||||
|
isSpin:false,
|
||||||
|
filesCount:result.data.files_count,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}).catch(error=>{})
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { projectsId, owner } = this.props.match.params;
|
const { projectsId , owner } = this.props.match.params;
|
||||||
const { comparesData = {} } = this.props;
|
|
||||||
const { commits, diff, commits_count } = comparesData;
|
|
||||||
const { activeKey } = this.state;
|
|
||||||
|
|
||||||
return (commits && commits.length === 0) || !diff ? (
|
const { footer_type, order_id, data , comparesData } = this.props;
|
||||||
''
|
let { isSpin , activeKey , filesCount, commitCount , filesData , commitsData } = this.state;
|
||||||
) : (
|
|
||||||
<div className="main mergeRequest" style={{ paddingTop: '0px' }}>
|
return (
|
||||||
<Tabs
|
!footer_type && !comparesData || (comparesData && ((comparesData.commits && comparesData.commits.length===0)||(comparesData && !comparesData.diff)) )?"":
|
||||||
activeKey={activeKey}
|
<div className="main" style={{paddingTop:"0px"}}>
|
||||||
className="custom-commit-tabs"
|
<Spin spinning={isSpin}>
|
||||||
animated={false}
|
<Tabs
|
||||||
onChange={this.changeTab}
|
activeKey={activeKey}
|
||||||
>
|
className="custom-commit-tabs"
|
||||||
{commits && commits.length > 0 && (
|
animated={false}
|
||||||
<TabPane
|
onChange={this.changeTab}
|
||||||
tab={
|
>
|
||||||
<span>
|
{
|
||||||
<span className="font-16">提交</span>
|
footer_type &&
|
||||||
{commits_count > 0 && (
|
<TabPane
|
||||||
<span className="tabNum">{commits_count}</span>
|
tab={
|
||||||
)}
|
<span><span className="font-16">评论</span>
|
||||||
</span>
|
{data && parseInt(data.comments_count) > 0 && <span className="tabNum">{data.comments_count}</span>}
|
||||||
}
|
</span>
|
||||||
key="1"
|
} key="1">
|
||||||
>
|
<Comments
|
||||||
<Commits
|
order_id={order_id}
|
||||||
{...this.props}
|
showNotification={this.props.showNotification}
|
||||||
commits={commits}
|
only_show_content={true}
|
||||||
projectsId={projectsId}
|
{...this.props}
|
||||||
owner={owner}
|
/>
|
||||||
></Commits>
|
</TabPane>
|
||||||
</TabPane>
|
}
|
||||||
)}
|
{
|
||||||
{diff && diff.files && diff.files.length > 0 && (
|
commitsData && commitsData.length > 0 &&
|
||||||
<TabPane
|
<TabPane tab={<span><span className="font-16">提交</span>
|
||||||
tab={
|
{commitCount > 0 && <span className="tabNum">{commitCount}</span>}
|
||||||
<span>
|
</span>} key="2">
|
||||||
<span className="font-16">文件</span>
|
<Commits {...this.props} commits={commitsData} projectsId={projectsId} owner={owner}></Commits>
|
||||||
{diff.files_count > 0 && (
|
</TabPane>
|
||||||
<span className="tabNum">{diff.files_count}</span>
|
}
|
||||||
)}
|
{
|
||||||
</span>
|
filesData && filesData.files && filesData.files.length>0 &&
|
||||||
}
|
<TabPane tab={
|
||||||
key="3"
|
<span><span className="font-16">文件</span>
|
||||||
>
|
{filesCount > 0 && <span className="tabNum">{filesCount}</span>}
|
||||||
<Files
|
</span>
|
||||||
{...this.props}
|
} key="3">
|
||||||
data={diff}
|
<Files {...this.props} data={filesData} projectsId={projectsId} owner={owner}/>
|
||||||
projectsId={projectsId}
|
</TabPane>
|
||||||
owner={owner}
|
}
|
||||||
/>
|
|
||||||
</TabPane>
|
</Tabs>
|
||||||
)}
|
</Spin>
|
||||||
</Tabs>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -165,8 +165,7 @@ class MergeForm extends Component {
|
||||||
this.setState({
|
this.setState({
|
||||||
isSpin: false,
|
isSpin: false,
|
||||||
});
|
});
|
||||||
const { pull_request_id } = result.data;
|
this.props.history.push(`/${owner}/${projectsId}/pulls`);
|
||||||
this.props.history.push(`/${owner}/${projectsId}/pulls/${pull_request_id}`);
|
|
||||||
const { getDetail } = this.props;
|
const { getDetail } = this.props;
|
||||||
getDetail && getDetail();
|
getDetail && getDetail();
|
||||||
} else {
|
} else {
|
||||||
|
@ -196,7 +195,7 @@ class MergeForm extends Component {
|
||||||
isSpin: false,
|
isSpin: false,
|
||||||
});
|
});
|
||||||
this.props.history.push(
|
this.props.history.push(
|
||||||
`/${owner}/${projectsId}/pulls/${mergeId}`
|
`/${owner}/${projectsId}/pulls/${mergeId}/Messagecount`
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
this.setState({
|
this.setState({
|
||||||
|
@ -265,7 +264,7 @@ class MergeForm extends Component {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
initialValue: title,
|
initialValue: title,
|
||||||
})(<Input placeholder="标题" maxLength={200} />)}
|
})(<Input placeholder="标题" maxLength={50} />)}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<MDEditor
|
<MDEditor
|
||||||
placeholder={"请输入合并请求的描述..."}
|
placeholder={"请输入合并请求的描述..."}
|
||||||
|
@ -288,7 +287,7 @@ class MergeForm extends Component {
|
||||||
type="default"
|
type="default"
|
||||||
className="ml30"
|
className="ml30"
|
||||||
onClick={()=>{
|
onClick={()=>{
|
||||||
this.props.history.push(merge_type === "new" ? `/${owner}/${projectsId}/pulls` : `/${owner}/${projectsId}/pulls/${mergeId}`)
|
this.props.history.push(merge_type === "new" ? `/${owner}/${projectsId}/pulls` : `/${owner}/${projectsId}/pulls/${mergeId}/detail`)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className="plr10">取消</span>
|
<span className="plr10">取消</span>
|
||||||
|
@ -301,8 +300,7 @@ class MergeForm extends Component {
|
||||||
{getFieldDecorator("assigned_to_id", {
|
{getFieldDecorator("assigned_to_id", {
|
||||||
initialValue: assigned_to_id,
|
initialValue: assigned_to_id,
|
||||||
})(
|
})(
|
||||||
<Select placeholder="未选择审查人员" showSearch>
|
<Select placeholder="审查人员" showSearch>
|
||||||
<Option key={0} value={""}>未选择审查人员</Option>
|
|
||||||
{this.renderSelect(members)}
|
{this.renderSelect(members)}
|
||||||
</Select>
|
</Select>
|
||||||
)}
|
)}
|
||||||
|
@ -313,11 +311,12 @@ class MergeForm extends Component {
|
||||||
})(
|
})(
|
||||||
<Select
|
<Select
|
||||||
placeholder={
|
placeholder={
|
||||||
issue_versions && issue_versions.length > 0? "未选择里程碑": "请添加里程碑"
|
issue_versions && issue_versions.length > 0
|
||||||
|
? "未选择里程碑"
|
||||||
|
: "请添加里程碑"
|
||||||
}
|
}
|
||||||
showSearch
|
showSearch
|
||||||
>
|
>
|
||||||
<Option key={0} value={""}>{issue_versions && issue_versions.length > 0? "未选择里程碑": "请添加里程碑"}</Option>
|
|
||||||
{this.renderSelect(issue_versions)}
|
{this.renderSelect(issue_versions)}
|
||||||
</Select>
|
</Select>
|
||||||
)}
|
)}
|
||||||
|
@ -328,11 +327,12 @@ class MergeForm extends Component {
|
||||||
})(
|
})(
|
||||||
<Select
|
<Select
|
||||||
placeholder={
|
placeholder={
|
||||||
issue_tags && issue_tags.length > 0 ? "未选择标记" : "请在仓库设置里添加标记"
|
issue_tags && issue_tags.length > 0
|
||||||
|
? "未选择标签"
|
||||||
|
: "请在仓库设置里添加标签"
|
||||||
}
|
}
|
||||||
showSearch
|
showSearch
|
||||||
>
|
>
|
||||||
<Option key={0} value={""}>{issue_tags && issue_tags.length > 0 ? "未选择标记" : "请在仓库设置里添加标记"}</Option>
|
|
||||||
{this.renderSelect(issue_tags)}
|
{this.renderSelect(issue_tags)}
|
||||||
</Select>
|
</Select>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -12,7 +12,7 @@ class Nodata extends Component{
|
||||||
<h3>欢迎使用合并请求!</h3>
|
<h3>欢迎使用合并请求!</h3>
|
||||||
|
|
||||||
<div className="color-grey-8">
|
<div className="color-grey-8">
|
||||||
合并请求可以帮助您与他人协作编写代码。在使用之前,请先创建一个 <Link className="color-blue" to={`/${owner}/${projectsId}/compare/master...master`}>合并请求</Link>
|
合并请求可以帮助您与他人协作编写代码。在使用之前,请先创建一个 <Link className="color-blue" to={`/${owner}/${projectsId}/pulls/new`}>合并请求</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,10 +2,9 @@ import React, { Component } from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { Input , Form , Select , Checkbox , Button , Spin , AutoComplete, Modal } from 'antd';
|
import { Input , Form , Select , Checkbox , Button , Spin , AutoComplete, Modal } from 'antd';
|
||||||
import { Base64 } from 'js-base64';
|
import { Base64 } from 'js-base64';
|
||||||
import { AlignCenter } from '../Component/layout';
|
|
||||||
|
|
||||||
import '../css/index.scss';
|
import '../css/index.scss';
|
||||||
import './new.scss'
|
import './new.css'
|
||||||
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
const Option = Select.Option;
|
const Option = Select.Option;
|
||||||
|
@ -45,12 +44,7 @@ class Index extends Component {
|
||||||
project_category_name: undefined,
|
project_category_name: undefined,
|
||||||
license_name: undefined,
|
license_name: undefined,
|
||||||
ignore_name: undefined,
|
ignore_name: undefined,
|
||||||
descNum:0,
|
descNum:0
|
||||||
|
|
||||||
categoreFlag:false,
|
|
||||||
languageFlag:false,
|
|
||||||
ignoreFlag:false,
|
|
||||||
licenseFlag:false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
componentDidMount = () => {
|
componentDidMount = () => {
|
||||||
|
@ -155,7 +149,7 @@ class Index extends Component {
|
||||||
if (mirror_status === 2 && sessionStorage.newProjectValue) {
|
if (mirror_status === 2 && sessionStorage.newProjectValue) {
|
||||||
Modal.warning({
|
Modal.warning({
|
||||||
title: '警告',
|
title: '警告',
|
||||||
content: '项目导入失败!请按操作规范重新导入项目!',
|
content: '镜像项目创建失败!请按操作规范重新创建项目!',
|
||||||
});
|
});
|
||||||
let newProjectValue = JSON.parse(sessionStorage.newProjectValue);
|
let newProjectValue = JSON.parse(sessionStorage.newProjectValue);
|
||||||
if (newProjectValue) {
|
if (newProjectValue) {
|
||||||
|
@ -195,16 +189,12 @@ class Index extends Component {
|
||||||
|
|
||||||
subMitFrom = () => {
|
subMitFrom = () => {
|
||||||
this.props.form.validateFieldsAndScroll((err, values) => {
|
this.props.form.validateFieldsAndScroll((err, values) => {
|
||||||
console.log(values);
|
|
||||||
if (!err) {
|
if (!err) {
|
||||||
this.setState({
|
this.setState({
|
||||||
isSpin: true
|
isSpin: true
|
||||||
})
|
})
|
||||||
const { projectsType } = this.props.match.params;
|
const { projectsType } = this.props.match.params;
|
||||||
const {
|
const { project_language_id, project_category_id, license_id, ignore_id , owners_id , owners_name } = this.state;
|
||||||
project_language_id, project_category_id, license_id, ignore_id , owners_id ,
|
|
||||||
ignoreFlag,licenseFlag,categoreFlag,languageFlag
|
|
||||||
} = this.state;
|
|
||||||
const decoderPass = Base64.encode(values.password);
|
const decoderPass = Base64.encode(values.password);
|
||||||
const url = (projectsType && projectsType === "mirror") ? "/projects/migrate.json" : "/projects.json";
|
const url = (projectsType && projectsType === "mirror") ? "/projects/migrate.json" : "/projects.json";
|
||||||
// 新建项目的时候,暂存数据,如果失败,返回的时候可以重新赋值
|
// 新建项目的时候,暂存数据,如果失败,返回的时候可以重新赋值
|
||||||
|
@ -212,14 +202,14 @@ class Index extends Component {
|
||||||
axios.post(url, {
|
axios.post(url, {
|
||||||
...values,
|
...values,
|
||||||
auth_password:decoderPass,
|
auth_password:decoderPass,
|
||||||
project_language_id:languageFlag ? project_language_id : undefined,
|
project_language_id,
|
||||||
project_category_id:categoreFlag ? project_category_id : undefined,
|
project_category_id,
|
||||||
license_id:licenseFlag ? license_id : undefined,
|
license_id,
|
||||||
ignore_id:ignoreFlag ? ignore_id : undefined,
|
ignore_id,
|
||||||
user_id:owners_id
|
user_id:owners_id
|
||||||
}).then((result) => {
|
}).then((result) => {
|
||||||
if (result && result.data.id) {
|
if (result && result.data.id) {
|
||||||
projectsType && projectsType !== "mirror" && this.props.showNotification(`项目创建成功!`);
|
projectsType && projectsType !== "mirror" && this.props.showNotification(`托管项目创建成功!`);
|
||||||
this.props.history.push(`/${result.data.login}/${result.data.identifier}`);
|
this.props.history.push(`/${result.data.login}/${result.data.identifier}`);
|
||||||
}
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
|
@ -285,16 +275,12 @@ class Index extends Component {
|
||||||
if(value.indexOf("/") > -1){
|
if(value.indexOf("/") > -1){
|
||||||
let arr = value.split("/");
|
let arr = value.split("/");
|
||||||
let first = arr[arr.length-1];
|
let first = arr[arr.length-1];
|
||||||
if(first.indexOf(".") > -1){
|
if(first.indexOf(".git") > -1){
|
||||||
let second = first.split('.')[0];
|
let second = first.split('.')[0];
|
||||||
if(!second)return;
|
if(!second)return;
|
||||||
this.props.form.setFieldsValue({
|
this.props.form.setFieldsValue({
|
||||||
repository_name:second
|
repository_name:second
|
||||||
})
|
})
|
||||||
}else{
|
|
||||||
this.props.form.setFieldsValue({
|
|
||||||
repository_name:first
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -327,35 +313,48 @@ class Index extends Component {
|
||||||
|
|
||||||
mirrorCheck,
|
mirrorCheck,
|
||||||
|
|
||||||
descNum,
|
descNum
|
||||||
|
|
||||||
ignoreFlag,
|
|
||||||
licenseFlag,
|
|
||||||
languageFlag,
|
|
||||||
categoreFlag
|
|
||||||
} = this.state;
|
} = this.state;
|
||||||
return (
|
return (
|
||||||
<div className="main back-white" style={{padding:"0px",border:"none"}}>
|
<div className="main back-white" style={{padding:"0px",border:"none"}}>
|
||||||
<div className="newPanel">
|
<div className="newPanel">
|
||||||
<div className="newPanel_title">{projectsType && projectsType === "mirror" ? "导入" : "新建"}项目</div>
|
<div className="newPanel_title">创建{projectsType && projectsType === "mirror" ? "镜像" : "托管"}项目</div>
|
||||||
<Spin spinning={isSpin}>
|
<Spin spinning={isSpin}>
|
||||||
<Form>
|
<Form>
|
||||||
<div className="newPanel_content">
|
<div className="newPanel_content">
|
||||||
|
<Form.Item
|
||||||
{
|
label="拥有者"
|
||||||
|
>
|
||||||
|
{getFieldDecorator('user_id', {
|
||||||
|
rules: [{
|
||||||
|
required: true, message: '请选择拥有者'
|
||||||
|
},{
|
||||||
|
validator:(rule, value, callback) => this.checkId(rule, value, callback, OwnerList, '拥有者')
|
||||||
|
}],
|
||||||
|
})(
|
||||||
|
<AutoComplete
|
||||||
|
placeholder="请选择拥有者"
|
||||||
|
onChange={(value, e) => this.ChangePlatform(value, e, 'owners', OwnerList)}
|
||||||
|
className="plateAutoComplete"
|
||||||
|
onBlur={(value) => this.blurCategory(value, OwnerList, "owners")}
|
||||||
|
>
|
||||||
|
{owners_list}
|
||||||
|
</AutoComplete>
|
||||||
|
)}
|
||||||
|
</Form.Item>
|
||||||
|
{
|
||||||
projectsType && projectsType === "mirror" &&
|
projectsType && projectsType === "mirror" &&
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="导入仓库URL"
|
label="镜像版本库地址"
|
||||||
style={{ marginBottom: "0px" }}
|
style={{ marginBottom: "0px" }}
|
||||||
colon={false}
|
|
||||||
>
|
>
|
||||||
{getFieldDecorator('clone_addr', {
|
{getFieldDecorator('clone_addr', {
|
||||||
rules: [{
|
rules: [{
|
||||||
required: true, message: '请填写镜像版本库地址'
|
required: true, message: '请填写镜像版本库地址'
|
||||||
}],
|
}],
|
||||||
})(
|
})(
|
||||||
<Input placeholder="请输入需要导入到本项目的仓库地址" onBlur={this.ChangeAddr} />
|
<Input placeholder="输入需要同步到本项目的镜像版本库地址" onChange={this.ChangeAddr} />
|
||||||
)}
|
)}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<p className="formTip color-orange">示例:https://github.com/facebook/reack.git</p>
|
<p className="formTip color-orange">示例:https://github.com/facebook/reack.git</p>
|
||||||
|
@ -363,16 +362,14 @@ class Index extends Component {
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
projectsType && projectsType === "mirror" &&
|
projectsType && projectsType === "mirror" &&
|
||||||
<div className="pb10">
|
<React.Fragment>
|
||||||
<p className="mt10 mb10 color-grey-3 pointer" onClick={this.changeMirrorCheck}>
|
<p className="mt10 mb10 color-grey-3 pointer" onClick={this.changeMirrorCheck}>
|
||||||
需要授权验证<i className={mirrorCheck ? "iconfont icon-xiajiantou font-13 ml10 color-grey-8":"iconfont icon-youjiantou font-13 ml10 color-grey-8"}></i>
|
需要授权验证<i className={mirrorCheck?"iconfont icon-xiajiantou font-13 ml10 color-grey-8":"iconfont icon-youjiantou font-13 ml10 color-grey-8"}></i>
|
||||||
<span className="ml20 font-12 color-red">如果导入项目为私有仓库,则必须填写相应平台正确的用户名和密码</span>
|
<span className="ml20 font-12 color-red">如果源项目为公有仓库,禁止填写用户名密码。如果源项目为私有仓库,则必须填写正确的用户名和密码!</span></p>
|
||||||
</p>
|
|
||||||
{
|
{
|
||||||
mirrorCheck &&
|
mirrorCheck &&
|
||||||
<div className="df mb10" style={{alignItems:'center'}}>
|
<div className="df mb20" style={{alignItems:'center'}}>
|
||||||
<span className="mr10">用户名</span>
|
<span className="mr10">用户名</span>
|
||||||
<input type="password" style={{display:"none"}} />
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
style={{ marginBottom: "0px" }}
|
style={{ marginBottom: "0px" }}
|
||||||
label=""
|
label=""
|
||||||
|
@ -386,153 +383,153 @@ class Index extends Component {
|
||||||
<span className="mr10">密码</span>
|
<span className="mr10">密码</span>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
style={{ marginBottom: "0px" }}
|
style={{ marginBottom: "0px" }}
|
||||||
|
label=""
|
||||||
>
|
>
|
||||||
{getFieldDecorator('password', {
|
{getFieldDecorator('password', {
|
||||||
rules: [],
|
rules: [],
|
||||||
})(
|
})(
|
||||||
<Input.Password placeholder="请输入对应平台的登录密码" autocomplete='new-password' style={{width:"240px"}}/>
|
<Input placeholder="请输入对应平台的登录密码" type="password" style={{width:"240px"}}/>
|
||||||
)}
|
)}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</React.Fragment>
|
||||||
}
|
}
|
||||||
<AlignCenter>
|
|
||||||
<Form.Item
|
|
||||||
label="拥有者"
|
|
||||||
style={{width:"260px"}}
|
|
||||||
colon={false}
|
|
||||||
className="explainPos"
|
|
||||||
>
|
|
||||||
{getFieldDecorator('user_id', {
|
|
||||||
rules: [{
|
|
||||||
required: true, message: '请选择拥有者'
|
|
||||||
},{
|
|
||||||
validator:(rule, value, callback) => this.checkId(rule, value, callback, OwnerList, '拥有者')
|
|
||||||
}],
|
|
||||||
})(
|
|
||||||
<AutoComplete
|
|
||||||
style={{width:"260px",height:"35px"}}
|
|
||||||
placeholder="请选择拥有者"
|
|
||||||
onChange={(value, e) => this.ChangePlatform(value, e, 'owners', OwnerList)}
|
|
||||||
className="plateAutoComplete"
|
|
||||||
onBlur={(value) => this.blurCategory(value, OwnerList, "owners")}
|
|
||||||
>
|
|
||||||
{owners_list}
|
|
||||||
</AutoComplete>
|
|
||||||
)}
|
|
||||||
</Form.Item>
|
|
||||||
<span className="ml10 mr10 mt10 font-18">/</span>
|
|
||||||
<Form.Item
|
|
||||||
label="项目名称"
|
|
||||||
className="flex1 explainPos"
|
|
||||||
colon={false}
|
|
||||||
>
|
|
||||||
{getFieldDecorator('name', {
|
|
||||||
rules: [{
|
|
||||||
required: true, message: '请填写项目名称'
|
|
||||||
}],
|
|
||||||
})(
|
|
||||||
<Input placeholder="例如:团队协作方法与研究" maxLength={50}/>
|
|
||||||
)}
|
|
||||||
</Form.Item>
|
|
||||||
</AlignCenter>
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label={<span>项目标识 <span className="color-grey-9">(项目url标识部分)</span></span>}
|
label="项目名称"
|
||||||
colon={false}
|
|
||||||
>
|
>
|
||||||
{getFieldDecorator('repository_name', {
|
{getFieldDecorator('name', {
|
||||||
rules: [{
|
rules: [{
|
||||||
required: true, message: '请填写项目标识'
|
required: true, message: '请填写项目名称'
|
||||||
}],
|
}],
|
||||||
})(
|
})(
|
||||||
<Input placeholder="项目标识请使用与项目相关的英文关键字" maxLength={100} />
|
<Input placeholder="例如:团队协作方法与研究" maxLength={50}/>
|
||||||
)}
|
)}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<div className="pr">
|
<div className="pr">
|
||||||
<span className="toprightNum">{descNum}/200</span>
|
<span className="toprightNum">{descNum}/200</span>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="项目简介"
|
label="项目简介"
|
||||||
colon={false}
|
|
||||||
style={{marginBottom:"0px"}}
|
|
||||||
>
|
>
|
||||||
{getFieldDecorator('description', {
|
{getFieldDecorator('description', {
|
||||||
rules: [],
|
rules: [{
|
||||||
|
required: true, message: '请填写项目简介'
|
||||||
|
}],
|
||||||
})(
|
})(
|
||||||
<Input.TextArea maxLength={200} placeholder="项目的介绍" autoSize={{ minRows: 2, maxRows: 6 }} onChange={this.changeDesc}/>
|
<Input.TextArea maxLength={200} placeholder="项目的介绍" autoSize={{ minRows: 2, maxRows: 6 }} onChange={this.changeDesc}/>
|
||||||
)}
|
)}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</div>
|
</div>
|
||||||
|
<Form.Item
|
||||||
|
label="仓库名称"
|
||||||
|
>
|
||||||
|
{getFieldDecorator('repository_name', {
|
||||||
|
rules: [{
|
||||||
|
required: true, message: '请填写仓库名称'
|
||||||
|
}],
|
||||||
|
})(
|
||||||
|
<Input placeholder="仓库名称请使用与项目相关的英文关键字" maxLength={100} />
|
||||||
|
)}
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label="项目类别"
|
||||||
|
>
|
||||||
|
{getFieldDecorator('project_category', {
|
||||||
|
rules: [{
|
||||||
|
required: true, message: '请选择大类别',
|
||||||
|
}, {
|
||||||
|
validator: (rule, value, callback) => this.checkId(rule, value, callback, CategoryList, '项目类别')
|
||||||
|
}],
|
||||||
|
})(
|
||||||
|
<AutoComplete
|
||||||
|
placeholder="请选择项目类别"
|
||||||
|
onChange={(value, e) => this.ChangePlatform(value, e, 'project_category', CategoryList)}
|
||||||
|
className="plateAutoComplete"
|
||||||
|
onBlur={(value) => this.blurCategory(value, CategoryList, "project_category")}
|
||||||
|
>
|
||||||
|
{project_category_list}
|
||||||
|
</AutoComplete>
|
||||||
|
)}
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label="项目语言"
|
||||||
|
>
|
||||||
|
{getFieldDecorator('project_language', {
|
||||||
|
rules: [{
|
||||||
|
required: true, message: '请选择项目语言'
|
||||||
|
}, {
|
||||||
|
validator: (rule, value, callback) => this.checkId(rule, value, callback, LanguageList, '项目语言')
|
||||||
|
}],
|
||||||
|
})(
|
||||||
|
<AutoComplete
|
||||||
|
placeholder="请选择项目语言"
|
||||||
|
onChange={(value, e) => this.ChangePlatform(value, e, 'project_language', LanguageList)}
|
||||||
|
className="plateAutoComplete"
|
||||||
|
onBlur={(value) => this.blurCategory(value, LanguageList, "project_language")}
|
||||||
|
>
|
||||||
|
{project_language_list}
|
||||||
|
</AutoComplete>
|
||||||
|
)}
|
||||||
|
</Form.Item>
|
||||||
{
|
{
|
||||||
(projectsType === "deposit" || !projectsType) &&
|
(projectsType === "deposit" || !projectsType) &&
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
className="privatePart"
|
label=".gitignore"
|
||||||
>
|
>
|
||||||
{getFieldDecorator('ignoreFlag')(
|
{getFieldDecorator('ignore', {
|
||||||
<Checkbox checked={ignoreFlag} onChange={(e)=>this.setState({ignoreFlag:e.target.checked})}>.gitignore</Checkbox>
|
rules: [{
|
||||||
|
required: true, message: '请选择gitignore'
|
||||||
|
}, {
|
||||||
|
validator: (rule, value, callback) => this.checkId(rule, value, callback, GitignoreList, 'gitignore')
|
||||||
|
}],
|
||||||
|
})(
|
||||||
|
<AutoComplete
|
||||||
|
placeholder="请选择gitignore,用来定义哪些文件不需要添加到版本管理中"
|
||||||
|
onChange={(value, e) => this.ChangePlatform(value, e, 'ignore', GitignoreList)}
|
||||||
|
className="plateAutoComplete"
|
||||||
|
onBlur={(value) => this.blurCategory(value, GitignoreList, "ignore")}
|
||||||
|
>
|
||||||
|
{ignore_list}
|
||||||
|
</AutoComplete>
|
||||||
)}
|
)}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
{ ignoreFlag &&
|
|
||||||
<Form.Item>
|
|
||||||
{getFieldDecorator('ignore', {
|
|
||||||
rules: [{
|
|
||||||
required: ignoreFlag, message: '请选择gitignore'
|
|
||||||
}, {
|
|
||||||
validator: (rule, value, callback) => this.checkId(rule, value, callback, GitignoreList, 'gitignore')
|
|
||||||
}],
|
|
||||||
})(
|
|
||||||
<AutoComplete
|
|
||||||
placeholder="请选择gitignore,用来定义哪些文件不需要添加到版本管理中"
|
|
||||||
onChange={(value, e) => this.ChangePlatform(value, e, 'ignore', GitignoreList)}
|
|
||||||
className="plateAutoComplete"
|
|
||||||
onBlur={(value) => this.blurCategory(value, GitignoreList, "ignore")}
|
|
||||||
>
|
|
||||||
{ignore_list}
|
|
||||||
</AutoComplete>
|
|
||||||
)}
|
|
||||||
</Form.Item>
|
|
||||||
}
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
className="privatePart"
|
label="开源许可证"
|
||||||
>
|
>
|
||||||
{getFieldDecorator('licenseFlag')(
|
{getFieldDecorator('license', {
|
||||||
<Checkbox checked={licenseFlag} onChange={(e)=>this.setState({licenseFlag:e.target.checked})}>开源许可证</Checkbox>
|
rules: [{
|
||||||
|
required: true, message: '请选择开源许可证'
|
||||||
|
}, {
|
||||||
|
validator: (rule, value, callback) => this.checkId(rule, value, callback, LicensesList, '开源许可证')
|
||||||
|
}],
|
||||||
|
})(
|
||||||
|
<AutoComplete
|
||||||
|
placeholder="请选择开源许可证"
|
||||||
|
onChange={(value, e) => this.ChangePlatform(value, e, 'license', LicensesList)}
|
||||||
|
className="plateAutoComplete"
|
||||||
|
onBlur={(value) => this.blurCategory(value, LicensesList, "license")}
|
||||||
|
>
|
||||||
|
{license_list}
|
||||||
|
</AutoComplete>
|
||||||
)}
|
)}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
{ licenseFlag &&
|
|
||||||
<Form.Item>
|
|
||||||
{getFieldDecorator('license', {
|
|
||||||
rules: [{
|
|
||||||
required: licenseFlag, message: '请选择开源许可证'
|
|
||||||
}, {
|
|
||||||
validator: (rule, value, callback) => this.checkId(rule, value, callback, LicensesList, '开源许可证')
|
|
||||||
}],
|
|
||||||
})(
|
|
||||||
<AutoComplete
|
|
||||||
placeholder="请选择开源许可证"
|
|
||||||
onChange={(value, e) => this.ChangePlatform(value, e, 'license', LicensesList)}
|
|
||||||
className="plateAutoComplete"
|
|
||||||
onBlur={(value) => this.blurCategory(value, LicensesList, "license")}
|
|
||||||
>
|
|
||||||
{license_list}
|
|
||||||
</AutoComplete>
|
|
||||||
)}
|
|
||||||
</Form.Item>
|
|
||||||
}
|
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
}
|
}
|
||||||
<Form.Item
|
<Form.Item
|
||||||
|
label="可见性"
|
||||||
|
style={{ margin: "0px" }}
|
||||||
className="privatePart"
|
className="privatePart"
|
||||||
>
|
>
|
||||||
{getFieldDecorator('private')(
|
{getFieldDecorator('private')(
|
||||||
<Checkbox value="limit">将项目设为私有<span className="font-13 color-grey-9">(只有项目所有人或拥有权限的项目成员才能看到)</span></Checkbox>
|
<Checkbox value="limit">将项目设为私有<span className="ml15 font-13 color-grey-9">(只有项目所有人或拥有权限的项目成员才能看到)</span></Checkbox>
|
||||||
)}
|
)}
|
||||||
</Form.Item >
|
</Form.Item >
|
||||||
{
|
{
|
||||||
projectsType && projectsType === "mirror" &&
|
projectsType && projectsType === "mirror" &&
|
||||||
<Form.Item
|
<Form.Item
|
||||||
|
label="迁移类型:"
|
||||||
|
style={{ margin: "0px" }}
|
||||||
className="privatePart"
|
className="privatePart"
|
||||||
>
|
>
|
||||||
{getFieldDecorator('is_mirror')(
|
{getFieldDecorator('is_mirror')(
|
||||||
|
@ -540,69 +537,12 @@ class Index extends Component {
|
||||||
)}
|
)}
|
||||||
</Form.Item >
|
</Form.Item >
|
||||||
}
|
}
|
||||||
<Form.Item
|
<div>
|
||||||
style={{ margin: "0px" }}
|
|
||||||
className="privatePart"
|
|
||||||
>
|
|
||||||
{getFieldDecorator('categoreFlag')(
|
|
||||||
<Checkbox checked={categoreFlag} onChange={(e)=>this.setState({categoreFlag:e.target.checked})}>项目类别</Checkbox>
|
|
||||||
)}
|
|
||||||
</Form.Item>
|
|
||||||
{categoreFlag &&
|
|
||||||
<Form.Item
|
|
||||||
className="privatePart"
|
|
||||||
>
|
|
||||||
{getFieldDecorator('project_category', {
|
|
||||||
rules: [{
|
|
||||||
required: categoreFlag, message: '请选择项目类别',
|
|
||||||
}, {
|
|
||||||
validator: (rule, value, callback) => this.checkId(rule, value, callback, CategoryList, '项目类别')
|
|
||||||
}],
|
|
||||||
})(
|
|
||||||
<AutoComplete
|
|
||||||
placeholder="请选择项目类别"
|
|
||||||
onChange={(value, e) => this.ChangePlatform(value, e, 'project_category', CategoryList)}
|
|
||||||
className="plateAutoComplete"
|
|
||||||
onBlur={(value) => this.blurCategory(value, CategoryList, "project_category")}
|
|
||||||
>
|
|
||||||
{project_category_list}
|
|
||||||
</AutoComplete>
|
|
||||||
)}
|
|
||||||
</Form.Item>
|
|
||||||
}
|
|
||||||
<Form.Item
|
|
||||||
className="privatePart"
|
|
||||||
>
|
|
||||||
{getFieldDecorator('languageFlag')(
|
|
||||||
<Checkbox checked={languageFlag} onChange={(e)=>this.setState({languageFlag:e.target.checked})}>项目语言</Checkbox>
|
|
||||||
)}
|
|
||||||
</Form.Item>
|
|
||||||
{languageFlag &&
|
|
||||||
<Form.Item>
|
|
||||||
{getFieldDecorator('project_language', {
|
|
||||||
rules: [{
|
|
||||||
required: languageFlag, message: '请选择项目语言'
|
|
||||||
}, {
|
|
||||||
validator: (rule, value, callback) => this.checkId(rule, value, callback, LanguageList, '项目语言')
|
|
||||||
}],
|
|
||||||
})(
|
|
||||||
<AutoComplete
|
|
||||||
placeholder="请选择项目语言"
|
|
||||||
onChange={(value, e) => this.ChangePlatform(value, e, 'project_language', LanguageList)}
|
|
||||||
className="plateAutoComplete"
|
|
||||||
onBlur={(value) => this.blurCategory(value, LanguageList, "project_language")}
|
|
||||||
>
|
|
||||||
{project_language_list}
|
|
||||||
</AutoComplete>
|
|
||||||
)}
|
|
||||||
</Form.Item>
|
|
||||||
}
|
|
||||||
<div className="mt20">
|
|
||||||
注:<span className="ant-form-item-required"></span> 为必填项,否则为选填
|
注:<span className="ant-form-item-required"></span> 为必填项,否则为选填
|
||||||
</div>
|
</div>
|
||||||
<Form.Item className="formTip mt20">
|
<Form.Item className="formTip mt20">
|
||||||
<Button type="primary" onClick={this.subMitFrom} className="mr20">{projectsType && projectsType === "mirror" ? "导入" : "创建"}项目</Button>
|
<Button type="primary" onClick={this.subMitFrom} className="mr20">创建项目</Button>
|
||||||
<Link to={'/explore'} className="btn_32">取消</Link>
|
<Link to={'/projects'} className="btn_32">取消</Link>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
|
@ -12,13 +12,7 @@
|
||||||
border-bottom: 1px solid #f0f0f0
|
border-bottom: 1px solid #f0f0f0
|
||||||
}
|
}
|
||||||
.newPanel_content{
|
.newPanel_content{
|
||||||
padding:2rem;
|
padding:1rem 2rem;
|
||||||
}
|
|
||||||
.newPanel_content form .ant-row.ant-form-item{
|
|
||||||
margin-bottom: 25px;
|
|
||||||
}
|
|
||||||
.newPanel_content .ant-form-item-label label{
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
}
|
||||||
.newPanel_content .ant-form-item-control-wrapper{
|
.newPanel_content .ant-form-item-control-wrapper{
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
@ -31,35 +25,24 @@
|
||||||
height: 35px;
|
height: 35px;
|
||||||
line-height: 35px;
|
line-height: 35px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.newContent_inline{
|
.newContent_inline{
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items:flex-end
|
align-items:flex-end
|
||||||
}
|
}
|
||||||
.explainPos{
|
|
||||||
.ant-form-explain{
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.newContent_inline > .ant-form-item:nth-child(2){
|
.newContent_inline > .ant-form-item:nth-child(2){
|
||||||
margin-left: 20px;
|
margin-left: 20px;
|
||||||
}
|
}
|
||||||
.privatePart{
|
.newPanel_content .privatePart .ant-form-item-label{
|
||||||
margin-bottom: 0px!important;
|
margin-left: 0px;
|
||||||
.ant-form-item-label{
|
|
||||||
margin-left: 0px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.newPanel_content .ant-form-item-label{
|
.newPanel_content .ant-form-item-label{
|
||||||
line-height: 25px;
|
line-height: 25px;
|
||||||
height: 25px;
|
height: 25px;
|
||||||
}
|
margin-left: -0.8rem;
|
||||||
.plateAutoComplete{
|
|
||||||
.ant-input{
|
|
||||||
height: 34px!important;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@media screen and (max-width: 750px){
|
@media screen and (max-width: 750px){
|
||||||
.newPanel_content{
|
.newPanel_content{
|
|
@ -65,18 +65,16 @@ 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>
|
||||||
<div className="editorBorder">
|
<Meditor
|
||||||
<Meditor
|
{...this.props}
|
||||||
{...this.props}
|
{...this.state}
|
||||||
{...this.state}
|
filepath={`${file_path}`}
|
||||||
filepath={`${file_path}`}
|
language = {language}
|
||||||
language = {language}
|
content={undefined}
|
||||||
content={undefined}
|
readOnly={false}
|
||||||
readOnly={false}
|
editorType="new"
|
||||||
editorType="new"
|
descName={filename && `Add ${filename}`}
|
||||||
descName={filename && `Add ${filename}`}
|
></Meditor>
|
||||||
></Meditor>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
|
|
|
@ -83,8 +83,8 @@ class UserSubmitComponent extends Component {
|
||||||
if (result.data && result.data.name) {
|
if (result.data && result.data.name) {
|
||||||
this.props.showNotification("文件新建成功!");
|
this.props.showNotification("文件新建成功!");
|
||||||
if(submitType === "1"){
|
if(submitType === "1"){
|
||||||
const { getDetail } = this.props;
|
const { getTopCount } = this.props;
|
||||||
getDetail && getDetail();
|
getTopCount && getTopCount(values.branchname);
|
||||||
}
|
}
|
||||||
let url = `/${owner}/${projectsId}${values.branchname ? `/tree/${turnbar(values.branchname)}`: (branch ? `/tree/${turnbar(branch)}` : "")}`;
|
let url = `/${owner}/${projectsId}${values.branchname ? `/tree/${turnbar(values.branchname)}`: (branch ? `/tree/${turnbar(branch)}` : "")}`;
|
||||||
this.props.history.push(url);
|
this.props.history.push(url);
|
||||||
|
@ -147,7 +147,6 @@ class UserSubmitComponent extends Component {
|
||||||
const { current_user, filepath, projectDetail , currentBranch } = this.props;
|
const { current_user, filepath, projectDetail , currentBranch } = this.props;
|
||||||
const { editor_type } = this.props;
|
const { editor_type } = this.props;
|
||||||
let b = currentBranch || branch;
|
let b = currentBranch || branch;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<span className="df" style={{ alignItems: "center" }}>
|
<span className="df" style={{ alignItems: "center" }}>
|
||||||
|
|
|
@ -8,13 +8,7 @@
|
||||||
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;
|
||||||
|
@ -45,7 +39,7 @@
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
.ant-input-group .ant-input:focus{
|
.ant-input-group .ant-input:focus{
|
||||||
border-right: 1px solid rgba(70, 106, 255, 1)!important;
|
border-right: 1px solid #d9d9d9!important;
|
||||||
}
|
}
|
||||||
.ant-btn-primary.grey{
|
.ant-btn-primary.grey{
|
||||||
border:1px solid #BBBBBB;
|
border:1px solid #BBBBBB;
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
import Editor from "react-monaco-editor";
|
import Editor from "react-monaco-editor";
|
||||||
// import {UnControlled as CodeMirror} from 'react-codemirror2'
|
|
||||||
|
|
||||||
import UserSubmitComponent from "./UserSubmitComponent";
|
import UserSubmitComponent from "./UserSubmitComponent";
|
||||||
|
|
||||||
import "./index.css";
|
import "./index.css";
|
||||||
|
@ -12,7 +10,6 @@ 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)=>{
|
||||||
|
@ -44,92 +41,42 @@ 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 className="editorBorderBox">
|
<div>
|
||||||
<Editor
|
<div className="branchTable" style={{border:"1px solid #eee"}}>
|
||||||
language={language ? language : "plaintext"}
|
<Editor
|
||||||
theme={"vs-grey"}
|
height="400px"
|
||||||
placeholder="请输入内容"
|
language={language ? language : "plaintext"}
|
||||||
value={editorValue}
|
theme={"vs-grey"}
|
||||||
options={editor_options}
|
placeholder="请输入内容"
|
||||||
onChange={this.changeEditor}
|
value={editorValue}
|
||||||
editorWillMount={this.editorWillMount}
|
options={editor_options}
|
||||||
editorDidMount={handleEditorMount}
|
onChange={this.changeEditor}
|
||||||
/>
|
editorWillMount={this.editorWillMount}
|
||||||
{/* <CodeMirror
|
/>
|
||||||
value={editorValue}
|
</div>
|
||||||
options={{
|
{!readOnly && (
|
||||||
theme: 'monokai',
|
<div style={{marginTop:"20px",padding:"20px"}}>
|
||||||
mode: 'JavaScript',
|
<UserSubmitComponent
|
||||||
extraKeys: {"Ctrl": "autocomplete"},//ctrl可以弹出提示
|
{...this.props}
|
||||||
styleActiveLine: true,
|
{...this.state}
|
||||||
lineNumbers: true,
|
filepath={`${this.props.filepath}`}
|
||||||
readOnly:true
|
content={editorValue}
|
||||||
}}
|
editor_type={editorType}
|
||||||
/> */}
|
currentBranch={currentBranch}
|
||||||
</div>
|
descName={descName}
|
||||||
{!readOnly && (
|
></UserSubmitComponent>
|
||||||
<div className="editorBorderSubmitBox" style={{marginTop:"20px",padding:"20px"}}>
|
</div>
|
||||||
<UserSubmitComponent
|
)}
|
||||||
{...this.props}
|
</div>
|
||||||
{...this.state}
|
|
||||||
filepath={`${this.props.filepath}`}
|
|
||||||
content={editorValue}
|
|
||||||
editor_type={editorType}
|
|
||||||
currentBranch={currentBranch}
|
|
||||||
descName={descName}
|
|
||||||
></UserSubmitComponent>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React , { Component } from 'react';
|
import React , { Component } from 'react';
|
||||||
|
|
||||||
import nodata from './Images/nodata.png';
|
import nodata from './Images/nodata.png';
|
||||||
import './css/index.scss';
|
|
||||||
class Nodata extends Component{
|
class Nodata extends Component{
|
||||||
render(){
|
render(){
|
||||||
const { _html , small } = this.props;
|
const { _html , small } = this.props;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue