Compare commits
346 Commits
master
...
dev_milita
Author | SHA1 | Date |
---|---|---|
![]() |
17d76aef35 | |
![]() |
472f20ae06 | |
![]() |
f61c5b7da5 | |
![]() |
9bb665c5d8 | |
![]() |
a58c7403b7 | |
![]() |
caaac57936 | |
![]() |
7b1f4759b6 | |
![]() |
d3419fba42 | |
![]() |
579cfc4ba0 | |
![]() |
bf5f865cc0 | |
![]() |
f1309a58d5 | |
![]() |
56676afdb7 | |
![]() |
f9f1a49a17 | |
![]() |
d1676b811d | |
![]() |
1f1c29720a | |
![]() |
6e7eecc5de | |
![]() |
c10de5ac30 | |
![]() |
c255e031be | |
![]() |
1162d7e7f4 | |
![]() |
b138d774fc | |
![]() |
aa9e75b4fd | |
![]() |
6c750cc68b | |
![]() |
b586eb9bec | |
![]() |
e751e5a7b4 | |
![]() |
86e6d0a9f1 | |
![]() |
03bdd37b2f | |
![]() |
7ca0af877e | |
![]() |
4047f08663 | |
![]() |
5b83144e2e | |
![]() |
135922bf30 | |
![]() |
05e5d4eb6c | |
|
d7b3303bcb | |
![]() |
507fe8788f | |
![]() |
d6dda2a980 | |
![]() |
8f0abdad2e | |
![]() |
ba93a044d3 | |
![]() |
a4e453a221 | |
![]() |
4e5b2dea73 | |
![]() |
ba3b6b5917 | |
![]() |
aa805dc22c | |
![]() |
65d616b116 | |
![]() |
17bdcd61ee | |
![]() |
a9cb22374d | |
![]() |
c6de7d0bde | |
![]() |
d52afc2cd4 | |
![]() |
dbcbc2c9ff | |
|
4357b1a546 | |
![]() |
7aeeb5c93e | |
![]() |
53cad9df93 | |
![]() |
a4cd1b4c1d | |
![]() |
b1305961d4 | |
|
7e27014dde | |
|
10c237498e | |
|
070f869aa6 | |
![]() |
c14ee5c359 | |
|
7ee151e652 | |
![]() |
7e3e35784e | |
![]() |
90f8e04e93 | |
![]() |
0dc7a1f582 | |
![]() |
b6f2eb107c | |
![]() |
3f6165585d | |
![]() |
e4005a03b3 | |
|
846a24aef4 | |
|
955eed9232 | |
![]() |
fee2aec384 | |
![]() |
97f3fa75c1 | |
|
eb180d3570 | |
|
9276136bfe | |
|
1bad39e83a | |
|
c9e7da7df3 | |
|
7f0b770dca | |
|
70536036e1 | |
|
2d8c3c5853 | |
|
0f92ff94a0 | |
|
6507c87bc8 | |
|
b423e4b7e7 | |
|
76b4cf0d9b | |
|
6d2a50ef5e | |
|
938be1da55 | |
|
954cf38074 | |
|
8de1c7a0d3 | |
|
82c35888f4 | |
|
bdcc7a4699 | |
|
e4d4375102 | |
|
b926be1c58 | |
|
54bffb41da | |
|
7c9bf94b91 | |
|
4097ebb69b | |
|
162fd200a5 | |
|
6611b6d16f | |
|
cc9cf251fe | |
|
8b3f4b3b5a | |
|
c6bc26c5ae | |
|
6e7da0ef5b | |
|
d9bd0387db | |
|
c0cfe12db4 | |
|
dc6cfc342e | |
|
c3ecbe1f97 | |
|
a59a8c3693 | |
|
14e4dc7d9e | |
|
97f62a5684 | |
|
e74a3b6a95 | |
|
38878183d5 | |
|
0e0c13f1a4 | |
|
a667a32de0 | |
|
230e597787 | |
|
f0ea3a53c4 | |
|
51a4680481 | |
|
61a4882e58 | |
|
148e8f91eb | |
|
8f52a091fa | |
|
62eabdf7c0 | |
|
d5490d5e71 | |
|
cef374c52d | |
|
7be60d3140 | |
|
feafa5b6f3 | |
|
2dd6ed108f | |
|
969323fdde | |
|
a73b4ff79a | |
|
16ca2a359e | |
|
444d954e72 | |
|
6fc31c0bb8 | |
|
cf73f72e19 | |
|
745a25a003 | |
|
b080df1449 | |
|
0aa2a4aec3 | |
|
4dc1c4c814 | |
|
ddc576b054 | |
|
caef7a0ab3 | |
|
85f0578302 | |
|
bff55b6810 | |
|
01f71bca87 | |
|
d3cea0ff3b | |
|
be6e3d273b | |
|
6b8f1e3749 | |
|
b5e145b4b5 | |
|
15b63be594 | |
|
032127bef6 | |
|
f4f843a7b9 | |
|
4cf8357463 | |
|
0ff1367ad8 | |
|
0e44cbbcdd | |
|
e736591a4f | |
|
d15900fc7c | |
|
4f87542f1f | |
|
94ee3601c9 | |
|
19d09c7901 | |
|
3b29605321 | |
|
6e82862307 | |
|
700ac5862e | |
|
4ccab2ed4f | |
|
3f3299a3b8 | |
|
b73a38351b | |
|
586c5d6d1d | |
|
819772d180 | |
|
e733f1886e | |
|
86d2442958 | |
|
b7fc83edf9 | |
|
74325b5dc7 | |
|
a25959bfa0 | |
|
fe72be2f30 | |
|
4d41f44100 | |
|
afa839e0b1 | |
|
83d59a2e64 | |
|
758f4267ed | |
|
38948a84cd | |
|
51d739f4a0 | |
|
706830928e | |
|
8dc08c3992 | |
|
70ec86569f | |
|
00b41844bb | |
|
81c93d2580 | |
|
a87e55103c | |
|
05101c5e32 | |
|
e72b3e687f | |
|
f25a52622d | |
|
f5fa216b23 | |
|
a57b96a1b8 | |
|
8efbea44ab | |
|
fa80b5d1df | |
|
6c95ff98f4 | |
|
cb7170a87c | |
|
7757e4b6b7 | |
|
cad9a4fc3a | |
|
dc20d3e270 | |
|
4503e1b176 | |
|
91fe328eaf | |
|
8d9d5c3ce3 | |
|
a2aa344e31 | |
|
981e199273 | |
|
b6d6309c3c | |
|
16aac3b835 | |
|
bdf3a8e72a | |
|
507976bf10 | |
|
b6c2c66321 | |
|
0b7fbe564c | |
|
ce958f3369 | |
|
0e176d9334 | |
|
3608b7b712 | |
|
b9888a81f6 | |
|
0bb6ec51c2 | |
|
7d2c90dfd1 | |
|
66c5f09813 | |
|
a4d38f8c86 | |
|
21a3c54754 | |
|
4493711521 | |
|
76b23f88db | |
|
bca9499844 | |
|
3137048aed | |
|
62b5d86082 | |
|
7a472651f1 | |
|
99c90295c0 | |
|
d7fd642f7f | |
|
97bc41e771 | |
|
6156d98af2 | |
|
6facc3e65f | |
|
c8f6891239 | |
|
11b5c87888 | |
|
2f538ff394 | |
|
48a153d434 | |
|
9c3ecabf47 | |
|
f18070da47 | |
|
1e87e0c8ec | |
|
bec68aa090 | |
|
aed83337fa | |
|
e5b7110090 | |
|
716916b7b6 | |
|
b5ccdbfcd6 | |
|
1e7df569e6 | |
|
701d9dfc99 | |
|
e7b3a01c47 | |
|
b19c084ac8 | |
|
1d4bb3f4fc | |
|
e0b267bd6c | |
|
4bf4aa7c78 | |
|
e3643be01b | |
|
9c8add0152 | |
|
edb7099131 | |
|
cce818d4e0 | |
![]() |
909663bc47 | |
|
9ea9da9672 | |
|
97bd7673e1 | |
|
2aa89426ad | |
|
5131dacf05 | |
|
6b63cd25aa | |
![]() |
8162b8b908 | |
|
7a59d43eec | |
![]() |
008ba8d1de | |
|
98a9344b02 | |
|
b8342288dd | |
|
09e81b9e78 | |
![]() |
7cf5e23cb9 | |
|
8594168d33 | |
![]() |
2d7c6cb82d | |
![]() |
c36925c136 | |
|
6ec6ab2308 | |
|
4109e4b07e | |
|
216e984740 | |
|
92f3934d5e | |
|
2ed7e0d4c4 | |
|
6cfe81aea3 | |
|
4dcbd51482 | |
|
c32b333bc2 | |
|
c965da7dd5 | |
|
b44399968f | |
|
2591f28ccc | |
|
5530e8c723 | |
|
fa26dc9fa5 | |
|
4cf40f9dfc | |
|
2c034f5dff | |
|
d68d8318c1 | |
|
41ae6b1f8d | |
|
a6e2171fca | |
|
916cc293ac | |
|
5565eac601 | |
|
860b71c7c6 | |
|
f1c2841fe0 | |
|
c6d5078d42 | |
|
ebe2d625fa | |
|
b5e1a91af5 | |
|
4b8d72a6eb | |
|
f0e1858cd4 | |
|
a92468953a | |
|
fdab967b6a | |
|
7e8929f166 | |
|
0a39ed80da | |
|
5ed44f1d63 | |
|
64e639ebea | |
|
3fb9eb40f3 | |
|
efc2443bb8 | |
|
2c3d917bd4 | |
|
617f139f52 | |
|
de550d5f42 | |
|
f12230dc91 | |
|
1df2639cd5 | |
|
c746e9e634 | |
|
d8d464a332 | |
|
83e337b2e9 | |
|
5a6b7bd717 | |
|
c68a3dbd6f | |
|
350f9426ea | |
|
5bda100e32 | |
|
dde7fa730a | |
|
3f8f1b8083 | |
|
6eef4bd09e | |
|
0dcaea3db4 | |
|
033134fa83 | |
|
1bab0b01f7 | |
|
7b2f233cae | |
|
2ecdd73c7f | |
|
4e7a2fa3d7 | |
|
91662e2e3e | |
|
c2129c994a | |
|
e968ece34c | |
|
70d407963e | |
|
00ccba74a1 | |
|
0790abb6f9 | |
|
6c4c161a1b | |
|
65a2bd43cf | |
|
10f813a443 | |
|
e79ec30c81 | |
|
2a7fea3612 | |
|
cc46a3ac30 | |
|
cca5f98c9b | |
|
d4535005c8 | |
|
73d128e0c9 | |
|
f09457a0ac | |
|
78c218b12b | |
|
d9f87fdd18 | |
|
33c3395221 | |
|
74d26a40d3 | |
|
3f78ed249c | |
|
07e1525f09 | |
|
a9161b86a2 | |
|
e0e6cdcc79 | |
|
3b0c708d82 | |
|
0922df3875 | |
|
ad3fe09cfb | |
|
91f4327eb4 | |
|
f2f910b5e4 | |
|
85d924db70 | |
![]() |
f1614a4b62 | |
![]() |
2fa71241db | |
![]() |
13c6556574 | |
|
5601b71937 | |
![]() |
1a024f8011 |
|
@ -86,3 +86,6 @@ typings/
|
||||||
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.idea/*
|
.idea/*
|
||||||
|
|
||||||
|
package.json
|
||||||
|
package-lock.json
|
|
@ -101,9 +101,13 @@ module.exports = {
|
||||||
extensions: [".web.js", ".mjs", ".js", ".json", ".web.jsx", ".jsx"],
|
extensions: [".web.js", ".mjs", ".js", ".json", ".web.jsx", ".jsx"],
|
||||||
alias: {
|
alias: {
|
||||||
educoder: __dirname + "/../src/common/educoder.js",
|
educoder: __dirname + "/../src/common/educoder.js",
|
||||||
|
src: path.join(paths.appSrc), // 整个源代码目录
|
||||||
|
forge: path.join(paths.appSrc, 'forge'),
|
||||||
|
military: path.join(paths.appSrc, 'military'),
|
||||||
// Support React Native Web
|
// Support React Native Web
|
||||||
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
|
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
|
||||||
"react-native": "react-native-web",
|
"react-native": "react-native-web",
|
||||||
|
'react-dom': '@hot-loader/react-dom',
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
// Prevents users from importing files from outside of src/ (or node_modules/).
|
// Prevents users from importing files from outside of src/ (or node_modules/).
|
||||||
|
|
|
@ -87,6 +87,9 @@ module.exports = {
|
||||||
extensions: [".web.js", ".mjs", ".js", ".json", ".web.jsx", ".jsx"],
|
extensions: [".web.js", ".mjs", ".js", ".json", ".web.jsx", ".jsx"],
|
||||||
alias: {
|
alias: {
|
||||||
educoder: __dirname + "/../src/common/educoder.js",
|
educoder: __dirname + "/../src/common/educoder.js",
|
||||||
|
src: path.join(paths.appSrc),
|
||||||
|
forge: path.join(paths.appSrc, 'forge'),
|
||||||
|
military: path.join(paths.appSrc, 'military'),
|
||||||
// Support React Native Web
|
// Support React Native Web
|
||||||
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
|
// https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/
|
||||||
"react-native": "react-native-web",
|
"react-native": "react-native-web",
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"educoder": ["./src/common/educoder.js"],
|
||||||
|
"forge":["./src/forge"],
|
||||||
|
"military":["./src/military"],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"node_modules",
|
||||||
|
"build"
|
||||||
|
]
|
||||||
|
}
|
12
package.json
|
@ -80,6 +80,7 @@
|
||||||
"react-color": "^2.18.0",
|
"react-color": "^2.18.0",
|
||||||
"react-content-loader": "^3.1.1",
|
"react-content-loader": "^3.1.1",
|
||||||
"react-cookies": "^0.1.1",
|
"react-cookies": "^0.1.1",
|
||||||
|
"react-countup": "^6.1.0",
|
||||||
"react-datepicker": "^2.14.1",
|
"react-datepicker": "^2.14.1",
|
||||||
"react-dev-utils": "^9.2.0-next.80",
|
"react-dev-utils": "^9.2.0-next.80",
|
||||||
"react-dom": "^16.13.1",
|
"react-dom": "^16.13.1",
|
||||||
|
@ -92,6 +93,7 @@
|
||||||
"react-resizable": "^1.10.1",
|
"react-resizable": "^1.10.1",
|
||||||
"react-router": "^4.2.0",
|
"react-router": "^4.2.0",
|
||||||
"react-router-dom": "^4.2.2",
|
"react-router-dom": "^4.2.2",
|
||||||
|
"react-slick": "^0.28.1",
|
||||||
"react-split-pane": "^0.1.91",
|
"react-split-pane": "^0.1.91",
|
||||||
"react-url-query": "^1.5.0",
|
"react-url-query": "^1.5.0",
|
||||||
"react-zmage": "^0.8.5-beta.31",
|
"react-zmage": "^0.8.5-beta.31",
|
||||||
|
@ -102,22 +104,22 @@
|
||||||
"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",
|
||||||
|
"slick-carousel": "^1.8.1",
|
||||||
"store": "^2.0.12",
|
"store": "^2.0.12",
|
||||||
"style-loader": "0.19.0",
|
"style-loader": "0.19.0",
|
||||||
"styled-components": "^4.4.1",
|
"styled-components": "^4.4.1",
|
||||||
"sw-precache-webpack-plugin": "0.11.4",
|
"sw-precache-webpack-plugin": "0.11.4",
|
||||||
"url-loader": "0.6.2",
|
"url-loader": "0.6.2",
|
||||||
|
"wangeditor-for-react": "^1.4.0",
|
||||||
"webpack-cli": "^3.3.11",
|
"webpack-cli": "^3.3.11",
|
||||||
"webpack-dev-server": "^3.10.3",
|
"webpack-dev-server": "^3.10.3",
|
||||||
"webpack-manifest-plugin": "^2.2.0",
|
"webpack-manifest-plugin": "^2.2.0",
|
||||||
"whatwg-fetch": "2.0.3",
|
"whatwg-fetch": "2.0.3",
|
||||||
"wrap-md-editor": "^0.2.20",
|
"wrap-md-editor": "^0.2.20"
|
||||||
"xterm": "4.8.1",
|
|
||||||
"xterm-addon-fit": "0.4.0"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node --max_old_space_size=15360 scripts/start.js",
|
"start": "node --max_old_space_size=15360 scripts/start.js",
|
||||||
"build": "NODE_ENV=production node --max_old_space_size=15360 scripts/build.js",
|
"build": "cross-env NODE_ENV=production node --max_old_space_size=15360 scripts/build.js",
|
||||||
"test-build": "NODE_ENV=testBuild node --max_old_space_size=15360 scripts/build.js",
|
"test-build": "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",
|
||||||
|
@ -184,6 +186,7 @@
|
||||||
"port": "3007",
|
"port": "3007",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/runtime": "7.0.0-beta.51",
|
"@babel/runtime": "7.0.0-beta.51",
|
||||||
|
"@hot-loader/react-dom": "^16.14.0",
|
||||||
"babel-cli": "^6.26.0",
|
"babel-cli": "^6.26.0",
|
||||||
"babel-core": "^6.26.0",
|
"babel-core": "^6.26.0",
|
||||||
"babel-plugin-import": "^1.13.0",
|
"babel-plugin-import": "^1.13.0",
|
||||||
|
@ -193,6 +196,7 @@
|
||||||
"babel-preset-stage-2": "^6.24.1",
|
"babel-preset-stage-2": "^6.24.1",
|
||||||
"compression-webpack-plugin": "^1.1.12",
|
"compression-webpack-plugin": "^1.1.12",
|
||||||
"concat": "^1.0.3",
|
"concat": "^1.0.3",
|
||||||
|
"cross-env": "^7.0.3",
|
||||||
"happypack": "^5.0.1",
|
"happypack": "^5.0.1",
|
||||||
"mockjs": "^1.1.0",
|
"mockjs": "^1.1.0",
|
||||||
"node-sass": "^4.12.0",
|
"node-sass": "^4.12.0",
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
/*头部导航条样式---2018-03-19--by-cs*/
|
/*头部导航条样式---2018-03-19--by-cs*/
|
||||||
.newHeader {
|
.newHeader {
|
||||||
background: #24292D !important;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 60px !important;
|
height: 60px !important;
|
||||||
min-width: 1200px;
|
min-width: 1200px;
|
||||||
|
|
|
@ -2346,6 +2346,7 @@ input::-ms-clear {
|
||||||
/*中间部分宽度固定为1200*/
|
/*中间部分宽度固定为1200*/
|
||||||
.newMain {
|
.newMain {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
padding-bottom: 110px;
|
||||||
min-width: 1200px;
|
min-width: 1200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3970,7 +3971,9 @@ html>body #ajax-indicator {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: relative;
|
position: relative;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
padding:0px 20px;
|
margin-right: 40px;
|
||||||
|
}.head-nav ul#header-nav li:first-child{
|
||||||
|
margin-left: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.head-nav ul#header-nav li a {
|
.head-nav ul#header-nav li a {
|
||||||
|
@ -4107,6 +4110,21 @@ em.vertical-line {
|
||||||
|
|
||||||
/* 右侧内容宽度变化的话,需要调整posi-search right的值*/
|
/* 右侧内容宽度变化的话,需要调整posi-search right的值*/
|
||||||
|
|
||||||
|
/*底部*/
|
||||||
|
.newFooter {
|
||||||
|
max-height: 110px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.newFooter {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
background: #323232;
|
||||||
|
clear: both;
|
||||||
|
min-width: 1200px;
|
||||||
|
z-index: 8;
|
||||||
|
left: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
.footercon {
|
.footercon {
|
||||||
border-bottom: 1px solid #47494d;
|
border-bottom: 1px solid #47494d;
|
||||||
|
|
|
@ -20,27 +20,6 @@ Created by iconfont
|
||||||
/>
|
/>
|
||||||
<missing-glyph />
|
<missing-glyph />
|
||||||
|
|
||||||
<glyph glyph-name="tijiao" unicode="" d="M776.340596 759.889666l-369.442335 0c-7.573056 0-14.839097-2.967819-20.263042-8.187088L201.197681 571.177294c-5.526284-5.423946-8.801119-12.997002-8.801119-20.774735l-1.023386-513.637418c0-7.777733 2.967819-15.043774 8.494104-20.570058 5.526284-5.526284 12.792325-8.494104 20.570058-8.494104L382.746352 7.700979c12.485309 0 22.514491 10.029182 22.514491 22.514491s-10.029182 22.514491-22.514491 22.514491L236.402159 52.729962l0.921047 467.687388 194.03398 0c16.681191 0 30.189886 13.508695 30.189886 30.189886L461.547072 714.860684l298.828703 0 0-665.200879L621.195283 49.659804c-12.485309 0-22.514491-10.029182-22.514491-22.514491s10.029182-22.514491 22.514491-22.514491l155.145313 0c16.06716 0 29.064162 12.997002 29.064162 29.064162L805.404757 730.825505C805.404757 746.892664 792.407755 759.889666 776.340596 759.889666zM416.518089 565.446332 259.837697 565.446332l153.610234 149.414351 3.172497 0L416.620428 565.446332zM713.30002 434.452928c0 12.485309-10.029182 22.514491-22.514491 22.514491L326.460124 456.96742c-12.485309 0-22.514491-10.029182-22.514491-22.514491l0 0c0-12.485309 10.029182-22.514491 22.514491-22.514491l364.325405 0C703.270837 411.938437 713.30002 421.967619 713.30002 434.452928L713.30002 434.452928zM713.30002 357.698981c0 12.485309-10.029182 22.514491-22.514491 22.514491L326.460124 380.213472c-12.485309 0-22.514491-10.029182-22.514491-22.514491l0 0c0-12.485309 10.029182-22.514491 22.514491-22.514491l364.325405 0C703.270837 335.184489 713.30002 345.213672 713.30002 357.698981L713.30002 357.698981zM713.30002 279.921647c0 12.485309-10.029182 22.514491-22.514491 22.514491L326.460124 302.436138c-12.485309 0-22.514491-10.029182-22.514491-22.514491l0 0c0-12.485309 10.029182-22.514491 22.514491-22.514491l364.325405 0C703.270837 257.407156 713.30002 267.436338 713.30002 279.921647L713.30002 279.921647zM501.970818 220.155906c-1.535079 1.535079-4.093544 1.43274-5.526284-0.102339l-54.853488-59.458725c-2.251449-2.456126-0.511693-6.447332 2.865481-6.447332L479.968019 154.147511l0-88.829902c0-2.251449 1.842095-4.298221 4.093544-4.298221l36.841895 0c2.251449 0 4.093544 2.046772 4.093544 4.298221L524.997002 154.045173l35.511493 0c3.479512 0 5.219268 4.195882 2.660804 6.652009L501.970818 220.155906z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="dataBase" unicode="" d="M512 793.4c110.7 0 215-12.3 293.9-34.7 35.8-10.2 65-22.1 84.5-34.7 18.6-12 21.3-19.7 21.6-20.6-0.2-0.9-3-8.6-21.6-20.6-19.5-12.5-48.7-24.5-84.5-34.7-78.9-22.3-183.2-34.7-293.9-34.7s-215 12.3-293.9 34.7c-35.8 10.2-65 22.1-84.5 34.7-18.6 12-21.3 19.7-21.6 20.6 0.2 0.9 3 8.6 21.6 20.6 19.5 12.5 48.7 24.5 84.5 34.7 78.9 22.4 183.2 34.7 293.9 34.7M512 833.4c-243 0-440-58.2-440-130s197-130 440-130 440 58.2 440 130-197 130-440 130zM112 705.6h-40v-641h40v641zM952 705.9h-40v-641h40v641zM912 65v-0.5c-0.2-0.9-3-8.6-21.6-20.6-19.5-12.5-48.7-24.5-84.5-34.7-78.9-22.3-183.2-34.6-293.9-34.6s-215 12.3-293.9 34.7c-35.8 10.2-65 22.1-84.5 34.7-18.6 12-21.3 19.7-21.6 20.6v0.3l-40-0.3v-0.1c0-71.8 197-130 440-130s440 58.2 440 130v0.4l-40 0.1zM912 275.5v-0.5c-0.2-0.9-3-8.6-21.6-20.6-19.5-12.5-48.7-24.5-84.5-34.7-78.9-22.3-183.2-34.7-293.9-34.7s-215 12.3-293.9 34.7c-35.8 10.2-65 22.1-84.5 34.7-18.6 12-21.3 19.7-21.6 20.6v0.3l-40-0.3v-0.1c0-71.8 197-130 440-130s440 58.2 440 130v0.4l-40 0.2zM912 497v-0.5c-0.2-0.9-3-8.6-21.6-20.6-19.5-12.5-48.7-24.5-84.5-34.7-78.9-22.3-183.2-34.7-293.9-34.7s-215 12.3-293.9 34.7c-35.8 10.2-65 22.1-84.5 34.7-18.6 12-21.3 19.7-21.6 20.6v0.3l-40-0.3v-0.1c0-71.8 197-130 440-130s440 58.2 440 130v0.4l-40 0.2z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="wenjian4" unicode="" d="M751.3-61.4H274.7c-82.7 0-150 67.3-150 150V679.8c0 82.7 67.3 150 150 150h138.9c13.8 0 25-11.2 25-25s-11.2-25-25-25H274.7c-55.1 0-100-44.9-100-100v-591.2c0-55.1 44.9-100 100-100h476.6c55.1 0 100 44.9 100 100v390H653.6c-32.4 0-62.8 12.6-85.7 35.6-22.9 23-35.4 53.5-35.2 85.9l0.9 204.9c0 10 6 19 15.2 22.9 9.2 3.9 19.8 2 27-4.8l317.7-301.2 0.3-0.3 0.5-0.5c4.3-4.5 6.9-10.6 6.9-17.2v-415c0.1-83-67.2-150.3-149.9-150.3z m-168 808.3l-0.6-147.1c-0.1-19 7.3-36.9 20.7-50.4 13.4-13.5 31.3-20.9 50.3-20.9h160L583.3 746.9zM701.4 298H324.6c-13.8 0-25 11.2-25 25s11.2 25 25 25h376.8c13.8 0 25-11.2 25-25s-11.2-25-25-25zM701.4 148.7H324.6c-13.8 0-25 11.2-25 25s11.2 25 25 25h376.8c13.8 0 25-11.2 25-25s-11.2-25-25-25z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="lianjie2" unicode="" d="M427.392 259.328a40.448 40.448 0 0 0-31.168 13.376c-93.44 93.44-93.44 244.864 0 342.784l209.28 209.28c93.44 93.44 249.344 93.44 342.784 0a243.264 243.264 0 0 0 71.232-169.216c0-62.272-26.688-124.608-71.232-169.152L832.64 361.728c-17.856-17.792-44.544-17.792-57.92 0-17.792 17.792-17.792 44.544 0 57.856l120.256 120.256a155.904 155.904 0 0 1 0 222.592 155.904 155.904 0 0 1-222.656 0l-209.28-209.28a155.904 155.904 0 0 1 0-222.592c17.856-17.792 17.856-44.48 0-57.856-8.832-4.48-22.208-13.376-35.584-13.376zM240.448-128c-66.816 0-124.672 26.688-169.216 71.232A243.264 243.264 0 0 0 0 112.448c0 62.272 26.688 124.608 71.232 169.152l120.192 120.192c17.856 17.856 44.544 17.856 57.92 0 17.792-17.792 17.792-44.48 0-57.856l-120.256-120.192a155.904 155.904 0 0 1 0-222.656 158.08 158.08 0 0 1 111.36-44.48 158.08 158.08 0 0 1 111.296 44.48l209.28 209.28a158.08 158.08 0 0 1 44.48 111.36c0 44.48-17.792 80.064-44.544 111.232-17.792 17.792-17.792 44.544 0 57.92 17.792 17.792 44.544 17.792 57.92 0a243.264 243.264 0 0 0 71.232-169.216c0-66.752-26.752-124.672-71.232-169.152l-209.28-209.28C365.056-101.312 307.2-128 240.448-128z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="fenzhi2" unicode="" d="M737.792 811.2a128 128 0 0 0 36.352-250.752C761.6 440.96 690.176 374.08 567.936 369.28l-14.208-0.256c-104.704 0-179.456-21.12-225.472-61.312l0.064-121.6a128 128 0 1 0-76.8 0V561.024a128 128 0 1 0 76.8 0l-0.128-160.96c53.44 28.352 121.6 43.264 203.84 45.44l21.76 0.32c88.064 0 133.248 35.456 143.36 115.968a128 128 0 0 0 40.64 249.344zM289.92 128a64 64 0 1 1 0-128 64 64 0 0 1 0 128z m0 619.2a64 64 0 1 1 0-128 64 64 0 0 1 0 128z m447.872 0a64 64 0 1 1 0-128 64 64 0 0 1 0 128z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="fenzhi-3" unicode="" d="M199.095774 895.999795a170.536926 170.536926 0 0 0 59.166708-330.526654c30.719994-284.446663 286.719943-339.046332 406.753199-349.85977a170.577886 170.577886 0 1 0 159.866848-229.826514 171.622366 171.622366 0 0 0-161.566688 113.786857c-241.766352 11.386878-325.406655 102.973419-407.326639 205.373399v-101.273579a170.659806 170.659806 0 1 0-113.786857 0V564.346742A170.721246 170.721246 0 0 0 199.095774 895.999795m0-113.786857a56.893429 56.893429 0 1 1 56.893428-56.893429 57.057269 57.057269 0 0 1-56.893428 56.893429m0-682.659704a56.893429 56.893429 0 1 1 56.893428-56.893428 57.057269 57.057269 0 0 1-56.893428 56.893428m625.766275 113.786858a56.893429 56.893429 0 1 1 56.893428-56.893429 57.057269 57.057269 0 0 1-56.893428 56.893429z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="tianping" unicode="" d="M669.5 495.5c0-74.4 60.5-134.9 134.9-134.9s134.9 60.5 134.9 134.9c0 30.3-21.4 84.9-63.7 162.3-31 56.8-62.5 105.9-62.8 106.4v0.1c-0.2 0.3-0.4 0.6-0.7 0.9 0 0.1-0.1 0.1-0.1 0.2-0.2 0.2-0.4 0.5-0.6 0.7-0.1 0.1-0.2 0.2-0.3 0.2-0.2 0.2-0.4 0.3-0.6 0.5-0.1 0.1-0.2 0.1-0.3 0.2-0.6 0.4-1.3 0.8-2 1.1-0.1 0-0.2 0.1-0.2 0.1l-0.9 0.3c-0.1 0-0.2 0.1-0.3 0.1-0.3 0.1-0.6 0.1-0.9 0.2h-0.3c-0.4 0-0.8 0.1-1.2 0.1H556.6c-4.6 20.4-22.8 35.7-44.6 35.7s-40-15.3-44.6-35.7H221.6c-0.4 0-0.8 0-1.2-0.1h-0.3c-0.3 0-0.6-0.1-0.9-0.2-0.1 0-0.2-0.1-0.3-0.1l-0.9-0.3c-0.1 0-0.2-0.1-0.2-0.1-0.7-0.3-1.4-0.7-2-1.1-0.1-0.1-0.2-0.1-0.3-0.2-0.2-0.2-0.4-0.3-0.6-0.5-0.1-0.1-0.2-0.2-0.3-0.2l-0.7-0.7-0.1-0.1c-0.2-0.3-0.5-0.6-0.7-0.9v-0.1c-0.3-0.5-31.8-49.5-62.8-106.4-42.3-77.4-63.7-132-63.7-162.3 0-74.4 60.5-134.9 134.9-134.9s134.9 60.5 134.9 134.9c0 30.3-21.4 84.9-63.7 162.3-20.6 37.7-41.4 72-53.1 91h227.7c3.9-17.2 17.4-30.7 34.6-34.6v-587.9H315.7c-5.5 0-10-4.5-10-10V55H172.9c-5.5 0-10-4.5-10-10v-71.4c0-5.5 4.5-10 10-10h678.2c5.5 0 10 4.5 10 10V45c0 5.5-4.5 10-10 10H718.3v61.4c0 5.5-4.5 10-10 10H522V714.2c17.2 3.9 30.7 17.4 34.6 34.6h229.7c-11.7-18.9-32.5-53.2-53.2-91-42.2-77.3-63.6-131.9-63.6-162.3z m171.6-512H182.9v51.4h658.3v-51.4z m-142.8 71.4H325.7v51.4h372.7v-51.4zM221.6 380.6c-63.4 0-114.9 51.6-114.9 114.9 0 1.1 0 2.2 0.1 3.4h229.7c0.1-1.2 0.1-2.3 0.1-3.4-0.1-63.3-51.6-114.9-115-114.9z m111.3 138.3H110.2c6.3 24.4 22.1 64.2 57.6 129.2 21.1 38.6 42.4 73.6 53.7 91.9 11.4-18.3 32.7-53.3 53.7-91.9 35.6-65 51.5-104.8 57.7-129.2zM512 733.1c-14.2 0-25.7 11.5-25.7 25.7s11.5 25.7 25.7 25.7 25.7-11.5 25.7-25.7-11.5-25.7-25.7-25.7z m292.4-352.5c-63.4 0-114.9 51.6-114.9 114.9 0 1.1 0 2.3 0.1 3.5 0.6-0.1 1.1-0.2 1.7-0.2h227.9c0.1-1.2 0.1-2.3 0.1-3.4 0.1-63.2-51.5-114.8-114.9-114.8z m0 359.4c11.4-18.3 32.7-53.3 53.7-91.9 35.5-65 51.3-104.9 57.6-129.2H693.1c6.3 24.4 22.1 64.2 57.6 129.2 21.1 38.7 42.3 73.7 53.7 91.9z" horiz-adv-x="1024" />
|
|
||||||
|
|
||||||
|
|
||||||
<glyph glyph-name="chexiao" unicode="" d="M530.496 524.928h-6.144V661.632c0 51.136-29.312 72.448-65.472 43.328L122.816 434.624c-36.096-28.992-36.096-76.48 0.128-105.472l333.504-267.648c36.16-28.992 67.968 0.448 67.968 43.584v144.256h50.496c145.856 0 257.152-62.976 325.248-184.576 13.376-22.08 27.456-17.28 27.456 0-2.944 216.576-186.368 460.16-397.12 460.16z" horiz-adv-x="1024" />
|
<glyph glyph-name="chexiao" unicode="" d="M530.496 524.928h-6.144V661.632c0 51.136-29.312 72.448-65.472 43.328L122.816 434.624c-36.096-28.992-36.096-76.48 0.128-105.472l333.504-267.648c36.16-28.992 67.968 0.448 67.968 43.584v144.256h50.496c145.856 0 257.152-62.976 325.248-184.576 13.376-22.08 27.456-17.28 27.456 0-2.944 216.576-186.368 460.16-397.12 460.16z" horiz-adv-x="1024" />
|
||||||
|
|
||||||
|
|
||||||
|
|
Before Width: | Height: | Size: 733 KiB After Width: | Height: | Size: 724 KiB |
After Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 8.8 KiB After Width: | Height: | Size: 9.7 KiB |
|
@ -2,10 +2,11 @@
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name=”Keywords” Content=”trustie,trustieforge,forge,确实让创建更美好,协同开发平台″>
|
<title>红山开源社区</title>
|
||||||
<meta name=”Keywords” Content=”TrustieOpenSourceProject″>
|
<meta name="keywords" content="红山开源,创客空间,群智共享">
|
||||||
<meta name=”Keywords” Content=”issue,bug,tracker,软件工程,课程实践″>
|
<meta name="keywords" content="红山开源社区,开源开放,众创,论坛">
|
||||||
<meta name=”Description” Content=”持续构建协同、共享、可信的软件创建生态开源创作与软件生产相结合,支持大规模群体开展软件协同创新活动”>
|
<meta name="keywords" content="issue,bug,tracker">
|
||||||
|
<meta name="description" content="红山开源是一个依托互联网群体智慧实现世界范围内资源深度融合、开放共享和协同创新的开源社区" />
|
||||||
<meta name="theme-color" content="#000000">
|
<meta name="theme-color" content="#000000">
|
||||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
|
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
|
||||||
|
|
||||||
|
|
42
src/App.js
|
@ -45,6 +45,21 @@ const OpsDetail = Loadable({
|
||||||
loader: () => import('./forge/DevOps/opsDetail'),
|
loader: () => import('./forge/DevOps/opsDetail'),
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
})
|
})
|
||||||
|
// Notice项目公告
|
||||||
|
const Notice = Loadable({
|
||||||
|
loader: () => import('./military/notice'),
|
||||||
|
loading: Loading,
|
||||||
|
})
|
||||||
|
//任务/需求
|
||||||
|
const Task = Loadable({
|
||||||
|
loader: () => import('./military/task'),
|
||||||
|
loading: Loading,
|
||||||
|
})
|
||||||
|
//任务/需求
|
||||||
|
const Qz2022 = Loadable({
|
||||||
|
loader: () => import('./military/qz2022'),
|
||||||
|
loading: Loading,
|
||||||
|
});
|
||||||
//403页面
|
//403页面
|
||||||
const Shixunauthority = Loadable({
|
const Shixunauthority = Loadable({
|
||||||
loader: () => import('./modules/403/Shixunauthority'),
|
loader: () => import('./modules/403/Shixunauthority'),
|
||||||
|
@ -75,6 +90,11 @@ const EducoderLogin = Loadable({
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const HomePage = Loadable({
|
||||||
|
loader: () => import('./home'),
|
||||||
|
loading: Loading,
|
||||||
|
})
|
||||||
|
|
||||||
class App extends Component {
|
class App extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
@ -121,6 +141,8 @@ class App extends Component {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
document.title = "loading...";
|
document.title = "loading...";
|
||||||
this.disableVideoContextMenu();
|
this.disableVideoContextMenu();
|
||||||
|
@ -240,6 +262,21 @@ class App extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
{/*公告*/}
|
||||||
|
<Route
|
||||||
|
path={"/notice"}
|
||||||
|
render={
|
||||||
|
(props) => {
|
||||||
|
return (<Notice {...this.props} {...props} {...this.state} />)
|
||||||
|
}
|
||||||
|
}>
|
||||||
|
</Route>
|
||||||
|
{/*任务*/}
|
||||||
|
<Route path="/task" component={Task} />
|
||||||
|
|
||||||
|
{/*任务*/}
|
||||||
|
<Route path="/competition/qz2022" component={Qz2022} />
|
||||||
|
|
||||||
{/*403*/}
|
{/*403*/}
|
||||||
<Route path="/403" component={Shixunauthority} />
|
<Route path="/403" component={Shixunauthority} />
|
||||||
|
|
||||||
|
@ -259,11 +296,12 @@ class App extends Component {
|
||||||
(props) => {
|
(props) => {
|
||||||
return (<InfosIndex {...this.props} {...this.state} />)
|
return (<InfosIndex {...this.props} {...this.state} />)
|
||||||
}
|
}
|
||||||
}></Route>
|
}></Route>
|
||||||
<Route exact path="/"
|
<Route exact path="/"
|
||||||
render={
|
render={
|
||||||
(props) => (
|
(props) => (
|
||||||
<Projects {...this.props} {...props} {...this.state}></Projects>
|
<HomePage {...props} {...this.props} {...this.state} />
|
||||||
|
// <Projects {...this.props} {...props} {...this.state}></Projects>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -2,17 +2,17 @@ import axios from 'axios';
|
||||||
import { requestProxy } from "./indexEduplus2RequestProxy";
|
import { requestProxy } from "./indexEduplus2RequestProxy";
|
||||||
import { broadcastChannelOnmessage, isDev, queryString } from 'educoder';
|
import { broadcastChannelOnmessage, isDev, queryString } from 'educoder';
|
||||||
import { notification } from 'antd';
|
import { notification } from 'antd';
|
||||||
|
import cookie from 'react-cookies';
|
||||||
import './index.css';
|
import './index.css';
|
||||||
|
|
||||||
let message501 = false;
|
let message501 = false;
|
||||||
|
|
||||||
broadcastChannelOnmessage('refreshPage', () => {
|
broadcastChannelOnmessage('refreshPage', () => {
|
||||||
window.location.reload();
|
window.location.reload()
|
||||||
})
|
})
|
||||||
|
|
||||||
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 开发期多个身份切换
|
||||||
|
@ -24,22 +24,58 @@ if (isDev) {
|
||||||
parsed = queryString.parse(_search);
|
parsed = queryString.parse(_search);
|
||||||
}
|
}
|
||||||
debugType = window.location.search.indexOf('debug=t') !== -1 ? 'teacher' :
|
debugType = window.location.search.indexOf('debug=t') !== -1 ? 'teacher' :
|
||||||
window.location.search.indexOf('debug=s') !== -1 ? 'student' :
|
window.location.search.indexOf('debug=s') !== -1 ? 'student' :
|
||||||
window.location.search.indexOf('debug=a') !== -1 ? 'admin' : parsed.debug || 'admin'
|
window.location.search.indexOf('debug=a') !== -1 ? 'admin' : parsed.debug || 'admin'
|
||||||
}
|
}
|
||||||
|
function clearAllCookie() {
|
||||||
|
cookie.remove('_educoder_session', { path: '/' });
|
||||||
|
cookie.remove('autologin_trustie', { path: '/' });
|
||||||
|
setpostcookie()
|
||||||
|
}
|
||||||
|
// clearAllCookie();
|
||||||
|
function setpostcookie() {
|
||||||
|
const str = window.location.pathname;
|
||||||
|
if (str.indexOf("/wxcode") !== -1) {
|
||||||
|
cookie.remove('_educoder_session', { path: '/' });
|
||||||
|
cookie.remove('autologin_trustie', { path: '/' });
|
||||||
|
const _params = window.location.search;
|
||||||
|
if (_params) {
|
||||||
|
let _search = _params.split('?')[1];
|
||||||
|
let _educoder_sessions = _search.split('&')[0].split('=');
|
||||||
|
cookie.save('_educoder_session', _educoder_sessions[1], { domain: '.educoder.net', path: '/' });
|
||||||
|
let autologin_trusties = _search.split('&')[1].split('=');
|
||||||
|
cookie.save('autologin_trustie', autologin_trusties[1], { domain: '.educoder.net', path: '/' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setpostcookie();
|
||||||
|
|
||||||
window._debugType = debugType;
|
window._debugType = debugType;
|
||||||
export function initAxiosInterceptors(props) {
|
export function initAxiosInterceptors(props) {
|
||||||
// 判断网络是否连接
|
initOnlineOfflineListener()
|
||||||
initOnlineOfflineListener();
|
// TODO 避免重复的请求 https://github.com/axios/axios#cancellation
|
||||||
|
var
|
||||||
|
proxy = "http://localhost:3000";
|
||||||
|
// proxy = "https://forge.osredm.com";
|
||||||
|
proxy = "http://117.50.100.12:49999";
|
||||||
|
// proxy = "http://111.8.36.180:8000";
|
||||||
|
|
||||||
var proxy = "https://testforgeplus.trustie.net";
|
|
||||||
|
const requestMap = {};
|
||||||
|
window.setfalseInRequestMap = function (keyName) {
|
||||||
|
requestMap[keyName] = false;
|
||||||
|
}
|
||||||
//响应前的设置
|
//响应前的设置
|
||||||
axios.interceptors.request.use(
|
axios.interceptors.request.use(
|
||||||
config => {
|
config => {
|
||||||
if(config.url.indexOf("http") !== -1) {
|
setpostcookie()
|
||||||
|
clearAllCookie()
|
||||||
|
|
||||||
|
if (config.url.indexOf(proxy) !== -1) {
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
requestProxy(config);
|
requestProxy(config)
|
||||||
|
|
||||||
let url = `/api${config.url}`;
|
let url = `/api${config.url}`;
|
||||||
|
|
||||||
if (`${config[0]}` !== `true`) {
|
if (`${config[0]}` !== `true`) {
|
||||||
|
@ -53,6 +89,11 @@ export function initAxiosInterceptors(props) {
|
||||||
} else {
|
} else {
|
||||||
config.url = url;
|
config.url = url;
|
||||||
}
|
}
|
||||||
|
setpostcookie();
|
||||||
|
}
|
||||||
|
if (config.url.indexOf('update_file') === -1) {
|
||||||
|
requestMap[config.url] = true;
|
||||||
|
window.setTimeout("setfalseInRequestMap('" + config.url + "')", 900)
|
||||||
}
|
}
|
||||||
return config;
|
return config;
|
||||||
},
|
},
|
||||||
|
@ -107,6 +148,8 @@ export function initAxiosInterceptors(props) {
|
||||||
message501 = false
|
message501 = false
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
|
requestMap[response.config.url] = false;
|
||||||
|
setpostcookie();
|
||||||
return response;
|
return response;
|
||||||
}, function (error) {
|
}, function (error) {
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
|
|
||||||
// 处理整点 半点
|
// 处理整点 半点
|
||||||
// 取传入时间往后的第一个半点
|
// 取传入时间往后的第一个半点
|
||||||
|
@ -12,7 +12,7 @@ export function handleDateString(dateString) {
|
||||||
if (miniute < 30 || miniute == 60) {
|
if (miniute < 30 || miniute == 60) {
|
||||||
return [ar[0], '30'].join(':')
|
return [ar[0], '30'].join(':')
|
||||||
}
|
}
|
||||||
if (miniute < 60) {
|
if (miniute < 60) {
|
||||||
// 加一个小时
|
// 加一个小时
|
||||||
const tempStr = [ar[0], '00'].join(':');
|
const tempStr = [ar[0], '00'].join(':');
|
||||||
const format = "YYYY-MM-DD HH:mm";
|
const format = "YYYY-MM-DD HH:mm";
|
||||||
|
@ -20,7 +20,7 @@ export function handleDateString(dateString) {
|
||||||
_moment.add(1, 'hours')
|
_moment.add(1, 'hours')
|
||||||
return _moment.format(format)
|
return _moment.format(format)
|
||||||
}
|
}
|
||||||
|
|
||||||
return dateString
|
return dateString
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,62 +38,91 @@ export function getNextHalfHourOfMoment(moment) {
|
||||||
return moment
|
return moment
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatSeconds(value) {
|
export function formatSeconds(value) {
|
||||||
|
|
||||||
var theTime = parseInt(value);// 秒
|
var theTime = parseInt(value);// 秒
|
||||||
var middle= 0;// 分
|
var middle = 0;// 分
|
||||||
var hour= 0;// 小时
|
var hour = 0;// 小时
|
||||||
|
|
||||||
if(theTime > 60) {
|
|
||||||
middle= parseInt(theTime/60);
|
|
||||||
theTime = parseInt(theTime%60);
|
|
||||||
if(middle> 60) {
|
|
||||||
hour= parseInt(middle/60);
|
|
||||||
middle= parseInt(middle%60);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var result = ""+parseInt(theTime)+"秒";
|
|
||||||
if(middle > 0) {
|
|
||||||
if(hour>0){
|
|
||||||
result = ""+parseInt(middle)+"分";
|
|
||||||
}else{
|
|
||||||
result = ""+parseInt(middle)+"分"+result;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if(hour> 0) {
|
|
||||||
result = ""+parseInt(hour)+"小时"+result;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export function formatDuring(mss){
|
if (theTime > 60) {
|
||||||
var days = parseInt(mss / (1000 * 60 * 60 * 24));
|
middle = parseInt(theTime / 60);
|
||||||
var hours = parseInt((mss % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
|
theTime = parseInt(theTime % 60);
|
||||||
var minutes = parseInt((mss % (1000 * 60 * 60)) / (1000 * 60));
|
if (middle > 60) {
|
||||||
// console.log("formatDuringformatDuring");
|
hour = parseInt(middle / 60);
|
||||||
// console.log(days);
|
middle = parseInt(middle % 60);
|
||||||
// console.log(hours);
|
}
|
||||||
// console.log(minutes);
|
}
|
||||||
// console.log(Math.abs(days));
|
var result = "" + parseInt(theTime) + "秒";
|
||||||
// console.log(Math.abs(hours));
|
if (middle > 0) {
|
||||||
// console.log(Math.abs(minutes));
|
if (hour > 0) {
|
||||||
|
result = "" + parseInt(middle) + "分";
|
||||||
|
} else {
|
||||||
|
result = "" + parseInt(middle) + "分" + result;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
}
|
||||||
days = Math.abs(days);
|
if (hour > 0) {
|
||||||
} catch (e) {
|
result = "" + parseInt(hour) + "小时" + result;
|
||||||
|
}
|
||||||
}
|
return result;
|
||||||
try {
|
|
||||||
hours = Math.abs(hours);
|
|
||||||
} catch (e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
minutes = Math.abs(minutes);
|
|
||||||
} catch (e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
return days + "天" + hours + "小时" + minutes + "分";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function formatDuring(s) {
|
||||||
|
s = Math.abs(s);
|
||||||
|
let days = Math.floor(s / (60 * 60 * 24));
|
||||||
|
let hours = Math.floor((s % (60 * 60 * 24)) / (60 * 60));
|
||||||
|
let minutes = Math.floor((s % (60 * 60)) / (60));
|
||||||
|
let second = Math.floor(s % 60);
|
||||||
|
|
||||||
|
if (days) {
|
||||||
|
if(hours){
|
||||||
|
return days + "天" + hours + "小时";
|
||||||
|
}
|
||||||
|
return days + "天";
|
||||||
|
}
|
||||||
|
if (hours) {
|
||||||
|
if(minutes){
|
||||||
|
return hours + "小时" + minutes + "分";
|
||||||
|
}
|
||||||
|
return hours + "小时" ;
|
||||||
|
}
|
||||||
|
if (minutes) {
|
||||||
|
return minutes + "分";
|
||||||
|
}
|
||||||
|
return second + "秒";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
返回:多久以前
|
||||||
|
backDate:以前的某个日期
|
||||||
|
*/
|
||||||
|
export function timeAgo(backDate) {
|
||||||
|
try {
|
||||||
|
moment(backDate);
|
||||||
|
} catch (e) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let time = new Date() - moment(backDate);
|
||||||
|
var days = Math.floor(time / (1000 * 60 * 60 * 24));
|
||||||
|
var hours = Math.floor((time % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
|
||||||
|
var minutes = Math.floor((time % (1000 * 60 * 60)) / (1000 * 60));
|
||||||
|
var seconds = Math.floor((time % (1000 * 60 * 60)) / 1000);
|
||||||
|
if (time <= 0) {
|
||||||
|
return "刚刚";
|
||||||
|
}
|
||||||
|
if (days) {
|
||||||
|
return days + "天前";
|
||||||
|
}
|
||||||
|
if (hours) {
|
||||||
|
return hours + "小时前";
|
||||||
|
}
|
||||||
|
if (minutes) {
|
||||||
|
return minutes + "分前";
|
||||||
|
}
|
||||||
|
if (seconds) {
|
||||||
|
return seconds + "秒前";
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,6 @@ export function isDev() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// const isMobile
|
// const isMobile
|
||||||
export const isMobile = (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase()));
|
export const isMobile = (/android|webos|iphone|ipad|ipod|blackberry|honor|huawei|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase()));
|
||||||
|
|
||||||
// const isWeiXin = (/MicroMessenger/i.test(navigator.userAgent.toLowerCase()));
|
// const isWeiXin = (/MicroMessenger/i.test(navigator.userAgent.toLowerCase()));
|
||||||
|
|
|
@ -68,7 +68,8 @@ export function appendFileSizeToUploadFile(item) {
|
||||||
return `${item.title}${uploadNameSizeSeperator}${item.filesize}`
|
return `${item.title}${uploadNameSizeSeperator}${item.filesize}`
|
||||||
}
|
}
|
||||||
export function appendFileSizeToUploadFileAll(fileList) {
|
export function appendFileSizeToUploadFileAll(fileList) {
|
||||||
return fileList.map(item => {
|
console.log('fileList',fileList);
|
||||||
|
return fileList && 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)}` })
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,23 +6,24 @@ const { Search } = Input;
|
||||||
const $ = window.$;
|
const $ = window.$;
|
||||||
const isDev = window.location.port == 3007;
|
const isDev = window.location.port == 3007;
|
||||||
const isdev2= window.location.hostname ==='www.educoder.net'
|
const isdev2= window.location.hostname ==='www.educoder.net'
|
||||||
export const TEST_HOST = "https://testforgeplus.trustie.net/"
|
export const TEST_HOST = "http://39.105.176.215:49999"
|
||||||
export function getImageUrl(path) {
|
export function getImageUrl(path) {
|
||||||
// https://www.educoder.net
|
// https://www.educoder.net
|
||||||
// https://testbdweb.trustie.net
|
// https://testbdweb.trustie.net
|
||||||
// const local = 'http://localhost:3000'
|
// const local = 'http://localhost:3000'
|
||||||
const local = 'https://testforgeplus.trustie.net';
|
const local = 'http://39.105.176.215:49999';
|
||||||
|
|
||||||
if (isDev) {
|
if (isDev) {
|
||||||
return `${local}/${path}`
|
return `${local}/${path}`
|
||||||
}
|
}
|
||||||
return `${path}`;
|
return `/${path}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getImage(path) {
|
export function getImage(path) {
|
||||||
// https://www.educoder.net
|
// https://www.educoder.net
|
||||||
// https://testbdweb.trustie.net
|
// https://testbdweb.trustie.net
|
||||||
// const local = 'http://localhost:3000'
|
// const local = 'http://localhost:3000'
|
||||||
const local = 'https://testforgeplus.trustie.net/';
|
const local = 'http://39.105.176.215:49999';
|
||||||
if(path.indexOf("http://")===-1){
|
if(path.indexOf("http://")===-1){
|
||||||
if (isDev) {
|
if (isDev) {
|
||||||
return `${local}/images/${path}`
|
return `${local}/images/${path}`
|
||||||
|
@ -33,6 +34,30 @@ export function getImage(path) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getTestImage(path) {
|
||||||
|
// https://www.educoder.net
|
||||||
|
// https://testbdweb.trustie.net
|
||||||
|
// const local = 'http://localhost:3000'
|
||||||
|
const local = 'http://117.50.100.12:49999';
|
||||||
|
if( path&&path.indexOf("http://")===-1){
|
||||||
|
if (isDev) {
|
||||||
|
return `${local}${path}`
|
||||||
|
}
|
||||||
|
return `${path}`;
|
||||||
|
}else{
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getLogoImageUrl(path) {
|
||||||
|
const local = 'http://117.50.100.12:49999';
|
||||||
|
|
||||||
|
if (isDev) {
|
||||||
|
return `${local}/${path}`
|
||||||
|
}
|
||||||
|
return `/${path}`;
|
||||||
|
}
|
||||||
|
|
||||||
export function getcdnImageUrl(path) {
|
export function getcdnImageUrl(path) {
|
||||||
// https://www.educoder.net
|
// https://www.educoder.net
|
||||||
// https://testbdweb.trustie.net
|
// https://testbdweb.trustie.net
|
||||||
|
@ -93,7 +118,7 @@ export function setImagesUrl(path){
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getUrl(path, goTest) {
|
export function getUrl(path, goTest) {
|
||||||
const local = 'https://testforgeplus.trustie.net'
|
const local = 'http://39.105.176.215:49999'
|
||||||
if (isDev) {
|
if (isDev) {
|
||||||
return `${local}${path?path:''}`
|
return `${local}${path?path:''}`
|
||||||
}
|
}
|
||||||
|
@ -162,28 +187,28 @@ export function getmyUrl(geturl) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getUploadActionUrl(path, goTest) {
|
export function getUploadActionUrl(path, goTest) {
|
||||||
return `${getUrl()}/api/attachments.json${isDev ?`${isDev ?`?debug=${window._debugType || 'admin'}` : ""}` : ""}`;
|
return `${getUrl()}/api/attachments.json`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getUploadLogoActionUrl() {
|
export function getUploadLogoActionUrl() {
|
||||||
return `${getUrl()}/api/resumes/logo.json${isDev ?`?debug=${window._debugType || 'admin'}` : ""}`;
|
return `${getUrl()}/api/resumes/logo.json?debug=${window._debugType || 'admin'}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getUploadActionUrltwo(id) {
|
export function getUploadActionUrltwo(id) {
|
||||||
return `${getUrlmys()}/api/shixuns/${id}/upload_data_sets.json${isDev ?`?debug=${window._debugType || 'admin'}` : ""}`
|
return `${getUrlmys()}/api/shixuns/${id}/upload_data_sets.json?debug=${window._debugType || 'admin'}`
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getUploadActionUrlthree() {
|
export function getUploadActionUrlthree() {
|
||||||
return `${getUrlmys()}/api/jupyters/import_with_tpm.json${isDev ?`?debug=${window._debugType || 'admin'}` : ""}`
|
return `${getUrlmys()}/api/jupyters/import_with_tpm.json?debug=${window._debugType || 'admin'}`
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getupload_git_file(id) {
|
export function getupload_git_file(id) {
|
||||||
return `${getUrlmys()}/api/shixuns/${id}/upload_git_file.json${isDev ?`?debug=${window._debugType || 'admin'}` : ""}`
|
return `${getUrlmys()}/api/shixuns/${id}/upload_git_file.json?debug=${window._debugType || 'admin'}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function getUploadActionUrlOfAuth(id) {
|
export function getUploadActionUrlOfAuth(id) {
|
||||||
return `${getUrl()}/api/users/accounts/${id}/auth_attachment.json${isDev ?`?debug=${window._debugType || 'admin'}` : ""}`
|
return `${getUrl()}/api/users/accounts/${id}/auth_attachment.json?debug=${window._debugType || 'admin'}`
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getRandomNumber(type) {
|
export function getRandomNumber(type) {
|
||||||
|
@ -233,3 +258,9 @@ export function publicSearchs(Placeholder,onSearch,onInputs,onChanges,loadings)
|
||||||
allowClear={true}
|
allowClear={true}
|
||||||
></Search>)
|
></Search>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getUrlToken(name, str) {
|
||||||
|
const reg = new RegExp(`(^|&)${ name}=([^&]*)(&|$)`);
|
||||||
|
const r = str.substr(1).match(reg);
|
||||||
|
if (r != null) return decodeURIComponent(r[2]); return null;
|
||||||
|
}
|
|
@ -64,7 +64,7 @@ function CommentItem({
|
||||||
const commentAvatar = (author) => (
|
const commentAvatar = (author) => (
|
||||||
<img
|
<img
|
||||||
className="item-flex flex-image"
|
className="item-flex flex-image"
|
||||||
src={author.image_url ? getImageUrl(`/${author.image_url}`) : 'https://b-ssl.duitang.com/uploads/item/201511/13/20151113110434_kyReJ.jpeg'}
|
src={author.image_url ? getImageUrl(`images/${author.image_url}`) : 'https://b-ssl.duitang.com/uploads/item/201511/13/20151113110434_kyReJ.jpeg'}
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
@ -6,7 +6,7 @@ export {
|
||||||
getUploadLogoActionUrl as getUploadLogoActionUrl,
|
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,getTestImage as getTestImage,getLogoImageUrl as getLogoImageUrl,getUrlToken as getUrlToken
|
||||||
} from './UrlTool';
|
} from './UrlTool';
|
||||||
|
|
||||||
export { setmiyah as setmiyah } from './Component';
|
export { setmiyah as setmiyah } from './Component';
|
||||||
|
@ -27,7 +27,7 @@ export {
|
||||||
markdownToHTML, uploadNameSizeSeperator, appendFileSizeToUploadFile, appendFileSizeToUploadFileAll, isImageExtension,
|
markdownToHTML, uploadNameSizeSeperator, appendFileSizeToUploadFile, appendFileSizeToUploadFileAll, isImageExtension,
|
||||||
downloadFile, sortDirections, validateLength, mdJSONParse, exportMdtoHtml
|
downloadFile, sortDirections, validateLength, mdJSONParse, exportMdtoHtml
|
||||||
} from './TextUtil'
|
} from './TextUtil'
|
||||||
export { handleDateString, getNextHalfHourOfMoment, formatDuring, formatSeconds } from './DateUtil'
|
export { handleDateString, getNextHalfHourOfMoment, formatDuring, formatSeconds ,timeAgo} from './DateUtil'
|
||||||
|
|
||||||
export { configShareForIndex, configShareForPaths, configShareForShixuns, configShareForCourses, configShareForCustom } from './util/ShareUtil'
|
export { configShareForIndex, configShareForPaths, configShareForShixuns, configShareForCourses, configShareForCustom } from './util/ShareUtil'
|
||||||
|
|
||||||
|
|
|
@ -67,14 +67,15 @@ function Index(props){
|
||||||
}
|
}
|
||||||
return(
|
return(
|
||||||
<div className="aboutPanels">
|
<div className="aboutPanels">
|
||||||
|
|
||||||
<div className="aboutContent">
|
<div className="aboutContent">
|
||||||
<AlignCenterBetween style={{padding:"14px 20px"}}>
|
<AlignCenterBetween style={{padding:"14px 0px"}}>
|
||||||
<span className="font-16"><i className="iconfont icon-xiangmujianjie mr5 font-16 color-blue"></i>项目简介</span>
|
<span className="font-16"><i className="iconfont icon-xiangmujianjie mr5 font-16 color-blue"></i>项目简介</span>
|
||||||
{ editOpration && !edit && <a onClick={editContent} className="color-blue">编辑</a> }
|
{ editOpration && !edit && <a onClick={editContent} className="color-blue">编辑</a> }
|
||||||
</AlignCenterBetween>
|
</AlignCenterBetween>
|
||||||
{
|
{
|
||||||
edit ?
|
edit ?
|
||||||
<div className="padding20">
|
<div>
|
||||||
<MDEditor
|
<MDEditor
|
||||||
placeholder={"请输入描述信息"}
|
placeholder={"请输入描述信息"}
|
||||||
height={500}
|
height={500}
|
||||||
|
@ -113,7 +114,7 @@ function Index(props){
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
:
|
:
|
||||||
<div className="padding20">
|
<div style={{padding:"20px 0px"}}>
|
||||||
{content ?
|
{content ?
|
||||||
<RenderHtml className="break_word_comments imageLayerParent" value={content} url={props.history.location}/>
|
<RenderHtml className="break_word_comments imageLayerParent" value={content} url={props.history.location}/>
|
||||||
:
|
:
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
.aboutContent{
|
.aboutContent{
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
border: 1px solid #EEEEEE;
|
border: 1px solid #EEEEEE;
|
||||||
|
padding:0px 30px;
|
||||||
width:100%;
|
width:100%;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
margin-top:20px;
|
margin-top:20px;
|
||||||
|
|
|
@ -33,7 +33,7 @@ class ActivityItem extends Component {
|
||||||
}
|
}
|
||||||
<p className="itemLine mt10">
|
<p className="itemLine mt10">
|
||||||
<Link to={`/users/${item && item.user_login}`} className="show-user-link">
|
<Link to={`/users/${item && item.user_login}`} className="show-user-link">
|
||||||
<img alt="" src={getImageUrl(`/${item.user_avatar}`)} className="createImage" />
|
<img alt="" src={getImageUrl(`images/${item.user_avatar}`)} className="createImage" />
|
||||||
<span className="mr20">{item.user_name}</span>
|
<span className="mr20">{item.user_name}</span>
|
||||||
</Link>
|
</Link>
|
||||||
{item.created_at && <span className="color-grey-9">创建于<span className="ml2 color-grey-6">{item.created_at}</span></span>}
|
{item.created_at && <span className="color-grey-9">创建于<span className="ml2 color-grey-6">{item.created_at}</span></span>}
|
||||||
|
|
|
@ -14,7 +14,7 @@ class CloneAddress extends Component {
|
||||||
const { http_url, downloadUrl } = this.props;
|
const { http_url, downloadUrl } = this.props;
|
||||||
return (
|
return (
|
||||||
<div className="gitAddressClone">
|
<div className="gitAddressClone">
|
||||||
{/* <p className="addressTips"><span>版本库地址已变更,请基于新地址提交代码</span></p> */}
|
<p className="addressTips"><span>版本库地址已变更,请基于新地址提交代码</span></p>
|
||||||
{
|
{
|
||||||
http_url && <span>HTTP</span>
|
http_url && <span>HTTP</span>
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,10 +102,9 @@ export default (({ projectsId , branch , owner , changeBranch , branchList , tag
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
return(
|
return(
|
||||||
<Popover placement='bottomLeft' visible={flag} content={menu} onClick={()=>setFlag(!flag)} overlayClassName="branch-tagBox-list">
|
<Popover placement="bottom" visible={flag} content={menu} onClick={()=>setFlag(!flag)} overlayClassName="branch-tagBox-list">
|
||||||
<div className="branch-tagBox">
|
<div className="branch-tagBox">
|
||||||
{/* {nav === 0 ?"分支":"标签"} */}
|
<span className="color-grey-9 mr3 ml8">{nav === 0 ?"分支":"标签"}:</span>
|
||||||
<span className="color-grey-9 mr3 ml8"><i className="iconfont icon-fenzhi2 font-18"></i></span>
|
|
||||||
<a className="ant-dropdown-link">
|
<a className="ant-dropdown-link">
|
||||||
{showValue}
|
{showValue}
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
min-width: 140px;
|
min-width: 240px;
|
||||||
}
|
}
|
||||||
.branch-tagBox-list .ant-popover-arrow{
|
.branch-tagBox-list .ant-popover-arrow{
|
||||||
display: none;
|
display: none;
|
||||||
|
|
|
@ -42,7 +42,7 @@ function AddMember({getID,login}){
|
||||||
className="user_img radius"
|
className="user_img radius"
|
||||||
width="28"
|
width="28"
|
||||||
height="28"
|
height="28"
|
||||||
src={getImageUrl(`/${item && item.image_url}`)}
|
src={getImageUrl(`images/${item && item.image_url}`)}
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
<span className="ml10" style={{ "vertical-align": "middle" }}>
|
<span className="ml10" style={{ "vertical-align": "middle" }}>
|
||||||
|
|
|
@ -6,7 +6,7 @@ import './Component.scss';
|
||||||
function Cards({img , title, desc , rightBtn , src}){
|
function Cards({img , title, desc , rightBtn , src}){
|
||||||
return(
|
return(
|
||||||
<div className="cards">
|
<div className="cards">
|
||||||
{img &&<div className="img"><img src={getImageUrl(`/${img}`)} alt=""/></div>}
|
{img &&<div className="img"><img src={getImageUrl(`images/${img}`)} alt=""/></div>}
|
||||||
<div className="content">
|
<div className="content">
|
||||||
<p className="titles">
|
<p className="titles">
|
||||||
<Link to={src}>{title}</Link>
|
<Link to={src}>{title}</Link>
|
||||||
|
|
|
@ -20,7 +20,6 @@ li.ant-menu-item{
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
margin-bottom:18px;
|
margin-bottom:18px;
|
||||||
min-height: 130px;
|
min-height: 130px;
|
||||||
border:1px solid #eee;
|
|
||||||
.img{
|
.img{
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
width: 190px;
|
width: 190px;
|
||||||
|
@ -62,7 +61,6 @@ li.ant-menu-item{
|
||||||
}
|
}
|
||||||
// Tabs
|
// Tabs
|
||||||
.tabsStyle{
|
.tabsStyle{
|
||||||
border:1px solid #eee;
|
|
||||||
.ant-tabs-bar.ant-tabs-top-bar{
|
.ant-tabs-bar.ant-tabs-top-bar{
|
||||||
padding-left: 35px;
|
padding-left: 35px;
|
||||||
margin-bottom: 0px;
|
margin-bottom: 0px;
|
||||||
|
@ -112,9 +110,6 @@ li.ant-menu-item{
|
||||||
right:240px;
|
right:240px;
|
||||||
z-index: 10000;
|
z-index: 10000;
|
||||||
}
|
}
|
||||||
.laterest{
|
|
||||||
color: #05690d;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 1800px){
|
@media screen and (max-width: 1800px){
|
||||||
.handleBox{
|
.handleBox{
|
||||||
|
@ -140,56 +135,4 @@ li.ant-menu-item{
|
||||||
.handleBox{
|
.handleBox{
|
||||||
right:0px;
|
right:0px;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
.ant-drawer{
|
|
||||||
z-index: 10000!important;
|
|
||||||
}
|
|
||||||
.ant-drawer-body{
|
|
||||||
padding:0px!important;
|
|
||||||
.drawerHead{
|
|
||||||
background-color: #333;
|
|
||||||
color: #fff;
|
|
||||||
padding:15px 20px;
|
|
||||||
}
|
|
||||||
.ant-tree{
|
|
||||||
margin:0px 20px!important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.menuPanels{
|
|
||||||
width: 240px;
|
|
||||||
height: 180px;
|
|
||||||
.ant-popover-content,.ant-popover-inner{
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.halfs{
|
|
||||||
margin-top: 24px;
|
|
||||||
padding:24px 0px 0px 0px;
|
|
||||||
border-top: 1px solid #e8e8e8;
|
|
||||||
.attrPerson{
|
|
||||||
padding-bottom: 24px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.menuinfos{
|
|
||||||
padding:15px 0px;
|
|
||||||
&>a{
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
border-right: 1px solid #eee;
|
|
||||||
flex: 1;
|
|
||||||
& >span:first-child{
|
|
||||||
font-size: 18px;
|
|
||||||
font-weight: 400;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
& >span:last-child{
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
&:last-child{
|
|
||||||
border-right: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,160 +0,0 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
|
||||||
import { AlignCenter , FlexAJ } from '../Component/layout';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import { Popover , Spin } from 'antd';
|
|
||||||
import { getImageUrl } from 'educoder';
|
|
||||||
import './Component.scss';
|
|
||||||
import { getUser } from '../GetData/getData';
|
|
||||||
import axios from 'axios';
|
|
||||||
|
|
||||||
function Contributors({contributors,owner,projectsId}){
|
|
||||||
const [ menuList ,setMenuList ]= useState([]);
|
|
||||||
const [ list , setList ]= useState(undefined);
|
|
||||||
const [ total , setTotal ]= useState(0);
|
|
||||||
const [ menu , setMenu ] = useState("");
|
|
||||||
const [ login , setLogin ] = useState(undefined);
|
|
||||||
const [ isSpin , setIsSpin ] = useState(false);
|
|
||||||
|
|
||||||
useEffect(()=>{
|
|
||||||
if(contributors && contributors.total_count>0){
|
|
||||||
setTotal(contributors.total_count);
|
|
||||||
setList(contributors.list);
|
|
||||||
}
|
|
||||||
},[contributors])
|
|
||||||
|
|
||||||
useEffect(()=>{
|
|
||||||
if(login){
|
|
||||||
getUsers(login);
|
|
||||||
}else{
|
|
||||||
setMenu(undefined);
|
|
||||||
}
|
|
||||||
},[login])
|
|
||||||
|
|
||||||
async function getUsers(login){
|
|
||||||
setIsSpin(true);
|
|
||||||
let a = menuList && menuList.filter(i=>i.login === login);
|
|
||||||
if(a.length === 0){
|
|
||||||
let result = await getUser(login);
|
|
||||||
let arr = menuList;
|
|
||||||
arr.push({...result});
|
|
||||||
setMenuList(arr);
|
|
||||||
setMenusFunc(result);
|
|
||||||
setIsSpin(false);
|
|
||||||
}else{
|
|
||||||
setMenusFunc(a[0]);
|
|
||||||
setIsSpin(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function setMenusFunc(data){
|
|
||||||
if(data){
|
|
||||||
let ele = (
|
|
||||||
<Spin spinning={isSpin}>
|
|
||||||
<FlexAJ>
|
|
||||||
<AlignCenter>
|
|
||||||
<Link to={`/users/${data.login}`}><img src={getImageUrl(`/${data.image_url}`)} alt="" className="radius" width="38px" height="38px"/></Link>
|
|
||||||
<Link to={`/users/${data.login}`} className="ml10">{data.name}</Link>
|
|
||||||
</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>
|
|
||||||
<AlignCenter className="menuinfos">
|
|
||||||
<a href={data.projects_url}>
|
|
||||||
<span>{data.projects_count}</span>
|
|
||||||
<span>项目数</span>
|
|
||||||
</a>
|
|
||||||
<a href={data.followers_url}>
|
|
||||||
<span>{data.followers_count}</span>
|
|
||||||
<span>粉丝数</span>
|
|
||||||
</a>
|
|
||||||
<a href={data.following_url}>
|
|
||||||
<span>{data.following_count}</span>
|
|
||||||
<span>关注数</span>
|
|
||||||
</a>
|
|
||||||
</AlignCenter>
|
|
||||||
{
|
|
||||||
data.organizations && data.organizations.length > 0 ?
|
|
||||||
<AlignCenter className="font-12 pt4 pb4">
|
|
||||||
<span>所属组织:</span>
|
|
||||||
<div className="task-hide flex1">
|
|
||||||
{renderArray(data.organizations)}
|
|
||||||
</div>
|
|
||||||
</AlignCenter>
|
|
||||||
:""
|
|
||||||
}
|
|
||||||
{
|
|
||||||
data.location && <AlignCenter className="font-12 pt4 pb4"><span>所在地址:</span><span className="ml5">{data.location}</span></AlignCenter>
|
|
||||||
}
|
|
||||||
</Spin>
|
|
||||||
)
|
|
||||||
setMenu(ele);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function FocusFunc(flag,login){
|
|
||||||
axios({
|
|
||||||
method: flag ? 'post' : 'delete',
|
|
||||||
url: `/watchers/${flag ? 'follow' : 'unfollow'}.json`,
|
|
||||||
params: {target_type: "user",id:login}
|
|
||||||
}).then(result => {
|
|
||||||
if (result && (result.data.status === 0 || result.data.status === 2)) {
|
|
||||||
let a = menuList && menuList.filter(i=>i.login === login);
|
|
||||||
if(a){
|
|
||||||
a[0].is_watch = flag;
|
|
||||||
}
|
|
||||||
setMenusFunc(a[0]);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderArray(array){
|
|
||||||
let str = "";
|
|
||||||
for(var i = 0;i<array.length;i++){
|
|
||||||
str += array[i].name +"、";
|
|
||||||
}
|
|
||||||
let substr = str.substr(0,str.length-1);
|
|
||||||
return (<span title={substr}>{substr}</span>)
|
|
||||||
}
|
|
||||||
|
|
||||||
function setVisibleFunc(flag,l,index){
|
|
||||||
if(l !== login){
|
|
||||||
setLogin(l);
|
|
||||||
}
|
|
||||||
var lx = list.concat();
|
|
||||||
lx.map(i=>i.visible =false);
|
|
||||||
if(flag){
|
|
||||||
lx[index].visible = flag;
|
|
||||||
}
|
|
||||||
lx.splice();
|
|
||||||
setList(lx);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(
|
|
||||||
<div className="halfs">
|
|
||||||
<FlexAJ>
|
|
||||||
<AlignCenter><span className="font-16 color-grey-6">贡献者</span>{ contributors && contributors.total_count > 0 && <span className="infoCount">{contributors.total_count}</span>}</AlignCenter>
|
|
||||||
<Link className="font-12 color-grey-9" to={`/projects/${owner}/${projectsId}/contribute`}>全部</Link>
|
|
||||||
</FlexAJ>
|
|
||||||
<div className="attrPerson" onMouseLeave={()=>setVisibleFunc(false)}>
|
|
||||||
{
|
|
||||||
total > 0 ?
|
|
||||||
list.map((item,key)=>{
|
|
||||||
return(
|
|
||||||
<Popover content={menu} visible={item.visible} overlayClassName="menuPanels" placement="top">
|
|
||||||
<Link key={key} to={`/users/${item.login}`}>
|
|
||||||
<img src={getImageUrl(`/${item.image_url}`)} alt="" onMouseOver={()=>setVisibleFunc(true,item.login,key)}/>
|
|
||||||
</Link>
|
|
||||||
</Popover>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
:""
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export default Contributors;
|
|
|
@ -1,99 +0,0 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
|
||||||
import { Drawer , Tree , Spin } from 'antd';
|
|
||||||
import './Component.scss';
|
|
||||||
import axios from 'axios';
|
|
||||||
const { TreeNode , DirectoryTree } = Tree;
|
|
||||||
|
|
||||||
function DrawerPanel({visible,onClose,branch,owner,projectsId,history, name , list}){
|
|
||||||
const [ treeData , setTreeData ] = useState(undefined);
|
|
||||||
const [ isSpin , setIsSpin ] = useState(true);
|
|
||||||
const [first , setFirst ] = useState(true);
|
|
||||||
useEffect(()=>{
|
|
||||||
if(visible && first){
|
|
||||||
if(list){
|
|
||||||
setTreeData(list);
|
|
||||||
setIsSpin(false);
|
|
||||||
}else{
|
|
||||||
getMenulist();
|
|
||||||
}
|
|
||||||
setFirst(false);
|
|
||||||
}
|
|
||||||
},[visible])
|
|
||||||
|
|
||||||
function getMenulist(){
|
|
||||||
const url = `/${owner}/${projectsId}/entries.json`;
|
|
||||||
axios.get(url,{ params: { ref: branch } }).then(result=>{
|
|
||||||
if(result){
|
|
||||||
setTreeData(result.data.entries);
|
|
||||||
}
|
|
||||||
setIsSpin(false);
|
|
||||||
}).catch(error=>{})
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderTreeNodes(data) {
|
|
||||||
return data && data.length > 0 && data.map((item) => {
|
|
||||||
return (
|
|
||||||
<TreeNode title={item.name} key={item.key} dataRef={item} isLeaf={item.type === "file"}>
|
|
||||||
{renderTreeNodes(item.children)}
|
|
||||||
</TreeNode>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function onLoadData(tr){
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
if (tr.props.children) {
|
|
||||||
resolve();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let en = [];
|
|
||||||
const url = `/${owner}/${projectsId}/sub_entries.json`;
|
|
||||||
axios.get(url, {
|
|
||||||
params:{
|
|
||||||
filepath:tr.props.dataRef.path,
|
|
||||||
ref:branch,
|
|
||||||
type:"dir"
|
|
||||||
}
|
|
||||||
}).then((result) => {
|
|
||||||
if(result){
|
|
||||||
en = result.data.entries;
|
|
||||||
}
|
|
||||||
}).catch(error=>{})
|
|
||||||
setTimeout(() => {
|
|
||||||
tr.props.dataRef.children = en;
|
|
||||||
setTreeData([...treeData]);
|
|
||||||
resolve();
|
|
||||||
}, 2000);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function selectTree(keys,event){
|
|
||||||
let dataref = event.node.props.dataRef;
|
|
||||||
if(dataref.type==="file"){
|
|
||||||
onClose();
|
|
||||||
history.push(`/projects/${owner}/${projectsId}/tree/${branch}/${dataref.path}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return(
|
|
||||||
<Drawer
|
|
||||||
placement="left"
|
|
||||||
visible={visible}
|
|
||||||
closable={false}
|
|
||||||
onClose={onClose}
|
|
||||||
width={"320px"}
|
|
||||||
maskStyle={{backgroundColor:'rgba(0,0,0,0.09)'}}
|
|
||||||
>
|
|
||||||
<Spin spinning={isSpin}>
|
|
||||||
<div className="drawerHead">
|
|
||||||
<p className="font-20">{name}</p>
|
|
||||||
<p><i class="iconfont icon-fenzhi2 font-18 color-grey-9 mr3"></i>{branch}</p>
|
|
||||||
</div>
|
|
||||||
<DirectoryTree loadData={onLoadData} onSelect={selectTree}>
|
|
||||||
{treeData && renderTreeNodes(treeData)}
|
|
||||||
</DirectoryTree>
|
|
||||||
</Spin>
|
|
||||||
</Drawer>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export default DrawerPanel;
|
|
|
@ -1,9 +0,0 @@
|
||||||
.ant-modal-mask{
|
|
||||||
z-index: 10000;
|
|
||||||
}
|
|
||||||
.ant-modal-wrap{
|
|
||||||
z-index: 10001;
|
|
||||||
.ant-form-explain{
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
import React , {forwardRef, useEffect} from 'react';
|
|
||||||
import { Modal , Form , Input , Button } from 'antd';
|
|
||||||
import './EAccount.scss';
|
|
||||||
|
|
||||||
function EducoderAccount({form , visible , onOk , email}){
|
|
||||||
const { getFieldDecorator, validateFields , setFieldsValue } = form;
|
|
||||||
|
|
||||||
useEffect(()=>{
|
|
||||||
if(email){
|
|
||||||
setFieldsValue({email})
|
|
||||||
}
|
|
||||||
},[email])
|
|
||||||
|
|
||||||
function onSure(){
|
|
||||||
validateFields((error,values)=>{
|
|
||||||
if(!error){
|
|
||||||
onOk(values);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
const layout = {
|
|
||||||
labelCol: { span: 5 },
|
|
||||||
wrapperCol: { span: 18 },
|
|
||||||
};
|
|
||||||
return(
|
|
||||||
<Modal
|
|
||||||
visible={visible}
|
|
||||||
title="提示"
|
|
||||||
width="500px"
|
|
||||||
closable={false}
|
|
||||||
footer={
|
|
||||||
<Button type="primary" onClick={onSure}>确定</Button>
|
|
||||||
}
|
|
||||||
centered
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<p className="mb15 edu-txt-center" style={{maxWidth:"350px",margin:"0px auto"}}>
|
|
||||||
为确保您能正常使用平台功能,请确认以下信息:
|
|
||||||
</p>
|
|
||||||
<Form {...layout}>
|
|
||||||
<Form.Item label="邮箱">
|
|
||||||
{getFieldDecorator("email",{
|
|
||||||
rules:[{required:true,message:"请输入邮箱账号"}]
|
|
||||||
})(
|
|
||||||
<Input placeholder="请输入您的邮箱账号" width="220px"/>
|
|
||||||
)}
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="密码">
|
|
||||||
{getFieldDecorator("password",{
|
|
||||||
rules:[{required:true,message:"请输入邮箱密码"}]
|
|
||||||
})(
|
|
||||||
<Input.Password placeholder="请输入您的邮箱密码" width="220px"/>
|
|
||||||
)}
|
|
||||||
</Form.Item>
|
|
||||||
</Form>
|
|
||||||
</div>
|
|
||||||
</Modal>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export default Form.create()(forwardRef(EducoderAccount));
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
|
||||||
|
|
||||||
import React , { useState , useEffect } from 'react';
|
import React , { useState , useEffect } from 'react';
|
||||||
import { Select } from 'antd';
|
import { Select } from 'antd';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
@ -57,7 +59,6 @@ const LANGUAGE = [
|
||||||
|
|
||||||
export default (({ language , select_language })=>{
|
export default (({ language , select_language })=>{
|
||||||
const [ languages , setLanguage ] = useState(undefined);
|
const [ languages , setLanguage ] = useState(undefined);
|
||||||
|
|
||||||
// useEffect(()=>{
|
// useEffect(()=>{
|
||||||
// const url = '/dev_ops/languages.json';
|
// const url = '/dev_ops/languages.json';
|
||||||
// axios.get(url).then(result=>{
|
// axios.get(url).then(result=>{
|
||||||
|
|
|
@ -5,7 +5,7 @@ import './Component.scss';
|
||||||
export default (()=>{
|
export default (()=>{
|
||||||
return(
|
return(
|
||||||
<div className="handleBox">
|
<div className="handleBox">
|
||||||
<a href="https://forum.trustie.net/forums/3075/detail" target="_blank" >
|
<a href="https://www.osredm.com/forums/594/detail" target="_blank" >
|
||||||
<img src={Handbook} alt=""/>
|
<img src={Handbook} alt=""/>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,54 +0,0 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
|
||||||
import { FlexAJ } from '../Component/layout';
|
|
||||||
|
|
||||||
function LanguagePower({languages}){
|
|
||||||
const [ array , setArray ] = useState(undefined);
|
|
||||||
|
|
||||||
useEffect(()=>{
|
|
||||||
if(languages){
|
|
||||||
let arr = [];
|
|
||||||
Object.keys(languages).map((item,key)=>{
|
|
||||||
arr.push({name:item,percent:languages[item],color:getColor()});
|
|
||||||
})
|
|
||||||
setArray(arr);
|
|
||||||
}
|
|
||||||
},[languages])
|
|
||||||
|
|
||||||
function getColor(){
|
|
||||||
let str = "#";
|
|
||||||
let arr = ["1","2","3","4","4","5","6","7","8","9","a","b","c","d","e","f"];
|
|
||||||
for(var i=0;i<6;i++){
|
|
||||||
let num = parseInt(Math.random() * 16);
|
|
||||||
str+=arr[num];
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
return(
|
|
||||||
<div>
|
|
||||||
<p className="font-16 color-grey-6">开发语言</p>
|
|
||||||
<div className="progress">
|
|
||||||
{
|
|
||||||
array && array.map((item,key)=>{
|
|
||||||
return(
|
|
||||||
<span style={{width:item.percent,backgroundColor:item.color}}></span>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
{
|
|
||||||
array && array.length > 0 &&
|
|
||||||
<FlexAJ className="progresstip">
|
|
||||||
{
|
|
||||||
array.map((item,key)=>{
|
|
||||||
return(
|
|
||||||
<span><i className="zero" style={{backgroundColor:`${item.color}`}}></i><span>{item.name}</span><span>{item.percent}</span></span>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</FlexAJ>
|
|
||||||
}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export default LanguagePower;
|
|
|
@ -45,7 +45,7 @@ const Div = styled.div`{
|
||||||
export default (({ user , img, name, time, focusStatus, is_current_user, login , successFunc }) => {
|
export default (({ user , img, name, time, focusStatus, is_current_user, login , successFunc }) => {
|
||||||
return (
|
return (
|
||||||
<Div>
|
<Div>
|
||||||
<Link to={`/users/${user && user.login}`}><Img src={getImageUrl(`/${img}`)} /></Link>
|
<Link to={`/users/${user && user.login}`}><Img src={getImageUrl(`images/${img}`)} /></Link>
|
||||||
<div className="m-infos">
|
<div className="m-infos">
|
||||||
<Link to={`/users/${user && user.login}`}><Name>{name}</Name></Link>
|
<Link to={`/users/${user && user.login}`}><Name>{name}</Name></Link>
|
||||||
<Time><I className="iconfont icon-shijian"></I>加入时间:{time}</Time>
|
<Time><I className="iconfont icon-shijian"></I>加入时间:{time}</Time>
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { AlignCenter , AlignTop , FlexAJ } from '../Component/layout';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
|
|
||||||
function Releases({owner,projectsId,releaseVersions}){
|
|
||||||
|
|
||||||
return(
|
|
||||||
<div>
|
|
||||||
<FlexAJ>
|
|
||||||
<AlignCenter><span className="font-16 color-grey-6">发行版</span>
|
|
||||||
{ releaseVersions && releaseVersions.total_count > 0 && <span className="infoCount">{releaseVersions.total_count}</span>}
|
|
||||||
</AlignCenter>
|
|
||||||
{ releaseVersions && releaseVersions.total_count > 0 ?
|
|
||||||
<Link className="font-12 color-grey-9" to={`/projects/${owner}/${projectsId}/releases`}>全部</Link>
|
|
||||||
:
|
|
||||||
<Link className="font-12 color-blue" to={`/projects/${owner}/${projectsId}/releases/new`}>新建</Link>
|
|
||||||
}
|
|
||||||
</FlexAJ>
|
|
||||||
{
|
|
||||||
releaseVersions && releaseVersions.total_count>0 ?
|
|
||||||
releaseVersions.list.map((item,key)=>{
|
|
||||||
return(
|
|
||||||
key === 0 &&<AlignTop className="mt10">
|
|
||||||
<i className="iconfont icon-biaoqian3 color-grey-6 font-18 mr10"></i>
|
|
||||||
<div>
|
|
||||||
<p className="font-16 color-grey-6">
|
|
||||||
<Link to={`/projects/${owner}/${projectsId}/releases/8/update`}>{item.name}</Link>
|
|
||||||
<span className="font-12 laterest ml5">最新</span>
|
|
||||||
</p>
|
|
||||||
<p className="color-grey-9 font-13">{item.created_at}</p>
|
|
||||||
</div>
|
|
||||||
</AlignTop>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
:""
|
|
||||||
}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export default Releases;
|
|
|
@ -44,7 +44,7 @@ export default ({ getUser })=>{
|
||||||
className="user_img radius"
|
className="user_img radius"
|
||||||
width="28"
|
width="28"
|
||||||
height="28"
|
height="28"
|
||||||
src={getImageUrl(`/${item && item.image_url}`)}
|
src={getImageUrl(`images/${item && item.image_url}`)}
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
<span className="ml10" style={{ "vertical-align": "middle" }}>
|
<span className="ml10" style={{ "vertical-align": "middle" }}>
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
|
|
||||||
export default ({ url , name , column , id , login })=>{
|
|
||||||
|
export default ({ url , name , column })=>{
|
||||||
const Img = styled.span`
|
const Img = styled.span`
|
||||||
display:flex;
|
display:flex;
|
||||||
${column && "flex-direction: column;text-align:center;"}
|
${column && "flex-direction: column;text-align:center;"}
|
||||||
|
@ -19,16 +19,8 @@ export default ({ url , name , column , id , login })=>{
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
return(
|
return(
|
||||||
id?
|
|
||||||
<Link to={`/users/${login}`}>
|
|
||||||
<Img>
|
|
||||||
{ url && <img src={url} alt=""/> }
|
|
||||||
<span>{name}</span>
|
|
||||||
</Img>
|
|
||||||
</Link>
|
|
||||||
:
|
|
||||||
<Img>
|
<Img>
|
||||||
{ url && <img src={url} alt=""/> }
|
<img src={url} alt=""/>
|
||||||
<span>{name}</span>
|
<span>{name}</span>
|
||||||
</Img>
|
</Img>
|
||||||
)
|
)
|
||||||
|
|
|
@ -24,33 +24,18 @@ export const AlignCenter = styled.div`{
|
||||||
display:flex;
|
display:flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}`
|
}`
|
||||||
export const AlignTop = styled.div`{
|
|
||||||
display:flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
}`
|
|
||||||
// 左右结构
|
// 左右结构
|
||||||
export const Box = styled.div`{
|
export const Box = styled.div`{
|
||||||
display:flex;
|
display:flex;
|
||||||
align-items:flex-start;
|
align-item:flex-start;
|
||||||
}`
|
|
||||||
export const LongWidth = styled.div`{
|
|
||||||
flex:1;
|
|
||||||
width:0;
|
|
||||||
border-radius:5px;
|
|
||||||
margin-bottom:30px;
|
|
||||||
}`
|
}`
|
||||||
export const Long = styled.div`{
|
export const Long = styled.div`{
|
||||||
width:78%;
|
width:72%;
|
||||||
border-radius:5px;
|
|
||||||
margin-bottom:30px;
|
|
||||||
}`
|
|
||||||
export const ShortWidth = styled.div`{
|
|
||||||
width:300px;
|
|
||||||
border-radius:5px;
|
border-radius:5px;
|
||||||
margin-bottom:30px;
|
margin-bottom:30px;
|
||||||
}`
|
}`
|
||||||
export const Short = styled.div`{
|
export const Short = styled.div`{
|
||||||
flex:1;
|
width:28%;
|
||||||
border-radius:5px;
|
border-radius:5px;
|
||||||
margin-bottom:30px;
|
margin-bottom:30px;
|
||||||
}`
|
}`
|
||||||
|
|
|
@ -36,7 +36,8 @@ function About(props, ref) {
|
||||||
const [ disabled, setDisabled ] = useState(false);
|
const [ disabled, setDisabled ] = useState(false);
|
||||||
const [ typeFlag, setTypeFlag] = useState(false);
|
const [ typeFlag, setTypeFlag] = useState(false);
|
||||||
|
|
||||||
const AuthorLogin = props.projectDetail && props.projectDetail.author && props.projectDetail.author.login;
|
|
||||||
|
const AuthorLogin = props.author && props.author.login;
|
||||||
const CurrentLogin = props.current_user && props.current_user.login;
|
const CurrentLogin = props.current_user && props.current_user.login;
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
if(CurrentLogin === AuthorLogin){
|
if(CurrentLogin === AuthorLogin){
|
||||||
|
@ -55,6 +56,11 @@ function About(props, ref) {
|
||||||
setIsSpining(false);
|
setIsSpining(false);
|
||||||
if(result && result.data ){
|
if(result && result.data ){
|
||||||
setStep(result.data.step);
|
setStep(result.data.step);
|
||||||
|
// setStep(0);
|
||||||
|
// setFieldsValue({...result.data.cloud_account});
|
||||||
|
// if(result.data.cloud_account){
|
||||||
|
// setDisabled(true);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}).catch(error=>{
|
}).catch(error=>{
|
||||||
setIsSpining(false);
|
setIsSpining(false);
|
||||||
|
|
|
@ -45,9 +45,9 @@ function Dispose(props){
|
||||||
}).then(result=>{
|
}).then(result=>{
|
||||||
if(result && result.data){
|
if(result && result.data){
|
||||||
setList(result.data.pipelines);
|
setList(result.data.pipelines);
|
||||||
|
setSpining(false);
|
||||||
}
|
}
|
||||||
setSpining(false);
|
}).catch(error=>{})
|
||||||
}).catch(error=>{setSpining(false);})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
|
@ -137,17 +137,13 @@ function Dispose(props){
|
||||||
props.history.push(`/projects/${owner}/${projectsId}/devops/mould`);
|
props.history.push(`/projects/${owner}/${projectsId}/devops/mould`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 参数管理
|
|
||||||
function toparameter(){
|
|
||||||
props.history.push(`/projects/${owner}/${projectsId}/devops/params`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const operate = current_user && (permission && permission !== "Reporter");
|
const operate = current_user && (permission && permission !== "Reporter");
|
||||||
|
|
||||||
return(
|
return(
|
||||||
<Spin spinning={spining}>
|
<Spin spinning={spining}>
|
||||||
<PipelineName branchList={branchList} visible={visible} value={updateInfo} onCancel={()=>setVisible(false)} onOk={onOk}/>
|
<PipelineName branchList={branchList} visible={visible} value={updateInfo} onCancel={()=>setVisible(false)} onOk={onOk}/>
|
||||||
<div className="disposePanel">
|
<div className="disposePanel">
|
||||||
<Head manager={ operate ? toModalManage : undefined} parameter={operate ? toparameter :undefined}/>
|
<Head manager={ operate ? toModalManage : undefined} />
|
||||||
<Div>
|
<Div>
|
||||||
{ operate && <Blueback onClick={()=>addNew(undefined,undefined)}>新增流水线</Blueback> }
|
{ operate && <Blueback onClick={()=>addNew(undefined,undefined)}>新增流水线</Blueback> }
|
||||||
<div className="mt20 disposeList">
|
<div className="mt20 disposeList">
|
||||||
|
|
|
@ -2,50 +2,16 @@ import React from 'react';
|
||||||
import { Table , Popconfirm } from 'antd';
|
import { Table , Popconfirm } from 'antd';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
// const STATUS = {
|
const STATUS = {
|
||||||
// running:"运行中",
|
running:"运行中",
|
||||||
// failure:"未通过",
|
failure:"未通过",
|
||||||
// error:"未通过",
|
error:"未通过",
|
||||||
// success:"已通过",
|
success:"已通过",
|
||||||
// killed:"已撤销",
|
killed:"已撤销",
|
||||||
// pending:"准备中"
|
pending:"准备中"
|
||||||
// }
|
|
||||||
function renderTableStatus(status) {
|
|
||||||
switch (status) {
|
|
||||||
case "running":
|
|
||||||
return (
|
|
||||||
<span className="statusTag running">
|
|
||||||
<i className="iconfont icon-yunhangzhong"></i>运行中
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
case "failure": case 'error':
|
|
||||||
return (
|
|
||||||
<span className="statusTag failed">
|
|
||||||
<i className="iconfont icon-weitongguo"></i>未通过
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
case "success":
|
|
||||||
return (
|
|
||||||
<span className="statusTag pass">
|
|
||||||
<i className="iconfont icon-yitongguo"></i>已通过
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
case 'killed':
|
|
||||||
return (
|
|
||||||
<span className="statusTag killed">
|
|
||||||
<i className="iconfont icon-weitongguo"></i>已撤销
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
default :
|
|
||||||
return (
|
|
||||||
<span className="statusTag Preparing">
|
|
||||||
<i className="iconfont icon-zhunbeizhong"></i>准备中
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
function List({ list, operate , projectsId , owner , showModal , deleteFunc }){
|
function List({ list, operate , projectsId , owner , showModal , deleteFunc }){
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
title:"流水线名称",
|
title:"流水线名称",
|
||||||
|
@ -66,7 +32,7 @@ function List({ list, operate , projectsId , owner , showModal , deleteFunc }){
|
||||||
ellipsis:true,
|
ellipsis:true,
|
||||||
render:(value,item)=>{
|
render:(value,item)=>{
|
||||||
return(
|
return(
|
||||||
<Link to={`/projects/${owner}/${projectsId}/tree/${item.branch}/${value}`} className="color-blue">{value}</Link>
|
<Link to={`/projects/${owner}/${projectsId}/branch/${item.branch}/tree/${value}`} className="color-blue">{value}</Link>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -95,10 +61,10 @@ function List({ list, operate , projectsId , owner , showModal , deleteFunc }){
|
||||||
title:"最近构建状态",
|
title:"最近构建状态",
|
||||||
dataIndex:"pipeline_status",
|
dataIndex:"pipeline_status",
|
||||||
key:1,
|
key:1,
|
||||||
width:"12%",
|
width:"10%",
|
||||||
ellipsis:true,
|
ellipsis:true,
|
||||||
render:(txt)=>{
|
render:(txt)=>{
|
||||||
return renderTableStatus(txt)
|
return(STATUS[txt])
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,18 +2,15 @@ import React from 'react';
|
||||||
import { AlignCenterBetween , Blueline , FlexAJ } from '../../Component/layout';
|
import { AlignCenterBetween , Blueline , FlexAJ } from '../../Component/layout';
|
||||||
|
|
||||||
|
|
||||||
function head({manager , parameter}){
|
function head({manager}){
|
||||||
return(
|
return(
|
||||||
<AlignCenterBetween>
|
<AlignCenterBetween>
|
||||||
<span className="font-20">工作流配置</span>
|
<span className="font-20">工作流配置</span>
|
||||||
<FlexAJ>
|
<FlexAJ>
|
||||||
{
|
<a href={`https://forum.trustie.net/forums/3111/detail`} target="_blank" className="color-grey-6"><i className="iconfont icon-tishi1 font-14 mr3"></i>模板使用说明</a>
|
||||||
parameter && <Blueline onClick={parameter}>参数管理</Blueline>
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
manager && <Blueline style={{marginLeft:"20px"}} onClick={manager}>模板管理</Blueline>
|
manager && <Blueline style={{marginLeft:"20px"}} onClick={manager}>模板管理</Blueline>
|
||||||
}
|
}
|
||||||
<a href={`https://forum.trustie.net/forums/3111/detail`} target="_blank" className="color-grey-6 ml20"><i className="iconfont icon-tishi1 font-14 mr3"></i>模板使用说明</a>
|
|
||||||
</FlexAJ>
|
</FlexAJ>
|
||||||
</AlignCenterBetween>
|
</AlignCenterBetween>
|
||||||
)
|
)
|
||||||
|
|
|
@ -26,11 +26,6 @@ const Mould = Loadable({
|
||||||
loader: () => import('./Mould'),
|
loader: () => import('./Mould'),
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
})
|
})
|
||||||
const Params = Loadable({
|
|
||||||
loader: () => import('./Manage/Params'),
|
|
||||||
loading: Loading,
|
|
||||||
})
|
|
||||||
|
|
||||||
export default ((props)=>{
|
export default ((props)=>{
|
||||||
|
|
||||||
return(
|
return(
|
||||||
|
@ -41,11 +36,6 @@ export default ((props)=>{
|
||||||
(p) => (<New {...props} {...p}/>)
|
(p) => (<New {...props} {...p}/>)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
<Route path="/projects/:owner/:projectsId/devops/params"
|
|
||||||
render={
|
|
||||||
(p) => (<Params {...props} {...p}/>)
|
|
||||||
}
|
|
||||||
></Route>
|
|
||||||
<Route path="/projects/:owner/:projectsId/devops/mould"
|
<Route path="/projects/:owner/:projectsId/devops/mould"
|
||||||
render={
|
render={
|
||||||
(p) => (<Mould {...props} {...p}/>)
|
(p) => (<Mould {...props} {...p}/>)
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import React , { useEffect , useState } from 'react';
|
import React , { useEffect , useState , useRef } from 'react';
|
||||||
import { Banner } from '../Component/layout';
|
import { Banner } from '../Component/layout';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
import Dispost from './Dispose';
|
import Dispost from './Dispose';
|
||||||
|
import Structure from './Structure';
|
||||||
|
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
@ -10,11 +11,22 @@ const Div = styled.div`{
|
||||||
padding:24px 30px;
|
padding:24px 30px;
|
||||||
}`;
|
}`;
|
||||||
export default ((props)=>{
|
export default ((props)=>{
|
||||||
|
const [ menu , setMenu ] = useState(false);
|
||||||
const [ permission , setPermission ] = useState("");
|
const [ permission , setPermission ] = useState("");
|
||||||
|
const childRef = useRef();
|
||||||
|
|
||||||
|
const path = props.location.pathname;
|
||||||
const owner = props.match.params.owner;
|
const owner = props.match.params.owner;
|
||||||
|
const projectsId = props.match.params.projectsId;
|
||||||
|
|
||||||
const projectDetail = props.projectDetail;
|
const projectDetail = props.projectDetail;
|
||||||
|
useEffect(()=>{
|
||||||
|
if(path === `/projects/${owner}/${projectsId}/devops/list`){
|
||||||
|
setMenu(true);
|
||||||
|
}else{
|
||||||
|
setMenu(false);
|
||||||
|
}
|
||||||
|
},[path])
|
||||||
|
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
if(projectDetail){
|
if(projectDetail){
|
||||||
|
@ -22,13 +34,22 @@ export default ((props)=>{
|
||||||
}
|
}
|
||||||
},[projectDetail])
|
},[projectDetail])
|
||||||
|
|
||||||
|
const updateChildState = () => {
|
||||||
|
// changeVal就是子组件暴露给父组件的方法
|
||||||
|
if (childRef.current) {
|
||||||
|
childRef.current.changeVal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return(
|
return(
|
||||||
<div className="disposePanel">
|
<div className="disposePanel">
|
||||||
<Banner>
|
<Banner>
|
||||||
{ permission !=="Reporter" && <Link to={`/projects/${owner}/${props.match.params.projectsId}/devops/dispose`}>工作流配置</Link>}
|
{ permission !=="Reporter" && <Link to={`/projects/${owner}/${props.match.params.projectsId}/devops/dispose`}>工作流配置</Link>}
|
||||||
|
{/* <Link to={`/projects/${owner}/${props.match.params.projectsId}/devops/list`}className={menu===true && "color-blue"}>构建列表</Link> */}
|
||||||
|
{/* { menu===true && <a onClick={updateChildState} style={{float:"right",fontSize:"14px",color:"#FF6E21",marginTop:"5px"}}>刷新</a>} */}
|
||||||
</Banner>
|
</Banner>
|
||||||
<Div>
|
<Div>
|
||||||
|
{/* { menu === true && <Structure {...props} wrappedComponentRef={(form) => childRef.current = form} ref={childRef}/> } */}
|
||||||
<Dispost {...props}/>
|
<Dispost {...props}/>
|
||||||
</Div>
|
</Div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,119 +0,0 @@
|
||||||
import React , { useEffect , useState , useRef } from 'react';
|
|
||||||
import { Banner , Blueback , FlexAJ , AlignCenter } from '../../Component/layout';
|
|
||||||
import { Input , Table , Popconfirm , Pagination } from 'antd';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import styled from 'styled-components';
|
|
||||||
import New from './ParamsNew';
|
|
||||||
import "./manage.scss";
|
|
||||||
import axios from 'axios';
|
|
||||||
import { result } from 'lodash';
|
|
||||||
|
|
||||||
const Div = styled.div`{
|
|
||||||
padding:24px 30px;
|
|
||||||
min-height:420px;
|
|
||||||
}`;
|
|
||||||
function Params(props){
|
|
||||||
const [ list ,setList ] = useState(undefined);
|
|
||||||
const [ editList ,setEditList ] = useState(undefined);
|
|
||||||
const [ visible ,setVisible ] = useState(false);
|
|
||||||
|
|
||||||
let projectsId = props.match.params.projectsId;
|
|
||||||
let owner = props.match.params.owner;
|
|
||||||
|
|
||||||
useEffect(()=>{
|
|
||||||
Init()
|
|
||||||
},[])
|
|
||||||
|
|
||||||
function Init(){
|
|
||||||
const url = `/ci/secrets.json`;
|
|
||||||
axios.get(url,{
|
|
||||||
params:{
|
|
||||||
owner,repo:projectsId
|
|
||||||
}
|
|
||||||
}).then(result=>{
|
|
||||||
if(result){
|
|
||||||
setList(result.data);
|
|
||||||
}
|
|
||||||
}).catch(error=>{})
|
|
||||||
}
|
|
||||||
|
|
||||||
const columns=[
|
|
||||||
{
|
|
||||||
title:"参数名",
|
|
||||||
dataIndex:"name",
|
|
||||||
key:1,
|
|
||||||
ellipsis:true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title:"操作",
|
|
||||||
dataIndex:"operation",
|
|
||||||
key:4,
|
|
||||||
render:(txt,item)=>{
|
|
||||||
return(
|
|
||||||
<React.Fragment>
|
|
||||||
<a className="mr10 color-grey-6" onClick={()=>editMouldFunc(item)}><i className="iconfont icon-zaibianji font-13 mr3"></i>编辑</a>
|
|
||||||
<Popconfirm title={"确定要删除此模板?"} onConfirm={()=>deleteMouldFunc(item.id,item.name)} okText="确定" cancelText={"取消"}>
|
|
||||||
<a className="mr10 color-grey-6"><i className="iconfont icon-lajitong font-13 mr3"></i>删除</a>
|
|
||||||
</Popconfirm>
|
|
||||||
</React.Fragment>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
// 编辑
|
|
||||||
function editMouldFunc(item){
|
|
||||||
setEditList(item);
|
|
||||||
setVisible(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除
|
|
||||||
function deleteMouldFunc(id,name){
|
|
||||||
if(id && name){
|
|
||||||
const url = `/ci/secrets/${id}.json`;
|
|
||||||
axios.delete(url,{
|
|
||||||
params:{owner,repo:projectsId,name}
|
|
||||||
}).then(result=>{
|
|
||||||
if(result){
|
|
||||||
Init();
|
|
||||||
props.showNotification(`参数删除成功!`);
|
|
||||||
}
|
|
||||||
}).catch(error=>{})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function successFunc(values,id){
|
|
||||||
const url = `/ci/secrets.json?owner=${owner}&repo=${projectsId}`;
|
|
||||||
axios.post(url,{
|
|
||||||
...values,id
|
|
||||||
}).then(result=>{
|
|
||||||
if(result){
|
|
||||||
props.showNotification(`${id ? '参数编辑':"新增参数"}成功!`);
|
|
||||||
Init();
|
|
||||||
}
|
|
||||||
}).catch(error=>{})
|
|
||||||
}
|
|
||||||
|
|
||||||
function CancelFunc(){
|
|
||||||
setVisible(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
return(
|
|
||||||
<div>
|
|
||||||
<New visble={visible} successFunc={successFunc} CancelFunc={CancelFunc} editList={editList}/>
|
|
||||||
<Banner>
|
|
||||||
<FlexAJ>
|
|
||||||
<span className="font-18">工作流 - 参数管理</span>
|
|
||||||
<Link to={`/projects/${owner}/${projectsId}/devops/dispose`} className="font-14 color-grey-9 ml20">返回</Link>
|
|
||||||
</FlexAJ>
|
|
||||||
</Banner>
|
|
||||||
<Div className="disposeList">
|
|
||||||
<div style={{textAlign:"right"}}>
|
|
||||||
<Blueback onClick={()=>setVisible(true)}>新建</Blueback>
|
|
||||||
</div>
|
|
||||||
<Table className="mt20" size="small" columns={columns} dataSource={list} rowKey={(row)=>row.id} pagination={false}></Table>
|
|
||||||
</Div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export default Params;
|
|
|
@ -1,73 +0,0 @@
|
||||||
import React , { useEffect , useState , useRef , forwardRef } from 'react';
|
|
||||||
import { Modal , Input , Form } from 'antd';
|
|
||||||
|
|
||||||
const { TextArea } = Input;
|
|
||||||
|
|
||||||
function ParamsNew({ form , visble,successFunc,CancelFunc ,editList }){
|
|
||||||
const { getFieldDecorator, validateFields , setFieldsValue } = form;
|
|
||||||
const layout = {
|
|
||||||
labelCol: { span: 5 },
|
|
||||||
wrapperCol: { span: 18 },
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(()=>{
|
|
||||||
if(editList && editList.id){
|
|
||||||
setFieldsValue({
|
|
||||||
name:editList.name,
|
|
||||||
data:editList.data
|
|
||||||
})
|
|
||||||
}else{
|
|
||||||
setFieldsValue({
|
|
||||||
name:undefined,
|
|
||||||
data:undefined
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},[editList])
|
|
||||||
|
|
||||||
// 确定
|
|
||||||
function onConfirmFunc(){
|
|
||||||
validateFields((error,values)=>{
|
|
||||||
if(!error){
|
|
||||||
successFunc(values,editList && editList.id);
|
|
||||||
onCancelFunc();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
function onCancelFunc(){
|
|
||||||
setFieldsValue({
|
|
||||||
name:undefined,
|
|
||||||
data:undefined
|
|
||||||
})
|
|
||||||
CancelFunc();
|
|
||||||
}
|
|
||||||
return(
|
|
||||||
<Modal
|
|
||||||
visible={visble}
|
|
||||||
okText={"确定"}
|
|
||||||
cancelText={"取消"}
|
|
||||||
onCancel={onCancelFunc}
|
|
||||||
onOk={onConfirmFunc}
|
|
||||||
title={"新建"}
|
|
||||||
closable={false}
|
|
||||||
width="500px"
|
|
||||||
>
|
|
||||||
<Form {...layout}>
|
|
||||||
<Form.Item label="参数名称">
|
|
||||||
{getFieldDecorator("name",{
|
|
||||||
rules:[{required:true,message:"请输入参数名称"}]
|
|
||||||
})(
|
|
||||||
<Input placeholder="请输入参数名称" width="220px"/>
|
|
||||||
)}
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="参数值">
|
|
||||||
{getFieldDecorator("data",{
|
|
||||||
rules:[{required:true,message:"请输入参数值"}]
|
|
||||||
})(
|
|
||||||
<TextArea placeholder="请输入参数值" width="220px" autoSize={{ minRows: 4, maxRows: 4 }}/>
|
|
||||||
)}
|
|
||||||
</Form.Item>
|
|
||||||
</Form>
|
|
||||||
</Modal>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export default Form.create()(forwardRef(ParamsNew));
|
|
|
@ -1,4 +0,0 @@
|
||||||
.ant-form-explain{
|
|
||||||
position: absolute;
|
|
||||||
bottom: -15px;
|
|
||||||
}
|
|
|
@ -1,8 +1,7 @@
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { Spin , Menu } from "antd";
|
import { Spin } from "antd";
|
||||||
import { FlexAJ, AlignCenter } from "../Component/layout";
|
import { FlexAJ, AlignCenter } from "../Component/layout";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import CodeSSH from './ssh/Index';
|
|
||||||
|
|
||||||
export default ({
|
export default ({
|
||||||
data,
|
data,
|
||||||
|
@ -18,8 +17,6 @@ export default ({
|
||||||
const [spining, setSpining] = useState(true);
|
const [spining, setSpining] = useState(true);
|
||||||
const [stage, setStage] = useState(undefined);
|
const [stage, setStage] = useState(undefined);
|
||||||
const [step, setStep] = useState(undefined);
|
const [step, setStep] = useState(undefined);
|
||||||
const [nav, setNav] = useState("0");
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setSpining(rightSpin);
|
setSpining(rightSpin);
|
||||||
}, [rightSpin]);
|
}, [rightSpin]);
|
||||||
|
@ -38,7 +35,6 @@ export default ({
|
||||||
: p[0];
|
: p[0];
|
||||||
|
|
||||||
setStep(sub);
|
setStep(sub);
|
||||||
setNav("0");
|
|
||||||
if (sub && sub.status !== "skipped") {
|
if (sub && sub.status !== "skipped") {
|
||||||
getStep(pre.number, sub.number);
|
getStep(pre.number, sub.number);
|
||||||
}
|
}
|
||||||
|
@ -69,55 +65,43 @@ export default ({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<Spin spinning={spining}>
|
||||||
{/* <Menu className="devopsNav" onClick={(e)=>{setNav(e.key)}} selectedKeys={[nav]} mode="horizontal">
|
<div className="rightMainContent">
|
||||||
<Menu.Item key={'0'} value="0">开发流水线</Menu.Item>
|
{data && data.status !== "error" ? (
|
||||||
<Menu.Item key={'1'} value="1">命令行</Menu.Item>
|
<div>
|
||||||
</Menu> */}
|
<FlexAJ className="items">
|
||||||
{
|
<span>{step && step.name}</span>
|
||||||
nav === "0" &&
|
<AlignCenter>
|
||||||
<Spin spinning={spining}>
|
{step && step.duration_time}
|
||||||
<div className="rightMainContent">
|
<i className="iconfont icon-sanjiaoxing-down"></i>
|
||||||
{data && data.status !== "error" ? (
|
</AlignCenter>
|
||||||
<div>
|
</FlexAJ>
|
||||||
<FlexAJ className="items">
|
<div>
|
||||||
<span>{step && step.name}</span>
|
{coders && coders.length > 0 ? (
|
||||||
<AlignCenter>
|
coders.map((item, key) => {
|
||||||
{step && step.duration_time}
|
return (
|
||||||
<i className="iconfont icon-sanjiaoxing-down"></i>
|
|
||||||
</AlignCenter>
|
|
||||||
</FlexAJ>
|
|
||||||
<div>
|
|
||||||
{coders && coders.length > 0 ? (
|
|
||||||
coders.map((item, key) => {
|
|
||||||
return (
|
|
||||||
<div className="opsDetailOut">
|
|
||||||
<span>{key + 1}</span>
|
|
||||||
<p>{item.out}</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})
|
|
||||||
) : empty ? (
|
|
||||||
<div className="opsDetailOut">
|
<div className="opsDetailOut">
|
||||||
<span>1</span>
|
<span>{key + 1}</span>
|
||||||
<p>
|
<p>{item.out}</p>
|
||||||
{stage && stage.name} – {step && step.name}: Skipped
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
) : (
|
);
|
||||||
""
|
})
|
||||||
)}
|
) : empty ? (
|
||||||
|
<div className="opsDetailOut">
|
||||||
|
<span>1</span>
|
||||||
|
<p>
|
||||||
|
{stage && stage.name} – {step && step.name}: Skipped
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
) : (
|
||||||
) : (
|
""
|
||||||
<div style={{ color: "red" }}>error:{data && data.error}</div>
|
)}
|
||||||
)}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Spin>
|
) : (
|
||||||
}
|
<div style={{ color: "red" }}>error:{data && data.error}</div>
|
||||||
{
|
)}
|
||||||
nav === "1" && <CodeSSH />
|
</div>
|
||||||
}
|
</Spin>
|
||||||
</React.Fragment>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -58,7 +58,6 @@ function Structure(props,ref){
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
author:item.author && item.author.name,
|
author:item.author && item.author.name,
|
||||||
image_url:item.author && item.author.image_url,
|
|
||||||
message: {
|
message: {
|
||||||
branch: item.branch_target,
|
branch: item.branch_target,
|
||||||
message: item.message,
|
message: item.message,
|
||||||
|
@ -188,7 +187,7 @@ function Structure(props,ref){
|
||||||
<i className="iconfont icon-weitongguo"></i>已撤销
|
<i className="iconfont icon-weitongguo"></i>已撤销
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
default:
|
case 'pending':
|
||||||
return (
|
return (
|
||||||
<span className="statusTag Preparing">
|
<span className="statusTag Preparing">
|
||||||
<i className="iconfont icon-zhunbeizhong"></i>准备中
|
<i className="iconfont icon-zhunbeizhong"></i>准备中
|
||||||
|
@ -245,7 +244,7 @@ function Structure(props,ref){
|
||||||
{meg.sha && <span className="color-orange">{meg.sha}</span>}
|
{meg.sha && <span className="color-orange">{meg.sha}</span>}
|
||||||
</div>
|
</div>
|
||||||
<AlignCenter>
|
<AlignCenter>
|
||||||
<img style={{borderRadius:"50%",marginRight:"10px",width:"25px",height:"25px"}} alt="" src={`${item.image_url && getUrl(`/images/${item.image_url}`)}`} />
|
<img style={{borderRadius:"50%",marginRight:"10px",width:"25px",height:"25px"}} src={`${current_user && getUrl(`/images/${current_user.image_url}`)}`} />
|
||||||
<div className="task-hide ml5" style={{ maxWidth: "300px" }}>
|
<div className="task-hide ml5" style={{ maxWidth: "300px" }}>
|
||||||
{meg.message}
|
{meg.message}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
padding:60px 0px;
|
padding:60px 0px;
|
||||||
}
|
}
|
||||||
.disposePanel{
|
.disposePanel{
|
||||||
border:1px solid #eee;
|
|
||||||
.language{
|
.language{
|
||||||
display: flex;
|
display: flex;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
|
@ -82,7 +81,48 @@
|
||||||
.ant-modal-close{
|
.ant-modal-close{
|
||||||
top:7px;
|
top:7px;
|
||||||
}
|
}
|
||||||
|
// 列表
|
||||||
|
.listPart{
|
||||||
|
.statusTag{
|
||||||
|
display: flex;
|
||||||
|
padding:0px 16px;
|
||||||
|
height: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
border-radius:20px;
|
||||||
|
float: left;
|
||||||
|
i{
|
||||||
|
font-size: 20px!important;
|
||||||
|
margin-right: 7px;
|
||||||
|
}
|
||||||
|
&.running{
|
||||||
|
background:#F1F8FF;
|
||||||
|
border:1px solid #5091FF;
|
||||||
|
color: #5091FF;
|
||||||
|
}
|
||||||
|
&.Preparing{
|
||||||
|
background:rgba(255,248,244,1);
|
||||||
|
border:1px solid rgba(255,110,33,1);
|
||||||
|
color:rgba(255,110,33,1) ;
|
||||||
|
}
|
||||||
|
&.pass{
|
||||||
|
background:#EEFDF5;
|
||||||
|
border:1px solid #28BD6C;
|
||||||
|
color:#28BD6C ;
|
||||||
|
}
|
||||||
|
&.failed{
|
||||||
|
background:#FCEEEE;
|
||||||
|
border:1px solid #F73030;
|
||||||
|
color:#F73030 ;
|
||||||
|
}
|
||||||
|
&.killed{
|
||||||
|
background:#eee;
|
||||||
|
border:1px solid #999;
|
||||||
|
color:#999 ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// ops详情
|
// ops详情
|
||||||
.opsDetailPanel{
|
.opsDetailPanel{
|
||||||
|
@ -194,18 +234,6 @@
|
||||||
&.rightSection{
|
&.rightSection{
|
||||||
width:100%;
|
width:100%;
|
||||||
background-color: #081930;
|
background-color: #081930;
|
||||||
.devopsNav{
|
|
||||||
background-color: #111c24;
|
|
||||||
border-bottom: none;
|
|
||||||
.ant-menu-item{
|
|
||||||
color: #ccc;
|
|
||||||
padding:0px;
|
|
||||||
margin:0px 20px!important;
|
|
||||||
}
|
|
||||||
.ant-menu-item.ant-menu-item-selected{
|
|
||||||
color: #1890ff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.rightMainContent{
|
.rightMainContent{
|
||||||
padding:24px 30px;
|
padding:24px 30px;
|
||||||
height:100vh;
|
height:100vh;
|
||||||
|
@ -481,41 +509,4 @@
|
||||||
}
|
}
|
||||||
.hide{
|
.hide{
|
||||||
display: none!important;
|
display: none!important;
|
||||||
}
|
|
||||||
.statusTag{
|
|
||||||
display: flex;
|
|
||||||
padding:0px 16px;
|
|
||||||
height: 32px;
|
|
||||||
line-height: 32px;
|
|
||||||
border-radius:20px;
|
|
||||||
float: left;
|
|
||||||
i{
|
|
||||||
font-size: 20px!important;
|
|
||||||
margin-right: 7px;
|
|
||||||
}
|
|
||||||
&.running{
|
|
||||||
background:#F1F8FF;
|
|
||||||
border:1px solid #5091FF;
|
|
||||||
color: #5091FF;
|
|
||||||
}
|
|
||||||
&.Preparing{
|
|
||||||
background:rgba(255,248,244,1);
|
|
||||||
border:1px solid rgba(255,110,33,1);
|
|
||||||
color:rgba(255,110,33,1) ;
|
|
||||||
}
|
|
||||||
&.pass{
|
|
||||||
background:#EEFDF5;
|
|
||||||
border:1px solid #28BD6C;
|
|
||||||
color:#28BD6C ;
|
|
||||||
}
|
|
||||||
&.failed{
|
|
||||||
background:#FCEEEE;
|
|
||||||
border:1px solid #F73030;
|
|
||||||
color:#F73030 ;
|
|
||||||
}
|
|
||||||
&.killed{
|
|
||||||
background:#eee;
|
|
||||||
border:1px solid #999;
|
|
||||||
color:#999 ;
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,42 +0,0 @@
|
||||||
import React, { useState, useEffect } from "react";
|
|
||||||
import XmlPanel from "./XmlPanel";
|
|
||||||
import mediator from "./mediator";
|
|
||||||
import axios from "axios";
|
|
||||||
|
|
||||||
// const defaulturl = `http://47.111.130.18:48088`;
|
|
||||||
const defaultValue = {
|
|
||||||
host: "106.75.231.63",
|
|
||||||
port: "2021",
|
|
||||||
ws_url: "wss://pre-webssh.educoder.net/ws",
|
|
||||||
username: "root",
|
|
||||||
secret: "Dron_123123",
|
|
||||||
};
|
|
||||||
function Index() {
|
|
||||||
const [sshConfigData, setSshConfigData] = useState(undefined);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!sshConfigData) {
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
setTimeout(() => {
|
|
||||||
mediator.publish("create-socket", 1);
|
|
||||||
}, 300);
|
|
||||||
}, [sshConfigData]);
|
|
||||||
|
|
||||||
// 获取服务器连接信息
|
|
||||||
function init() {
|
|
||||||
const url = `/api/ci/pipelines/ssh_server.json`;
|
|
||||||
axios.get(url).then(result=>{
|
|
||||||
if(result && result.data){
|
|
||||||
setSshConfigData({...result.data})
|
|
||||||
}
|
|
||||||
}).catch(error=>{})
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<XmlPanel
|
|
||||||
sshConfigData={sshConfigData||{}}
|
|
||||||
sid={1}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
export default Index;
|
|
|
@ -1,219 +0,0 @@
|
||||||
import React, { useRef, useEffect, useState } from 'react';
|
|
||||||
import { Base64 } from 'js-base64';
|
|
||||||
|
|
||||||
import { Terminal } from 'xterm';
|
|
||||||
import 'xterm/css/xterm.css';
|
|
||||||
import mediator from './mediator';
|
|
||||||
import ResizeObserver from 'resize-observer-polyfill';
|
|
||||||
|
|
||||||
function getColsAndRows(width, height, term) {
|
|
||||||
let w = term._core._renderService.dimensions.actualCellWidth || 9.5;
|
|
||||||
let h = term._core._renderService.dimensions.actualCellHeight || 18;
|
|
||||||
const rows = Math.floor(height / h);
|
|
||||||
const cols = Math.floor(width / w);
|
|
||||||
return [cols, rows];
|
|
||||||
}
|
|
||||||
|
|
||||||
function onLayout(term, el) {
|
|
||||||
const ro = new ResizeObserver(entries => {
|
|
||||||
console.log(entries);
|
|
||||||
for (let entry of entries) {
|
|
||||||
if (entry.target.offsetHeight > 0 || entry.target.offsetWidth > 0) {
|
|
||||||
const [cols, rows] = getColsAndRows(
|
|
||||||
entry.target.offsetWidth,
|
|
||||||
entry.target.offsetHeight,
|
|
||||||
term,
|
|
||||||
);
|
|
||||||
console.log('cols, rows', cols, rows);
|
|
||||||
term.resize(cols, rows);
|
|
||||||
mediator.publish('ssh-xterm-resize', {
|
|
||||||
columns: cols,
|
|
||||||
rows: rows,
|
|
||||||
width: entry.target.offsetWidth,
|
|
||||||
height: entry.target.offsetHeight,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
ro.observe(el);
|
|
||||||
return ro;
|
|
||||||
}
|
|
||||||
|
|
||||||
const TimeTicket = 30000;
|
|
||||||
|
|
||||||
//建立 websockt 来交互
|
|
||||||
//根据容器大小计算行数和列数并做到自适应
|
|
||||||
//socket 与 term 需要分开初始化 因为socket 可能重置连接
|
|
||||||
//mediator 监听消息,如果和id匹配,则建立连接,重置,或关闭连接
|
|
||||||
|
|
||||||
export default ({ sshConfigData, sid }) => {
|
|
||||||
const [term, setTerm] = useState(null);
|
|
||||||
|
|
||||||
const { ws_url, password, port, secret } = sshConfigData;
|
|
||||||
const el = useRef();
|
|
||||||
const socket = useRef();
|
|
||||||
const isFirstConnected = useRef(false);
|
|
||||||
|
|
||||||
//term init
|
|
||||||
useEffect(() => {
|
|
||||||
if (el.current && ws_url) {
|
|
||||||
const term = new Terminal({ fontSize: 16, rendererType: 'dom' });
|
|
||||||
term.open(el.current);
|
|
||||||
|
|
||||||
term.onData(data => {
|
|
||||||
if (socket.current) {
|
|
||||||
if (socket.current.readyState === 1) {
|
|
||||||
socket.current.send(JSON.stringify({ tp: 'client', data: data }));
|
|
||||||
mediator.publish('on-operating-ssh'); //有操作则自动延时
|
|
||||||
} else {
|
|
||||||
//断开连接后重连
|
|
||||||
// socket.current = null
|
|
||||||
// mediator.publish('create-socket', sid)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
term.write('Connecting...');
|
|
||||||
setTerm(term);
|
|
||||||
const ro = onLayout(term, el.current);
|
|
||||||
return () => {
|
|
||||||
term.dispose();
|
|
||||||
ro.unobserve(el.current);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}, [ws_url, el.current]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (term && ws_url) {
|
|
||||||
function createSocket() {
|
|
||||||
const socketInstance = new WebSocket(ws_url);
|
|
||||||
socket.current = socketInstance;
|
|
||||||
|
|
||||||
socketInstance.onopen = () => {
|
|
||||||
let container = term.element.parentElement;
|
|
||||||
if (container) {
|
|
||||||
let width = container.offsetWidth;
|
|
||||||
let height = container.offsetHeight;
|
|
||||||
console.log('init', {
|
|
||||||
tp: 'init',
|
|
||||||
data: {
|
|
||||||
...sshConfigData,
|
|
||||||
secret: secret,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
rows: term.rows,
|
|
||||||
columns: term.cols,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
socketInstance.send(
|
|
||||||
JSON.stringify({
|
|
||||||
tp: 'init',
|
|
||||||
data: {
|
|
||||||
...sshConfigData,
|
|
||||||
secret: secret,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
rows: term.rows,
|
|
||||||
columns: term.cols,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
term.focus();
|
|
||||||
};
|
|
||||||
socketInstance.onerror = error => {
|
|
||||||
console.log(
|
|
||||||
'------in socket error----',
|
|
||||||
error,
|
|
||||||
socketInstance,
|
|
||||||
ws_url,
|
|
||||||
);
|
|
||||||
//连接报错后,重新请求资源
|
|
||||||
// mediator.publish('on-recreate-socket')
|
|
||||||
};
|
|
||||||
socketInstance.onmessage = event => {
|
|
||||||
if (!isFirstConnected.current) {
|
|
||||||
term.write('\r');
|
|
||||||
// term.focus()
|
|
||||||
setTimeout(() => {
|
|
||||||
// term.clear();
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
isFirstConnected.current = true;
|
|
||||||
console.log('event:', event);
|
|
||||||
|
|
||||||
const data = Base64.decode(event.data.toString());
|
|
||||||
let w = term._core._renderService.dimensions.actualCellWidth || 9.5;
|
|
||||||
|
|
||||||
console.log('data:', data, w, term);
|
|
||||||
term.write(data);
|
|
||||||
};
|
|
||||||
|
|
||||||
socketInstance.onclose = evt => {
|
|
||||||
if (tid) {
|
|
||||||
clearInterval(tid);
|
|
||||||
}
|
|
||||||
term.write('\r\nconnection closed');
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const tid = setInterval(() => {
|
|
||||||
if (socket.current) {
|
|
||||||
socket.current.send(JSON.stringify({ tp: 'h' }));
|
|
||||||
}
|
|
||||||
}, TimeTicket);
|
|
||||||
|
|
||||||
const unSubCreate = mediator.subscribe('create-socket', id => {
|
|
||||||
if (sid === id) {
|
|
||||||
if (socket.current && socket.current.readyState === 1) {
|
|
||||||
term.focus();
|
|
||||||
} else {
|
|
||||||
createSocket();
|
|
||||||
}
|
|
||||||
term.focus();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const unSubClose = mediator.subscribe('close-socket', id => {
|
|
||||||
if (sid === id) {
|
|
||||||
if (socket.current) {
|
|
||||||
socket.current.close();
|
|
||||||
isFirstConnected.current = false;
|
|
||||||
term.clear();
|
|
||||||
}
|
|
||||||
socket.current = null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const unSubResize = mediator.subscribe('ssh-xterm-resize', option => {
|
|
||||||
if (socket.current && socket.current.readyState === 1) {
|
|
||||||
socket.current.send(
|
|
||||||
JSON.stringify({ tp: 'resize', data: { ...option } }),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const unSubAddTime = mediator.subscribe('ssh-add-connect-time', () => {
|
|
||||||
if (socket.current && socket.current.readyState === 1) {
|
|
||||||
socket.current.send(JSON.stringify({ tp: 'overtime' }));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
unSubClose();
|
|
||||||
unSubCreate();
|
|
||||||
unSubResize();
|
|
||||||
unSubAddTime();
|
|
||||||
if (socket.current) {
|
|
||||||
socket.current.close();
|
|
||||||
isFirstConnected.current = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}, [term, ws_url, port]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div ref={el} className="xterm-panel" style={{height:"100%"}}>
|
|
||||||
{!ws_url ? <p style={{ color: '#fff' }}>正在连接命令行服务...</p> : null}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
|
@ -1,46 +0,0 @@
|
||||||
function Mediator(obj) {
|
|
||||||
const channels = {};
|
|
||||||
|
|
||||||
const mediator = {
|
|
||||||
subscribe: function(channel, cb) {
|
|
||||||
if (!channels[channel]) {
|
|
||||||
channels[channel] = [];
|
|
||||||
}
|
|
||||||
channels[channel].push(cb);
|
|
||||||
return this.unsubscribe.bind(null, channel, cb);
|
|
||||||
},
|
|
||||||
|
|
||||||
unsubscribe: function(channel, cb) {
|
|
||||||
let rs = channels[channel];
|
|
||||||
let index = -1;
|
|
||||||
if (rs) {
|
|
||||||
for (let i = 0; i < rs.length; i++) {
|
|
||||||
if (rs[i].name === cb.name) {
|
|
||||||
index = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (index >= 0) {
|
|
||||||
channels[channel].splice(index, 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
publish: function(channel) {
|
|
||||||
if (!channels[channel]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
channels[channel].forEach(subscription => {
|
|
||||||
subscription.apply(null, args);
|
|
||||||
});
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
return obj ? Object.assign(obj, mediator) : mediator;
|
|
||||||
}
|
|
||||||
const mediator = new Mediator();
|
|
||||||
export default mediator;
|
|
|
@ -10,12 +10,4 @@ export const getTag = async (id,owner)=>{
|
||||||
// 获取hooks(仓库设置-管理web钩子)列表
|
// 获取hooks(仓库设置-管理web钩子)列表
|
||||||
export const getHooks = async (id,params)=>{
|
export const getHooks = async (id,params)=>{
|
||||||
return (await axios.get(`/projects/${id}/hooks.json`,{params})).data;
|
return (await axios.get(`/projects/${id}/hooks.json`,{params})).data;
|
||||||
}
|
|
||||||
// 获取子目录列表
|
|
||||||
export const getSubEntries = async (owner,projectsId,params)=>{
|
|
||||||
return (await axios.get(`/${owner}/${projectsId}/sub_entries.json`,{params})).data;
|
|
||||||
}
|
|
||||||
// 获取用户信息
|
|
||||||
export const getUser = async (login)=>{
|
|
||||||
return (await axios.get(`/users/${login}/hovercard.json`)).data;
|
|
||||||
}
|
}
|
|
@ -1,66 +0,0 @@
|
||||||
import React, { useEffect , useState } from 'react';
|
|
||||||
import './header.scss';
|
|
||||||
|
|
||||||
function Footer(){
|
|
||||||
const [ value , setValue ] = useState(undefined);
|
|
||||||
|
|
||||||
useEffect(()=>{
|
|
||||||
try {
|
|
||||||
var chromesettingArray = JSON.parse(localStorage.getItem('chromesetting'));
|
|
||||||
setValue(chromesettingArray.footer);
|
|
||||||
} catch (e) {
|
|
||||||
}
|
|
||||||
},[])
|
|
||||||
|
|
||||||
function showhtml(htmlString){
|
|
||||||
var html = {__html:htmlString};
|
|
||||||
return <div dangerouslySetInnerHTML={html}></div> ;
|
|
||||||
}
|
|
||||||
|
|
||||||
return(
|
|
||||||
<div>
|
|
||||||
<div style={{height:"483px"}}></div>
|
|
||||||
<div className="newFooter edu-txt-center">
|
|
||||||
{value && showhtml(value)}
|
|
||||||
{/* <div className="footerInfos">
|
|
||||||
<ul>
|
|
||||||
<li>社区</li>
|
|
||||||
<li><a href={`/`} target="_blank">网站首页</a></li>
|
|
||||||
<li><a href={`https://www.trustie.net/agreement`} target="_blank">服务协议</a></li>
|
|
||||||
<li><a href={`https://forum.trustie.net/forums/1168/detail`} target="_blank">帮助中心</a></li>
|
|
||||||
<li><a href={`https://forum.trustie.net/`} target="_blank">问吧交流</a></li>
|
|
||||||
<li><a href={`https://www.trustie.net/cooperation`} target="_blank">合作伙伴</a></li>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li>支持与服务</li>
|
|
||||||
<li><a href={`https://forgeplus.trustie.net/docs/api`} target="_blank">API文档</a></li>
|
|
||||||
<li><a href={`https://forum.trustie.net/forums/1168/detail`} target="_blank">帮助中心</a></li>
|
|
||||||
<li><a href={`https://git-scm.com`} target="_blank">Git常用命令</a></li>
|
|
||||||
<li><a href={`https://forum.trustie.net/forums/3080/detail`} target="_blank">DevOps使用文档</a></li>
|
|
||||||
<li><a href={`https://forgeplus.trustie.net/projects/jasder/forgeplus/tree/master/CHANGELOG.md`} target="_blank">日志更新</a></li>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li>合作伙伴</li>
|
|
||||||
<li><a href={`http://www.sei.pku.edu.cn`} target="_blank">北京大学</a></li>
|
|
||||||
<li><a href={`http://scse.buaa.edu.cn`} target="_blank">北京航空航天大学</a></li>
|
|
||||||
<li><a href={`https://www.nju.edu.cn`} target="_blank">南京大学</a></li>
|
|
||||||
<li><a href={`https://www.xtu.edu.cn`} target="_blank">湘潭大学</a></li>
|
|
||||||
<li><a href={`http://www.iscas.ac.cn`} target="_blank">ISCAS</a></li>
|
|
||||||
<li><a href={`https://www.ucloud.cn`} target="_blank">UCloud优刻得</a></li>
|
|
||||||
<li><a href={`http://www.inforbus.com`} target="_blank">中创软件</a></li>
|
|
||||||
<li><a href={`https://www.inspur.com`} target="_blank">浪潮集团</a></li>
|
|
||||||
<li><a href={`http://www.copu.org.cn`} target="_blank">中国开源软件推进联盟</a></li>
|
|
||||||
<li><a href={`https://www.sjtu.edu.cn`} target="_blank">上海交通大学</a></li>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li>合作伙伴</li>
|
|
||||||
<li><span>热线:</span></li>
|
|
||||||
<li><span>QQ群:1071514693</span></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<p className="footerCopy">© Copyright 2007~2021 国防科技大学Trustie团队 & IntelliDE <a href="https://beian.miit.gov.cn">湘ICP备 17009477号</a></p> */}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export default Footer;
|
|
|
@ -1,730 +0,0 @@
|
||||||
import React, { Component } from 'react';
|
|
||||||
import AccountProfile from "../../modules/user/AccountProfile";
|
|
||||||
import { getImageUrl } from 'educoder'
|
|
||||||
import axios from 'axios';
|
|
||||||
import { Modal, Input, message, notification , Dropdown , Menu ,Divider } from 'antd';
|
|
||||||
|
|
||||||
import LoginDialog from '../../modules/login/LoginDialog';
|
|
||||||
import GotoQQgroup from '../../modal/GotoQQgroup'
|
|
||||||
// import 'antd/lib/modal/style/index.css';
|
|
||||||
// import 'antd/lib/checkbox/style/index.css';
|
|
||||||
// import 'antd/lib/radio/style/index.css';
|
|
||||||
// import 'antd/lib/input/style/index.css';
|
|
||||||
import '../../modules/tpm/TPMIndex.css';
|
|
||||||
import logo from '../../modules/tpm/images/logo.png';
|
|
||||||
import './header.scss';
|
|
||||||
const $ = window.$
|
|
||||||
// TODO 这部分脚本从公共脚本中直接调用
|
|
||||||
const { Search } = Input;
|
|
||||||
let old_url;
|
|
||||||
|
|
||||||
window._header_componentHandler = null;
|
|
||||||
// 非trustie链接则新开页跳转
|
|
||||||
const str = ['www.trustie.net','forgeplus.trustie.net','forum.trustie.net','testforgeplus.trustie.net']
|
|
||||||
class NewHeader extends Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props)
|
|
||||||
this.state = {
|
|
||||||
Addcoursestypes: false,
|
|
||||||
tojoinitemtype: false,
|
|
||||||
tojoinclasstitle: undefined,
|
|
||||||
rolearr: ["", ""],
|
|
||||||
Checkboxteacherchecked: false,
|
|
||||||
Checkboxstudentchecked: false,
|
|
||||||
Checkboxteachingchecked: false,
|
|
||||||
Checkboxteachertype: false,
|
|
||||||
Checkboxteachingtype: false,
|
|
||||||
code_notice: false,
|
|
||||||
checked_notice: false,
|
|
||||||
RadioGroupvalue: undefined,
|
|
||||||
submitapplications: false,
|
|
||||||
isRender: false,
|
|
||||||
showSearchOpentype: false,
|
|
||||||
showTrial: false,
|
|
||||||
setevaluatinghides: false,
|
|
||||||
occupation: 0,
|
|
||||||
mydisplay: false,
|
|
||||||
headtypesonClickbool: false,
|
|
||||||
headtypess: "/",
|
|
||||||
settings: null,
|
|
||||||
goshowqqgtounp: false,
|
|
||||||
visiblemyss: false,
|
|
||||||
openSearch:false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
componentDidMount() {
|
|
||||||
// this.getAppdata();
|
|
||||||
this.geturlsdata();
|
|
||||||
window._header_componentHandler = this;
|
|
||||||
|
|
||||||
//下拉框的显示隐藏
|
|
||||||
var hoverTimeout;
|
|
||||||
var hoveredPanel;
|
|
||||||
$(".edu-menu-panel").hover(function () {
|
|
||||||
if (hoverTimeout) { // 一次只显示一个panel
|
|
||||||
if (hoveredPanel && hoveredPanel !== this) {
|
|
||||||
$(hoveredPanel).find(".edu-menu-list").hide()
|
|
||||||
}
|
|
||||||
clearTimeout(hoverTimeout);
|
|
||||||
hoverTimeout = null;
|
|
||||||
}
|
|
||||||
hoveredPanel = this;
|
|
||||||
$(this).find(".edu-menu-list").show();
|
|
||||||
}, function () {
|
|
||||||
var that = this;
|
|
||||||
// 延迟hide
|
|
||||||
hoverTimeout = setTimeout(function () {
|
|
||||||
$(that).find(".edu-menu-list").hide();
|
|
||||||
}, 800)
|
|
||||||
|
|
||||||
});
|
|
||||||
//获取游览器地址
|
|
||||||
try {
|
|
||||||
window.sessionStorage.setItem("yslgeturls", JSON.stringify(window.location.href))
|
|
||||||
} catch (e) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
SearchInput = (open,item)=>{
|
|
||||||
if(open){
|
|
||||||
return(
|
|
||||||
<div
|
|
||||||
onBlur={() => {
|
|
||||||
setTimeout(() => {
|
|
||||||
this.setState({
|
|
||||||
openSearch:false
|
|
||||||
})
|
|
||||||
}, 300)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Search placeholder="实践课程/教学课堂/实践项目/交流问答"
|
|
||||||
className={`search-input mr20`}
|
|
||||||
onSearch={(value)=>this.onGlobalSearch(value,item)}
|
|
||||||
autoFocus={true}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}else{
|
|
||||||
return <i className="iconfont icon-sousuo font-18 color-grey-6 ml30" onClick={() => {
|
|
||||||
this.setState({openSearch:true})
|
|
||||||
}} />
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onGlobalSearch=(value,item)=>{
|
|
||||||
window.location.href=`${item}?value=` + value;
|
|
||||||
}
|
|
||||||
|
|
||||||
openNotification = (messge) => {
|
|
||||||
notification.open({
|
|
||||||
message: "提示",
|
|
||||||
description:
|
|
||||||
messge,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
componentWillReceiveProps(newProps, oldProps) {
|
|
||||||
this.setState({
|
|
||||||
user: newProps.user
|
|
||||||
})
|
|
||||||
if (newProps.Headertop !== undefined) {
|
|
||||||
old_url = newProps.Headertop.old_url
|
|
||||||
}
|
|
||||||
}
|
|
||||||
getCookie = (key) => {
|
|
||||||
var arr, reg = RegExp('(^| )' + key + '=([^;]+)(;|$)');
|
|
||||||
if (arr === document.cookie.match(reg))
|
|
||||||
return decodeURIComponent(arr[2]);
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
delCookie = (name) => {
|
|
||||||
var exp = new Date();
|
|
||||||
exp.setTime(exp.getTime() - 1);
|
|
||||||
var cval = this.getCookie(name);
|
|
||||||
if (cval != null) {
|
|
||||||
document.cookie = name + "=" + cval + ";expires=" + exp.toGMTString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onLogout = () => {
|
|
||||||
const url = `/accounts/logout.json`
|
|
||||||
this.delCookie("autologin_trustie")
|
|
||||||
axios.get(url, {
|
|
||||||
}).then((response) => {
|
|
||||||
if (response.data.status === 1) {
|
|
||||||
this.setState({
|
|
||||||
user: undefined
|
|
||||||
})
|
|
||||||
window.location.href = "/login"
|
|
||||||
message.success('退出成功');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
tojoinclass = () => {
|
|
||||||
let { user } = this.state;
|
|
||||||
if (user === undefined) {
|
|
||||||
this.setState({
|
|
||||||
isRender: true
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (user && user.login === "") {
|
|
||||||
this.setState({
|
|
||||||
isRender: true
|
|
||||||
})
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (user && user.profile_completed === false) {
|
|
||||||
this.setState({
|
|
||||||
AccountProfiletype: true
|
|
||||||
})
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.setState({
|
|
||||||
Addcoursestypes: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
tojoinitem = () => {
|
|
||||||
if (this.props.user && this.props.user.email === undefined || this.props.user && this.props.user.email === null || this.props.user && this.props.user.email === "") {
|
|
||||||
this.openNotification("请先绑定邮箱,谢谢");
|
|
||||||
return
|
|
||||||
}
|
|
||||||
let { user } = this.state;
|
|
||||||
if (user === undefined) {
|
|
||||||
this.setState({
|
|
||||||
isRender: true
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (user && user.login === "") {
|
|
||||||
this.setState({
|
|
||||||
isRender: true
|
|
||||||
})
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (user && user.profile_completed === false) {
|
|
||||||
this.setState({
|
|
||||||
AccountProfiletype: true
|
|
||||||
})
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
tojoinitemtype: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
submitstatevalue = (sum, value, data) => {
|
|
||||||
this.setState({
|
|
||||||
Addcoursestypes: false,
|
|
||||||
tojoinitemtype: false,
|
|
||||||
tojoinclasstitle: undefined,
|
|
||||||
rolearr: ["", ""],
|
|
||||||
Checkboxteacherchecked: false,
|
|
||||||
Checkboxstudentchecked: false,
|
|
||||||
Checkboxteachingchecked: false,
|
|
||||||
Checkboxteachertype: false,
|
|
||||||
Checkboxteachingtype: false,
|
|
||||||
code_notice: false,
|
|
||||||
checked_notice: false,
|
|
||||||
submitapplicationssum: sum,
|
|
||||||
submitapplications: true,
|
|
||||||
submitapplicationsvalue: value,
|
|
||||||
submitapplicationsvaluedata: data,
|
|
||||||
RadioGroupvalue: undefined
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
onChangeRadioGroup = (e) => {
|
|
||||||
this.setState({
|
|
||||||
RadioGroupvalue: e.target.value,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
submitsubmitapplications = () => {
|
|
||||||
let {
|
|
||||||
submitapplicationssum,
|
|
||||||
submitapplicationsvaluedata
|
|
||||||
} = this.state;
|
|
||||||
this.setState({
|
|
||||||
submitapplications: false,
|
|
||||||
RadioGroupvalue: undefined
|
|
||||||
})
|
|
||||||
if (submitapplicationssum === 0) {
|
|
||||||
if (submitapplicationsvaluedata !== undefined) {
|
|
||||||
window.location.href = "/courses/" + submitapplicationsvaluedata;
|
|
||||||
}
|
|
||||||
} else if (submitapplicationssum === 1) {
|
|
||||||
if (submitapplicationsvaluedata !== undefined) {
|
|
||||||
window.location.href = "/projects/" + submitapplicationsvaluedata;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
hidesubmitapplications = () => {
|
|
||||||
this.setState({
|
|
||||||
Addcoursestypes: false,
|
|
||||||
tojoinitemtype: false,
|
|
||||||
tojoinclasstitle: undefined,
|
|
||||||
rolearr: ["", ""],
|
|
||||||
Checkboxteacherchecked: false,
|
|
||||||
Checkboxstudentchecked: false,
|
|
||||||
Checkboxteachingchecked: false,
|
|
||||||
Checkboxteachertype: false,
|
|
||||||
Checkboxteachingtype: false,
|
|
||||||
code_notice: false,
|
|
||||||
checked_notice: false,
|
|
||||||
submitapplications: false,
|
|
||||||
RadioGroupvalue: undefined
|
|
||||||
})
|
|
||||||
}
|
|
||||||
educoderlogin = () => {
|
|
||||||
//登录账号
|
|
||||||
this.setState({
|
|
||||||
isRender: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
educoderloginysl = () => {
|
|
||||||
//退出账号
|
|
||||||
var url = `/accounts/logout.json`;
|
|
||||||
axios.get((url)).then((result) => {
|
|
||||||
if (result !== undefined) {
|
|
||||||
window.location.href = "/";
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
console.log(error);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
hideAddcoursestypes = () => {
|
|
||||||
this.setState({
|
|
||||||
Addcoursestypes: false
|
|
||||||
})
|
|
||||||
};
|
|
||||||
HideAddcoursestypess = (i) => {
|
|
||||||
console.log("调用了");
|
|
||||||
this.setState({
|
|
||||||
Addcoursestypes: false,
|
|
||||||
mydisplay: true,
|
|
||||||
occupation: i,
|
|
||||||
})
|
|
||||||
};
|
|
||||||
ModalCancelsy = () => {
|
|
||||||
this.setState({
|
|
||||||
mydisplay: false,
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
hidetojoinclass = () => {
|
|
||||||
this.setState({
|
|
||||||
tojoinclasstype: false,
|
|
||||||
tojoinitemtype: false,
|
|
||||||
tojoinclasstitle: undefined,
|
|
||||||
rolearr: ["", ""],
|
|
||||||
Checkboxteacherchecked: false,
|
|
||||||
Checkboxstudentchecked: false,
|
|
||||||
Checkboxteachingchecked: false,
|
|
||||||
Checkboxteachertype: false,
|
|
||||||
Checkboxteachingtype: false,
|
|
||||||
code_notice: false,
|
|
||||||
checked_notice: false,
|
|
||||||
RadioGroupvalue: undefined
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 关闭
|
|
||||||
cancelModulationModels = () => {
|
|
||||||
this.setState({ isRenders: false })
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
setevaluatinghides = () => {
|
|
||||||
this.setState({
|
|
||||||
setevaluatinghides: true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
//修改登录方法
|
|
||||||
Modifyloginvalue = () => {
|
|
||||||
this.setState({
|
|
||||||
isRender: false,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
hideAccountProfile = () => {
|
|
||||||
this.setState({
|
|
||||||
AccountProfiletype: false
|
|
||||||
})
|
|
||||||
};
|
|
||||||
headtypesonClick = (url, bool) => {
|
|
||||||
this.setState({
|
|
||||||
headtypess: url,
|
|
||||||
headtypesonClickbool: bool,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
//获取数据为空的时候
|
|
||||||
gettablogourlnull = () => {
|
|
||||||
this.setState({
|
|
||||||
settings: undefined
|
|
||||||
});
|
|
||||||
var link = document.createElement('link'),
|
|
||||||
oldLink = document.getElementById('dynamic-favicon');
|
|
||||||
link.id = 'dynamic-favicon';
|
|
||||||
link.rel = 'shortcut icon';
|
|
||||||
link.href = "/react/build/./favicon.ico";
|
|
||||||
if (oldLink) {
|
|
||||||
document.head.removeChild(oldLink);
|
|
||||||
}
|
|
||||||
document.head.appendChild(link);
|
|
||||||
};
|
|
||||||
|
|
||||||
//获取数据的时候
|
|
||||||
gettablogourldata = (response) => {
|
|
||||||
document.title = response.data.setting.name;
|
|
||||||
var link = document.createElement('link'),
|
|
||||||
oldLink = document.getElementById('dynamic-favicon');
|
|
||||||
link.id = 'dynamic-favicon';
|
|
||||||
link.rel = 'shortcut icon';
|
|
||||||
link.href = '/' + response.data.setting.tab_logo_url;
|
|
||||||
if (oldLink) {
|
|
||||||
document.head.removeChild(oldLink);
|
|
||||||
}
|
|
||||||
document.head.appendChild(link);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleVisibleChanges = (boll) => {
|
|
||||||
this.setState({
|
|
||||||
visiblemyss: boll,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
getAppdata = () => {
|
|
||||||
try {
|
|
||||||
var chromesettingArray = JSON.parse(localStorage.getItem('chromesetting'));
|
|
||||||
var chromesettingresponseArray = JSON.parse(localStorage.getItem('chromesettingresponse'));
|
|
||||||
this.setState({
|
|
||||||
settings: chromesettingArray
|
|
||||||
});
|
|
||||||
if (chromesettingArray.tab_logo_url) {
|
|
||||||
this.gettablogourldata(chromesettingresponseArray);
|
|
||||||
} else {
|
|
||||||
this.gettablogourlnull();
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
this.geturlsdata();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
geturlsdata = () => {
|
|
||||||
let url = "/setting.json";
|
|
||||||
axios.get(url).then((response) => {
|
|
||||||
if (response && response.data) {
|
|
||||||
this.setState({ settings: response.data.setting });
|
|
||||||
// localStorage.setItem('chromesetting', JSON.stringify(response.data.setting));
|
|
||||||
// localStorage.setItem('chromesettingresponse', JSON.stringify(response));
|
|
||||||
try {
|
|
||||||
if (response.data.setting.tab_logo_url) {
|
|
||||||
this.gettablogourldata(response);
|
|
||||||
} else {
|
|
||||||
this.gettablogourlnull();
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
this.gettablogourlnull();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.gettablogourlnull();
|
|
||||||
}
|
|
||||||
}).catch((error) => {
|
|
||||||
this.gettablogourlnull();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
matchpaths = (url) => {
|
|
||||||
const { match } = this.props;
|
|
||||||
if(url){
|
|
||||||
if (match.path.indexOf(url) > -1) {
|
|
||||||
return true
|
|
||||||
}else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 处理弹框
|
|
||||||
setgoshowqqgtounp = (bool) => {
|
|
||||||
this.setState({
|
|
||||||
goshowqqgtounp: bool
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
addMenu=(list)=>{
|
|
||||||
return(
|
|
||||||
list && list.length >0 &&
|
|
||||||
<div className="dropdownFlex">
|
|
||||||
<Menu>
|
|
||||||
{
|
|
||||||
list.map((item,key)=>{
|
|
||||||
return(
|
|
||||||
(item.name !=="加入课堂" && item.name !=="加入开发项目") && <Menu.Item><a href={item.url}>{item.name}</a></Menu.Item>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</Menu>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { match} = this.props;
|
|
||||||
let current_user = this.props.user;
|
|
||||||
let { Addcoursestypes,
|
|
||||||
tojoinitemtype,
|
|
||||||
tojoinclasstitle,
|
|
||||||
code_notice,
|
|
||||||
checked_notice,
|
|
||||||
AccountProfiletype,
|
|
||||||
submitapplications,
|
|
||||||
submitapplicationsvalue,
|
|
||||||
user,
|
|
||||||
isRender,
|
|
||||||
showSearchOpentype,
|
|
||||||
headtypesonClickbool,
|
|
||||||
headtypess,
|
|
||||||
settings,
|
|
||||||
goshowqqgtounp,
|
|
||||||
openSearch,
|
|
||||||
} = this.state;
|
|
||||||
/*用户名称 用户头像url*/
|
|
||||||
let activeIndex = false;
|
|
||||||
let activeForums = false;
|
|
||||||
let activeShixuns = false;
|
|
||||||
let activePaths = false;
|
|
||||||
let coursestype = false;
|
|
||||||
let activePackages = false;
|
|
||||||
let activeMoopCases = false;
|
|
||||||
let activeCompetitions = false;
|
|
||||||
|
|
||||||
if (match.path === '/forums') {
|
|
||||||
activeForums = true;
|
|
||||||
} else if (match.path.startsWith('/shixuns')) {
|
|
||||||
activeShixuns = true;
|
|
||||||
} else if (match.path.startsWith('/paths')) {
|
|
||||||
activePaths = true;
|
|
||||||
} else if (match.path.startsWith('/courses')) {
|
|
||||||
coursestype = true;
|
|
||||||
} else if (match.path.startsWith('/crowdsourcing')) {
|
|
||||||
activePackages = true;
|
|
||||||
} else if (match.path.startsWith('/moop_cases')) {
|
|
||||||
activeMoopCases = true;
|
|
||||||
} else if (match.path.startsWith('/competitions')) {
|
|
||||||
activeCompetitions = true;
|
|
||||||
} else {
|
|
||||||
activeIndex = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
let headtypes = '/';
|
|
||||||
if (settings) {
|
|
||||||
if (settings.navbar) {
|
|
||||||
if (settings.navbar.length > 0) {
|
|
||||||
if (match.path === '/') {
|
|
||||||
if (headtypesonClickbool === false) {
|
|
||||||
headtypes = undefined;
|
|
||||||
} else {
|
|
||||||
headtypes = headtypess;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (var i = 0; i < settings.navbar.length; i++) {
|
|
||||||
if (match.path === settings.navbar[i].link) {
|
|
||||||
headtypes = settings.navbar[i].link;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let shixuntype = false;
|
|
||||||
let pathstype = false;
|
|
||||||
let coursestypes = false;
|
|
||||||
if (this.props && this.props.mygetHelmetapi != null) {
|
|
||||||
let shixun = "/shixuns";
|
|
||||||
let paths = "/paths";
|
|
||||||
let courses = "/courses";
|
|
||||||
this.props.mygetHelmetapi.navbar.map((item, key) => {
|
|
||||||
var reg = RegExp(item.link);
|
|
||||||
if (shixun.match(reg)) {
|
|
||||||
if (item.hidden === true) {
|
|
||||||
shixuntype = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (paths.match(reg)) {
|
|
||||||
if (item.hidden === true) {
|
|
||||||
pathstype = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (courses.match(reg)) {
|
|
||||||
if (item.hidden === true) {
|
|
||||||
coursestypes = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
let search_url = settings && settings.common && settings.common.search;
|
|
||||||
let notice_url = settings && settings.common && settings.common.notice;
|
|
||||||
return (
|
|
||||||
<div className="newHeaders" id="nHeader">
|
|
||||||
<div className="headerContent">
|
|
||||||
{isRender === true ?
|
|
||||||
<LoginDialog
|
|
||||||
{...this.props}
|
|
||||||
{...this.state}
|
|
||||||
Modifyloginvalue={() => this.Modifyloginvalue()}
|
|
||||||
/> : ""}
|
|
||||||
|
|
||||||
{AccountProfiletype === true ?
|
|
||||||
<AccountProfile
|
|
||||||
hideAccountProfile={() => this.hideAccountProfile()}
|
|
||||||
{...this.props}
|
|
||||||
{...this.state}
|
|
||||||
/> : ""}
|
|
||||||
{
|
|
||||||
goshowqqgtounp === true ?
|
|
||||||
<GotoQQgroup {...this.state} {...this.props} setgoshowqqgtounp={(bool) => this.setgoshowqqgtounp(bool)}></GotoQQgroup>
|
|
||||||
:""
|
|
||||||
}
|
|
||||||
<a href={settings && settings.new_course.default_url} className={"fl mr30"} style={{minWidth:"45px"}}>
|
|
||||||
{
|
|
||||||
settings && settings.nav_logo_url ?
|
|
||||||
<img alt="可控开源社区" className="logoimg" style={{ heigth: "40px" }} src={getImageUrl(`/${settings.nav_logo_url}`)}></img>
|
|
||||||
:
|
|
||||||
<img alt="可控开源社区" className="logoimg" style={{ heigth: "40px" }} src={logo}></img>
|
|
||||||
}
|
|
||||||
</a>
|
|
||||||
<div className="head-nav pr" id={"head-navpre1"}>
|
|
||||||
{
|
|
||||||
settings && settings.navbar && settings.navbar.length > 0 ?
|
|
||||||
<ul id="header-nav">
|
|
||||||
{
|
|
||||||
settings.navbar && settings.navbar.map((item, key) => {
|
|
||||||
var new_link = item.link;
|
|
||||||
var user_login = this.props.user && this.props.user.login;
|
|
||||||
var is_hidden = item.hidden
|
|
||||||
if (new_link && (new_link.indexOf("courses") > -1 || new_link.indexOf("contests") > -1)) {
|
|
||||||
if (user_login) {
|
|
||||||
if (new_link.indexOf("courses") > -1) {
|
|
||||||
new_link = new_link.replace(/courses/g, "users/" + user_login + "/courses")
|
|
||||||
} else if (new_link.indexOf("contests") > -1) {
|
|
||||||
new_link = new_link.replace(/contests/g, "users/" + user_login + "/contests")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
is_hidden = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (user_login && (new_link && new_link.indexOf("homes") > -1)) {
|
|
||||||
new_link = new_link.replace(/homes/g, "users/" + user_login + "/user_activities")
|
|
||||||
}
|
|
||||||
|
|
||||||
var waiLian = (new_link && str.filter(item=>new_link.indexOf(item)>-1) );
|
|
||||||
var wl = waiLian && waiLian.length>0;
|
|
||||||
return (
|
|
||||||
<li key={key} onClick={() => this.headtypesonClick(item.link, true)} className={`${this.matchpaths(item.link) === true ? 'pr active' : 'pr'}`} style={!is_hidden ? { display: 'flex' } : { display: 'none' }}>
|
|
||||||
<a href={new_link} target={wl ? "_self":"_blank"}>{item.name}</a>
|
|
||||||
</li>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</ul>
|
|
||||||
: ""
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
<div className="head-right">
|
|
||||||
{search_url ? this.SearchInput(openSearch,search_url):""}
|
|
||||||
{
|
|
||||||
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">
|
|
||||||
<i className="iconfont icon-tianjiafangda color-grey-6 ml30"></i>
|
|
||||||
</Dropdown>:""
|
|
||||||
}
|
|
||||||
|
|
||||||
{this.props.user && this.props.user.login && notice_url ?
|
|
||||||
<div className="ml30 edu-menu-panel">
|
|
||||||
{user && user.login &&
|
|
||||||
<a href={`${notice_url}`} style={{ position: 'relative' }}>
|
|
||||||
<i className="iconfont icon-xiaoxilingdang color-grey-6"></i>
|
|
||||||
<span className="newslight" style={{ display: this.props.Headertop === undefined ? "none" : this.props.Headertop.new_message === true ? "block" : "none" }}>
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
}
|
|
||||||
</div>:""
|
|
||||||
}
|
|
||||||
<Modal
|
|
||||||
keyboard={false}
|
|
||||||
title="提示"
|
|
||||||
visible={submitapplications}
|
|
||||||
closable={false}
|
|
||||||
footer={null}
|
|
||||||
>
|
|
||||||
<div className="task_popup_con ml30">
|
|
||||||
<div className="mr15">
|
|
||||||
<ul>
|
|
||||||
<div className="task-popup-content">
|
|
||||||
<p className="task-popup-text-center font-16">
|
|
||||||
{submitapplicationsvalue}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<li className="clearfix mt10 edu-txt-center">
|
|
||||||
<a className="task-btn mr10"
|
|
||||||
onClick={this.hidesubmitapplications}>取消</a>
|
|
||||||
<a
|
|
||||||
className="task-btn task-btn-orange ml20"
|
|
||||||
onClick={this.submitsubmitapplications}>确定</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Modal>
|
|
||||||
</div>
|
|
||||||
{!user || (user && !user.login) ?
|
|
||||||
<span className="font-15 ml30">
|
|
||||||
<a onClick={() => this.educoderlogin()} className="mr5 color-grey-6">登录</a>
|
|
||||||
{
|
|
||||||
settings && settings.common && settings.common.register &&
|
|
||||||
<span><em className="vertical-line"></em><a className="ml5 color-grey-6" href={`${settings.common.register}`} target="_blank">注册</a></span>
|
|
||||||
}
|
|
||||||
</span>
|
|
||||||
:
|
|
||||||
<div className="ml30 edu-menu-panel" style={{ height: "70px", lineHeight: "70px" }}>
|
|
||||||
<a href={`/users/${this.props.current_user === undefined ? "" : this.props.current_user.login}/courses`}>
|
|
||||||
<img alt="头像" className="radius" height="34" id="nh_user_logo" name="avatar_image" src={getImageUrl(`/${user.image_url}`)} width="34">
|
|
||||||
</img>
|
|
||||||
</a>
|
|
||||||
<ul className="edu-menu-list" style={{ top: '60px', textAlign: 'center' }}>
|
|
||||||
<li className="bor-bottom-greyE" style={{cursor:"default",background:"#fff"}}>{this.props.current_user.username}</li>
|
|
||||||
{
|
|
||||||
settings && settings.personal && settings.personal.length > 0 && settings.personal.map((item,key)=>{
|
|
||||||
return(
|
|
||||||
<li key={key}><a href={item.url} target="_blank">{item.name}</a></li>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
<li className="bor-top-greyE">
|
|
||||||
<a onClick={() => this.educoderloginysl()}>退出</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default NewHeader;
|
|
|
@ -1,16 +1,75 @@
|
||||||
|
|
||||||
.dropdownFlex{
|
.dropdownFlex{
|
||||||
display:flex;
|
display:flex;
|
||||||
padding:5px;
|
|
||||||
background:#fff;
|
background:#fff;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
.ant-menu-vertical > .ant-menu-item{
|
.ant-menu-vertical > .ant-menu-item{
|
||||||
border:none
|
border:none;
|
||||||
|
height: 35px;
|
||||||
|
line-height: 35px;
|
||||||
|
margin:0px;
|
||||||
|
&.ant-menu-item-selected{
|
||||||
|
background-color: #fff;
|
||||||
|
a{color: rgba(0, 0, 0, 0.65)!important;}
|
||||||
|
}
|
||||||
|
&.ant-menu-item-active{
|
||||||
|
a{color: #4cacff!important;}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ant-menu-vertical{
|
||||||
|
border:none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.currentImg{
|
||||||
|
width: 34px;
|
||||||
|
height: 34px;
|
||||||
|
border-radius: 50%;
|
||||||
|
margin-left: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.currentMenu{
|
||||||
|
width: 120px;
|
||||||
|
text-align: center;
|
||||||
|
padding:0px;
|
||||||
|
.currentName{
|
||||||
|
padding:0px 8px;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
li{
|
||||||
|
height: 40px;
|
||||||
|
line-height: 40px;
|
||||||
|
padding:0px!important;
|
||||||
|
cursor: default;
|
||||||
|
&:hover{
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
&:first-child{
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
}
|
||||||
|
&:last-child{
|
||||||
|
border-top: 1px solid #eee;
|
||||||
|
a{
|
||||||
|
border-radius: 0px 0px 4px 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a{
|
||||||
|
padding:0px;
|
||||||
|
margin:0px;
|
||||||
|
display: block;
|
||||||
|
color: #666;
|
||||||
|
&:hover{
|
||||||
|
color: #fff;
|
||||||
|
background: #4CACFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.newFooter {
|
.newFooter {
|
||||||
position: absolute;
|
// position: absolute;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background: #323232;
|
background: #323232;
|
||||||
|
@ -18,6 +77,7 @@
|
||||||
min-width: 1200px;
|
min-width: 1200px;
|
||||||
z-index: 8;
|
z-index: 8;
|
||||||
left: 0px;
|
left: 0px;
|
||||||
|
padding-bottom: 15px;
|
||||||
p {
|
p {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
margin-bottom:0px !important;
|
margin-bottom:0px !important;
|
||||||
|
@ -59,4 +119,249 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
.inviteForm{
|
||||||
|
.ant-form-item{
|
||||||
|
margin-right: 0px;
|
||||||
|
}
|
||||||
|
.ant-form-item-label{
|
||||||
|
width: 110px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
.ant-form-explain{
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 右上角小铃铛单独样式
|
||||||
|
.notice-popover{
|
||||||
|
z-index: 1000001;
|
||||||
|
//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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footEdition{
|
||||||
|
background-color: #171B23;
|
||||||
|
.footContent{
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
padding:86px 0px;
|
||||||
|
justify-content: space-around;
|
||||||
|
width: 1200px;
|
||||||
|
margin:0px auto;
|
||||||
|
ul{
|
||||||
|
min-width: 120px;
|
||||||
|
text-align: left;
|
||||||
|
margin-right: 80px;
|
||||||
|
&.center{
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
&>p{
|
||||||
|
height: 22px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #FFFFFF;
|
||||||
|
line-height: 22px;
|
||||||
|
}
|
||||||
|
&>img{
|
||||||
|
width: 100px;
|
||||||
|
height: 100%;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
margin-top: 25px;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
li{
|
||||||
|
height: 20px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 400;
|
||||||
|
line-height: 20px;
|
||||||
|
color: #BDC2D1;
|
||||||
|
margin-bottom: 15px!important;
|
||||||
|
a{
|
||||||
|
color: #BDC2D1!important;
|
||||||
|
&:hover{
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.thehead{
|
||||||
|
height: 25px;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #FFFFFF;
|
||||||
|
line-height: 25px;
|
||||||
|
margin-bottom: 20px!important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.theline{
|
||||||
|
.imgCon{
|
||||||
|
width: 90px;
|
||||||
|
height: 90px;
|
||||||
|
padding:5px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background-color: #fff;
|
||||||
|
img{
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.copyrightDesc{
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #BDC2D1;
|
||||||
|
line-height: 28px;
|
||||||
|
padding:15px 0px;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #1B212C;
|
||||||
|
a{
|
||||||
|
color: #BDC2D1!important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.regBtn{
|
||||||
|
height: 40px;
|
||||||
|
background: #466AFF;
|
||||||
|
border-radius: 2px;
|
||||||
|
display: inline-block;
|
||||||
|
padding:0px 18px;
|
||||||
|
margin-left: 20px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #FFFFFF!important;
|
||||||
|
line-height: 40px;
|
||||||
|
&:hover{
|
||||||
|
color: #FFFFFF!important;
|
||||||
|
background-color: #355CFF;
|
||||||
|
}
|
||||||
}
|
}
|
Before Width: | Height: | Size: 64 KiB |
After Width: | Height: | Size: 90 KiB |
After Width: | Height: | Size: 222 KiB |
|
@ -6,6 +6,7 @@ import { withRouter } from "react-router";
|
||||||
import { SnackbarHOC } from "educoder";
|
import { SnackbarHOC } from "educoder";
|
||||||
import { CNotificationHOC } from "../modules/courses/common/CNotificationHOC";
|
import { CNotificationHOC } from "../modules/courses/common/CNotificationHOC";
|
||||||
import { TPMIndexHOC } from "../modules/tpm/TPMIndexHOC";
|
import { TPMIndexHOC } from "../modules/tpm/TPMIndexHOC";
|
||||||
|
// import Handbook from './Component/Handbook';
|
||||||
import "./css/index.scss";
|
import "./css/index.scss";
|
||||||
|
|
||||||
import Loadable from "react-loadable";
|
import Loadable from "react-loadable";
|
||||||
|
@ -34,6 +35,7 @@ class Index extends Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className="newMain clearfix">
|
<div className="newMain clearfix">
|
||||||
|
{/* <Handbook /> */}
|
||||||
<Switch {...this.props}>
|
<Switch {...this.props}>
|
||||||
<Route
|
<Route
|
||||||
path="/projects/:projectsType/new/:OIdentifier"
|
path="/projects/:projectsType/new/:OIdentifier"
|
||||||
|
@ -47,12 +49,6 @@ class Index extends Component {
|
||||||
<ProjectNew {...this.props} {...props} />
|
<ProjectNew {...this.props} {...props} />
|
||||||
)}
|
)}
|
||||||
></Route>
|
></Route>
|
||||||
<Route
|
|
||||||
path="/projects/new"
|
|
||||||
render={(props) => (
|
|
||||||
<ProjectNew {...this.props} {...props} />
|
|
||||||
)}
|
|
||||||
></Route>
|
|
||||||
<Route
|
<Route
|
||||||
path="/projects/:owner/:projectsId"
|
path="/projects/:owner/:projectsId"
|
||||||
render={(props) => (
|
render={(props) => (
|
||||||
|
|
|
@ -1,449 +0,0 @@
|
||||||
import React , { useEffect , useState } from 'react';
|
|
||||||
import { WhiteBack , Box , LongWidth , ShortWidth , Gap , AlignCenter , FlexAJ } from '../Component/layout';
|
|
||||||
import { Dropdown , Menu , Divider , Spin, Button } from 'antd';
|
|
||||||
import { getImageUrl } from "educoder";
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import CloneAddress from '../Branch/CloneAddress';
|
|
||||||
|
|
||||||
import SelectBranch from '../Branch/Select';
|
|
||||||
import User from '../Component/User';
|
|
||||||
import axios from 'axios';
|
|
||||||
import Path from './CoderDepotPath';
|
|
||||||
import Catalogue from './CoderDepotCatalogue';
|
|
||||||
import ReadMe from './CoderDepotReadme';
|
|
||||||
import CoderRootFileDetail from './CoderRootFileDetail';
|
|
||||||
import './Index.scss';
|
|
||||||
import Releases from '../Component/Releases';
|
|
||||||
import Contributors from '../Component/Contributors';
|
|
||||||
import LanguagePower from '../Component/LanguagePower';
|
|
||||||
import DrawerPanel from '../Component/DrawerPanel';
|
|
||||||
import UpdateDescModal from './sub/UpdateDescModal';
|
|
||||||
import Nodata from '../Nodata';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* projectDetail.type:0是托管项目,1是镜像项目,2是同步镜像项目(为2时不支持在线创建、在线上传、在线修改、在线删除、创建合并请求等功能)
|
|
||||||
*/
|
|
||||||
function CoderDepot(props){
|
|
||||||
const [ projectDetail , setProjectDetail ]= useState(undefined);
|
|
||||||
const [ treeValue , setTreeValue ] = useState(undefined);
|
|
||||||
const [ treeValuePath , setTreeValuePath ] = useState(undefined);
|
|
||||||
const [ lastCommit,setLastCommit ] = useState(undefined);
|
|
||||||
const [ lastCommitAuthor,setLastCommitAuthor ] = useState(undefined);
|
|
||||||
const [ type ,setType ] = useState('dir');
|
|
||||||
const [ hide , setHide ] = useState(true);
|
|
||||||
const [ hideBtn , setHideBtn ] = useState(false);
|
|
||||||
const [ commitCount ,setCommitCount ] = useState(0);
|
|
||||||
const [ dirInfo ,setDirInfo ] = useState(undefined);//文件夹目录列表
|
|
||||||
const [ fileInfo ,setFileInfo ] = useState(undefined);//文件内容信息
|
|
||||||
const [ zip_url , setZip_url ] = useState(undefined);
|
|
||||||
const [ tar_url , setTar_url ] = useState(undefined);
|
|
||||||
const [ readOnly , setReadOnly] = useState(true);
|
|
||||||
const [ isSpin , setIsSpin] = useState(true);
|
|
||||||
const [ visible ,setVisible ] = useState(false);
|
|
||||||
const [ mainFlag ,setMainFlag ] = useState(false);
|
|
||||||
const [ openModal , setOpenModal ] = useState(false);
|
|
||||||
const [ desc , setDesc ] = useState(undefined);
|
|
||||||
const [ website , setWebsite ] = useState(undefined);
|
|
||||||
const [ lesson_url , setLessonUrl ] = useState(undefined);
|
|
||||||
|
|
||||||
const owner = props.match.params.owner;
|
|
||||||
const projectsId = props.match.params.projectsId;
|
|
||||||
const branchName = props.match.params.branchName;
|
|
||||||
let pathname = props.history.location.pathname;
|
|
||||||
useEffect(()=>{
|
|
||||||
if(props.projectDetail){
|
|
||||||
setProjectDetail(props.projectDetail);
|
|
||||||
setDesc(props.projectDetail.description);
|
|
||||||
setWebsite(props.projectDetail.website);
|
|
||||||
setLessonUrl(props.projectDetail.lesson_url);
|
|
||||||
}
|
|
||||||
},[props])
|
|
||||||
|
|
||||||
useEffect(()=>{
|
|
||||||
if(treeValue){
|
|
||||||
setTreeValuePath(treeValue.split('/'));
|
|
||||||
}else{
|
|
||||||
setTreeValuePath(undefined);
|
|
||||||
}
|
|
||||||
},[treeValue])
|
|
||||||
|
|
||||||
useEffect(()=>{
|
|
||||||
if (pathname && projectDetail){
|
|
||||||
if(pathname.indexOf(`/projects/${owner}/${projectsId}`) > -1 && pathname.indexOf(`/tree/${branchName}/`) > -1) {
|
|
||||||
let url = pathname.split(`/tree/${branchName}/`)[1];
|
|
||||||
setTreeValue(url);
|
|
||||||
getFileInfo(url,branchName);
|
|
||||||
}else{
|
|
||||||
setTreeValue(undefined);
|
|
||||||
getDirInfo(branchName ||projectDetail.default_branch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},[pathname,projectDetail])
|
|
||||||
|
|
||||||
// 获取主目录列表
|
|
||||||
function getDirInfo(branch){
|
|
||||||
setIsSpin(true);
|
|
||||||
const url = `/${owner}/${projectsId}/entries.json`;
|
|
||||||
axios.get(url, {
|
|
||||||
params: { ref: branch }
|
|
||||||
}).then((result) => {
|
|
||||||
if (result) {
|
|
||||||
setCommitCount(result.data.commits_count);
|
|
||||||
setDirInfo(result.data.entries);
|
|
||||||
setFileInfo(undefined);
|
|
||||||
setTar_url(result.data.tar_url);
|
|
||||||
setZip_url(result.data.zip_url);
|
|
||||||
let c = result.data.last_commit
|
|
||||||
setLastCommit(c && c.commit);
|
|
||||||
setLastCommitAuthor(c && c.committer);
|
|
||||||
setMainFlag(true);
|
|
||||||
setReadOnly(true);
|
|
||||||
}
|
|
||||||
setTimeout(function(){setIsSpin(false);},500);
|
|
||||||
}).catch(error=>{setIsSpin(false);})
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(()=>{
|
|
||||||
if(projectDetail && lastCommit)
|
|
||||||
{
|
|
||||||
let ele = document.getElementById("ptxt");
|
|
||||||
if(ele){
|
|
||||||
let h = ele.offsetHeight;
|
|
||||||
if( h > 18 ) setHideBtn(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},[projectDetail,lastCommit])
|
|
||||||
// 获取子目录列表
|
|
||||||
function getFileInfo(path, ref){
|
|
||||||
setIsSpin(true);
|
|
||||||
const url = `/${owner}/${projectsId}/sub_entries.json`;
|
|
||||||
axios.get(url, {
|
|
||||||
params:{
|
|
||||||
filepath:path,
|
|
||||||
ref:ref || branchName,
|
|
||||||
type
|
|
||||||
}
|
|
||||||
}).then((result) => {
|
|
||||||
if (result) {
|
|
||||||
let en = result.data.entries;
|
|
||||||
if(en.type){
|
|
||||||
setDirInfo(undefined);
|
|
||||||
setFileInfo(en);
|
|
||||||
setType(en.type);
|
|
||||||
}else{
|
|
||||||
setFileInfo(undefined);
|
|
||||||
setDirInfo(en);
|
|
||||||
setType("dir");
|
|
||||||
}
|
|
||||||
let c = result.data.last_commit
|
|
||||||
setLastCommit(c && c.commit);
|
|
||||||
setLastCommitAuthor(c && c.committer);
|
|
||||||
setMainFlag(false);
|
|
||||||
setReadOnly(true);
|
|
||||||
}
|
|
||||||
setTimeout(function(){setIsSpin(false);},500)
|
|
||||||
}).catch(error=>{setIsSpin(false);})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 切换分支或者标签
|
|
||||||
function changeBranch(value){
|
|
||||||
let url = `/projects/${owner}/${projectsId}${value && `/tree/${value}`}${treeValue ? `/${treeValue}`:""}`;
|
|
||||||
props.history.push(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 文件相关的下拉项
|
|
||||||
const fileMenu =(
|
|
||||||
<Menu>
|
|
||||||
<Menu.Item><a onClick={()=>urlLink(`/projects/${owner}/${projectsId}/${branchName || (projectDetail && projectDetail.default_branch)}/uploadfile${treeValue === undefined ? "" : `/${treeValue}`}`)}>上传文件</a></Menu.Item>
|
|
||||||
<Menu.Item><a onClick={()=>urlLink(`/projects/${owner}/${projectsId}/${branchName || (projectDetail && projectDetail.default_branch)}/newfile${treeValue === undefined ? "" : `/${treeValue}`}`)}>新建文件</a></Menu.Item>
|
|
||||||
</Menu>
|
|
||||||
)
|
|
||||||
|
|
||||||
function getPathUrl(array,index){
|
|
||||||
if(array && array.length>0 && index){
|
|
||||||
let str = "";
|
|
||||||
for(let i=0;i<index;i++){
|
|
||||||
str += `/${array[i]}`;
|
|
||||||
}
|
|
||||||
return str.substr(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 页面地址返回到主目录
|
|
||||||
function returnMain(){
|
|
||||||
setTreeValue(undefined);
|
|
||||||
let branch = branchName || (projectDetail && projectDetail.default_branch);
|
|
||||||
props.history.push(`/projects/${owner}/${projectsId}/tree/${branch}`);
|
|
||||||
};
|
|
||||||
// 子目录路径返回链接
|
|
||||||
function returnUlr(url){
|
|
||||||
props.history.push(`/projects/${owner}/${projectsId}/tree${branchName?`/${branchName}`:""}/${url}`);
|
|
||||||
}
|
|
||||||
// 点击跳转到子目录
|
|
||||||
function goToSubRoot(path,type,filename){
|
|
||||||
setType(type);
|
|
||||||
props.history.push(`/projects/${owner}/${projectsId}${`/tree/${branchName || (projectDetail && projectDetail.default_branch)}`}${path?`/${path}`:""}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onEdit(readOnly){
|
|
||||||
setReadOnly(readOnly);
|
|
||||||
}
|
|
||||||
function ChangeFile(path, readOnly){
|
|
||||||
//点击直接跳转页面 加载一次路由
|
|
||||||
props.history.push(`/projects/${owner}/${projectsId}/tree/${branchName || (projectDetail && projectDetail.default_branch)}/${path}`);
|
|
||||||
setType("file");
|
|
||||||
setReadOnly(readOnly);
|
|
||||||
};
|
|
||||||
|
|
||||||
function changeHide(hide){
|
|
||||||
setHide(!hide);
|
|
||||||
}
|
|
||||||
|
|
||||||
function urlLink(link){
|
|
||||||
if(props.checkIfLogin()===false){
|
|
||||||
props.showLoginDialog()
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
props.history.push(link);
|
|
||||||
}
|
|
||||||
|
|
||||||
const downloadMenu = (
|
|
||||||
<div className="downMenu">
|
|
||||||
<div style={{padding:"20px",borderBottom:"1px solid #eee"}}>
|
|
||||||
<CloneAddress
|
|
||||||
http_url={projectDetail && projectDetail.clone_url}
|
|
||||||
showNotification={props.showNotification}/>
|
|
||||||
</div>
|
|
||||||
<Menu className="edu-txt-center">
|
|
||||||
<Menu.Item><a href={zip_url}>下载 ZIP</a></Menu.Item>
|
|
||||||
<Menu.Item><a href={tar_url}>下载 TAR.GZ</a></Menu.Item>
|
|
||||||
</Menu>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
// 确认修改简介、website、实践课程链接
|
|
||||||
function okUpdate(d,w,l){
|
|
||||||
const url = `/${owner}/${projectsId}.json`;
|
|
||||||
axios.put(url,{
|
|
||||||
description:d,website:w,lesson_url:l
|
|
||||||
}).then(result=>{
|
|
||||||
if(result && result.data && result.data.id){
|
|
||||||
setDesc(result.data.description);
|
|
||||||
setWebsite(result.data.website);
|
|
||||||
setLessonUrl(result.data.lesson_url);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
let n = fileInfo && fileInfo.name;
|
|
||||||
const mdFlag = n && n.substring(n.length-3,n.length) === ".md";
|
|
||||||
|
|
||||||
return(
|
|
||||||
<WhiteBack>
|
|
||||||
<UpdateDescModal desc={desc} website={website} lesson_url={lesson_url} visible={openModal} onCancel={()=>setOpenModal(false)} onOk={okUpdate}/>
|
|
||||||
<Spin spinning={isSpin}>
|
|
||||||
{
|
|
||||||
(dirInfo || fileInfo) &&
|
|
||||||
<React.Fragment>
|
|
||||||
<DrawerPanel
|
|
||||||
history={props.history}
|
|
||||||
owner={owner}
|
|
||||||
projectsId={projectsId}
|
|
||||||
name={projectDetail && projectDetail.name}
|
|
||||||
branch={branchName || (projectDetail && projectDetail.default_branch)}
|
|
||||||
visible={visible}
|
|
||||||
onClose={()=>setVisible(false)}
|
|
||||||
list = {mainFlag ? dirInfo : undefined}
|
|
||||||
/>
|
|
||||||
<div className="drawerBtn" onClick={()=>setVisible(true)}>
|
|
||||||
<i className="iconfont icon-youjiantou font-16"></i>
|
|
||||||
<span>目录</span>
|
|
||||||
</div>
|
|
||||||
</React.Fragment>
|
|
||||||
}
|
|
||||||
<div style={{minHeight:"500px"}}>
|
|
||||||
{
|
|
||||||
projectDetail &&
|
|
||||||
<Box className="Panels">
|
|
||||||
<LongWidth>
|
|
||||||
<div className="panelmenu">
|
|
||||||
<FlexAJ>
|
|
||||||
<AlignCenter>
|
|
||||||
<div className="mr20">
|
|
||||||
{
|
|
||||||
props && props.platform ?
|
|
||||||
<SelectBranch
|
|
||||||
repo_id={projectDetail && projectDetail.repo_id}
|
|
||||||
projectsId={projectsId}
|
|
||||||
branch={branchName || (projectDetail && projectDetail.default_branch)}
|
|
||||||
changeBranch={changeBranch}
|
|
||||||
owner={owner}
|
|
||||||
history={props.history}
|
|
||||||
branchList={projectDetail && projectDetail.branches && projectDetail.branches.list}
|
|
||||||
></SelectBranch>
|
|
||||||
:
|
|
||||||
<span>分支:<span className="color-grey-6">{branchName || (projectDetail && projectDetail.default_branch)}</span></span>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
<AlignCenter className="mr20">
|
|
||||||
<Link to={`/projects/${owner}/${projectsId}/branchs`} className="color-grey-9">
|
|
||||||
<i className="iconfont icon-fenzhi2 font-18 color-grey-9 mr3"></i>
|
|
||||||
<span className="color-grey-6 mr3">{projectDetail && projectDetail.branches && projectDetail.branches.total_count}个</span>分支
|
|
||||||
</Link>
|
|
||||||
</AlignCenter>
|
|
||||||
<AlignCenter className="mr20">
|
|
||||||
<Link to={`/projects/${owner}/${projectsId}/tag`} 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>标签
|
|
||||||
</Link>
|
|
||||||
</AlignCenter>
|
|
||||||
</AlignCenter>
|
|
||||||
<AlignCenter>
|
|
||||||
<div className="mr20 addOptionBtn">
|
|
||||||
{
|
|
||||||
projectDetail.type !== 2 &&
|
|
||||||
<a onClick={()=>urlLink(`/projects/${owner}/${projectsId}/pulls/new`)} >+ 合并请求</a>
|
|
||||||
}
|
|
||||||
<a onClick={()=>urlLink(`/projects/${owner}/${projectsId}/issues/new`)} >+ 任务</a>
|
|
||||||
</div>
|
|
||||||
{ type === "dir" && projectDetail.type !== 2 &&
|
|
||||||
<Dropdown overlay={fileMenu} className="mr20">
|
|
||||||
<Button type="default">文件 <i className="iconfont icon-sanjiaoxing-down ml3 font-14 color-grey-9"></i></Button>
|
|
||||||
</Dropdown>
|
|
||||||
}
|
|
||||||
|
|
||||||
<Dropdown overlay={downloadMenu} placement="bottomRight">
|
|
||||||
<Button type={'primary'}>下载 <i className="iconfont icon-sanjiaoxing-down ml3 font-14 color-white"></i></Button>
|
|
||||||
</Dropdown>
|
|
||||||
</AlignCenter>
|
|
||||||
</FlexAJ>
|
|
||||||
{
|
|
||||||
dirInfo || fileInfo ?
|
|
||||||
<div className="listtable">
|
|
||||||
{
|
|
||||||
lastCommit &&
|
|
||||||
<div className="listtablehead">
|
|
||||||
<User url={getImageUrl(`/${lastCommitAuthor && lastCommitAuthor.image_url}`)} name={lastCommitAuthor && lastCommitAuthor.name} id={lastCommitAuthor && lastCommitAuthor.id} login={lastCommitAuthor && lastCommitAuthor.login}/>
|
|
||||||
<div className={hideBtn && hide ? "ellipsistxt hide" :"ellipsistxt"}><p id="ptxt">{lastCommit && lastCommit.message}</p></div>
|
|
||||||
{ hideBtn && <span className="ellipsis" onClick={()=>changeHide(hide)}><i className="iconfont icon-shenglvehao"></i></span> }
|
|
||||||
|
|
||||||
<span className="ml12 color-grey-9 mt3">{lastCommit && lastCommit.time_from_now}</span>
|
|
||||||
{ commitCount ? <Link to={`/projects/${owner}/${projectsId}/commits`} className="ml12 color-grey-9"><i className="iconfont icon-tijiao mr3 font-17 color-grey-9"></i>{commitCount}次提交</Link>:"" }
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
<ul className="listtablebody">
|
|
||||||
{
|
|
||||||
treeValuePath && treeValuePath.length > 0 &&
|
|
||||||
<Path
|
|
||||||
identifier={projectDetail && projectDetail.identifier}
|
|
||||||
treeValuePath={treeValuePath}
|
|
||||||
returnUlr={returnUlr}
|
|
||||||
returnMain={returnMain}
|
|
||||||
getPathUrl={getPathUrl}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
{
|
|
||||||
dirInfo && dirInfo.length > 0 &&
|
|
||||||
dirInfo.map((item,key)=>{
|
|
||||||
return(
|
|
||||||
<Catalogue
|
|
||||||
owner={owner}
|
|
||||||
item={item}
|
|
||||||
projectsId={projectsId}
|
|
||||||
goToSubRoot={goToSubRoot}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
{
|
|
||||||
fileInfo &&
|
|
||||||
<CoderRootFileDetail
|
|
||||||
{...props}
|
|
||||||
detail={fileInfo}
|
|
||||||
readOnly={readOnly}
|
|
||||||
md={mdFlag}
|
|
||||||
onEdit={onEdit}
|
|
||||||
currentBranch={branchName || (projectDetail && projectDetail.default_branch)}
|
|
||||||
type={projectDetail.type}
|
|
||||||
></CoderRootFileDetail>
|
|
||||||
}
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
: ""
|
|
||||||
}
|
|
||||||
{
|
|
||||||
(dirInfo && dirInfo.length === 0) && (fileInfo && fileInfo.length === 0) ? <Nodata _html="暂未发现文件"/> :""
|
|
||||||
}
|
|
||||||
{/* readme文件显示(显示文件详情时不显示readme文件) */}
|
|
||||||
{ dirInfo && (projectDetail && projectDetail.readme) ? <ReadMe ChangeFile={ChangeFile} readme={projectDetail && projectDetail.readme} operate={props && (props.isManager || props.isDeveloper) && projectDetail.type !==2 } history={props.history} /> :"" }
|
|
||||||
</div>
|
|
||||||
</LongWidth>
|
|
||||||
{
|
|
||||||
!fileInfo &&
|
|
||||||
<ShortWidth>
|
|
||||||
<Gap style={{paddingLeft:"30px"}}>
|
|
||||||
<div className="panelmenu">
|
|
||||||
<FlexAJ className="font-18 color-grey-6 mb20" style={{lineHeight:"28px"}}>简介
|
|
||||||
{projectDetail.permission && (projectDetail.permission==="Admin" || projectDetail.permission==="Owner") && <i onClick={()=>setOpenModal(true)} className="iconfont icon-anquanshezhi color-grey-9 font-15"></i>}
|
|
||||||
</FlexAJ>
|
|
||||||
{desc && <p className="font-14 color-grey-9 mb15 task-hide-2" style={{lineHeight:"22px",WebkitLineClamp:"4",textAlign:"justify",wordBreak:"break-all"}}>{desc}</p>}
|
|
||||||
{
|
|
||||||
website &&
|
|
||||||
<p className="color-grey-6 df">
|
|
||||||
<i className="iconfont icon-lianjie2 font-15 mr10 color-grey-9"></i>
|
|
||||||
<a href={website} target="_blank" style={{wordBreak:"break-all",lineHeight:"20px",marginTop:"5px",textDecoration:"underline"}}>{website}</a>
|
|
||||||
</p>
|
|
||||||
}
|
|
||||||
<p>
|
|
||||||
<i className="iconfont icon-wenjian4 font-15 mr10 color-grey-9"></i>
|
|
||||||
<a href="#readme" className="color-grey-6">README.md</a>
|
|
||||||
</p>
|
|
||||||
<p className="color-grey-6">
|
|
||||||
<i className="iconfont icon-dataBase font-15 mr10 color-grey-9"></i>
|
|
||||||
<span>{projectDetail && projectDetail.size}</span>
|
|
||||||
</p>
|
|
||||||
{
|
|
||||||
projectDetail && projectDetail.license_name &&
|
|
||||||
<p className="color-grey-6">
|
|
||||||
<i className="iconfont icon-tianping font-16 mr10 color-grey-9"></i>
|
|
||||||
<span>{projectDetail.license_name}</span>
|
|
||||||
</p>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
{
|
|
||||||
lesson_url &&
|
|
||||||
<div>
|
|
||||||
<Divider />
|
|
||||||
<p className="font-16 color-grey-6">实践课程</p>
|
|
||||||
<a href={lesson_url} target="_blank" className="color-grey-6" style={{textDecoration:"underline"}}>{lesson_url}</a>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
{/* 发布 */}
|
|
||||||
{
|
|
||||||
projectDetail && projectDetail.release_versions &&
|
|
||||||
<React.Fragment>
|
|
||||||
<Divider />
|
|
||||||
<Releases owner={owner} projectsId={projectsId} releaseVersions={projectDetail.release_versions} history={props.history}/>
|
|
||||||
</React.Fragment>
|
|
||||||
}
|
|
||||||
{/* 贡献者 */}
|
|
||||||
{
|
|
||||||
projectDetail && projectDetail.contributors &&
|
|
||||||
<Contributors contributors={projectDetail && projectDetail.contributors} owner={owner} projectsId={projectsId} />
|
|
||||||
}
|
|
||||||
{/* 语言 */}
|
|
||||||
{ projectDetail && projectDetail.languages &&
|
|
||||||
<React.Fragment>
|
|
||||||
<Divider />
|
|
||||||
<LanguagePower languages={projectDetail.languages}/>
|
|
||||||
</React.Fragment>
|
|
||||||
}
|
|
||||||
</Gap>
|
|
||||||
</ShortWidth>
|
|
||||||
}
|
|
||||||
</Box>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</Spin>
|
|
||||||
</WhiteBack>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export default CoderDepot;
|
|
|
@ -1,22 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import { truncateCommitId } from '../common/util';
|
|
||||||
|
|
||||||
function CoderDepotCatalogue({item , goToSubRoot , owner , projectsId }){
|
|
||||||
return(
|
|
||||||
<li>
|
|
||||||
<span>
|
|
||||||
<a onClick={()=>goToSubRoot(item.path,item.type,item.name)}>
|
|
||||||
<i className={item.type === 'dir' ? "iconfont icon-wenjianjia1 color-green-file font-15 mr5":"iconfont icon-wenjia color-green-file font-15 mr5"}></i>{item.name}
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
<span title="init project">
|
|
||||||
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${item.commit && item.commit.sha}`)}`} title={item.commit && item.commit.message}>
|
|
||||||
{item.commit && item.commit.message}
|
|
||||||
</Link>
|
|
||||||
</span>
|
|
||||||
<span>{item.commit && item.commit.time_from_now}</span>
|
|
||||||
</li>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export default CoderDepotCatalogue;
|
|
|
@ -1,30 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
|
|
||||||
function CoderDepotPath({treeValuePath , returnUlr , returnMain , getPathUrl , identifier}){
|
|
||||||
return(
|
|
||||||
<li className="listtablepath">
|
|
||||||
<p>
|
|
||||||
<a
|
|
||||||
onClick={returnMain}
|
|
||||||
className="color-blue"
|
|
||||||
>
|
|
||||||
{identifier}
|
|
||||||
</a>
|
|
||||||
{treeValuePath.map((item, key) => {
|
|
||||||
return (
|
|
||||||
<React.Fragment>
|
|
||||||
{
|
|
||||||
key === treeValuePath.length-1 ?
|
|
||||||
<span className="color-grey-6 subFileName" key={key}>{item}</span>
|
|
||||||
:
|
|
||||||
<a onClick={()=>returnUlr(`${getPathUrl(treeValuePath,key+1)}`)} className="color-blue subFileName">{item}</a>
|
|
||||||
}
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export default CoderDepotPath;
|
|
|
@ -1,62 +0,0 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
|
||||||
import RenderHtml from '../../components/render-html';
|
|
||||||
import { Dropdown , Menu , Spin } from 'antd';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
const $ = window.$;
|
|
||||||
|
|
||||||
function CoderDepotReadme({ operate , history , readme , ChangeFile }){
|
|
||||||
const [ menuList ,setMenuList ] = useState(undefined);
|
|
||||||
|
|
||||||
useEffect(()=>{
|
|
||||||
if(readme && readme.content){
|
|
||||||
let path = history.location.pathname;
|
|
||||||
const items = $.map($("#readme").find("h1,h2,h3,h4,h5,h6"), function (el, _) {
|
|
||||||
const anchor = el.id;
|
|
||||||
const level = el.tagName.replace("H", "");
|
|
||||||
const href = `#${anchor}`;
|
|
||||||
return { href:`${path}${href}`,text:el.textContent , level:level }
|
|
||||||
});
|
|
||||||
setMenuList(items);
|
|
||||||
}
|
|
||||||
},[readme])
|
|
||||||
|
|
||||||
function menu(){
|
|
||||||
if(menuList && menuList.length > 0){
|
|
||||||
let hash = history.location.hash;
|
|
||||||
return(
|
|
||||||
<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{
|
|
||||||
return <Spin />
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return(
|
|
||||||
<div className="commonBox" id="readme">
|
|
||||||
<div className="commonBox-title">
|
|
||||||
<Dropdown overlay={menu()}>
|
|
||||||
<i className="iconfont icon-zhangjie1 font-16 color-grey-3 mr10"></i>
|
|
||||||
</Dropdown>
|
|
||||||
<span className="commonBox-title-read">README.md</span>
|
|
||||||
{
|
|
||||||
operate ?
|
|
||||||
<a className="ml20 pull-right" onClick={() =>ChangeFile(readme && readme.path, false)}>
|
|
||||||
<i className="iconfont icon-bianji6 font-16 color-blue"></i>
|
|
||||||
</a>
|
|
||||||
:""
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
<div className="commonBox-info">
|
|
||||||
<RenderHtml className="break_word_comments imageLayerParent" value={readme && readme.content} url={history.location}/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export default CoderDepotReadme;
|
|
|
@ -32,7 +32,7 @@ export default ((props)=>{
|
||||||
return(
|
return(
|
||||||
<li key={key}>
|
<li key={key}>
|
||||||
<div>
|
<div>
|
||||||
<Link to={`/projects/${owner}/${projectsId}/tree/${item.name}`} className="color-blue font-15" style={{"maxWidth":"100px"}}>{item.name}</Link>
|
<Link to={`/projects/${owner}/${projectsId}/branch/${item.name}`} className="color-blue font-15" style={{"maxWidth":"100px"}}>{item.name}</Link>
|
||||||
<p className="f-wrap-alignCenter mt15">
|
<p className="f-wrap-alignCenter mt15">
|
||||||
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${item.last_commit.sha}`)}`} className="mr5 commitKey" style={{marginLeft:0}}>{item.last_commit && truncateCommitId(item.last_commit.sha)}</Link>
|
<Link to={`/projects/${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-3 hide-1 messages leftPoint">{item.last_commit && item.last_commit.message}</span>
|
||||||
|
|
|
@ -74,7 +74,6 @@ class CoderRootCommit extends Component{
|
||||||
array.push({
|
array.push({
|
||||||
name:item.author && item.author.name,
|
name:item.author && item.author.name,
|
||||||
login: item.author && item.author.login,
|
login: item.author && item.author.login,
|
||||||
id: item.author && item.author.id,
|
|
||||||
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,
|
||||||
|
@ -108,7 +107,7 @@ class CoderRootCommit extends Component{
|
||||||
let branch = branchName || defaultBranch;
|
let branch = branchName || defaultBranch;
|
||||||
return(
|
return(
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<div className={"main"}>
|
<div className={commit_class}>
|
||||||
<div className="f-wrap-between">
|
<div className="f-wrap-between">
|
||||||
<SelectBranch
|
<SelectBranch
|
||||||
repo_id={projectDetail && projectDetail.repo_id}
|
repo_id={projectDetail && projectDetail.repo_id}
|
||||||
|
@ -137,18 +136,10 @@ class CoderRootCommit extends Component{
|
||||||
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${item.sha}`)}`} className="flex1 ml20 font-16 color-grey-3">{item.message}</Link>
|
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${item.sha}`)}`} className="flex1 ml20 font-16 color-grey-3">{item.message}</Link>
|
||||||
</p>
|
</p>
|
||||||
<p className="f-wrap-alignCenter mt15">
|
<p className="f-wrap-alignCenter mt15">
|
||||||
{
|
<Link to={`/users/${item.login}`} className="show-user-link">
|
||||||
item.id ?
|
{item.image_url?<img src={getImageUrl(`images/${item.image_url}`)} alt="" width="28px" height="28px" className="mr15 radius"/>:""}
|
||||||
<Link to={`/users/${item.login}`} className="show-user-link">
|
<label className="font-14 color-grey-6" style={{verticalAlign:'middle'}}>{item.name ?`${item.name}:`:""}提交于 {item.time_from_now}</label>
|
||||||
{item.image_url?<img src={getImageUrl(`/${item.image_url}`)} alt="" width="28px" height="28px" className="mr15 radius"/>:""}
|
</Link>
|
||||||
<label className="font-14 color-grey-6" style={{verticalAlign:'middle'}}>{item.name ?`${item.name}:`:""}提交于 {item.time_from_now}</label>
|
|
||||||
</Link>:
|
|
||||||
<span className="show-user-link">
|
|
||||||
{item.image_url?<img src={getImageUrl(`/${item.image_url}`)} alt="" width="28px" height="28px" className="mr15 radius"/>:""}
|
|
||||||
<label className="font-14 color-grey-6" style={{verticalAlign:'middle'}}>{item.name ?`${item.name}:`:""}提交于 {item.time_from_now}</label>
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,517 @@
|
||||||
|
import React, { Component } from "react";
|
||||||
|
import { Menu, Spin } from "antd";
|
||||||
|
import { getImageUrl } from "educoder";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
|
||||||
|
import './list.css';
|
||||||
|
import SelectBranch from '../Branch/Select';
|
||||||
|
import CloneAddress from '../Branch/CloneAddress';
|
||||||
|
import RootTable from './RootTable';
|
||||||
|
import CoderRootFileDetail from './CoderRootFileDetail';
|
||||||
|
import { truncateCommitId } from '../common/util';
|
||||||
|
import RenderHtml from '../../components/render-html';
|
||||||
|
import Nodata from '../Nodata';
|
||||||
|
import { getBranch } from '../GetData/getData';
|
||||||
|
|
||||||
|
import axios from "axios";
|
||||||
|
/**
|
||||||
|
* address:http和SSH,http_url(对应git地址)
|
||||||
|
* filePath:点击目录时当前目录的路径
|
||||||
|
* subfileType:保存当前点击目录的文件类型(显示目录列表时才显示新建文件,如果点击的是文件就不显示新建文件按钮)
|
||||||
|
* readMeContent:根目录下面的readme文件内容
|
||||||
|
*/
|
||||||
|
function getPathUrl(array,index){
|
||||||
|
if(array && array.length>0 && index){
|
||||||
|
let str = "";
|
||||||
|
for(let i=0;i<index;i++){
|
||||||
|
str += `/${array[i]}`;
|
||||||
|
}
|
||||||
|
return str.substr(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class CoderRootDirectory extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
address: "http",
|
||||||
|
filePath: undefined,
|
||||||
|
subFileType: undefined,
|
||||||
|
readMeContent: undefined,
|
||||||
|
readMeFile: undefined,
|
||||||
|
|
||||||
|
isSpin: true,
|
||||||
|
|
||||||
|
branchList: undefined,
|
||||||
|
fileDetail: undefined,
|
||||||
|
branchLastCommit: undefined,
|
||||||
|
lastCommitAuthor: undefined,
|
||||||
|
|
||||||
|
rootList: undefined,
|
||||||
|
readOnly: true,
|
||||||
|
zip_url:undefined,
|
||||||
|
tar_url:undefined,
|
||||||
|
chooseType:undefined,
|
||||||
|
|
||||||
|
md:false,
|
||||||
|
treeValue:undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
changeAddress = (address) => {
|
||||||
|
this.setState({
|
||||||
|
address,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidMount = () => {
|
||||||
|
this.Init();
|
||||||
|
this.getBranchs();
|
||||||
|
};
|
||||||
|
// 获取分支列表
|
||||||
|
getBranchs=()=>{
|
||||||
|
const { projectsId , owner } = this.props.match.params;
|
||||||
|
axios.get(`/${owner}/${projectsId}/branches.json`).then(result=>{
|
||||||
|
this.setState({
|
||||||
|
branchList:result.data
|
||||||
|
})
|
||||||
|
}).catch((error)=>{})
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate = (prevState) => {
|
||||||
|
const { location } = this.props;
|
||||||
|
const prevlocation = prevState && prevState.location;
|
||||||
|
if (location !== prevlocation) {
|
||||||
|
this.setState({
|
||||||
|
isSpin: true,
|
||||||
|
});
|
||||||
|
this.Init();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Init = () => {
|
||||||
|
let { pathname } = this.props.history.location;
|
||||||
|
const { branchName , owner , projectsId } = this.props.match.params;
|
||||||
|
const { defaultBranch } = this.props;
|
||||||
|
let branch = branchName || defaultBranch;
|
||||||
|
if (pathname && (pathname.indexOf(`/projects/${owner}/${projectsId}`) > -1 && pathname.indexOf(`/tree/${branchName}/`) > -1)) {
|
||||||
|
let url = pathname.split(`/tree/${branchName}/`)[1];
|
||||||
|
this.setState({treeValue:url})
|
||||||
|
this.getFileDetail(decodeURI(url),branch);
|
||||||
|
} else {
|
||||||
|
this.getProjectRoot(branch);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 页面地址返回到主目录
|
||||||
|
returnMain = (branch) => {
|
||||||
|
const { projectsId , owner , branchName } = this.props.match.params;
|
||||||
|
this.setState({
|
||||||
|
readOnly:true,
|
||||||
|
treeValue:undefined
|
||||||
|
})
|
||||||
|
this.props.history.push(`/projects/${owner}/${projectsId}${branchName?`/tree/${branchName}`:""}`);
|
||||||
|
this.getProjectRoot(branch);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取根目录
|
||||||
|
getProjectRoot = (branch) => {
|
||||||
|
const { projectsId , owner } = this.props.match.params;
|
||||||
|
const url = `/${owner}/${projectsId}/entries.json`;
|
||||||
|
axios.get(url, { params: { ref: branch } })
|
||||||
|
.then((result) => {
|
||||||
|
if (result) {
|
||||||
|
let last_commit = result.data && result.data.last_commit;
|
||||||
|
let entries = result.data && result.data.entries;
|
||||||
|
this.setState({
|
||||||
|
filePath: undefined,
|
||||||
|
fileDetail: [],
|
||||||
|
isSpin: false,
|
||||||
|
branchLastCommit: last_commit && last_commit.commit,
|
||||||
|
lastCommitAuthor:
|
||||||
|
last_commit && (last_commit.author || (last_commit.commit && last_commit.commit.author)),
|
||||||
|
zip_url: result.data.zip_url,
|
||||||
|
tar_url: result.data.tar_url
|
||||||
|
});
|
||||||
|
if (entries && entries.length > 0) {
|
||||||
|
this.renderData(entries);
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
rootList: entries,
|
||||||
|
subFileType: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).catch((error) => {});
|
||||||
|
};
|
||||||
|
|
||||||
|
ChangeFile = (arr, readOnly) => {
|
||||||
|
const { projectsId , owner } = this.props.match.params;
|
||||||
|
//点击直接跳转页面 加载一次路由
|
||||||
|
this.props.history.push(`/projects/${owner}/${projectsId}/tree/${arr.path}`);
|
||||||
|
this.setState({
|
||||||
|
readOnly: readOnly,
|
||||||
|
chooseType:"file"
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取子目录
|
||||||
|
getFileDetail = (path, ref) => {
|
||||||
|
this.setState({
|
||||||
|
filePath: decodeURI(path),
|
||||||
|
});
|
||||||
|
const { projectsId , owner , branchName } = this.props.match.params;
|
||||||
|
const { chooseType } = this.state;
|
||||||
|
const url = `/${owner}/${projectsId}/sub_entries.json`;
|
||||||
|
axios.get(url,{
|
||||||
|
params:{
|
||||||
|
filepath:path,
|
||||||
|
ref:ref || branchName,
|
||||||
|
type:chooseType
|
||||||
|
}
|
||||||
|
}).then((result)=>{
|
||||||
|
let entries = result.data && result.data.entries;
|
||||||
|
this.setState({
|
||||||
|
isSpin:false
|
||||||
|
})
|
||||||
|
if(result){
|
||||||
|
if(entries){
|
||||||
|
// 返回对象entries.type则是文件类型,否则是文件夹
|
||||||
|
if(entries.type){
|
||||||
|
this.setState({
|
||||||
|
fileDetail:[entries],
|
||||||
|
rootList:[],
|
||||||
|
subFileType:false
|
||||||
|
})
|
||||||
|
}else{
|
||||||
|
this.setState({
|
||||||
|
fileDetail:[],
|
||||||
|
rootList:entries,
|
||||||
|
branchLastCommit:result.data.last_commit && result.data.last_commit.commit,
|
||||||
|
lastCommitAuthor:result.data.last_commit && (result.data.last_commit.author || (result.data.last_commit.commit && result.data.last_commit.commit.author))
|
||||||
|
})
|
||||||
|
this.renderData(entries);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
this.setState({
|
||||||
|
fileDetail:[],
|
||||||
|
rootList:[],
|
||||||
|
isSpin:false,
|
||||||
|
subFileType:false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
this.setState({
|
||||||
|
isSpin:false
|
||||||
|
})
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
renderData = (data) => {
|
||||||
|
const rootList = [];
|
||||||
|
const readMeContent = [];
|
||||||
|
const readMeFile = [];
|
||||||
|
data && data.map((item, key) => {
|
||||||
|
rootList.push({
|
||||||
|
key,
|
||||||
|
message: item.commit && item.commit.message,
|
||||||
|
...item,
|
||||||
|
});
|
||||||
|
if (item.is_readme_file) {
|
||||||
|
readMeContent.push({ ...item });
|
||||||
|
readMeFile.push({ ...item });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.setState({
|
||||||
|
rootList: rootList,
|
||||||
|
readMeContent,
|
||||||
|
readMeFile,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 点击跳转到子目录
|
||||||
|
goToSubRoot=(path,type,filename)=>{
|
||||||
|
this.setState({
|
||||||
|
chooseType:type
|
||||||
|
})
|
||||||
|
const { projectsId, owner , branchName } = this.props.match.params;
|
||||||
|
const { defaultBranch } = this.props;
|
||||||
|
this.props.history.push(`/projects/${owner}/${projectsId}${`/tree/${branchName || defaultBranch}`}${path?`/${path}`:""}`);
|
||||||
|
if(filename.substring(filename.length - 3) === ".md"){
|
||||||
|
this.setState({
|
||||||
|
md:true
|
||||||
|
})
|
||||||
|
}else{
|
||||||
|
this.setState({
|
||||||
|
md:false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// readme文件内容
|
||||||
|
renderReadMeContent = (readMeContent, permission) => {
|
||||||
|
const { fileDetail, readMeFile } = this.state;
|
||||||
|
if (fileDetail && fileDetail.length !== 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (readMeContent && readMeContent.length > 0) {
|
||||||
|
return (
|
||||||
|
<div className="commonBox">
|
||||||
|
<div className="commonBox-title">
|
||||||
|
<span className="mr10">
|
||||||
|
<i className="iconfont icon-wenjian1 font-16 color-grey-9 fl mt3"></i>
|
||||||
|
</span>
|
||||||
|
<span className="commonBox-title-read">
|
||||||
|
{readMeContent[0].name}
|
||||||
|
</span>
|
||||||
|
{permission ?
|
||||||
|
<a
|
||||||
|
onClick={() => this.ChangeFile(readMeFile[0], false)}
|
||||||
|
className="ml20 pull-right"
|
||||||
|
>
|
||||||
|
<i className="iconfont icon-bianji6 font-16 color-blue"></i>
|
||||||
|
</a>
|
||||||
|
:
|
||||||
|
""
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div className="commonBox-info">
|
||||||
|
{readMeContent[0].content ?
|
||||||
|
<RenderHtml className="break_word_comments imageLayerParent" value={readMeContent[0].content} url={this.props.history.location}/>
|
||||||
|
:
|
||||||
|
<span>暂无~</span>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 选择分支
|
||||||
|
changeBranch = (value) => {
|
||||||
|
const { projectsId , owner } = this.props.match.params;
|
||||||
|
const { treeValue } = this.state;
|
||||||
|
let url = `/projects/${owner}/${projectsId}${value && `/tree/${value}`}${treeValue ? `/${treeValue}`:""}`;
|
||||||
|
this.props.history.push(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 子目录路径返回链接
|
||||||
|
returnUlr=(url)=>{
|
||||||
|
this.setState({
|
||||||
|
chooseType:"dir",
|
||||||
|
readOnly:true,
|
||||||
|
treeValue:url
|
||||||
|
})
|
||||||
|
const { projectsId , owner , branchName } = this.props.match.params;
|
||||||
|
this.props.history.push(`/projects/${owner}/${projectsId}${branchName?`/branch/${branchName}`:""}/tree/${url}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
onEdit=(readOnly)=>{
|
||||||
|
this.setState({
|
||||||
|
readOnly
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
downloadUrl = (zip_url,tar_url) => {
|
||||||
|
return(
|
||||||
|
<Menu>
|
||||||
|
{zip_url && (
|
||||||
|
<Menu.Item>
|
||||||
|
<a href={zip_url}>ZIP</a>
|
||||||
|
</Menu.Item>
|
||||||
|
)}
|
||||||
|
{tar_url && (
|
||||||
|
<Menu.Item>
|
||||||
|
<a href={tar_url}>TAR.GZ</a>
|
||||||
|
</Menu.Item>
|
||||||
|
)}
|
||||||
|
</Menu>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
title = (branchLastCommit,lastCommitAuthor) => {
|
||||||
|
if (branchLastCommit) {
|
||||||
|
const { projectsId , owner } = this.props.match.params;
|
||||||
|
return (
|
||||||
|
<div className="f-wrap-alignCenter">
|
||||||
|
{lastCommitAuthor ? (
|
||||||
|
<React.Fragment>
|
||||||
|
{lastCommitAuthor.login ? (
|
||||||
|
<Link
|
||||||
|
to={`/users/${lastCommitAuthor.login}/projects`}
|
||||||
|
className="show-user-link"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={getImageUrl(`images/${lastCommitAuthor.image_url}`)}
|
||||||
|
className="radius mr10"
|
||||||
|
width="32"
|
||||||
|
height="32"
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
<span className="mr15">{lastCommitAuthor.name}</span>
|
||||||
|
</Link>
|
||||||
|
) : (
|
||||||
|
<span className="mr15">{lastCommitAuthor.name}</span>
|
||||||
|
)}
|
||||||
|
</React.Fragment>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${branchLastCommit.sha}`)}`} className="color-blue flex-1 hide-1">
|
||||||
|
{branchLastCommit.message}
|
||||||
|
</Link>
|
||||||
|
<span>{branchLastCommit.time_from_now}</span>
|
||||||
|
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${branchLastCommit.sha}`)}`} className="commitKey">
|
||||||
|
{truncateCommitId(branchLastCommit.sha)}
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
render(){
|
||||||
|
const { branchLastCommit , lastCommitAuthor , rootList ,filePath , fileDetail , subFileType , readMeContent, isSpin , zip_url , tar_url , branchList} = this.state;
|
||||||
|
const { isManager , isDeveloper , projectDetail , platform , defaultBranch } = this.props;
|
||||||
|
|
||||||
|
const { projectsId , owner , branchName } = this.props.match.params;
|
||||||
|
let branch = branchName || defaultBranch;
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
key:"name",
|
||||||
|
dataIndex: 'name',
|
||||||
|
width:"30%",
|
||||||
|
render: (text,item) => (
|
||||||
|
<a onClick={()=>this.goToSubRoot(item.path,item.type,text)} className="ml12 task-hide" style={{ display: "block", maxWidth: "345px" }}>
|
||||||
|
<i className={ item.type === "file" ? "iconfont icon-wenjia font-15 color-green-file mr5" : "iconfont icon-wenjianjia1 color-green-file font-15 mr5"}></i>{text}
|
||||||
|
</a>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key:"message",
|
||||||
|
dataIndex: "message",
|
||||||
|
width: "60%",
|
||||||
|
render: (text, item) =>
|
||||||
|
item.commit && item.commit.message ?
|
||||||
|
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${item.commit.sha}`)}`} title={item.commit.message} className="task-hide" style={{ display: "block", maxWidth: "670px" }} >
|
||||||
|
{item.commit.message}
|
||||||
|
</Link>
|
||||||
|
: ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key:"time_from_now",
|
||||||
|
dataIndex: "time_from_now",
|
||||||
|
width: "10%",
|
||||||
|
className: "edu-txt-right",
|
||||||
|
render: (text, item) =>
|
||||||
|
item.commit && item.commit.time_from_now ?
|
||||||
|
<a title={item.commit.created_at} className="mr12" style={{ cursor: "default", color: "#888" }} >
|
||||||
|
{item.commit.time_from_now}
|
||||||
|
</a>
|
||||||
|
:""
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const urlRoot = filePath === undefined ? "" : `/${filePath}`;
|
||||||
|
let array = filePath && filePath.split("/");
|
||||||
|
return (
|
||||||
|
<Spin spinning={isSpin}>
|
||||||
|
<div className="main" style={{minHeight:'400px'}}>
|
||||||
|
<div className="f-wrap-between mb20">
|
||||||
|
<div className="f-wrap-alignCenter">
|
||||||
|
{
|
||||||
|
platform ?
|
||||||
|
<SelectBranch
|
||||||
|
repo_id={projectDetail && projectDetail.repo_id}
|
||||||
|
projectsId={projectsId}
|
||||||
|
branch={branch}
|
||||||
|
changeBranch={this.changeBranch}
|
||||||
|
owner={owner}
|
||||||
|
history={this.props.history}
|
||||||
|
branchList={branchList}
|
||||||
|
></SelectBranch>
|
||||||
|
:
|
||||||
|
<span>分支:<span className="color-grey-6">master</span></span>
|
||||||
|
}
|
||||||
|
|
||||||
|
{filePath && (
|
||||||
|
<span className="ml20 font-16">
|
||||||
|
<a
|
||||||
|
onClick={() => this.returnMain(branch)}
|
||||||
|
className="color-blue"
|
||||||
|
>
|
||||||
|
{projectDetail && projectDetail.identifier}
|
||||||
|
</a>
|
||||||
|
{array &&
|
||||||
|
array.map((item, key) => {
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
{
|
||||||
|
key === array.length-1 ?
|
||||||
|
<span className="color-grey-6 subFileName" key={key}>{item}</span>
|
||||||
|
:
|
||||||
|
<a onClick={()=>this.returnUlr(`${getPathUrl(array,key+1)}`)} className="color-blue subFileName">{item}</a>
|
||||||
|
}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="f-wrap-alignCenter">
|
||||||
|
{subFileType && (projectDetail && parseInt(projectDetail.type)) !== 2 && (isManager || isDeveloper) && platform && (
|
||||||
|
<div>
|
||||||
|
<span>
|
||||||
|
<Link to={`/projects/${owner}/${projectsId}/${branch}/uploadfile${urlRoot}`} >
|
||||||
|
<span className="color-green mr30">上传文件</span>
|
||||||
|
</Link>
|
||||||
|
</span>
|
||||||
|
<span className="mr30">
|
||||||
|
<Link
|
||||||
|
to={`/projects/${owner}/${projectsId}/${branch}/newfile${urlRoot}`}
|
||||||
|
>
|
||||||
|
<span className="color-blue">新建文件</span>
|
||||||
|
</Link>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{projectDetail && projectDetail.clone_url && (
|
||||||
|
<CloneAddress
|
||||||
|
http_url={projectDetail.clone_url}
|
||||||
|
downloadUrl={this.downloadUrl(zip_url,tar_url)}
|
||||||
|
showNotification={this.props.showNotification}
|
||||||
|
></CloneAddress>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/* 主目录列表 */}
|
||||||
|
{rootList && rootList.length > 0 && (
|
||||||
|
<RootTable
|
||||||
|
columns={columns}
|
||||||
|
data={rootList}
|
||||||
|
title={() => this.title(branchLastCommit,lastCommitAuthor)}
|
||||||
|
></RootTable>
|
||||||
|
)}
|
||||||
|
{/* 子目录列表、文件 */}
|
||||||
|
{fileDetail && fileDetail.length > 0 && (
|
||||||
|
<CoderRootFileDetail
|
||||||
|
detail={fileDetail[0]}
|
||||||
|
{...this.props}
|
||||||
|
{...this.state}
|
||||||
|
readOnly={this.state.readOnly}
|
||||||
|
onEdit={this.onEdit}
|
||||||
|
currentBranch={branch}
|
||||||
|
></CoderRootFileDetail>
|
||||||
|
)}
|
||||||
|
{
|
||||||
|
(rootList && rootList.length === 0) && (fileDetail && fileDetail.length === 0) && <Nodata _html="暂未发现文件!"/>
|
||||||
|
}
|
||||||
|
{ rootList && this.renderReadMeContent(readMeContent, isManager || isDeveloper)}
|
||||||
|
</div>
|
||||||
|
</Spin>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default CoderRootDirectory;
|
|
@ -24,25 +24,13 @@ class CoderRootFileDetail extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount = () => {
|
componentDidMount = () => {
|
||||||
const { detail , mdFlag } = this.props;
|
const { detail } = this.props;
|
||||||
this.setState({
|
this.setState({
|
||||||
value: detail.content,
|
value: detail.content,
|
||||||
});
|
});
|
||||||
this.languages_total();
|
this.languages_total();
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidUpdate=(prevProps)=>{
|
|
||||||
const { content } = this.props && this.props.detail;
|
|
||||||
const prevcontent = prevProps.detail && prevProps.detail.content;
|
|
||||||
if (content && prevcontent) {
|
|
||||||
if (prevcontent !== content){
|
|
||||||
this.setState({
|
|
||||||
description: content
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
languages_total = () => {
|
languages_total = () => {
|
||||||
const { detail } = this.props;
|
const { detail } = this.props;
|
||||||
const file_name = detail.path.split("/").pop().split(".").pop();
|
const file_name = detail.path.split("/").pop().split(".").pop();
|
||||||
|
@ -176,16 +164,15 @@ class CoderRootFileDetail extends Component {
|
||||||
current_user,
|
current_user,
|
||||||
isManager,
|
isManager,
|
||||||
isDeveloper,
|
isDeveloper,
|
||||||
currentBranch,
|
|
||||||
platform,
|
|
||||||
md,
|
md,
|
||||||
type
|
currentBranch,
|
||||||
|
platform
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const { language, languages, description } = this.state;
|
const { language, languages, description } = this.state;
|
||||||
let flag = current_user && current_user.login && (isManager || isDeveloper);
|
let flag = current_user && current_user.login && (isManager || isDeveloper);
|
||||||
const Option = Select.Option;
|
const Option = Select.Option;
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<div className="mb20">
|
||||||
<div className="grid-item branchTitle">
|
<div className="grid-item branchTitle">
|
||||||
<div className="grid-item">
|
<div className="grid-item">
|
||||||
<span className="ml20 color-grey-6 font-16">
|
<span className="ml20 color-grey-6 font-16">
|
||||||
|
@ -198,18 +185,17 @@ class CoderRootFileDetail extends Component {
|
||||||
{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>
|
</a>
|
||||||
{
|
<a onClick={() => this.EditFile(false)} className="ml20">
|
||||||
type !==2 &&
|
<i className="iconfont icon-bianji1 font-15 color-grey-6"></i>
|
||||||
<a onClick={() => this.EditFile(false)} className="ml20">
|
</a>
|
||||||
<i className="iconfont icon-bianji1 font-15 color-grey-6"></i>
|
</span>
|
||||||
</a>
|
|
||||||
}
|
|
||||||
</span>:""
|
|
||||||
}
|
}
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
|
@ -240,21 +226,18 @@ class CoderRootFileDetail extends Component {
|
||||||
</button>
|
</button>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
)}
|
)}
|
||||||
{
|
|
||||||
type !==2 &&
|
<Popconfirm
|
||||||
<Popconfirm
|
title="确认删除这个文件?"
|
||||||
title="确认删除这个文件?"
|
className="ml20"
|
||||||
className="ml20"
|
okText="确定"
|
||||||
okText="确定"
|
cancelText="取消"
|
||||||
cancelText="取消"
|
onConfirm={this.deleteFile}
|
||||||
onConfirm={this.deleteFile}
|
>
|
||||||
>
|
<a>
|
||||||
<a>
|
<i className="iconfont icon-shanchu font-15 color-grey-6"></i>
|
||||||
<i className="iconfont icon-shanchu font-15 color-grey-6"></i>
|
</a>
|
||||||
</a>
|
</Popconfirm>
|
||||||
</Popconfirm>
|
|
||||||
}
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
|
@ -262,7 +245,11 @@ class CoderRootFileDetail extends Component {
|
||||||
<div>
|
<div>
|
||||||
{detail.image_type ? (
|
{detail.image_type ? (
|
||||||
<div className="edu-txt-center pt20 pb20">
|
<div className="edu-txt-center pt20 pb20">
|
||||||
<img alt="" src={detail.download_url} style={{ maxWidth: "80%" }} />
|
<img
|
||||||
|
alt=""
|
||||||
|
src={detail.download_url}
|
||||||
|
style={{ maxWidth: "80%" }}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : detail.direct_download ? (
|
) : detail.direct_download ? (
|
||||||
<div className="mt20 text-center">
|
<div className="mt20 text-center">
|
||||||
|
@ -281,14 +268,14 @@ class CoderRootFileDetail extends Component {
|
||||||
{...this.state}
|
{...this.state}
|
||||||
language={language ? language : "javascript"}
|
language={language ? language : "javascript"}
|
||||||
filepath={`/${detail.path}`}
|
filepath={`/${detail.path}`}
|
||||||
content={description}
|
content={detail.content}
|
||||||
readOnly={readOnly}
|
readOnly={readOnly}
|
||||||
editorType="update"
|
editorType="update"
|
||||||
currentBranch={currentBranch}
|
currentBranch={currentBranch}
|
||||||
></Meditor>
|
></Meditor>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</React.Fragment>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,10 @@ const UploadFile = Loadable({
|
||||||
loader: () => import('../Newfile/upload_file'),
|
loader: () => import('../Newfile/upload_file'),
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
})
|
})
|
||||||
|
const CoderRootDirectory = Loadable({
|
||||||
|
loader: () => import('./CoderRootDirectory'),
|
||||||
|
loading: Loading,
|
||||||
|
})
|
||||||
const CoderRootCommit = Loadable({
|
const CoderRootCommit = Loadable({
|
||||||
loader: () => import('./CoderRootCommit'),
|
loader: () => import('./CoderRootCommit'),
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
|
@ -67,7 +71,6 @@ class CoderRootIndex extends Component{
|
||||||
this.getTopCount(branchName || defaultBranch);
|
this.getTopCount(branchName || defaultBranch);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取<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`;
|
||||||
|
@ -102,6 +105,13 @@ class CoderRootIndex extends Component{
|
||||||
(props) => (<FileNew {...this.props} {...props} {...this.state} getTopCount={this.getTopCount} />)
|
(props) => (<FileNew {...this.props} {...props} {...this.state} getTopCount={this.getTopCount} />)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
|
|
||||||
|
{/* diff */}
|
||||||
|
<Route path="/projects/:owner/:projectsId/commits/branch/:branchName"
|
||||||
|
render={
|
||||||
|
(props) => (<CoderRootCommit {...this.props} {...props} {...this.state} commit_class="main" getTopCount={this.getTopCount} />)
|
||||||
|
}
|
||||||
|
></Route>
|
||||||
<Route path="/projects/:owner/:projectsId/commits/:sha"
|
<Route path="/projects/:owner/:projectsId/commits/:sha"
|
||||||
render={
|
render={
|
||||||
(props) => (<Diff {...this.props} {...props} {...this.state}/>)
|
(props) => (<Diff {...this.props} {...props} {...this.state}/>)
|
||||||
|
@ -112,6 +122,7 @@ class CoderRootIndex extends Component{
|
||||||
() => (<CoderRootCommit {...this.props} {...this.state} commit_class="main" getTopCount={this.getTopCount} />)
|
() => (<CoderRootCommit {...this.props} {...this.state} commit_class="main" getTopCount={this.getTopCount} />)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
|
|
||||||
<Route path="/projects/:owner/:projectsId/releases/:versionId/update"
|
<Route path="/projects/:owner/:projectsId/releases/:versionId/update"
|
||||||
render={
|
render={
|
||||||
(props) => (<CoderRootVersionUpdate {...this.props} {...this.state} {...props} />)
|
(props) => (<CoderRootVersionUpdate {...this.props} {...this.state} {...props} />)
|
||||||
|
@ -122,21 +133,33 @@ class CoderRootIndex extends Component{
|
||||||
() => (<CoderRootVersionNew {...this.props} {...this.state} />)
|
() => (<CoderRootVersionNew {...this.props} {...this.state} />)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
|
|
||||||
<Route path="/projects/:owner/:projectsId/releases"
|
<Route path="/projects/:owner/:projectsId/releases"
|
||||||
render={
|
render={
|
||||||
() => (<CoderRootVersion {...this.props} {...this.state} />)
|
() => (<CoderRootVersion {...this.props} {...this.state} />)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
|
|
||||||
<Route path="/projects/:owner/:projectsId/tag"
|
<Route path="/projects/:owner/:projectsId/tag"
|
||||||
render={
|
render={
|
||||||
() => (<CoderRootTag {...this.props} {...this.state} />)
|
() => (<CoderRootTag {...this.props} {...this.state} />)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
|
<Route path="/projects/:owner/:projectsId/tree/:branchName"
|
||||||
|
render={
|
||||||
|
(props) => (<CoderRootDirectory {...this.props} {...this.state} getTopCount={this.getTopCount} />)
|
||||||
|
}
|
||||||
|
></Route>
|
||||||
<Route path="/projects/:owner/:projectsId/branchs"
|
<Route path="/projects/:owner/:projectsId/branchs"
|
||||||
render={
|
render={
|
||||||
() => (<CoderRootBranch {...this.props} {...this.state} />)
|
() => (<CoderRootBranch {...this.props} {...this.state} />)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
|
<Route path="/projects/:owner/:projectsId"
|
||||||
|
render={
|
||||||
|
() => (<CoderRootDirectory {...this.props} {...this.state} getTopCount={this.getTopCount} />)
|
||||||
|
}
|
||||||
|
></Route>
|
||||||
</Switch>
|
</Switch>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,9 +2,9 @@ import React, { Component } from 'react';
|
||||||
import { Spin, Tooltip } from 'antd';
|
import { Spin, Tooltip } from 'antd';
|
||||||
import { Link, Route, Switch } from 'react-router-dom';
|
import { Link, Route, Switch } from 'react-router-dom';
|
||||||
import { Content } from '../Component/layout';
|
import { Content } from '../Component/layout';
|
||||||
import DetailBanner from './sub/DetailBanner';
|
|
||||||
import '../css/index.scss'
|
import '../css/index.scss'
|
||||||
import './list.css';
|
import './list.css';
|
||||||
|
import SpecialModal from './SpecialModal';
|
||||||
|
|
||||||
import Loadable from 'react-loadable';
|
import Loadable from 'react-loadable';
|
||||||
import Loading from '../../Loading';
|
import Loading from '../../Loading';
|
||||||
|
@ -97,19 +97,7 @@ const ForkUsers = Loadable({
|
||||||
loader: () => import('../UsersList/fork_users'),
|
loader: () => import('../UsersList/fork_users'),
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
})
|
})
|
||||||
const Contribute = Loadable({
|
|
||||||
loader: () => import('./sub/Contribute'),
|
|
||||||
loading: Loading,
|
|
||||||
})
|
|
||||||
|
|
||||||
const CoderRootCommit = Loadable({
|
|
||||||
loader: () => import('./CoderRootCommit'),
|
|
||||||
loading: Loading,
|
|
||||||
})
|
|
||||||
const CoderDepot = Loadable({
|
|
||||||
loader: () => import('./CoderDepot'),
|
|
||||||
loading: Loading,
|
|
||||||
})
|
|
||||||
|
|
||||||
const TrendsIndex = Loadable({
|
const TrendsIndex = Loadable({
|
||||||
loader: () => import('../Activity/Activity'),
|
loader: () => import('../Activity/Activity'),
|
||||||
|
@ -120,10 +108,6 @@ const DevAbout = Loadable({
|
||||||
loader: () => import('../About/Index'),
|
loader: () => import('../About/Index'),
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
})
|
})
|
||||||
const Source = Loadable({
|
|
||||||
loader: () => import('../Source/Index'),
|
|
||||||
loading: Loading,
|
|
||||||
})
|
|
||||||
const DevIndex = Loadable({
|
const DevIndex = Loadable({
|
||||||
loader: () => import('../DevOps/Index'),
|
loader: () => import('../DevOps/Index'),
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
|
@ -149,8 +133,6 @@ function checkPathname(projectsId,owner,pathname){
|
||||||
name="setting"
|
name="setting"
|
||||||
}else if(url.indexOf(`/devops`)>-1){
|
}else if(url.indexOf(`/devops`)>-1){
|
||||||
name="devops"
|
name="devops"
|
||||||
}else if(url.indexOf(`/source`)>-1){
|
|
||||||
name="source"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return name;
|
return name;
|
||||||
|
@ -170,6 +152,7 @@ class Detail extends Component {
|
||||||
watched: false,
|
watched: false,
|
||||||
praised: false,
|
praised: false,
|
||||||
http_url: undefined,
|
http_url: undefined,
|
||||||
|
author: undefined,
|
||||||
branchs: undefined,
|
branchs: undefined,
|
||||||
branchList: undefined,
|
branchList: undefined,
|
||||||
project: null,
|
project: null,
|
||||||
|
@ -180,7 +163,9 @@ class Detail extends Component {
|
||||||
defaultBranch:undefined,
|
defaultBranch:undefined,
|
||||||
|
|
||||||
// 非本平台项目
|
// 非本平台项目
|
||||||
platform:false
|
platform:false,
|
||||||
|
visible:false,
|
||||||
|
user_apply_signatures:[]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,6 +182,7 @@ class Detail extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
getProject = (num) => {
|
getProject = (num) => {
|
||||||
|
const {user} = this.props;
|
||||||
const { projectsId , owner } = this.props.match.params;
|
const { projectsId , owner } = this.props.match.params;
|
||||||
const url = `/${owner}/${projectsId}/simple.json`;
|
const url = `/${owner}/${projectsId}/simple.json`;
|
||||||
axios.get(url).then((result) => {
|
axios.get(url).then((result) => {
|
||||||
|
@ -206,6 +192,24 @@ class Detail extends Component {
|
||||||
open_devops:result.data.open_devops,
|
open_devops:result.data.open_devops,
|
||||||
platform:result.data.platform && result.data.platform !== 'educoder'
|
platform:result.data.platform && result.data.platform !== 'educoder'
|
||||||
})
|
})
|
||||||
|
let signa = result.data.user_apply_signatures && result.data.user_apply_signatures[0];
|
||||||
|
if(result.data.is_secret && !result.data.is_member && (!signa || (signa && signa.status !== "passed")) && user.login !== owner){
|
||||||
|
this.setState({
|
||||||
|
visible:true,
|
||||||
|
is_secret:result.data.is_secret,
|
||||||
|
user_apply_signatures:signa
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 工作流:两种状态进入的链接不同
|
||||||
|
const pathname = this.props.history.location.pathname;
|
||||||
|
if(pathname===`/projects/${owner}/${projectsId}/devops`){
|
||||||
|
if(result.data.open_devops && pathname === `/projects/${owner}/${projectsId}/devops`){
|
||||||
|
this.props.history.push(`/projects/${owner}/${projectsId}/devops/list`);
|
||||||
|
}else if(result.data.open_devops===false && pathname !== `/projects/${owner}/${projectsId}/devops`){
|
||||||
|
this.props.history.push(`/projects/${owner}/${projectsId}/devops`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (result.data.type !== 0 && result.data.mirror_status === 1) {
|
if (result.data.type !== 0 && result.data.mirror_status === 1) {
|
||||||
console.log("--------start channel --------");
|
console.log("--------start channel --------");
|
||||||
|
@ -264,8 +268,7 @@ class Detail extends Component {
|
||||||
|
|
||||||
getDetail = () => {
|
getDetail = () => {
|
||||||
const { projectsId , owner } = this.props.match.params;
|
const { projectsId , owner } = this.props.match.params;
|
||||||
this.getBanner();
|
const url = `/${owner}/${projectsId}.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) {
|
||||||
this.setState({
|
this.setState({
|
||||||
|
@ -275,6 +278,7 @@ class Detail extends Component {
|
||||||
isReporter: result.data.permission && result.data.permission === "Reporter",
|
isReporter: result.data.permission && result.data.permission === "Reporter",
|
||||||
isDeveloper: result.data.permission && result.data.permission === "Developer",
|
isDeveloper: result.data.permission && result.data.permission === "Developer",
|
||||||
http_url: result.data.clone_url,
|
http_url: result.data.clone_url,
|
||||||
|
author: result.data.author,
|
||||||
praised: result.data.praised,
|
praised: result.data.praised,
|
||||||
watched: result.data.watched,
|
watched: result.data.watched,
|
||||||
watchers_count: result.data.watchers_count,
|
watchers_count: result.data.watchers_count,
|
||||||
|
@ -286,19 +290,6 @@ class Detail extends Component {
|
||||||
}).catch((error) => { })
|
}).catch((error) => { })
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取动态导航栏菜单
|
|
||||||
getBanner(){
|
|
||||||
const { projectsId , owner } = this.props.match.params;
|
|
||||||
const url = `/${owner}/${projectsId}/menu_list.json`;
|
|
||||||
axios.get(url).then(result=>{
|
|
||||||
if(result){
|
|
||||||
this.setState({
|
|
||||||
bannerList:result.data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}).catch(error=>{})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 关注和取消关注
|
// 关注和取消关注
|
||||||
focusFunc = (flag) => {
|
focusFunc = (flag) => {
|
||||||
const { platform } = this.state;
|
const { platform } = this.state;
|
||||||
|
@ -389,13 +380,24 @@ class Detail extends Component {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hideModal=()=>{
|
||||||
|
this.setState({
|
||||||
|
visible:false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
sureModal=()=>{
|
||||||
|
this.hideModal();
|
||||||
|
this.props.history.push('/projects');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { projectDetail, watchers_count, praises_count,
|
const { projectDetail, watchers_count, praises_count,
|
||||||
forked_count, firstSync , secondSync ,
|
forked_count, firstSync , secondSync ,
|
||||||
isManager, watched, praised,
|
isManager, watched, praised,
|
||||||
project , open_devops , platform , defaultBranch , bannerList } = this.state;
|
project , open_devops , platform , defaultBranch , project_id , user_apply_signatures , visible } = this.state;
|
||||||
const url = this.props.history.location.pathname;
|
const url = this.props.history.location.pathname;
|
||||||
const urlArr = url.split("/");
|
const urlArr = url.split("/");
|
||||||
const urlFlag = (urlArr.length === 3);
|
const urlFlag = (urlArr.length === 3);
|
||||||
|
@ -422,18 +424,19 @@ class Detail extends Component {
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
<SpecialModal {...this.props} visible={visible} hideModal={this.sureModal} user_apply_signatures={user_apply_signatures} project_id={project_id} sureModal={this.sureModal}></SpecialModal>
|
||||||
<div className="detailHeader-wrapper">
|
<div className="detailHeader-wrapper">
|
||||||
<div className="normal">
|
<div className="normal">
|
||||||
<div className="f-wrap-between pb15" style={{ position: "relative" }}>
|
<div className="f-wrap-between pb15" style={{ position: "relative" }}>
|
||||||
<p className="font-22 df flex-1 lineH2 mt15" style={{ alignItems: "center" }}>
|
<p className="color-white font-22 df flex-1 lineH2 mt15" style={{ alignItems: "center" }}>
|
||||||
{project && project.author &&
|
{project && project.author &&
|
||||||
<Link to={`${project.author.type ==="Organization" ? "/organize":'/users'}/${project.author.login}`} className="show-user-link">
|
<Link to={`/users/${project.author.login}`} className="show-user-link color-white">
|
||||||
{project.author.name}
|
{project.author.name}
|
||||||
</Link>
|
</Link>
|
||||||
}
|
}
|
||||||
<span className="ml5 mr5">/</span>
|
<span className="ml5 mr5">/</span>
|
||||||
<span className="hide-1 flex-1 df">
|
<span className="hide-1 flex-1 df">
|
||||||
<Link to={`/projects/${owner}/${projectsId}`} className="font-22">{project && project.name}</Link>
|
<Link to={`/projects/${owner}/${projectsId}`} className="color-white font-22">{project && project.name}</Link>
|
||||||
{
|
{
|
||||||
projectDetail && projectDetail.forked_from_project_id && projectDetail.fork_info ?
|
projectDetail && projectDetail.forked_from_project_id && projectDetail.fork_info ?
|
||||||
<Tooltip placement={'right'} title={text}>
|
<Tooltip placement={'right'} title={text}>
|
||||||
|
@ -470,15 +473,14 @@ class Detail extends Component {
|
||||||
<span>{watched ? '取消关注' : '关注'}</span>
|
<span>{watched ? '取消关注' : '关注'}</span>
|
||||||
</a>
|
</a>
|
||||||
{
|
{
|
||||||
watchers_count > 0 ?
|
|
||||||
platform ?
|
platform ?
|
||||||
<Link className="detail_tag_btn_count" style={{color:`${watched?"#2878FF":"#666"}`}} to={platform?{ pathname: `/projects/${owner}/${projectsId}/watchers`, state }:""}>
|
<Link className="detail_tag_btn_count" style={{color:`${watched?"#2878FF":"#666"}`}} to={platform?{ pathname: `/projects/${owner}/${projectsId}/watchers`, 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>
|
</span>
|
||||||
<span className="detail_tag_btn">
|
<span 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)}>
|
||||||
|
@ -486,30 +488,24 @@ class Detail extends Component {
|
||||||
<span>{praised ? '取消点赞' : '点赞'}</span>
|
<span>{praised ? '取消点赞' : '点赞'}</span>
|
||||||
</a>
|
</a>
|
||||||
{
|
{
|
||||||
praises_count > 0 ?
|
|
||||||
platform ?
|
platform ?
|
||||||
<Link className="detail_tag_btn_count" style={{color:`${praised?"#2878FF":"#666"}`}} to={{ pathname: `/projects/${owner}/${projectsId}/stargazers`, state }}>
|
<Link className="detail_tag_btn_count" style={{color:`${praised?"#2878FF":"#666"}`}} to={{ pathname: `/projects/${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>
|
</span>
|
||||||
<span className="detail_tag_btn">
|
<span className="detail_tag_btn">
|
||||||
<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"></i>复刻 (Fork)
|
||||||
<i className="iconfont icon-fork color-grey-9 mr3"></i>复刻
|
</a>
|
||||||
</a>
|
|
||||||
</Tooltip>
|
|
||||||
{
|
{
|
||||||
forked_count > 0 ?
|
|
||||||
platform ?
|
platform ?
|
||||||
<Link className="detail_tag_btn_count" to={{ pathname: `/projects/${owner}/${projectsId}/fork_users`, state }}>
|
<Link className="detail_tag_btn_count" to={{ pathname: `/projects/${owner}/${projectsId}/fork_users`, state }}>
|
||||||
{forked_count}
|
{forked_count}
|
||||||
</Link>
|
</Link>
|
||||||
:
|
:
|
||||||
<span className="detail_tag_btn_count">{forked_count}</span>
|
<span className="detail_tag_btn_count">{praises_count}</span>
|
||||||
:""
|
|
||||||
}
|
}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
@ -517,36 +513,83 @@ class Detail extends Component {
|
||||||
</div>
|
</div>
|
||||||
{
|
{
|
||||||
firstSync ? "" :
|
firstSync ? "" :
|
||||||
<DetailBanner
|
<div className="f-wrap-between pb20">
|
||||||
history={this.props.history}
|
<ul className="headerMenu-wrapper">
|
||||||
list={bannerList}
|
<li className={pathname==="about" ? "active" : ""}>
|
||||||
owner={owner}
|
<Link to={{ pathname: `/projects/${owner}/${projectsId}/about`, state }}>
|
||||||
projectsId={projectsId}
|
<i className={ pathname === "about" ? "iconfont icon-zhuye1 color-blue mr5 font-14":"iconfont icon-zhuye1 color-white font-14 mr5"}></i>
|
||||||
pathname={pathname}
|
<span>主页</span>
|
||||||
state={state}
|
</Link>
|
||||||
projectDetail={projectDetail}
|
</li>
|
||||||
open_devops={open_devops}
|
<li className={(pathname==="" || urlFlag) ? "active" : ""}>
|
||||||
platform={platform}
|
<Link to={{ pathname: `/projects/${owner}/${projectsId}`, state }}>
|
||||||
urlFlag={urlFlag}
|
<i className={(pathname==="" || urlFlag) ? "iconfont icon-daimaku color-blue mr5 font-14":"iconfont icon-daimaku color-white font-14 mr5"}></i>
|
||||||
isManager={isManager}
|
<span>代码库</span>
|
||||||
/>
|
</Link>
|
||||||
|
</li>
|
||||||
|
<li className={pathname==="issues" ? "active" : ""}>
|
||||||
|
<Link to={{ pathname: `/projects/${owner}/${projectsId}/issues`, state }}>
|
||||||
|
<i className={pathname==="issues" ? "iconfont icon-renwu color-blue mr5 font-14":"iconfont icon-renwu color-white font-14 mr5"}></i>
|
||||||
|
<span>易修 (Issue)</span>
|
||||||
|
{projectDetail && projectDetail.issues_count ? <span className="num">{projectDetail.issues_count}</span> : ""}
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
{
|
||||||
|
projectDetail && parseInt(projectDetail.type) !== 2 && platform &&
|
||||||
|
<li className={pathname==="pulls" ? "active" : ""}>
|
||||||
|
<Link to={{ pathname: `/projects/${owner}/${projectsId}/pulls`, state }}>
|
||||||
|
<i className={pathname==="pulls" ? "iconfont icon-hebingqingqiu1 color-blue mr5 font-14":"iconfont icon-hebingqingqiu1 color-white font-14 mr5"}></i>
|
||||||
|
<span>合并请求</span>
|
||||||
|
{projectDetail && projectDetail.pull_requests_count ? <span className="num">{projectDetail.pull_requests_count}</span> : ""}
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
{/* {
|
||||||
|
platform &&
|
||||||
|
<li className={pathname==="devops" ? "active" : ""}>
|
||||||
|
<Link to={{ pathname: `/projects/${owner}/${projectsId}/devops${open_devops ? `/list`:""}`, state }}>
|
||||||
|
<i className="iconfont icon-gongzuoliu font-13 mr8"></i>工作流(beta版)
|
||||||
|
{projectDetail && projectDetail.ops_count ? <span>{projectDetail.ops_count}</span> : ""}
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
} */}
|
||||||
|
|
||||||
|
<li className={pathname==="milestones" ? "active" : ""}>
|
||||||
|
<Link to={{ pathname: `/projects/${owner}/${projectsId}/milestones`, state }}>
|
||||||
|
<i className={pathname==="milestones" ? "iconfont icon-lichengbei color-blue mr5 font-14":"iconfont icon-lichengbei color-white font-14 mr5"}></i>
|
||||||
|
<span>里程碑</span>
|
||||||
|
{projectDetail && projectDetail.versions_count ? <span className="num">{projectDetail.versions_count}</span> :""}
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
<li className={pathname==="activity" ? "active" : ""}>
|
||||||
|
<Link to={{ pathname: `/projects/${owner}/${projectsId}/activity`, state }}>
|
||||||
|
<i className={pathname==="activity" ? "iconfont icon-tongzhi color-blue mr5 font-14":"iconfont icon-tongzhi color-white font-14 mr5"}></i>
|
||||||
|
<span>动态</span>
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
{
|
||||||
|
isManager && platform &&
|
||||||
|
<li className={url.indexOf("/setting") > 0 ? "active" : ""}>
|
||||||
|
<Link to={`/projects/${owner}/${projectsId}/setting`}>
|
||||||
|
<i className={url.indexOf("/setting") > 0 ? "iconfont icon-cangku color-blue mr5 font-14":"iconfont icon-cangku color-white font-14 mr5"}></i>
|
||||||
|
<span>仓库设置</span>
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{
|
{
|
||||||
firstSync ?
|
firstSync ?
|
||||||
<Content className="spincontent">
|
<Content className="spincontent">
|
||||||
<Spin className="spinstyle" tip={project && `正在从 ${project.mirror_url} 迁移`} size="large" />
|
<Spin className="spinstyle" tip={project && `正在从 ${project.mirror_url} 迁移`} size="large">
|
||||||
|
</Spin>
|
||||||
</Content>
|
</Content>
|
||||||
:
|
:
|
||||||
<Spin spinning={secondSync} className="spinstyle" tip="正在同步镜像" size="large">
|
<Spin spinning={secondSync} className="spinstyle" tip="正在同步镜像" size="large">
|
||||||
<Switch {...this.props}>
|
<Switch {...this.props}>
|
||||||
{/* 资源 */}
|
|
||||||
<Route path="/projects/:owner/:projectsId/source"
|
|
||||||
render={
|
|
||||||
() => (<Source {...this.props} {...this.state} {...common} />)
|
|
||||||
}
|
|
||||||
></Route>
|
|
||||||
{/* 主页 */}
|
{/* 主页 */}
|
||||||
<Route path="/projects/:owner/:projectsId/about"
|
<Route path="/projects/:owner/:projectsId/about"
|
||||||
render={
|
render={
|
||||||
|
@ -637,7 +680,6 @@ class Detail extends Component {
|
||||||
(props) => (<OrderIndex {...this.props} {...props} {...this.state} {...common} />)
|
(props) => (<OrderIndex {...this.props} {...props} {...this.state} {...common} />)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
{/* 新建合并请求 */}
|
|
||||||
<Route path="/projects/:owner/:projectsId/pulls/new"
|
<Route path="/projects/:owner/:projectsId/pulls/new"
|
||||||
render={
|
render={
|
||||||
(props) => (<CreateMerge {...this.props} {...props} {...this.state} {...common} is_fork={true} />)
|
(props) => (<CreateMerge {...this.props} {...props} {...this.state} {...common} is_fork={true} />)
|
||||||
|
@ -664,6 +706,11 @@ class Detail extends Component {
|
||||||
(props) => (<MergeIndexDetail {...this.props} {...props} {...this.state} {...common} />)
|
(props) => (<MergeIndexDetail {...this.props} {...props} {...this.state} {...common} />)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
|
<Route path="/projects/:owner/:projectsId/coders/filesurl"
|
||||||
|
render={
|
||||||
|
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state} {...common} />)
|
||||||
|
}
|
||||||
|
></Route>
|
||||||
<Route path="/projects/:owner/:projectsId/watchers"
|
<Route path="/projects/:owner/:projectsId/watchers"
|
||||||
render={
|
render={
|
||||||
(props) => (<WatchUsers {...this.props} {...props} {...this.state} {...common} />)
|
(props) => (<WatchUsers {...this.props} {...props} {...this.state} {...common} />)
|
||||||
|
@ -679,32 +726,19 @@ class Detail extends Component {
|
||||||
(props) => (<ForkUsers {...this.props} {...props} {...this.state} {...common} />)
|
(props) => (<ForkUsers {...this.props} {...props} {...this.state} {...common} />)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
{/* 贡献者列表 */}
|
|
||||||
<Route path="/projects/:owner/:projectsId/contribute"
|
|
||||||
render={
|
|
||||||
() => (<Contribute {...this.props} {...this.state} {...common} />)
|
|
||||||
}
|
|
||||||
></Route>
|
|
||||||
|
|
||||||
{/* 代码库----详情页面 */}
|
|
||||||
<Route path="/projects/:owner/:projectsId/commits/branch/:branchName"
|
<Route path="/projects/:owner/:projectsId/commits/branch/:branchName"
|
||||||
render={
|
render={
|
||||||
(props) => (<CoderRootCommit {...this.props} {...props} {...this.state} {...common}/>)
|
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state} {...common} />)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
<Route path="/projects/:owner/:projectsId/tree/:branchName"
|
<Route path="/projects/:owner/:projectsId/tree/:branchName"
|
||||||
render={
|
render={
|
||||||
(props) => (<CoderDepot {...this.props} {...props} {...this.state} {...common}/>)
|
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state} {...common} />)
|
||||||
}
|
|
||||||
></Route>
|
|
||||||
<Route path="/projects/:owner/:projectsId/:subIndex"
|
|
||||||
render={
|
|
||||||
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state} {...common}/>)
|
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
<Route path="/projects/:owner/:projectsId"
|
<Route path="/projects/:owner/:projectsId"
|
||||||
render={
|
render={
|
||||||
(props) => (<CoderDepot {...this.props} {...props} {...this.state} {...common}/>)
|
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state} {...common} />)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
</Switch>
|
</Switch>
|
||||||
|
|
|
@ -59,13 +59,13 @@ export default ({ match , history }) => {
|
||||||
{commit && commit.message &&
|
{commit && commit.message &&
|
||||||
<pre className="task-hide" style={{marginBottom:"0px",height:"28px",whiteSpace:"pre-wrap"}}>{commit.message}</pre>
|
<pre className="task-hide" style={{marginBottom:"0px",height:"28px",whiteSpace:"pre-wrap"}}>{commit.message}</pre>
|
||||||
}
|
}
|
||||||
<Button type="primary" onClick={()=>{history.push(`/projects/${owner}/${projectsId}/tree/${truncateCommitId(sha)}`)}} className="ml30">浏览代码</Button>
|
<Button type="primary" onClick={()=>{history.push(`/projects/${owner}/${projectsId}/branch/${truncateCommitId(sha)}`)}} className="ml30">浏览代码</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="f-wrap-between" style={{ alignItems: "center" }}>
|
<div className="f-wrap-between" style={{ alignItems: "center" }}>
|
||||||
<ul className="df">
|
<ul className="df">
|
||||||
<User
|
<User
|
||||||
url={(committer && getImageUrl(`/${committer.image_url}`))|| "https://dss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3025493530,1989042357&fm=26&gp=0.jpg"}
|
url={(committer && getImageUrl(`images/${committer.image_url}`))|| "https://dss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3025493530,1989042357&fm=26&gp=0.jpg"}
|
||||||
name={committer && committer.name}
|
name={committer && committer.name}
|
||||||
/>
|
/>
|
||||||
{committer && committer.time_from_now && <li className="ml20 mt2">{committer.time_from_now}</li>}
|
{committer && committer.time_from_now && <li className="ml20 mt2">{committer.time_from_now}</li>}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { Menu, Input , Spin, Pagination , Popover , Select } from 'antd';
|
import { Menu, Input , Spin, Pagination , Popover, Affix, } from 'antd';
|
||||||
import { getImageUrl } from 'educoder';
|
|
||||||
import '../css/index.scss'
|
import '../css/index.scss'
|
||||||
import './list.css';
|
import './list.css';
|
||||||
import './Index.scss';
|
import './Index.scss';
|
||||||
|
@ -9,7 +8,7 @@ import ListItem from './IndexItem'
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import img_new from '../Images/new.png';
|
import img_new from '../Images/new.png';
|
||||||
import img_array from '../Images/array.png';
|
import img_array from '../Images/array.png';
|
||||||
import banner from '../Images/banner_list.jpg';
|
import banner from '../Images/banner_list.png';
|
||||||
const Search = Input.Search;
|
const Search = Input.Search;
|
||||||
|
|
||||||
class Index extends Component {
|
class Index extends Component {
|
||||||
|
@ -23,7 +22,6 @@ class Index extends Component {
|
||||||
sort: undefined,
|
sort: undefined,
|
||||||
total: 0,
|
total: 0,
|
||||||
isSpin: true,
|
isSpin: true,
|
||||||
project_type: undefined,
|
|
||||||
category_id: undefined,
|
category_id: undefined,
|
||||||
|
|
||||||
typeList: undefined,
|
typeList: undefined,
|
||||||
|
@ -37,8 +35,8 @@ class Index extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount = () => {
|
componentDidMount = () => {
|
||||||
const { page, limit, search, sort, project_type, category_id , languageId } = this.state;
|
const { page,search, sort,category_id , languageId } = this.state;
|
||||||
this.getListData(page, limit, search, sort, project_type, category_id , languageId);
|
this.getListData(page,search, sort,category_id , languageId);
|
||||||
|
|
||||||
this.getType();
|
this.getType();
|
||||||
|
|
||||||
|
@ -73,19 +71,24 @@ class Index extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取列表
|
// 获取列表
|
||||||
getListData = (page, limit, search, sort, project_type, category_id,languageId) => {
|
getListData = (page,search, sort,category_id,language_id) => {
|
||||||
const { current_user } = this.props;
|
const { current_user } = this.props;
|
||||||
const url = `/projects.json`;
|
const url = `/projects.json`;
|
||||||
|
if(category_id==0){
|
||||||
|
category_id=undefined;
|
||||||
|
}
|
||||||
|
if(language_id==0){
|
||||||
|
language_id=undefined;
|
||||||
|
}
|
||||||
axios.get(url, {
|
axios.get(url, {
|
||||||
params: {
|
params: {
|
||||||
user_id: current_user && current_user.user_id,
|
user_id: current_user && current_user.user_id,
|
||||||
page,
|
page,
|
||||||
limit,
|
limit:15,
|
||||||
search,
|
search,
|
||||||
sort_by: sort,
|
sort_by: sort,
|
||||||
project_type,
|
|
||||||
category_id,
|
category_id,
|
||||||
language_id:languageId
|
language_id
|
||||||
}
|
}
|
||||||
}).then((result) => {
|
}).then((result) => {
|
||||||
if (result) {
|
if (result) {
|
||||||
|
@ -103,7 +106,11 @@ class Index extends Component {
|
||||||
const url = `/projects/group_type_list.json`;
|
const url = `/projects/group_type_list.json`;
|
||||||
axios.get(url).then((result) => {
|
axios.get(url).then((result) => {
|
||||||
if (result && result.data) {
|
if (result && result.data) {
|
||||||
this.setTypeList(result.data, undefined)
|
result.data.unshift({
|
||||||
|
name:'全部语言',
|
||||||
|
id:0,
|
||||||
|
});
|
||||||
|
this.setTypeList(result.data, 0)
|
||||||
}
|
}
|
||||||
}).catch((error) => { })
|
}).catch((error) => { })
|
||||||
}
|
}
|
||||||
|
@ -112,7 +119,7 @@ class Index extends Component {
|
||||||
this.setState({
|
this.setState({
|
||||||
typeList: list.map((item, key) => {
|
typeList: list.map((item, key) => {
|
||||||
return (
|
return (
|
||||||
<li key={key} className={active_type && active_type === item.project_type ? 'active' : ''} onClick={() => this.changeType(`${item.project_type}`, list)}>
|
<li key={key} className={ parseInt(active_type) === item.id ? 'active' : ''} onClick={() => this.changeType(`${item.id}`, list)}>
|
||||||
<p>
|
<p>
|
||||||
<span className="font-16">{item.name}</span>
|
<span className="font-16">{item.name}</span>
|
||||||
<span className="color-blue">{item.projects_count}</span>
|
<span className="color-blue">{item.projects_count}</span>
|
||||||
|
@ -123,16 +130,16 @@ class Index extends Component {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 切换类型
|
// 切换语言类型
|
||||||
changeType = (type, list) => {
|
changeType = (id, list) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
isSpin: true,
|
isSpin: true,
|
||||||
project_type: type,
|
languageId: id,
|
||||||
search: undefined
|
search: undefined
|
||||||
})
|
})
|
||||||
this.setTypeList(list, type)
|
this.setTypeList(list, id);
|
||||||
const { page, limit, sort, category_id , languageId } = this.state;
|
const { page,sort, category_id} = this.state;
|
||||||
this.getListData(page, limit, undefined, sort, type, category_id , languageId);
|
this.getListData(page,undefined, sort,category_id , id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取类型
|
// 获取类型
|
||||||
|
@ -141,7 +148,11 @@ class Index extends Component {
|
||||||
|
|
||||||
axios.get(url).then((result) => {
|
axios.get(url).then((result) => {
|
||||||
if (result && result.data) {
|
if (result && result.data) {
|
||||||
this.setCategoryList(result.data, undefined);
|
result.data.unshift({
|
||||||
|
name:'全部类别',
|
||||||
|
id:0,
|
||||||
|
});
|
||||||
|
this.setCategoryList(result.data, 0);
|
||||||
}
|
}
|
||||||
}).catch((error) => { })
|
}).catch((error) => { })
|
||||||
}
|
}
|
||||||
|
@ -150,7 +161,7 @@ class Index extends Component {
|
||||||
this.setState({
|
this.setState({
|
||||||
categoryList: list.map((item, key) => {
|
categoryList: list.map((item, key) => {
|
||||||
return (
|
return (
|
||||||
<li key={key} className={active_id && parseInt(active_id) === item.id ? 'active' : ''} onClick={() => this.changeCategory(`${item.id}`, list)}>
|
<li key={key} className={ parseInt(active_id) === item.id ? 'active' : ''} onClick={() => this.changeCategory(`${item.id}`, list)}>
|
||||||
<p>
|
<p>
|
||||||
<span className="font-16">{item.name}</span>
|
<span className="font-16">{item.name}</span>
|
||||||
<span className="color-blue">{item.projects_count}</span>
|
<span className="color-blue">{item.projects_count}</span>
|
||||||
|
@ -167,8 +178,8 @@ class Index extends Component {
|
||||||
page: 1
|
page: 1
|
||||||
});
|
});
|
||||||
this.setCategoryList(list, id)
|
this.setCategoryList(list, id)
|
||||||
const { limit, sort, project_type , languageId } = this.state;
|
const { sort,languageId } = this.state;
|
||||||
this.getListData(1, limit, undefined, sort, project_type, id , languageId);
|
this.getListData(1,undefined, sort,id , languageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 排序
|
// 排序
|
||||||
|
@ -179,8 +190,8 @@ class Index extends Component {
|
||||||
search: undefined,
|
search: undefined,
|
||||||
isSpin: true
|
isSpin: true
|
||||||
})
|
})
|
||||||
const { limit, project_type, category_id , languageId } = this.state;
|
const {category_id , languageId } = this.state;
|
||||||
this.getListData(1, limit, undefined, e.key, project_type, category_id , languageId);
|
this.getListData(1,undefined, e.key,category_id , languageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 搜索
|
// 搜索
|
||||||
|
@ -192,8 +203,8 @@ class Index extends Component {
|
||||||
project_type: undefined,
|
project_type: undefined,
|
||||||
sort: "updated_on"
|
sort: "updated_on"
|
||||||
})
|
})
|
||||||
const { limit, sort, category_id , languageId } = this.state;
|
const {sort, category_id , languageId } = this.state;
|
||||||
this.getListData(1, limit, value, sort, undefined, category_id , languageId);
|
this.getListData(1,value, sort,category_id , languageId);
|
||||||
}
|
}
|
||||||
changeSearchValue = (e) => {
|
changeSearchValue = (e) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
|
@ -205,23 +216,14 @@ class Index extends Component {
|
||||||
this.setState({
|
this.setState({
|
||||||
page
|
page
|
||||||
})
|
})
|
||||||
const { limit, search, sort, project_type, category_id , languageId } = this.state;
|
const {search, sort,category_id , languageId } = this.state;
|
||||||
this.getListData(page, limit, search, sort, project_type, category_id , languageId);
|
this.getListData(page,search, sort, category_id , languageId);
|
||||||
}
|
}
|
||||||
|
|
||||||
getoDetail=(login,identifier)=>{
|
getoDetail=(login,identifier)=>{
|
||||||
this.props.history.push(`/projects/${login}/${identifier}`);
|
this.props.history.push(`/projects/${login}/${identifier}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 选择语言类别
|
|
||||||
changeLanguage=(e)=>{
|
|
||||||
this.setState({
|
|
||||||
isSpin:true,
|
|
||||||
languageId:e === 0 ?undefined:e
|
|
||||||
})
|
|
||||||
const { page, limit, sort , project_type , category_id } = this.state;
|
|
||||||
this.getListData(page, limit, undefined, sort, project_type, category_id ,e === 0 ?undefined:e);
|
|
||||||
}
|
|
||||||
|
|
||||||
menu =()=> {
|
menu =()=> {
|
||||||
return(
|
return(
|
||||||
|
@ -255,15 +257,14 @@ class Index extends Component {
|
||||||
render() {
|
render() {
|
||||||
const { current_user } = this.props;
|
const { current_user } = this.props;
|
||||||
|
|
||||||
const { projectsList , recommendList , languageList , languageId ,
|
const { projectsList , isSpin , total , search , limit , page , typeList , categoryList } = this.state;
|
||||||
isSpin, total, search, limit, page, typeList, categoryList } = this.state;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<p className="t_project_banner">
|
<p className="t_project_banner">
|
||||||
<img src={banner} width="100%" alt=""/>
|
<img src={banner} width="100%" alt=""/>
|
||||||
</p>
|
</p>
|
||||||
{
|
{/* {
|
||||||
recommendList && recommendList.length>0 &&
|
recommendList && recommendList.length>0 &&
|
||||||
<div className="recommandProjects">
|
<div className="recommandProjects">
|
||||||
{
|
{
|
||||||
|
@ -271,7 +272,7 @@ class Index extends Component {
|
||||||
return(
|
return(
|
||||||
<div onClick={()=>this.getoDetail(item.author && item.author.login,item.identifier)}>
|
<div onClick={()=>this.getoDetail(item.author && item.author.login,item.identifier)}>
|
||||||
<div className="mainInfo">
|
<div className="mainInfo">
|
||||||
<img src={getImageUrl(`/${item.author && item.author.image_url}`)} alt=""/>
|
<img src={getUrl(`/images/${item.author && item.author.image_url}`)} alt=""/>
|
||||||
<p className="school">{item.name}</p>
|
<p className="school">{item.name}</p>
|
||||||
<p className="name">{item.author && item.author.name}</p>
|
<p className="name">{item.author && item.author.name}</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -285,44 +286,29 @@ class Index extends Component {
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
*/}
|
||||||
<div className="ProjectListIndex">
|
<div className="ProjectListIndex">
|
||||||
<div className="list-left">
|
|
||||||
|
<Affix className="affix-list-left" offsetTop={90}>
|
||||||
|
<div className="affix-list-content">
|
||||||
<ul className="list-l-Menu">
|
<ul className="list-l-Menu">
|
||||||
<li className="MenuTitle"><i className="iconfont icon-xiangmuleixing color-grey-9 font-15 mr5"></i>项目类型</li>
|
<li className="MenuTitle" onClick={() => {this.getType();this.changeType(undefined, this.state.typeList);}}>
|
||||||
{typeList}
|
<span><i className="iconfont icon-bianchengyuyan color-grey-9 font-15 mr5"></i>
|
||||||
|
语言</span></li>
|
||||||
|
<div className="list-affix">{typeList}</div>
|
||||||
</ul>
|
</ul>
|
||||||
<ul className="list-l-Menu">
|
<ul className="list-l-Menu">
|
||||||
<li className="MenuTitle"><i className="iconfont icon-xiangmuleibie color-grey-9 font-15 mr5"></i>项目类别</li>
|
<li className="MenuTitle" onClick={() => {this.getCategory();this.changeCategory(undefined, this.state.categoryList);}}>
|
||||||
{categoryList}
|
<span><i className="iconfont icon-xiangmuleibie color-grey-9 font-15 mr5"></i>项目类别</span></li>
|
||||||
|
<div className="list-affix">{categoryList}</div>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
</Affix>
|
||||||
|
|
||||||
<div className="list-right boxShandow radius-2" style={{padding:0}}>
|
<div className="list-right boxShandow radius-2" style={{padding:0}}>
|
||||||
<Spin spinning={isSpin}>
|
<Spin spinning={isSpin}>
|
||||||
<div className="list-r-operation">
|
<div className="list-r-operation">
|
||||||
<div>
|
<div>
|
||||||
<Select
|
|
||||||
showSearch
|
|
||||||
placeholder="请选择语言"
|
|
||||||
style={{width:"150px",marginRight:"20px"}}
|
|
||||||
size={"large"}
|
|
||||||
onChange={this.changeLanguage}
|
|
||||||
value={languageId}
|
|
||||||
allowClear={true}
|
|
||||||
optionFilterProp="children"
|
|
||||||
filterOption={(input,option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
|
|
||||||
>
|
|
||||||
<Select.Option key={0} value={0}>请选择语言</Select.Option>
|
|
||||||
{
|
|
||||||
languageList && languageList.length>0 && languageList.map((item,key)=>{
|
|
||||||
return(
|
|
||||||
<Select.Option key={item.id} value={item.id}>
|
|
||||||
{item.name}
|
|
||||||
</Select.Option>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</Select>
|
|
||||||
<Search
|
<Search
|
||||||
placeholder="输入项目名称关键字进行搜索"
|
placeholder="输入项目名称关键字进行搜索"
|
||||||
enterButton="搜索"
|
enterButton="搜索"
|
||||||
|
@ -350,7 +336,7 @@ class Index extends Component {
|
||||||
</Popover>
|
</Popover>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ListItem {...this.props} {...this.state} projects={projectsList}></ListItem>
|
<ListItem {...this.props} {...this.state} projects={projectsList} getListData={this.getListData}></ListItem>
|
||||||
{this.pagination(total,limit,page)}
|
{this.pagination(total,limit,page)}
|
||||||
</Spin>
|
</Spin>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
width: 220px;
|
width: 220px;
|
||||||
margin-right: 25px;
|
margin-right: 25px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border: 1px solid #eee;
|
|
||||||
&:last-child{
|
&:last-child{
|
||||||
margin-right: 0px;
|
margin-right: 0px;
|
||||||
}
|
}
|
||||||
|
@ -73,243 +72,15 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.singleBtn{
|
||||||
// coderDepot
|
display: inline-block;
|
||||||
.Panels{
|
.ant-upload-list-item{
|
||||||
max-width: 1200px;
|
position: absolute;
|
||||||
margin: 0 auto;
|
bottom: 0px;
|
||||||
.panelmenu{
|
width: 100%;
|
||||||
padding-top:30px;
|
left: 0px;
|
||||||
}
|
.ant-upload-list-item-name{
|
||||||
.addOptionBtn{
|
text-align: left;
|
||||||
height: 32px;
|
|
||||||
line-height: 30px;
|
|
||||||
display: flex;
|
|
||||||
border:1px solid #d9d9d9;
|
|
||||||
border-radius: 2px;
|
|
||||||
a{
|
|
||||||
padding:0px 13px;
|
|
||||||
color: rgba(0, 0, 0, 0.65);
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
}
|
||||||
& > a:first-child{
|
|
||||||
border-right: 1px solid #d9d9d9;
|
|
||||||
}
|
|
||||||
& > a:last-child{
|
|
||||||
border-right: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.infoCount{
|
|
||||||
display: inline-block;
|
|
||||||
padding:0px 5px;
|
|
||||||
height: 16px;
|
|
||||||
line-height: 16px;
|
|
||||||
background-color: #eee;
|
|
||||||
color:#999;
|
|
||||||
border-radius: 12px;
|
|
||||||
margin-left: 10px;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
.attrPerson{
|
|
||||||
padding-top: 15px;
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
a{
|
|
||||||
margin: 10px 10px 0px 0px;
|
|
||||||
img{
|
|
||||||
border-radius: 50%;
|
|
||||||
width: 35px;
|
|
||||||
height: 35px;
|
|
||||||
}
|
|
||||||
&:nth-child(6){
|
|
||||||
margin-right: 0px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.progress{
|
|
||||||
display: flex;
|
|
||||||
border-radius: 10px;
|
|
||||||
height: 7px;
|
|
||||||
margin-top: 12px;
|
|
||||||
span{
|
|
||||||
border-left: 1px solid #fff;
|
|
||||||
&:first-child{
|
|
||||||
border-left: none;
|
|
||||||
border-radius: 10px 0px 0px 10px;
|
|
||||||
}
|
|
||||||
&:last-child{
|
|
||||||
border-radius: 0px 10px 10px 0px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.progresstip{
|
|
||||||
margin-top: 15px;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
i.zero{
|
|
||||||
position: absolute;
|
|
||||||
display: block;
|
|
||||||
border-radius: 50%;
|
|
||||||
height: 8px;
|
|
||||||
width: 8px;
|
|
||||||
left: 0px;
|
|
||||||
top:10px
|
|
||||||
}
|
|
||||||
&>span{
|
|
||||||
padding-left: 15px;
|
|
||||||
position: relative;
|
|
||||||
min-width: 33.5%;
|
|
||||||
span{
|
|
||||||
color: #666;
|
|
||||||
&:last-child{
|
|
||||||
color: #999;
|
|
||||||
margin-left: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.listtable{
|
|
||||||
margin-top: 20px;
|
|
||||||
border:1px solid #d9d9d9;
|
|
||||||
border-radius: 4px;
|
|
||||||
.listtablehead{
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: flex-start;
|
|
||||||
border-bottom: 1px solid #d9d9d9;
|
|
||||||
padding:7px 20px;
|
|
||||||
border-radius: 4px 4px 0px 0px;
|
|
||||||
background-color: #FAFBFC;
|
|
||||||
.ellipsistxt{
|
|
||||||
margin-left: 13px;
|
|
||||||
line-height:18px;
|
|
||||||
margin-top:6px;
|
|
||||||
flex:1;
|
|
||||||
width: 0;
|
|
||||||
color: #666;
|
|
||||||
&>p{
|
|
||||||
word-break:break-all;
|
|
||||||
}
|
|
||||||
&.hide{
|
|
||||||
height: 18px;
|
|
||||||
overflow: hidden;
|
|
||||||
position: relative;
|
|
||||||
padding-right:8px;
|
|
||||||
}
|
|
||||||
&.hide::after{
|
|
||||||
position: absolute;
|
|
||||||
right: 0px;
|
|
||||||
bottom: 0px;
|
|
||||||
content:"...";
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.ellipsis{
|
|
||||||
margin-left: 8px;
|
|
||||||
cursor: pointer;
|
|
||||||
border-radius: 2px;
|
|
||||||
background-color: #c1c1c1;
|
|
||||||
padding:0px 4px;
|
|
||||||
height: 14px;
|
|
||||||
line-height: 14px;
|
|
||||||
margin-top: 9px;
|
|
||||||
i{
|
|
||||||
font-size: 15px!important;
|
|
||||||
color: #fff;
|
|
||||||
height: 14px;
|
|
||||||
line-height: 14px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.listtablebody{
|
|
||||||
li.listtablepath{
|
|
||||||
a{color: #40a9ff;}
|
|
||||||
p{
|
|
||||||
margin-bottom: 0px!important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
li{
|
|
||||||
height: 42px;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
border-bottom: 1px solid #d9d9d9;
|
|
||||||
padding:0px 20px 0px 24px;
|
|
||||||
& > span:first-child{
|
|
||||||
width: 30%;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
& > span:nth-child(2){
|
|
||||||
width: 60%;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
& > span:nth-child(3){
|
|
||||||
width: 10%;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&> li:last-child{
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.drawerBtn{
|
|
||||||
position: fixed;
|
|
||||||
left: -13px;
|
|
||||||
border:1px solid rgb(207,205,223);
|
|
||||||
width: 34px;
|
|
||||||
border-radius: 0px 12px 12px 0px;
|
|
||||||
height: 70px;
|
|
||||||
top:50%;
|
|
||||||
margin-top: -35px;
|
|
||||||
cursor: pointer;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: flex-end;
|
|
||||||
justify-content: center;
|
|
||||||
&:hover{
|
|
||||||
box-shadow: 1px 0px 7px rgba(0,0,0,0.1);
|
|
||||||
}
|
|
||||||
span{
|
|
||||||
writing-mode: vertical-lr;
|
|
||||||
color: #202429;
|
|
||||||
width: 25px;
|
|
||||||
}
|
|
||||||
i{
|
|
||||||
color: #24292e;
|
|
||||||
height: 18px;
|
|
||||||
line-height: 18px;
|
|
||||||
width: 18px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.downMenu{
|
|
||||||
box-shadow: 0px 0px 9px rgba(134, 134, 134,0.4);
|
|
||||||
background-color: #fff;
|
|
||||||
.ant-menu-vertical .ant-menu-item:hover{
|
|
||||||
background-color: #e6f7ff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.menuslist{
|
|
||||||
max-height: 200px;
|
|
||||||
overflow-y: auto;
|
|
||||||
padding:10px 15px;
|
|
||||||
border-radius: 4px;
|
|
||||||
.ant-dropdown-menu-item{
|
|
||||||
border-radius: 8px;
|
|
||||||
text-align: left!important;
|
|
||||||
a{
|
|
||||||
width: 350px;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.ant-dropdown-menu-item.active{
|
|
||||||
background-color: #e6f7ff;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -6,72 +6,123 @@ import '../css/index.scss';
|
||||||
import Nodata from '../Nodata';
|
import Nodata from '../Nodata';
|
||||||
import './list.css';
|
import './list.css';
|
||||||
import img_parise from '../Images/parise.png';
|
import img_parise from '../Images/parise.png';
|
||||||
|
import SpecialModal from './SpecialModal';
|
||||||
|
|
||||||
class IndexItem extends Component {
|
class IndexItem extends Component {
|
||||||
|
constructor(props){
|
||||||
|
super(props);
|
||||||
|
this.state={
|
||||||
|
visible:false,
|
||||||
|
user_apply_signatures:[],
|
||||||
|
project_id:undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
TurnToDetail = (login, url) => {
|
TurnToDetail = (login, url) => {
|
||||||
this.props.history.push({
|
this.props.history.push({
|
||||||
pathname: url,
|
pathname: url,
|
||||||
state: login
|
state: login
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* link:跳转到详情的地址
|
||||||
|
* user_apply_signatures:是否已经发送访问特殊开源项目的文件
|
||||||
|
* project_id:项目id
|
||||||
|
* is_secret:是否是特殊开源许可证项目
|
||||||
|
* id:创建者login
|
||||||
|
* is_member:是否是项目成员(如果是项目成员可以直接进入项目)
|
||||||
|
* */
|
||||||
|
projectHref=(link , user_apply_signatures,project_id,is_secret , id,is_member)=>{
|
||||||
|
const { user , showLoginDialog } = this.props;
|
||||||
|
if(is_secret && (!user || (user && !user.login))){
|
||||||
|
showLoginDialog();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let signa = user_apply_signatures && user_apply_signatures[0];
|
||||||
|
if((is_secret && !is_member && (!signa || (signa && signa.status !== "passed"))) && user.login !== id ){
|
||||||
|
this.setState({
|
||||||
|
visible:true,
|
||||||
|
user_apply_signatures:user_apply_signatures.length>0 ? user_apply_signatures[0] : undefined,
|
||||||
|
project_id
|
||||||
|
})
|
||||||
|
}else{
|
||||||
|
this.props.history.push(link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hideModal=()=>{
|
||||||
|
this.setState({
|
||||||
|
visible:false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
sureModal=()=>{
|
||||||
|
this.hideModal();
|
||||||
|
const { getListData } = this.props;
|
||||||
|
getListData && getListData(1);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { projects } = this.props;
|
const { projects } = this.props;
|
||||||
return (
|
const { visible , user_apply_signatures , project_id } = this.state;
|
||||||
<div className="project-list minH-670">
|
const renderList = (
|
||||||
{ projects && projects.length > 0 ? projects.map((item, key) => {
|
projects && projects.length > 0 ? projects.map((item, key) => {
|
||||||
return (
|
return (
|
||||||
<div className="p-r-Item" key={key}>
|
<div className="p-r-Item" key={key}>
|
||||||
{
|
{
|
||||||
item.platform === "educoder" ?
|
item.platform === "educoder" ?
|
||||||
<a href="javascript:void(0)" style={{cursor:"default"}} className="show-user-link">
|
<a style={{cursor:"default"}} className="show-user-link">
|
||||||
<img className="p-r-photo" alt="" src={item.author && item.author.image_url} ></img>
|
<img className="p-r-photo" alt="" src={item.author && item.author.image_url} ></img>
|
||||||
</a>
|
</a>
|
||||||
:
|
:
|
||||||
<Link to={item.author && (item.author.type === "Organization" ? `/organize/${item.author.login}`:`/users/${item.author.login}`)} className="show-user-link">
|
<Link to={`/users/${item.author.login}`} className="show-user-link">
|
||||||
<img className="p-r-photo" alt="" src={getImageUrl(`/${item.author && item.author.image_url}`)} ></img>
|
<img className="p-r-photo" alt="" src={getImageUrl(`${item.author && item.author.image_url}`)} ></img>
|
||||||
</Link>
|
</Link>
|
||||||
}
|
}
|
||||||
<div className="p-r-Infos">
|
<div className="p-r-Infos">
|
||||||
<div className="p-r-name">
|
<div className="p-r-name">
|
||||||
<Link to={`/projects/${item.author.login}/${item.identifier}`} className="hide-1 color-grey-3 font-18 task-hide " style={{ whiteSpace: "wrap", display: 'flex', width: 400 }}>
|
<a onClick={()=>this.projectHref(`/projects/${item.author.login}/${item.identifier}`,item.user_apply_signatures, item.id,item.is_secret,item.author.login,item.is_member)} className="hide-1 color-grey-3 font-18 task-hide fwt-500 " style={{ whiteSpace: "wrap", display: 'flex', width: 400 }}>
|
||||||
{item.author.name}/{item.name}
|
{item.author.name}/{item.name}
|
||||||
{
|
{
|
||||||
item.forked_from_project_id ?
|
item.forked_from_project_id ?
|
||||||
<span className="ml5">
|
|
||||||
<i className="iconfont icon-fork font-18 color-orange" />
|
|
||||||
</span>
|
|
||||||
: ""
|
|
||||||
}
|
|
||||||
{
|
|
||||||
item.type && item.type !== 0 ?
|
|
||||||
item.type === 2 ?
|
|
||||||
<Tooltip title="该项目是一个镜像" className="ml5">
|
|
||||||
<i className="iconfont icon-banbenku font-18 color-green" />
|
|
||||||
</Tooltip>:
|
|
||||||
<span className="ml5">
|
<span className="ml5">
|
||||||
<i className="iconfont icon-jingxiang font-18 color-green" />
|
<i className="iconfont icon-fork font-18 color-orange" />
|
||||||
</span>:""
|
</span>
|
||||||
}
|
: ""
|
||||||
</Link>
|
}
|
||||||
<span className="p-r-tags">
|
{
|
||||||
<span className="pariseTag"><img src={img_parise} alt="" className="pariseImg" />赞 {item.praises_count}</span>
|
item.type && item.type !== 0 ?
|
||||||
<span><i className="iconfont icon-fork mr3 font-16" style={{ color: "#1B8FFF" }} />fork {item.forked_count}</span>
|
item.type === 2 ?
|
||||||
</span>
|
<Tooltip title="该项目是一个镜像" className="ml5">
|
||||||
</div>
|
<i className="iconfont icon-banbenku font-18 color-green" />
|
||||||
<p className="break_word task-hide-2 mt10" style={{ maxHeight: "44px",lineHeight:"22px" }}>{item.description}</p>
|
</Tooltip>:
|
||||||
|
<span className="ml5">
|
||||||
|
<i className="iconfont icon-jingxiang font-18 color-green" />
|
||||||
|
</span>:""
|
||||||
|
}
|
||||||
|
</a>
|
||||||
|
<span className="p-r-tags">
|
||||||
|
<span className="pariseTag"><img src={img_parise} alt="" className="pariseImg" />赞 {item.praises_count}</span>
|
||||||
|
<span><i className="iconfont icon-fork mr3 font-16" style={{ color: "#1B8FFF" }} />fork {item.forked_count}</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<p className="break_word task-hide-2 mt8 color-grey-3 " style={{ maxHeight: "44px",lineHeight:"22px" }}>{item.description}</p>
|
||||||
|
|
||||||
<div className="p-r-about">
|
<div className="p-r-about">
|
||||||
<span className="p-r-detail">
|
<span className="p-r-detail">
|
||||||
{/* <span><label>浏览量:</label>{item.visits}</span> */}
|
{/* <span><label>浏览量:</label>{item.visits}</span> */}
|
||||||
{/* {item.category && item.category.id && <span>{item.category.name}</span>} */}
|
{/* {item.category && item.category.id && <span>{item.category.name}</span>} */}
|
||||||
{item.last_update_time ? <span><label>更新于</label>{item.time_ago}</span> : ""}
|
{item.last_update_time ? <span><label>更新于</label>{item.time_ago}</span> : ""}
|
||||||
{item.language && item.language.id ? <span className="color-grey-3">{item.language.name}</span> : ""}
|
{item.language && item.language.id ? <span className="color-grey-3">{item.language.name}</span> : ""}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
</div>
|
||||||
}) : <Nodata _html="暂无数据~"></Nodata>}
|
)
|
||||||
|
}) : <Nodata _html="暂无数据~"></Nodata>
|
||||||
|
)
|
||||||
|
return (
|
||||||
|
<div className="project-list minH-670">
|
||||||
|
<SpecialModal {...this.props} visible={visible} hideModal={this.hideModal} user_apply_signatures={user_apply_signatures} project_id={project_id} sureModal={this.sureModal}></SpecialModal>
|
||||||
|
{renderList}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
import React , { useEffect , useState } from 'react';
|
||||||
|
import { Modal } from 'antd';
|
||||||
|
import UploadSingle from '../Upload/single';
|
||||||
|
import './Index.scss';
|
||||||
|
import axios from 'axios';
|
||||||
|
import { getUrl } from 'educoder';
|
||||||
|
|
||||||
|
function SpecialModal({ visible , hideModal , sureModal , showNotification , user_apply_signatures , project_id }){
|
||||||
|
const [ id ,setId ] = useState(undefined);
|
||||||
|
|
||||||
|
|
||||||
|
function loadFunc(id){
|
||||||
|
setId(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
function sure(){
|
||||||
|
if(!user_apply_signatures || (user_apply_signatures && user_apply_signatures.status !== "waiting")){
|
||||||
|
if(!id || (id && id.length === 0)){
|
||||||
|
showNotification("请先提交文件进行审核!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const url = `/apply_signatures.json`;
|
||||||
|
axios.post(url,{
|
||||||
|
attachment_id:id,
|
||||||
|
project_id:project_id
|
||||||
|
}).then(result=>{
|
||||||
|
if(result && result.data.id){
|
||||||
|
showNotification("已提交文件,正在等待审核!");
|
||||||
|
sureModal();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}else{
|
||||||
|
sureModal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(
|
||||||
|
<Modal title="提示" visible={visible} closable={false} onCancel={hideModal} onOk={sure}>
|
||||||
|
{
|
||||||
|
!user_apply_signatures || (user_apply_signatures && user_apply_signatures.status !== "waiting") ?
|
||||||
|
<div style={{width:"420px",textAlign:'center',margin:"0 auto",paddingBottom:"30px",position:"relative"}}>
|
||||||
|
<div>该项目为私有项目,请先<a href={getUrl(`/api/apply_signatures/template_file`)} className="color-blue">下载</a>开源协议,阅读并填写<br/>相关信息后,将协议<UploadSingle size={"5"} load={loadFunc} showNotification={showNotification} className={'singleBtn'}><span className="color-blue" style={{cursor:"pointer"}}>上传</span></UploadSingle>,平台审核通过后即可进入当前项目</div>
|
||||||
|
</div>
|
||||||
|
:
|
||||||
|
<p style={{textAlign:'center'}}>您上传的文件正在审核中,通过后才能访问当前项目</p>
|
||||||
|
}
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default SpecialModal;
|
|
@ -18,17 +18,18 @@
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
.list-left > div{
|
.affix-list-left{
|
||||||
border:1px solid #eee;
|
width: 26%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
.list-left > div.bgcF{
|
.affix-list-content{
|
||||||
border:none;
|
padding-right:20px;
|
||||||
}
|
}
|
||||||
.list-right{
|
.list-right{
|
||||||
width:74%;
|
width:74%;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
padding:10px;
|
padding:10px;
|
||||||
border:1px solid #eee;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -215,9 +216,7 @@
|
||||||
}
|
}
|
||||||
/* -----------详情------------ */
|
/* -----------详情------------ */
|
||||||
.detailHeader-wrapper{
|
.detailHeader-wrapper{
|
||||||
background-color:#FAFBFC;
|
background:linear-gradient(82deg,rgba(82,91,215,1) 0%,rgba(34,24,171,1) 100%);
|
||||||
/* background: url(../Images/forgeBanner.jpg) no-repeat center; */
|
|
||||||
/* background-size:cover; */
|
|
||||||
}
|
}
|
||||||
.headerMenu-wrapper{
|
.headerMenu-wrapper{
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
@ -229,36 +228,42 @@
|
||||||
text-align: center;
|
text-align: center;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
line-height: 28px;
|
line-height: 28px;
|
||||||
margin-right: 40px;
|
border:1px solid transparent;
|
||||||
|
}
|
||||||
|
.headerMenu-wrapper{
|
||||||
|
font-size: 16px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
.headerMenu-wrapper li{
|
||||||
|
padding:0px 18px;
|
||||||
|
position: relative;
|
||||||
|
text-align: center;
|
||||||
|
height: 30px;
|
||||||
|
line-height: 30px;
|
||||||
}
|
}
|
||||||
.headerMenu-wrapper li a{
|
.headerMenu-wrapper li a{
|
||||||
color: #666;
|
color: #fff;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
.headerMenu-wrapper li a > img{
|
.headerMenu-wrapper li a > img{
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
}
|
}
|
||||||
.headerMenu-wrapper li a > span.num{
|
.headerMenu-wrapper li a > span{
|
||||||
height: 28px;
|
display: block;
|
||||||
line-height: 29px;
|
margin-left: 5px;
|
||||||
margin-left: 8px;
|
font-size: 16px;
|
||||||
font-size: 12px;
|
|
||||||
color: #2878FF;
|
|
||||||
float: right;
|
|
||||||
}
|
}
|
||||||
.headerMenu-wrapper li.active::after{
|
.headerMenu-wrapper li.active{
|
||||||
position: absolute;
|
border-radius: 15px;
|
||||||
bottom:0px;
|
border:1px solid #71A6FF;
|
||||||
height:2px;
|
|
||||||
background-color: #5091FF;
|
|
||||||
content:'';
|
|
||||||
left: 0px;
|
|
||||||
width:100%;
|
|
||||||
}
|
}
|
||||||
.detail_tag_btn{
|
.detail_tag_btn{
|
||||||
height:26px;
|
height:26px;
|
||||||
line-height: 26px;
|
line-height: 26px;
|
||||||
border-radius:5px;
|
border-radius:5px;
|
||||||
border:1px solid #f1f1f1;
|
border:1px solid #71A6FF;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-left: 30px
|
margin-left: 30px
|
||||||
|
@ -266,21 +271,29 @@
|
||||||
.ant-tooltip {
|
.ant-tooltip {
|
||||||
max-width: fit-content!important;
|
max-width: fit-content!important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.detail_tag_btn_name{
|
.detail_tag_btn_name{
|
||||||
padding:0px 10px;
|
padding:0px 10px;
|
||||||
color: #666!important;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
color: #fff;
|
||||||
}
|
}
|
||||||
.detail_tag_btn_name img{
|
.detail_tag_btn_name img{
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
.detail_tag_btn_count{
|
.detail_tag_btn_count{
|
||||||
padding:0px 10px;
|
padding:0px 10px;
|
||||||
background: #fff;
|
color: #fff !important;
|
||||||
|
background: rgba(255,255,255,0.2);
|
||||||
border-radius: 0px 4px 4px 0px;
|
border-radius: 0px 4px 4px 0px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
height:100%;
|
}
|
||||||
|
.detail_tag_btn_count:hover{
|
||||||
|
/* color: #1C91FF !important; */
|
||||||
|
background: rgba(255,255,255,0.5);
|
||||||
}
|
}
|
||||||
.files-md{
|
.files-md{
|
||||||
|
border:1px solid #eee;
|
||||||
padding:20px;
|
padding:20px;
|
||||||
}
|
}
|
||||||
/* 详情-代码 */
|
/* 详情-代码 */
|
||||||
|
@ -430,11 +443,18 @@
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
/* 分支 */
|
/* 分支 */
|
||||||
|
.branchTable{
|
||||||
|
border:1px solid #f7f7f7;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
.branchTitle{
|
.branchTitle{
|
||||||
padding:8px 10px;
|
padding:12px 10px;
|
||||||
color: #333;
|
color: #333;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
border-bottom: 1px solid #d9d9d9;
|
background:rgba(241,248,255,1);
|
||||||
|
}
|
||||||
|
.branchUl{
|
||||||
|
padding:0px 30px;
|
||||||
}
|
}
|
||||||
.branchUl li{
|
.branchUl li{
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -547,19 +567,17 @@
|
||||||
}
|
}
|
||||||
.commonBox{
|
.commonBox{
|
||||||
border:1px solid #ddd;
|
border:1px solid #ddd;
|
||||||
margin-top: 30px;
|
margin-top: 25px;
|
||||||
border-radius: 4px;
|
|
||||||
}
|
}
|
||||||
.commonBox .commonBox-title{
|
.commonBox .commonBox-title{
|
||||||
padding:0px 20px;
|
padding:0px 15px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
background: #FAFBFC;/* F1F8FF */
|
background: #F1F8FF;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
height: 45px;
|
height: 50px;
|
||||||
line-height: 45px;
|
line-height: 50px;
|
||||||
border-bottom: 1px solid #d9d9d9;
|
border-bottom: 1px solid #ddd;
|
||||||
border-radius: 4px 4px 0px 0px;
|
|
||||||
}
|
}
|
||||||
.synchronism{
|
.synchronism{
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -576,7 +594,7 @@
|
||||||
.commonBox .commonBox-info{
|
.commonBox .commonBox-info{
|
||||||
padding:20px 15px;
|
padding:20px 15px;
|
||||||
}
|
}
|
||||||
.commonBox-title-read{vertical-align: middle;color: #666;}
|
.commonBox-title-read{vertical-align: middle;}
|
||||||
|
|
||||||
@media screen and (max-width: 370px){
|
@media screen and (max-width: 370px){
|
||||||
.p-r-tags,.p-r-btn{
|
.p-r-tags,.p-r-btn{
|
||||||
|
@ -666,7 +684,7 @@ a.color-grey-ccc:hover{
|
||||||
|
|
||||||
.commitList{
|
.commitList{
|
||||||
padding:0px 30px;
|
padding:0px 30px;
|
||||||
min-height: 400px;
|
min-height: 450px;
|
||||||
}
|
}
|
||||||
.commitList > div{
|
.commitList > div{
|
||||||
border-bottom: 1px solid #EEEEEE;
|
border-bottom: 1px solid #EEEEEE;
|
||||||
|
|
|
@ -1,80 +0,0 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
|
||||||
import { WhiteBack , AlignCenter } from '../../Component/layout';
|
|
||||||
import "./sub.scss";
|
|
||||||
import axios from 'axios';
|
|
||||||
import { Pagination , Spin } from 'antd';
|
|
||||||
import NoData from '../../Nodata';
|
|
||||||
import { getImageUrl } from 'educoder';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
|
|
||||||
function Contribute(props){
|
|
||||||
const [ list , setList ] = useState(undefined);
|
|
||||||
const [ page , setPage ] = useState(1);
|
|
||||||
const [ total , setTotal ] = useState(0);
|
|
||||||
const [ isSpin , setIsSpin ] = useState(true);
|
|
||||||
|
|
||||||
const owner = props.match.params.owner;
|
|
||||||
const projectsId = props.match.params.projectsId;
|
|
||||||
const LIMIT = 20;
|
|
||||||
useEffect(()=>{
|
|
||||||
if(owner && projectsId){
|
|
||||||
getData();
|
|
||||||
}
|
|
||||||
},[owner,projectsId,page]);
|
|
||||||
|
|
||||||
function getData(){
|
|
||||||
setIsSpin(true);
|
|
||||||
const url = `/${owner}/${projectsId}/contributors.json`;
|
|
||||||
axios.get(url,{
|
|
||||||
params:{
|
|
||||||
limit:LIMIT,page,
|
|
||||||
}
|
|
||||||
}).then(result=>{
|
|
||||||
if(result){
|
|
||||||
setList(result.data.contributors);
|
|
||||||
setTotal(result.data.total_count);
|
|
||||||
setIsSpin(false);
|
|
||||||
}
|
|
||||||
}).catch(error=>{})
|
|
||||||
}
|
|
||||||
|
|
||||||
return(
|
|
||||||
<WhiteBack>
|
|
||||||
<Spin spinning={isSpin}>
|
|
||||||
<div className="boxPanel">
|
|
||||||
<p className="font-18 mb20">贡献者列表</p>
|
|
||||||
{
|
|
||||||
list && list.length > 0 ?
|
|
||||||
<div className="contrbuteList">
|
|
||||||
{
|
|
||||||
list.map((item,key)=>{
|
|
||||||
return(
|
|
||||||
<AlignCenter>
|
|
||||||
<img alt="" style={{borderRadius:"50%",marginRight:"10px"}} src={getImageUrl(`/${item.image_url}`)} width="50px" height="50px"/>
|
|
||||||
<div>
|
|
||||||
<Link to={`/users/${item.login}`} className="font-16">{item.name}</Link>
|
|
||||||
<p className="font-12 color-grey-9">提交{item.contributions}次</p>
|
|
||||||
</div>
|
|
||||||
</AlignCenter>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
:""
|
|
||||||
}
|
|
||||||
{
|
|
||||||
list && list.length === 0 ? <NoData _html="暂无贡献者" />:""
|
|
||||||
}
|
|
||||||
{
|
|
||||||
total > LIMIT ?
|
|
||||||
<div className="mt20 edu-txt-center">
|
|
||||||
<Pagination simple pageSize={LIMIT} onChange={(p)=>{setPage(p)}} current={page} total={total}/>
|
|
||||||
</div>
|
|
||||||
:""
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</Spin>
|
|
||||||
</WhiteBack>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export default Contribute;
|
|
|
@ -1,127 +0,0 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
|
||||||
import { Skeleton , Tooltip} from 'antd';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
|
|
||||||
function DetailBanner({ history,list , owner , projectsId , isManager , url , pathname , state , urlFlag , projectDetail , platform ,open_devops }){
|
|
||||||
const [ menuName , setMenuName ] = useState(undefined);
|
|
||||||
useEffect(()=>{
|
|
||||||
if(list){
|
|
||||||
// 没有资源库banner但是通过连接进资源库页面时
|
|
||||||
if(pathname && pathname==="source"){
|
|
||||||
let a = list.filter(item=>item.menu_name === "resources");
|
|
||||||
if(a && a.length === 0){
|
|
||||||
history.push(`/projects/${owner}/${projectsId}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setMenuName(list);
|
|
||||||
}
|
|
||||||
},[list]);
|
|
||||||
return(
|
|
||||||
<div className="f-wrap-between mt15">
|
|
||||||
{
|
|
||||||
menuName && projectDetail ?
|
|
||||||
<ul className="headerMenu-wrapper">
|
|
||||||
{
|
|
||||||
menuName.map((item,key)=>{
|
|
||||||
return(
|
|
||||||
<React.Fragment>
|
|
||||||
{
|
|
||||||
item.menu_name === "home" &&
|
|
||||||
<li className={pathname==="about" ? "active" : ""}>
|
|
||||||
<Link to={{ pathname: `/projects/${owner}/${projectsId}/about`, state }}>
|
|
||||||
<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>
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
}
|
|
||||||
{
|
|
||||||
item.menu_name === "code" &&
|
|
||||||
<li className={(pathname==="" || urlFlag) ? "active" : ""}>
|
|
||||||
<Link to={{ pathname: `/projects/${owner}/${projectsId}`, state }}>
|
|
||||||
<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>
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
}
|
|
||||||
{
|
|
||||||
item.menu_name === "issues" &&
|
|
||||||
<li className={pathname==="issues" ? "active" : ""}>
|
|
||||||
<Tooltip title="易修是Issue的中文名,即问题列表" placement="bottom">
|
|
||||||
<Link to={{ pathname: `/projects/${owner}/${projectsId}/issues`, state }}>
|
|
||||||
<i className={pathname==="issues" ? "iconfont icon-renwu color-grey-3 mr5 font-14":"iconfont icon-renwu color-grey-6 font-14 mr5"}></i>
|
|
||||||
<span>易修</span>
|
|
||||||
{projectDetail && projectDetail.issues_count ? <span className="num">{projectDetail.issues_count}</span> : ""}
|
|
||||||
</Link>
|
|
||||||
</Tooltip>
|
|
||||||
</li>
|
|
||||||
}
|
|
||||||
{
|
|
||||||
item.menu_name === "pulls" && projectDetail && parseInt(projectDetail.type) !== 2 && platform ?
|
|
||||||
<li className={pathname==="pulls" ? "active" : ""}>
|
|
||||||
<Link to={{ pathname: `/projects/${owner}/${projectsId}/pulls`, state }}>
|
|
||||||
<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>
|
|
||||||
{projectDetail && projectDetail.pull_requests_count ? <span className="num">{projectDetail.pull_requests_count}</span> : ""}
|
|
||||||
</Link>
|
|
||||||
</li>:""
|
|
||||||
}
|
|
||||||
{
|
|
||||||
item.menu_name === "devops" && platform ?
|
|
||||||
<li className={pathname==="devops" ? "active" : ""}>
|
|
||||||
<Link to={{ pathname: `/projects/${owner}/${projectsId}/devops${open_devops ? `/dispose`:""}`, state }}>
|
|
||||||
<i className="iconfont icon-gongzuoliu font-13 mr8"></i>工作流(beta版)
|
|
||||||
{projectDetail && projectDetail.ops_count ? <span>{projectDetail.ops_count}</span> : ""}
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
:""
|
|
||||||
}
|
|
||||||
{/* {
|
|
||||||
item.menu_name === "resources" &&
|
|
||||||
<li className={pathname==="source" ? "active" : ""}>
|
|
||||||
<Link to={{ pathname: `/projects/${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>
|
|
||||||
<span>资源库</span>
|
|
||||||
{projectDetail && projectDetail.source_count ? <span className="num">{projectDetail.source_count}</span> :""}
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
} */}
|
|
||||||
{
|
|
||||||
item.menu_name === "versions" &&
|
|
||||||
<li className={pathname==="milestones" ? "active" : ""}>
|
|
||||||
<Link to={{ pathname: `/projects/${owner}/${projectsId}/milestones`, state }}>
|
|
||||||
<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>
|
|
||||||
{projectDetail && projectDetail.versions_count ? <span className="num">{projectDetail.versions_count}</span> :""}
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
}
|
|
||||||
{
|
|
||||||
item.menu_name === "activity" &&
|
|
||||||
<li className={pathname==="activity" ? "active" : ""}>
|
|
||||||
<Link to={{ pathname: `/projects/${owner}/${projectsId}/activity`, state }}>
|
|
||||||
<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>
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
}
|
|
||||||
{
|
|
||||||
item.menu_name === "setting" &&
|
|
||||||
<li className={pathname === "setting" ? "active" : ""}>
|
|
||||||
<Link to={`/projects/${owner}/${projectsId}/setting`}>
|
|
||||||
<i className={url && url.indexOf("/setting") > 0 ? "iconfont icon-cangku color-grey-3 mr5 font-14":"iconfont icon-cangku color-grey-6 font-14 mr5"}></i>
|
|
||||||
<span>仓库设置</span>
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
}
|
|
||||||
</React.Fragment>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</ul>
|
|
||||||
:
|
|
||||||
<Skeleton paragraph={false} active={true}/>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export default DetailBanner;
|
|
|
@ -1,63 +0,0 @@
|
||||||
import React , { forwardRef, useEffect } from 'react';
|
|
||||||
import {Form , Modal , Input } from 'antd';
|
|
||||||
import "./sub.scss";
|
|
||||||
const { TextArea } = Input;
|
|
||||||
function UpdateDescModal({form , visible , onCancel , onOk,desc,website,lesson_url}){
|
|
||||||
const { getFieldDecorator, validateFields , setFieldsValue } = form;
|
|
||||||
|
|
||||||
useEffect(()=>{
|
|
||||||
if(desc || website){
|
|
||||||
setFieldsValue({
|
|
||||||
website,desc,lesson_url
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},[desc,website])
|
|
||||||
|
|
||||||
function onSure(){
|
|
||||||
validateFields((err,values)=>{
|
|
||||||
if(!err){
|
|
||||||
onCancel();
|
|
||||||
onOk(values.desc,values.website,values.lesson_url)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return(
|
|
||||||
<Modal
|
|
||||||
title={"修改信息"}
|
|
||||||
closable={false}
|
|
||||||
visible={visible}
|
|
||||||
centered
|
|
||||||
onCancel={onCancel}
|
|
||||||
onOk={onSure}
|
|
||||||
okText="确定"
|
|
||||||
cancelText="取消"
|
|
||||||
width="400px"
|
|
||||||
className={"descmodal"}
|
|
||||||
>
|
|
||||||
<Form>
|
|
||||||
<Form.Item label="仓库描述">
|
|
||||||
{getFieldDecorator("desc",{
|
|
||||||
rules:[]
|
|
||||||
})(
|
|
||||||
<TextArea placeholder="仓库描述" rows={4} maxLength={200}/>
|
|
||||||
)}
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="website">
|
|
||||||
{getFieldDecorator("website",{
|
|
||||||
rules:[]
|
|
||||||
})(
|
|
||||||
<Input placeholder="website链接"/>
|
|
||||||
)}
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="实践课程">
|
|
||||||
{getFieldDecorator("lesson_url",{
|
|
||||||
rules:[]
|
|
||||||
})(
|
|
||||||
<Input placeholder="实践课程链接"/>
|
|
||||||
)}
|
|
||||||
</Form.Item>
|
|
||||||
</Form>
|
|
||||||
</Modal>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export default Form.create()(forwardRef(UpdateDescModal));
|
|
|
@ -1,23 +0,0 @@
|
||||||
.boxPanel{
|
|
||||||
width: 1200px;
|
|
||||||
margin:0px auto;
|
|
||||||
padding:20px 0px;
|
|
||||||
min-height: 500px;
|
|
||||||
.contrbuteList{
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
& > div{
|
|
||||||
width: 20%;
|
|
||||||
}
|
|
||||||
align-items: flex-start;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.descmodal{
|
|
||||||
.ant-row.ant-form-item{
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
.ant-col.ant-form-item-label{
|
|
||||||
height: 20px;
|
|
||||||
line-height: 20px;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -22,7 +22,7 @@ function Commits({ commits , projectsId , owner }){
|
||||||
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(item.sha)}`} className="color-blue">浏览代码</Link>
|
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(item.sha)}`} className="color-blue">浏览代码</Link>
|
||||||
</FlexAJ>
|
</FlexAJ>
|
||||||
<AlignCenter className="mt15">
|
<AlignCenter className="mt15">
|
||||||
<User url={getImageUrl(`/${item.committer && item.committer.image_url}`)} name={`${item.committer && item.committer.name}`}></User><span>:提交于{item.time_from_now}</span>
|
<User url={getImageUrl(`images/${item.committer && item.committer.image_url}`)} name={`${item.committer && item.committer.name}`}></User><span>:提交于{item.time_from_now}</span>
|
||||||
</AlignCenter>
|
</AlignCenter>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -47,7 +47,7 @@ function Files({data,history,owner,projectsId}){
|
||||||
<span>{item.name}</span>
|
<span>{item.name}</span>
|
||||||
</AlignCenter>
|
</AlignCenter>
|
||||||
<span>
|
<span>
|
||||||
<Button className="mr20" onClick={()=>{history.push(`/projects/${owner}/${projectsId}/tree/${truncateCommitId(item.sha)}/${item.name}`)}}>查看文件</Button>
|
<Button className="mr20" onClick={()=>{history.push(`/projects/${owner}/${projectsId}/tree/${truncateCommitId(item.sha)}/${item.name}`)}}>查看文件</Button>
|
||||||
<span className="color-green">+{item.addition}</span>
|
<span className="color-green">+{item.addition}</span>
|
||||||
<span className="color-red ml20">-{item.deletion}</span>
|
<span className="color-red ml20">-{item.deletion}</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { Tag } from "antd";
|
import { Popconfirm, Tag } from "antd";
|
||||||
import { AlignCenter } from '../Component/layout';
|
|
||||||
import { getImageUrl } from "educoder";
|
import { getImageUrl } from "educoder";
|
||||||
import "./merge.css";
|
import "./merge.css";
|
||||||
|
|
||||||
|
@ -75,13 +74,13 @@ class MergeItem extends Component {
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
className="radius"
|
className="radius"
|
||||||
src={getImageUrl(`/${item && item.avatar_url}`)}
|
src={getImageUrl(`images/${item && item.avatar_url}`)}
|
||||||
alt=""
|
alt=""
|
||||||
width="24"
|
width="24"
|
||||||
height="24"
|
height="24"
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
<AlignCenter>
|
<span>
|
||||||
<Link
|
<Link
|
||||||
to={`/users/${item && item.author_login}`}
|
to={`/users/${item && item.author_login}`}
|
||||||
className="show-user-link color-grey-8 ml5"
|
className="show-user-link color-grey-8 ml5"
|
||||||
|
@ -99,7 +98,7 @@ class MergeItem extends Component {
|
||||||
<span className="ml15">
|
<span className="ml15">
|
||||||
<Tag className="pr-branch-tag">
|
<Tag className="pr-branch-tag">
|
||||||
<Link
|
<Link
|
||||||
to={`/projects/${item.is_original ? item.fork_project_user : owner}/${ item.is_original ? item.fork_project_identifier : projectsId }/tree/${item.pull_request_head}`}
|
to={`/projects/${item.is_original ? item.fork_project_user : owner}/${ item.is_original ? item.fork_project_identifier : projectsId }/branch/${item.pull_request_head}`}
|
||||||
className="maxW200px hide-1 ver-middle"
|
className="maxW200px hide-1 ver-middle"
|
||||||
>
|
>
|
||||||
{item.is_original
|
{item.is_original
|
||||||
|
@ -117,7 +116,7 @@ class MergeItem extends Component {
|
||||||
</span>
|
</span>
|
||||||
<Tag className="pr-branch-tag">
|
<Tag className="pr-branch-tag">
|
||||||
<Link
|
<Link
|
||||||
to={`/projects/${owner}/${projectsId}/tree/${item.pull_request_base}`}
|
to={`/projects/${owner}/${projectsId}/branch/${item.pull_request_base}`}
|
||||||
className="maxW200px hide-1 ver-middle"
|
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}`} */}
|
||||||
|
@ -125,7 +124,7 @@ class MergeItem extends Component {
|
||||||
</Link>
|
</Link>
|
||||||
</Tag>
|
</Tag>
|
||||||
</span>
|
</span>
|
||||||
</AlignCenter>
|
</span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<ul
|
<ul
|
||||||
|
|
|
@ -101,7 +101,7 @@ class MergeSubmit extends Component{
|
||||||
render: (text,item) => (
|
render: (text,item) => (
|
||||||
<span className="f-wrap-alignCenter">
|
<span className="f-wrap-alignCenter">
|
||||||
<Link to={`/users/${item.login}`} className="show-user-link">
|
<Link to={`/users/${item.login}`} className="show-user-link">
|
||||||
<img src={getImageUrl(`/${item.image_url}`)} alt="" width="28px" height="28px" className="mr3 radius"/>
|
<img src={getImageUrl(`images/${item.image_url}`)} alt="" width="28px" height="28px" className="mr3 radius"/>
|
||||||
<label className="hide-1" style={{maxWidth:"75px",'vertical-align':'middle'}}>{text}</label>
|
<label className="hide-1" style={{maxWidth:"75px",'vertical-align':'middle'}}>{text}</label>
|
||||||
</Link>
|
</Link>
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -305,7 +305,7 @@ class MessageCount extends Component {
|
||||||
<div className="mt15">
|
<div className="mt15">
|
||||||
<Tag className="pr-branch-tag">
|
<Tag className="pr-branch-tag">
|
||||||
<Link
|
<Link
|
||||||
to={`/projects/${owner}/${data.pull_request.is_original?data.project_identifier:projectsId}/tree/${data.pull_request.head}`}
|
to={`/projects/${owner}/${data.pull_request.is_original?data.project_identifier:projectsId}/branch/${data.pull_request.head}`}
|
||||||
className="ver-middle"
|
className="ver-middle"
|
||||||
>
|
>
|
||||||
{data.pull_request.is_original ? data.pull_request.fork_project_user : data.issue.project_author_name}:{data.pull_request.head}
|
{data.pull_request.is_original ? data.pull_request.fork_project_user : data.issue.project_author_name}:{data.pull_request.head}
|
||||||
|
@ -320,7 +320,7 @@ class MessageCount extends Component {
|
||||||
</span>
|
</span>
|
||||||
<Tag className="pr-branch-tag">
|
<Tag className="pr-branch-tag">
|
||||||
<Link
|
<Link
|
||||||
to={`/projects/${owner}/${projectsId}/tree/${data.pull_request.base}`}
|
to={`/projects/${owner}/${projectsId}/branch/${data.pull_request.base}`}
|
||||||
className="ver-middle"
|
className="ver-middle"
|
||||||
>
|
>
|
||||||
{/* {data.pull_request.is_fork ? data.pull_request.base : `${data.pull_request.pull_request_user}:${data.pull_request.base}`} */}
|
{/* {data.pull_request.is_fork ? data.pull_request.base : `${data.pull_request.pull_request_user}:${data.pull_request.base}`} */}
|
||||||
|
@ -331,14 +331,26 @@ class MessageCount extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
<div className="mt15">
|
<div className="mt15">
|
||||||
<Link to={`/users/${data.issue.author_login}`} className="show-user-link">
|
<Link
|
||||||
<img className="mr5" src={getImageUrl(`/${data.issue.author_picture}`)}
|
to={`/users/${data.issue.author_login}`}
|
||||||
alt="" width="24" height="24" style={{borderRadius:"50%"}}
|
className="show-user-link"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
className="mr5"
|
||||||
|
src={getImageUrl(
|
||||||
|
`images/${data.issue.author_picture}`
|
||||||
|
)}
|
||||||
|
alt=""
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
/>
|
/>
|
||||||
</Link>
|
</Link>
|
||||||
<span className="ver-middle">
|
<span className="ver-middle">
|
||||||
<span className="color-grey-8 mr5">由</span>
|
<span className="color-grey-8 mr5">由</span>
|
||||||
<Link to={`/users/${data.issue.author_login}`} className="show-user-link color-blue">
|
<Link
|
||||||
|
to={`/users/${data.issue.author_login}`}
|
||||||
|
className="show-user-link color-blue"
|
||||||
|
>
|
||||||
{data.issue.author_name}
|
{data.issue.author_name}
|
||||||
</Link>
|
</Link>
|
||||||
<span className="ml5 color-grey-8">
|
<span className="ml5 color-grey-8">
|
||||||
|
|
|
@ -253,9 +253,27 @@ class merge extends Component {
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
</Menu>
|
</Menu>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const Paginations = (
|
||||||
|
<React.Fragment>
|
||||||
|
{search_count > limit ? (
|
||||||
|
<div className="mt30 mb50 edu-txt-center">
|
||||||
|
<Pagination
|
||||||
|
simple
|
||||||
|
defaultCurrent={page}
|
||||||
|
total={search_count}
|
||||||
|
pageSize={limit}
|
||||||
|
onChange={this.ChangePage}
|
||||||
|
></Pagination>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
return (
|
return (
|
||||||
<div className="main" style={{padding:"0px"}}>
|
<div className="main">
|
||||||
<div className="topWrapper" style={{borderBottom:"none",padding:"20px"}}>
|
<div className="topWrapper" style={{borderBottom:"none"}}>
|
||||||
<div className="target-detail-search">
|
<div className="target-detail-search">
|
||||||
<Search
|
<Search
|
||||||
placeholder="输入关键字搜索合并请求"
|
placeholder="输入关键字搜索合并请求"
|
||||||
|
@ -401,21 +419,9 @@ class merge extends Component {
|
||||||
{...this.props}
|
{...this.props}
|
||||||
{...this.state}
|
{...this.state}
|
||||||
></OrderItem>
|
></OrderItem>
|
||||||
|
{Paginations}
|
||||||
</div>
|
</div>
|
||||||
):""}
|
):""}
|
||||||
{search_count > select_params.limit ? (
|
|
||||||
<div className="mt30 mb50 edu-txt-center">
|
|
||||||
<Pagination
|
|
||||||
simple
|
|
||||||
current={select_params.page}
|
|
||||||
total={search_count}
|
|
||||||
pageSize={select_params.limit}
|
|
||||||
onChange={this.ChangePage}
|
|
||||||
></Pagination>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
""
|
|
||||||
)}
|
|
||||||
{ data && data.issues && data.issues.length === 0 ? <NoneData _html="暂时还没有相关数据!" projectsId={projectsId} owner={owner} /> :""}
|
{ data && data.issues && data.issues.length === 0 ? <NoneData _html="暂时还没有相关数据!" projectsId={projectsId} owner={owner} /> :""}
|
||||||
</Spin>
|
</Spin>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -43,7 +43,9 @@ class Index extends Component {
|
||||||
project_language_name: undefined,
|
project_language_name: undefined,
|
||||||
project_category_name: undefined,
|
project_category_name: undefined,
|
||||||
license_name: undefined,
|
license_name: undefined,
|
||||||
ignore_name: undefined
|
ignore_name: undefined,
|
||||||
|
|
||||||
|
licenseForDisabled:undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
componentDidMount = () => {
|
componentDidMount = () => {
|
||||||
|
@ -145,7 +147,7 @@ class Index extends Component {
|
||||||
_data = data.filter(item => item.name.toLowerCase().indexOf(name.toLowerCase()) > -1);
|
_data = data.filter(item => item.name.toLowerCase().indexOf(name.toLowerCase()) > -1);
|
||||||
}
|
}
|
||||||
let list = _data && _data.map((item) => (
|
let list = _data && _data.map((item) => (
|
||||||
<Option key={item.id} value={item.name}>
|
<Option key={item.id} value={item.name} onClick={()=>this.selectSerect(item.is_secret)}>
|
||||||
{item.name}
|
{item.name}
|
||||||
</Option>
|
</Option>
|
||||||
));
|
));
|
||||||
|
@ -155,6 +157,17 @@ class Index extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
selectSerect=(flag)=>{
|
||||||
|
if(flag){
|
||||||
|
this.props.form.setFieldsValue({
|
||||||
|
private:true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
licenseForDisabled:flag
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
subMitFrom = () => {
|
subMitFrom = () => {
|
||||||
this.props.form.validateFieldsAndScroll((err, values) => {
|
this.props.form.validateFieldsAndScroll((err, values) => {
|
||||||
if (!err) {
|
if (!err) {
|
||||||
|
@ -164,7 +177,7 @@ class Index extends Component {
|
||||||
const { projectsType } = this.props.match.params;
|
const { projectsType } = this.props.match.params;
|
||||||
const { project_language_id, project_category_id, license_id, ignore_id , owners_id , owners_name } = this.state;
|
const { project_language_id, project_category_id, license_id, ignore_id , owners_id , owners_name } = 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 === "deposit" ? "/projects.json" : "/projects/migrate.json";
|
||||||
axios.post(url, {
|
axios.post(url, {
|
||||||
...values,
|
...values,
|
||||||
auth_password:decoderPass,
|
auth_password:decoderPass,
|
||||||
|
@ -179,7 +192,7 @@ class Index extends Component {
|
||||||
this.setState({
|
this.setState({
|
||||||
isSpin: false
|
isSpin: false
|
||||||
})
|
})
|
||||||
this.props.showNotification(`${projectsType && projectsType === "mirror" ? "镜像" : "托管"}项目创建成功!`);
|
this.props.showNotification(`${projectsType === "deposit" ? "托管" : "镜像"}项目创建成功!`);
|
||||||
this.props.history.push(`/projects/${owners_name}/${result.data.identifier}`);
|
this.props.history.push(`/projects/${owners_name}/${result.data.identifier}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -198,7 +211,8 @@ class Index extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
ChangePlatform = (value, e, name, list) => {
|
ChangePlatform = (value, e, name, list) => {
|
||||||
this.setOptionsList(list, name, value)
|
this.setOptionsList(list, name, value);
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
[name + "_id"]: e.key,
|
[name + "_id"]: e.key,
|
||||||
[name + "_name"]: value,
|
[name + "_name"]: value,
|
||||||
|
@ -272,13 +286,14 @@ class Index extends Component {
|
||||||
project_category_list,
|
project_category_list,
|
||||||
license_list,
|
license_list,
|
||||||
ignore_list,
|
ignore_list,
|
||||||
|
licenseForDisabled,
|
||||||
|
|
||||||
mirrorCheck
|
mirrorCheck
|
||||||
} = this.state;
|
} = this.state;
|
||||||
return (
|
return (
|
||||||
<div className="main back-white" style={{padding:"0px",border:"none"}}>
|
<div className="main back-white">
|
||||||
<div className="newPanel">
|
<div className="newPanel">
|
||||||
<div className="newPanel_title">创建{projectsType && projectsType === "mirror" ? "镜像" : "托管"}项目</div>
|
<div className="newPanel_title">创建{projectsType === "deposit" ? "托管" : "镜像"}项目</div>
|
||||||
<Spin spinning={isSpin}>
|
<Spin spinning={isSpin}>
|
||||||
<Form>
|
<Form>
|
||||||
<div className="newPanel_content">
|
<div className="newPanel_content">
|
||||||
|
@ -303,7 +318,7 @@ class Index extends Component {
|
||||||
)}
|
)}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
{
|
{
|
||||||
projectsType && projectsType === "mirror" &&
|
projectsType !== "deposit" &&
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="镜像版本库地址"
|
label="镜像版本库地址"
|
||||||
|
@ -321,7 +336,7 @@ class Index extends Component {
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
projectsType && projectsType === "mirror" &&
|
projectsType !== "deposit" &&
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<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></p>
|
<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></p>
|
||||||
{
|
{
|
||||||
|
@ -428,7 +443,7 @@ class Index extends Component {
|
||||||
)}
|
)}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
{
|
{
|
||||||
(projectsType === "deposit" || !projectsType) &&
|
projectsType === "deposit" &&
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label=".gitignore"
|
label=".gitignore"
|
||||||
|
@ -477,12 +492,12 @@ class Index extends Component {
|
||||||
style={{ margin: "0px" }}
|
style={{ margin: "0px" }}
|
||||||
className="privatePart"
|
className="privatePart"
|
||||||
>
|
>
|
||||||
{getFieldDecorator('private')(
|
{getFieldDecorator('private',{valuePropName:"checked"})(
|
||||||
<Checkbox value="limit">将项目设为私有<span className="ml15 font-13 color-grey-9">(只有项目所有人或拥有权限的项目成员才能看到)</span></Checkbox>
|
<Checkbox value="limit" disabled={licenseForDisabled}>将项目设为私有<span className="ml15 font-13 color-grey-9">(只有项目所有人或拥有权限的项目成员才能看到)</span></Checkbox>
|
||||||
)}
|
)}
|
||||||
</Form.Item >
|
</Form.Item >
|
||||||
{
|
{
|
||||||
projectsType && projectsType === "mirror" &&
|
projectsType !== "deposit" &&
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="迁移类型:"
|
label="迁移类型:"
|
||||||
style={{ margin: "0px" }}
|
style={{ margin: "0px" }}
|
||||||
|
|
|
@ -54,7 +54,7 @@ class UserSubmitComponent extends Component {
|
||||||
const { getTopCount } = this.props;
|
const { getTopCount } = this.props;
|
||||||
getTopCount && getTopCount(values.branchname);
|
getTopCount && getTopCount(values.branchname);
|
||||||
}
|
}
|
||||||
let url = `/projects/${owner}/${projectsId}${values.branchname ? `/tree/${values.branchname}`: (branch ? `/tree/${branch}` : "")}`;
|
let url = `/projects/${owner}/${projectsId}${values.branchname ? `/branch/${values.branchname}`: (branch ? `/branch/${branch}` : "")}`;
|
||||||
this.props.history.push(url);
|
this.props.history.push(url);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -89,7 +89,7 @@ class UserSubmitComponent extends Component {
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
this.setState({ isSpin: false });
|
this.setState({ isSpin: false });
|
||||||
if (result.data && result.data.status === 1) {
|
if (result.data && result.data.status === 1) {
|
||||||
let url = `/projects/${owner}/${projectsId}${(values.branchname ? `/tree/${values.branchname}` : ((currentBranch || branch) ? `/tree/${currentBranch || branch}`:""))}`;
|
let url = `/projects/${owner}/${projectsId}${(values.branchname ? `/branch/${values.branchname}` : ((currentBranch || branch) ? `/branch/${currentBranch || branch}`:""))}`;
|
||||||
this.props.history.push(url);
|
this.props.history.push(url);
|
||||||
this.props.showNotification("文件修改成功!");
|
this.props.showNotification("文件修改成功!");
|
||||||
}
|
}
|
||||||
|
@ -114,10 +114,10 @@ class UserSubmitComponent extends Component {
|
||||||
const { editor_type } = this.props;
|
const { editor_type } = this.props;
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<span className="df" style={{ alignItems: "center" }}>
|
<span className="df mt30" style={{ alignItems: "center" }}>
|
||||||
<Link to={`/users/${current_user && current_user.login}`} className="show-user-link" >
|
<Link to={`/users/${current_user && current_user.login}`} className="show-user-link" >
|
||||||
<img
|
<img
|
||||||
src={getImageUrl(`/${current_user && current_user.image_url}`)}
|
src={getImageUrl(`images/${current_user && current_user.image_url}`)}
|
||||||
alt=""
|
alt=""
|
||||||
className="screwImg"
|
className="screwImg"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -61,6 +61,10 @@
|
||||||
.screwPanel .ant-radio-wrapper{
|
.screwPanel .ant-radio-wrapper{
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
.branchTable{
|
||||||
|
border:1px solid #eaeaea;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
.branchTable .margin-view-overlays{
|
.branchTable .margin-view-overlays{
|
||||||
border-right: 1px solid #eaeaea;
|
border-right: 1px solid #eaeaea;
|
||||||
background-color: #fbfbfb;
|
background-color: #fbfbfb;
|
||||||
|
|