forked from Gitlink/forgeplus-react
Compare commits
364 Commits
Author | SHA1 | Date |
---|---|---|
caishi | 705bfb07bd | |
caishi | 202081bbeb | |
caishi | d783d998fc | |
caishi | af8872176c | |
caishi | 037a79de67 | |
caishi | 51925542b8 | |
caishi | a408d435f3 | |
caishi | 016f7f1a7e | |
caishi | ff06efe109 | |
caishi | c33561c212 | |
caishi | 2deb6f8f9d | |
caishi | 63d69a955e | |
caishi | e7eceb5b23 | |
caishi | c28ae9adb3 | |
caishi | 870fbaa2a9 | |
caishi | 227b686046 | |
caishi | 582f7a39b3 | |
caishi | ac4b7542e2 | |
caishi | 3a3a0251aa | |
caishi | 2fcb645d42 | |
caishi | 93a53e2c7f | |
caishi | 79d8f4e5ad | |
caishi | ae34240bfb | |
caishi | 4d652d238d | |
caishi | efaf0c29b5 | |
caishi | 81ad2358f5 | |
caishi | 605d5a047d | |
caishi | 1474f5d3fe | |
caishi | 8d509f1473 | |
caishi | 4ba63fd8fa | |
caishi | e10f9893e0 | |
caishi | 63d7045444 | |
caishi | 6da4dbc165 | |
caishi | c0ddd6eaee | |
caishi | f65f4c273a | |
caishi | 0cdb491433 | |
caishi | ac47ba1b29 | |
caishi | 2bd6f9cb1e | |
caishi | 0636e0a925 | |
caishi | 631b05dfd6 | |
caishi | 4e48b0b363 | |
caishi | 1af504825c | |
caishi | fb41baacc1 | |
caishi | 09065383c1 | |
caishi | e94cf68cc5 | |
caishi | c32e215b27 | |
caishi | 5fa2fd99b9 | |
caishi | 2f6597355c | |
caishi | 20ab8a6683 | |
caishi | 1eb3c20af4 | |
caishi | afb599f5be | |
caishi | a7f709a663 | |
caishi | d6d6df806d | |
caishi | 6cc97bd039 | |
caishi | 037150a63c | |
caishi | 63c2cfed70 | |
caishi | 52dc63362b | |
caishi | 29e3f0d59d | |
caishi | 233e6a8226 | |
caishi | 80cd6fbae0 | |
caishi | 8fa31edaae | |
caishi | 49d3db6746 | |
caishi | ffbb5ba34e | |
caishi | bc11ec68e3 | |
caishi | 2d2deec224 | |
caishi | a67cabbfb4 | |
caishi | ceb1915939 | |
caishi | 4c65e1981e | |
caishi | 09598d0e2c | |
caishi | e09490d424 | |
caishi | a42a670146 | |
caishi | b8d40259e5 | |
caishi | 487a2f0495 | |
caishi | ab34369642 | |
caishi | f12228aa51 | |
caishi | 5477c41f78 | |
caishi | dc05f9ce35 | |
caishi | b601582d15 | |
caishi | 832b18e7f5 | |
caishi | 8c58f77afb | |
caishi | 2c363965dd | |
caishi | 60a7f39c16 | |
caishi | 9811276a7c | |
caishi | a27c74b9aa | |
caishi | 80cae93045 | |
caishi | 78aba67917 | |
caishi | 43223c7787 | |
caishi | 961587921a | |
caishi | 2f595d750a | |
caishi | bcaec7a2db | |
caishi | 70ea6259ae | |
caishi | 5d6953f2b3 | |
caishi | c8eda704e5 | |
caishi | 5d6b95ab8f | |
caishi | 426ea3fece | |
caishi | ab052ebace | |
caishi | 648c6e235b | |
caishi | 96253f3f58 | |
caishi | 101478d924 | |
caishi | dccbd6735d | |
caishi | a0ebba839e | |
caishi | 171f14bd2a | |
caishi | c3e09f2672 | |
caishi | 6296434527 | |
caishi | e2dbda3083 | |
caishi | 02f382e6fb | |
caishi | b568aef34e | |
caishi | 2c83221376 | |
caishi | 6a4fe4d277 | |
caishi | 99f7aea290 | |
caishi | 50f39afffa | |
caishi | d0ccc92cc6 | |
caishi | 2add7911dc | |
caishi | ec1ff5d479 | |
caishi | 55f23dea0d | |
caishi | 26e74e7ed4 | |
caishi | 3384cd2703 | |
caishi | 0290822ebf | |
caishi | 31edf6ff45 | |
caishi | 8a1feed72b | |
caishi | 0c0203a8ef | |
caishi | 45e69cb14a | |
caishi | d7f3c766b4 | |
caishi | a3226dca4e | |
caishi | d16ee801ec | |
caishi | c3eb6edddc | |
caishi | ad8a127170 | |
caishi | cbaf72b341 | |
caishi | a4b5b67da6 | |
caishi | da31875a5a | |
caishi | b7a92b17e7 | |
caishi | f4332db4ad | |
caishi | 99174c2782 | |
caishi | f33f1f3ce5 | |
caishi | 5d99d63267 | |
caishi | 9137b666ea | |
caishi | 1250a9b10b | |
caishi | 6ea82be73a | |
caishi | 964427b8fc | |
caishi | afd6904349 | |
caishi | 72fcbcd4dd | |
caishi | 80f1e4d448 | |
caishi | 3071c785bc | |
caishi | d01e8e32d4 | |
caishi | e469ddae24 | |
caishi | f8b9003e15 | |
caishi | 19f66b0bcc | |
caishi | 2ceaead909 | |
caishi | 8d386ff70b | |
caishi | d11cb7fc40 | |
caishi | 696fb22a58 | |
caishi | 67b510923b | |
caishi | ad3c9f837f | |
caishi | b8476cec1a | |
caishi | fcd859638e | |
caishi | 518d341ed5 | |
caishi | b4a608bcc3 | |
caishi | 658fd1b4f9 | |
caishi | 58228e90c7 | |
caishi | 10466ac4a2 | |
caishi | 98d40482f3 | |
caishi | 03cd10f599 | |
caishi | 59836f69d0 | |
caishi | 591974aa6d | |
caishi | eaa46dbcee | |
caishi | 0c5dd61fdc | |
caishi | 26d2e0f541 | |
caishi | daa5cc212c | |
caishi | 7a8cbac912 | |
caishi | 3b208ba751 | |
caishi | 9380c0172c | |
caishi | 34ba476011 | |
caishi | 185228d4b6 | |
caishi | cae10cec2a | |
caishi | 006ceff8fc | |
caishi | c71d8512df | |
caishi | 3b85567a1a | |
caishi | ea77a13b6f | |
caishi | fcf03f2631 | |
caishi | e65a1debc5 | |
caishi | a2406bbf4b | |
caishi | eee8d4659c | |
Sylor-huang | 7eef81b91a | |
Sylor-huang | bd85703412 | |
Sylor-huang | 7a2d1b7db1 | |
caishi | 828cc2470d | |
caishi | 7b7b206741 | |
caishi | 5181d636d9 | |
caishi | f68842beff | |
caishi | 6deb8db08f | |
caishi | 3a2d93c3a6 | |
caishi | b71980f6dc | |
caishi | 586d9e0c05 | |
caishi | 029bb89b11 | |
caishi | 2278d03c47 | |
caishi | a22b5b3701 | |
caishi | df438212c1 | |
caishi | e1164875b0 | |
caishi | c53de4ad15 | |
caishi | ef22be7e96 | |
caishi | a235879dd0 | |
caishi | 0b007b35d9 | |
caishi | 68935245f0 | |
caishi | f7fe479859 | |
caishi | 9d0adc0747 | |
caishi | 0e0eee8aaf | |
caishi | 7e47cad744 | |
caishi | 5e7fedb471 | |
caishi | 4ef05163d7 | |
caishi | 4d9567bb94 | |
caishi | 246782f961 | |
caishi | e5d9728807 | |
caishi | dd8856f7ac | |
caishi | 502dfde9a2 | |
caishi | 05ded94662 | |
caishi | bbe3766a40 | |
caishi | 05080e7948 | |
caishi | b59e83ee00 | |
caishi | 0a67b9606a | |
caishi | 2b063bb8f7 | |
caishi | 2905bb41a7 | |
caishi | d66b0580b7 | |
caishi | d7e0d5b246 | |
caishi | fac62fc99e | |
caishi | e294b14015 | |
caishi | 59a0834300 | |
caishi | 21b1c8cba3 | |
caishi | 0929200f43 | |
caishi | 8df79a85d2 | |
caishi | 94a2946d52 | |
caishi | 5c91569bac | |
caishi | a4dbda8c5d | |
caishi | e3c1e7b82f | |
caishi | 7795fe1d04 | |
caishi | 5d0afb265b | |
caishi | 45fc4dcdcd | |
caishi | 2129a222e5 | |
caishi | 68eb499a8c | |
caishi | 5f36f9306a | |
caishi | e95ef11058 | |
caishi | 851afbc6c4 | |
caishi | ee79efa6de | |
caishi | 6b203d9d24 | |
caishi | 0d1345f957 | |
caishi | 57363291f1 | |
caishi | 2ba469f210 | |
caishi | 06f0c53d3b | |
caishi | 9005106332 | |
caishi | 89b78bc046 | |
caishi | a38b74041e | |
caishi | ccb5eb8ae5 | |
caishi | ef65594004 | |
caishi | b27f0e796d | |
caishi | 92699347ec | |
caishi | 0062e84a45 | |
caishi | 5827e96a53 | |
caishi | 8cc13f77e1 | |
caishi | ac5b50c26d | |
caishi | b2eca51bd8 | |
caishi | cbfb9c3ffe | |
caishi | 1867497d52 | |
caishi | d6fa304d01 | |
caishi | bf84063a3c | |
caishi | 43fc24e114 | |
caishi | a2e1b2abd1 | |
caishi | 4edef931d5 | |
caishi | 49795b0682 | |
caishi | 0c59855e9c | |
caishi | ef19107fcd | |
caishi | 0712904506 | |
caishi | 2f755e8d65 | |
caishi | 0dd33faeb5 | |
caishi | 0dd722d898 | |
caishi | 2e04851b66 | |
caishi | f9588407b8 | |
caishi | e9fef026a6 | |
caishi | 5e36abb259 | |
caishi | 0cb6986aed | |
caishi | 80ef857048 | |
caishi | 5bc172a492 | |
caishi | e42de09b99 | |
caishi | 3591666e5e | |
caishi | eb8cae5fb3 | |
caishi | 8645eb8e1b | |
caishi | 02f286ffad | |
caishi | ee6356daa0 | |
caishi | 62b99c7921 | |
caishi | 4ce8e4edd1 | |
caishi | bba939094c | |
caishi | 8d3c5c4c06 | |
caishi | d1e7d2e935 | |
caishi | ac2ac26036 | |
caishi | 42ddb67c0e | |
caishi | 849f695a78 | |
caishi | d80f1d32dc | |
caishi | b6dfe2cd4a | |
caishi | 7edaa9e09c | |
caishi | ded423ee2c | |
caishi | a5657390fe | |
sylor_huang@126.com | 5a8daf7cfe | |
caishi | 51c2729916 | |
caishi | aca923fe07 | |
caishi | 3949584549 | |
caishi | d029a9ab6f | |
caishi | 46097ee5e1 | |
caishi | c66717bf1b | |
caishi | 8b1b923c92 | |
caishi | 4afa382c7c | |
caishi | b27f6d5732 | |
caishi | 4e657a4c15 | |
caishi | 229b5a704e | |
caishi | 69a9137c34 | |
caishi | 8cee70c195 | |
caishi | f7adc17b5d | |
caishi | 48d9580e78 | |
caishi | f3d6e8c6dc | |
caishi | a14b125d34 | |
caishi | 593f76bba0 | |
caishi | 45273782c5 | |
caishi | c3ed52bc32 | |
caishi | 8397daec22 | |
caishi | 1e80457885 | |
caishi | c052cf715b | |
caishi | 53e444d85e | |
caishi | cd6540a84c | |
caishi | 10d4ad7221 | |
caishi | 440e7cd91e | |
Jasder | 0991fee06a | |
Jasder | 8307c014f6 | |
Jasder | dace62e2de | |
caishi | 74ea4d504d | |
caishi | 942e88a6ea | |
caishi | 87449bde46 | |
caishi | 3060c4bb2b | |
caishi | b6bc59a775 | |
caishi | 745179adae | |
caishi | 15bd20122a | |
caishi | afeff6b0af | |
caishi | b66c1c01de | |
caishi | ec98b6ad44 | |
caishi | e252f168f8 | |
caishi | 6944406c49 | |
caishi | 2f09ca4315 | |
caishi | 4329b89ddf | |
caishi | 30f0fd82de | |
caishi | 6795e61870 | |
caishi | 3169867415 | |
caishi | d697ad24a7 | |
caishi | f05b6eb804 | |
caishi | d702a92e81 | |
caishi | 11e58a200c | |
sylor_huang@126.com | 6d478dd911 | |
caishi | 15d3102c51 | |
caishi | bac40864eb | |
caishi | cccdfeab32 | |
caishi | 3abbaa8899 | |
caishi | 42a1418181 | |
caishi | ec073cdf71 | |
caishi | a09b81df3f | |
caishi | a411d2c111 | |
caishi | 2f1bac24d5 | |
caishi | 940c9c0253 | |
caishi | dfbcc09e5b | |
837816638@qq.com | 40cc47dd93 |
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"presets": [
|
||||||
|
"es2015",
|
||||||
|
"react",
|
||||||
|
"stage-2"
|
||||||
|
],
|
||||||
|
"plugins": [[
|
||||||
|
"transform-runtime",
|
||||||
|
{
|
||||||
|
"helpers": false,
|
||||||
|
"polyfill": false,
|
||||||
|
"regenerator": true,
|
||||||
|
"moduleName": "babel-runtime"
|
||||||
|
}
|
||||||
|
]]
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
<h3>前端react环境安装:</h3>
|
||||||
|
<p>1、 安装node v6.9.x;此安装包含了node和npm。</p>
|
||||||
|
<p>2、 安装cnpm(命令行): npm install -g cnpm --registry=https://registry.npm.taobao.org</p>
|
||||||
|
<p>3、 安装依赖的js库(public/react目录下<即项目package.json所在目录>,开启命令行): cnpm install</p>
|
||||||
|
<p>4、 如果你的ruby服务使用的是3000端口,则需要在package.json中修改"port"参数的值</p>
|
||||||
|
<p>5、 启动服务(命令行-目录同3): npm start</p>
|
||||||
|
<p>6、 build初始化 npm run build</p>
|
||||||
|
|
||||||
|
|
||||||
|
<h3>分支信息:</h3>
|
||||||
|
<p>相关代码提交到对应分支,能上线的代码先提交到develop分支上测试版,测试通过后合并提交到master分支上线正式版</p>
|
||||||
|
<p>master:开发环境(正式环境)</p>
|
||||||
|
<p>develop:测试环境</p>
|
||||||
|
<p>dev_local:本地版本</p>
|
||||||
|
<p>dev_chain:含有区块链相关内容的分支</p>
|
||||||
|
<p>PS:新增加的需求功能先新建新分支开发,在测试版测试没问题后再分别合并到develop和master分支</p>
|
|
@ -17,16 +17,7 @@ const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
|
||||||
const paths = require("./paths");
|
const paths = require("./paths");
|
||||||
const getClientEnvironment = require("./env");
|
const getClientEnvironment = require("./env");
|
||||||
|
|
||||||
// Some apps do not use client-side routing with pushState.
|
|
||||||
// For these, "homepage" can be set to "." to enable relative asset paths.
|
|
||||||
let publicPath = "/react/build/";
|
let publicPath = "/react/build/";
|
||||||
// let nodeEnv = process.env.NODE_ENV
|
|
||||||
// if (nodeEnv === 'testBuild') {
|
|
||||||
// publicPath = 'https://testforgeplus.trustie.net/react/build/';
|
|
||||||
// }
|
|
||||||
// if (nodeEnv === 'production') {
|
|
||||||
// publicPath = 'https://forgeplus.trustie.net/react/build/';
|
|
||||||
// }
|
|
||||||
const publicUrl = publicPath.slice(0, -1);
|
const publicUrl = publicPath.slice(0, -1);
|
||||||
const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== "false";
|
const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== "false";
|
||||||
const env = getClientEnvironment(publicPath);
|
const env = getClientEnvironment(publicPath);
|
||||||
|
@ -141,7 +132,6 @@ module.exports = {
|
||||||
name: "static/media/[name].[hash:8].[ext]",
|
name: "static/media/[name].[hash:8].[ext]",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// Process JS with Babel.
|
|
||||||
{
|
{
|
||||||
test: /\.(js|jsx|mjs)$/,
|
test: /\.(js|jsx|mjs)$/,
|
||||||
include: paths.appSrc,
|
include: paths.appSrc,
|
||||||
|
@ -161,10 +151,8 @@ module.exports = {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
test: /\.css$/,
|
test: /\.css$/,
|
||||||
|
|
||||||
use: [
|
use: [
|
||||||
{
|
{
|
||||||
loader: MiniCssExtractPlugin.loader,
|
loader: MiniCssExtractPlugin.loader,
|
||||||
|
|
|
@ -1,35 +1,40 @@
|
||||||
{
|
{
|
||||||
"name": "educoder",
|
"name": "forge",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ant-design/colors": {
|
"@ant-design/colors": {
|
||||||
"version": "3.2.2",
|
"version": "3.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-3.2.2.tgz",
|
"resolved": "https://registry.npm.taobao.org/@ant-design/colors/download/@ant-design/colors-3.2.2.tgz?cache=0&sync_timestamp=1612935637470&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40ant-design%2Fcolors%2Fdownload%2F%40ant-design%2Fcolors-3.2.2.tgz",
|
||||||
"integrity": "sha512-YKgNbG2dlzqMhA9NtI3/pbY16m3Yl/EeWBRa+lB1X1YaYxHrxNexiQYCLTWO/uDvAjLFMEDU+zR901waBtMtjQ==",
|
"integrity": "sha1-WtQ9YZ6RHzSI66wwPWBuZqhCOQM=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"tinycolor2": "^1.4.1"
|
"tinycolor2": "^1.4.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@ant-design/create-react-context": {
|
"@ant-design/create-react-context": {
|
||||||
"version": "0.2.5",
|
"version": "0.2.5",
|
||||||
"resolved": "https://registry.npmjs.org/@ant-design/create-react-context/-/create-react-context-0.2.5.tgz",
|
"resolved": "https://registry.npm.taobao.org/@ant-design/create-react-context/download/@ant-design/create-react-context-0.2.5.tgz",
|
||||||
"integrity": "sha512-1rMAa4qgP2lfl/QBH9i78+Gjxtj9FTMpMyDGZsEBW5Kih72EuUo9958mV8PgpRkh4uwPSQ7vVZWXeyNZXVAFDg==",
|
"integrity": "sha1-9fWpFjtHcgl3EoNzl60w4i55+Fg=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"gud": "^1.0.0",
|
"gud": "^1.0.0",
|
||||||
"warning": "^4.0.3"
|
"warning": "^4.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@ant-design/css-animation": {
|
||||||
|
"version": "1.7.3",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/@ant-design/css-animation/download/@ant-design/css-animation-1.7.3.tgz?cache=0&sync_timestamp=1596106749762&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40ant-design%2Fcss-animation%2Fdownload%2F%40ant-design%2Fcss-animation-1.7.3.tgz",
|
||||||
|
"integrity": "sha1-YKHJcAFOhrKPlAUQ1p5QPkKPETY="
|
||||||
|
},
|
||||||
"@ant-design/icons": {
|
"@ant-design/icons": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-2.1.1.tgz",
|
"resolved": "https://registry.npm.taobao.org/@ant-design/icons/download/@ant-design/icons-2.1.1.tgz",
|
||||||
"integrity": "sha512-jCH+k2Vjlno4YWl6g535nHR09PwCEmTBKAG6VqF+rhkrSPRLfgpU2maagwbZPLjaHuU5Jd1DFQ2KJpQuI6uG8w=="
|
"integrity": "sha1-e5wI3/1PXUHbZn2dvl4BB9C9mko="
|
||||||
},
|
},
|
||||||
"@ant-design/icons-react": {
|
"@ant-design/icons-react": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/@ant-design/icons-react/-/icons-react-2.0.1.tgz",
|
"resolved": "https://registry.npm.taobao.org/@ant-design/icons-react/download/@ant-design/icons-react-2.0.1.tgz",
|
||||||
"integrity": "sha512-r1QfoltMuruJZqdiKcbPim3d8LNsVPB733U0gZEUSxBLuqilwsW28K2rCTWSMTjmFX7Mfpf+v/wdiFe/XCqThw==",
|
"integrity": "sha1-F6JRNXGrMXrKKSfljOol3THlNvs=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ant-design/colors": "^3.1.0",
|
"@ant-design/colors": "^3.1.0",
|
||||||
"babel-runtime": "^6.26.0"
|
"babel-runtime": "^6.26.0"
|
||||||
|
@ -446,8 +451,8 @@
|
||||||
},
|
},
|
||||||
"@types/react-slick": {
|
"@types/react-slick": {
|
||||||
"version": "0.23.4",
|
"version": "0.23.4",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-slick/-/react-slick-0.23.4.tgz",
|
"resolved": "https://registry.npm.taobao.org/@types/react-slick/download/@types/react-slick-0.23.4.tgz",
|
||||||
"integrity": "sha512-vXoIy4GUfB7/YgqubR4H7RALo+pRdMYCeLgWwV3MPwl5pggTlEkFBTF19R7u+LJc85uMqC7RfsbkqPLMQ4ab+A==",
|
"integrity": "sha1-yX4qnn49GTPGhZO46CdS+rHozlM=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/react": "*"
|
"@types/react": "*"
|
||||||
}
|
}
|
||||||
|
@ -863,9 +868,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"antd": {
|
"antd": {
|
||||||
"version": "3.26.16",
|
"version": "3.26.20",
|
||||||
"resolved": "https://registry.npmjs.org/antd/-/antd-3.26.16.tgz",
|
"resolved": "https://registry.nlark.com/antd/download/antd-3.26.20.tgz",
|
||||||
"integrity": "sha512-EYRwlEf8FCPCVRk5yDcgjSZOC0exu+m75SwlSQU+Mh17f9wGhLeL2/DV7/Sra1r+BZlfiahFdkgrLY7UgMMBEQ==",
|
"integrity": "sha1-8/Vw76qllQoUSULyHrKqqgiOlAc=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ant-design/create-react-context": "^0.2.4",
|
"@ant-design/create-react-context": "^0.2.4",
|
||||||
"@ant-design/icons": "~2.1.1",
|
"@ant-design/icons": "~2.1.1",
|
||||||
|
@ -925,16 +930,16 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"raf": {
|
"raf": {
|
||||||
"version": "3.4.1",
|
"version": "3.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
|
"resolved": "https://registry.npm.taobao.org/raf/download/raf-3.4.1.tgz",
|
||||||
"integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
|
"integrity": "sha1-B0LpmkplUvRF1z4+4DKK8P8e3jk=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"performance-now": "^2.1.0"
|
"performance-now": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rc-pagination": {
|
"rc-pagination": {
|
||||||
"version": "1.20.14",
|
"version": "1.20.15",
|
||||||
"resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-1.20.14.tgz",
|
"resolved": "https://registry.npm.taobao.org/rc-pagination/download/rc-pagination-1.20.15.tgz",
|
||||||
"integrity": "sha512-sNKwbFrxiqATqcIIShfrFs8BT03n4UUwTAMYae+JhHTmILQmXdvimEnZbVuWcno6G02DAJcLrFpmkn1h2tmEJw==",
|
"integrity": "sha1-zLTNDpvU5H9y8p6kMsA1C/ez2Ac=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "6.x",
|
"babel-runtime": "6.x",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
|
@ -944,8 +949,8 @@
|
||||||
},
|
},
|
||||||
"rc-rate": {
|
"rc-rate": {
|
||||||
"version": "2.5.1",
|
"version": "2.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.5.1.tgz",
|
"resolved": "https://registry.npm.taobao.org/rc-rate/download/rc-rate-2.5.1.tgz?cache=0&sync_timestamp=1605573559401&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-rate%2Fdownload%2Frc-rate-2.5.1.tgz",
|
||||||
"integrity": "sha512-3iJkNJT8xlHklPCdeZtUZmJmRVUbr6AHRlfSsztfYTXVlHrv2TcPn3XkHsH+12j812WVB7gvilS2j3+ffjUHXg==",
|
"integrity": "sha1-Vfxf0j6p3MciULmoiYA0efSEKWE=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"classnames": "^2.2.5",
|
"classnames": "^2.2.5",
|
||||||
"prop-types": "^15.5.8",
|
"prop-types": "^15.5.8",
|
||||||
|
@ -955,8 +960,8 @@
|
||||||
},
|
},
|
||||||
"rc-select": {
|
"rc-select": {
|
||||||
"version": "9.2.3",
|
"version": "9.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/rc-select/-/rc-select-9.2.3.tgz",
|
"resolved": "https://registry.nlark.com/rc-select/download/rc-select-9.2.3.tgz?cache=0&sync_timestamp=1618886345948&other_urls=https%3A%2F%2Fregistry.nlark.com%2Frc-select%2Fdownload%2Frc-select-9.2.3.tgz",
|
||||||
"integrity": "sha512-WhswxOMWiNnkXRbxyrj0kiIvyCfo/BaRPaYbsDetSIAU2yEDwKHF798blCP5u86KLOBKBvtxWLFCkSsQw1so5w==",
|
"integrity": "sha1-ZDQOLW72TovDz8b0aP/ShiVYmsI=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "^6.23.0",
|
"babel-runtime": "^6.23.0",
|
||||||
"classnames": "2.x",
|
"classnames": "2.x",
|
||||||
|
@ -974,8 +979,8 @@
|
||||||
},
|
},
|
||||||
"rc-tree": {
|
"rc-tree": {
|
||||||
"version": "2.1.4",
|
"version": "2.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-2.1.4.tgz",
|
"resolved": "https://registry.npm.taobao.org/rc-tree/download/rc-tree-2.1.4.tgz?cache=0&sync_timestamp=1615350038621&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-tree%2Fdownload%2Frc-tree-2.1.4.tgz",
|
||||||
"integrity": "sha512-Xey794Iavgs8YldFlXcZLOhfcIhlX5Oz/yfKufknBXf2AlZCOkc7aHqSM9uTF7fBPtTGPhPxNEfOqHfY7b7xng==",
|
"integrity": "sha1-73WfPnmaIbQ8Hs+ceU6hwU5wtZs=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ant-design/create-react-context": "^0.2.4",
|
"@ant-design/create-react-context": "^0.2.4",
|
||||||
"classnames": "2.x",
|
"classnames": "2.x",
|
||||||
|
@ -1083,8 +1088,8 @@
|
||||||
},
|
},
|
||||||
"array-tree-filter": {
|
"array-tree-filter": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/array-tree-filter/-/array-tree-filter-2.1.0.tgz",
|
"resolved": "https://registry.npm.taobao.org/array-tree-filter/download/array-tree-filter-2.1.0.tgz",
|
||||||
"integrity": "sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw=="
|
"integrity": "sha1-hzrAD+yDdJ8lWsjdCDgUtPYykZA="
|
||||||
},
|
},
|
||||||
"array-union": {
|
"array-union": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
|
@ -1254,6 +1259,55 @@
|
||||||
"ast-types-flow": "0.0.7"
|
"ast-types-flow": "0.0.7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"babel-cli": {
|
||||||
|
"version": "6.26.0",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/babel-cli/download/babel-cli-6.26.0.tgz",
|
||||||
|
"integrity": "sha1-UCq1SHTX24itALiHoGODzgPQAvE=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"babel-core": "^6.26.0",
|
||||||
|
"babel-polyfill": "^6.26.0",
|
||||||
|
"babel-register": "^6.26.0",
|
||||||
|
"babel-runtime": "^6.26.0",
|
||||||
|
"chokidar": "^1.6.1",
|
||||||
|
"commander": "^2.11.0",
|
||||||
|
"convert-source-map": "^1.5.0",
|
||||||
|
"fs-readdir-recursive": "^1.0.0",
|
||||||
|
"glob": "^7.1.2",
|
||||||
|
"lodash": "^4.17.4",
|
||||||
|
"output-file-sync": "^1.1.2",
|
||||||
|
"path-is-absolute": "^1.0.1",
|
||||||
|
"slash": "^1.0.0",
|
||||||
|
"source-map": "^0.5.6",
|
||||||
|
"v8flags": "^2.1.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"chokidar": {
|
||||||
|
"version": "1.7.0",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/chokidar/download/chokidar-1.7.0.tgz?cache=0&sync_timestamp=1602585438968&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fchokidar%2Fdownload%2Fchokidar-1.7.0.tgz",
|
||||||
|
"integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true,
|
||||||
|
"requires": {
|
||||||
|
"anymatch": "^1.3.0",
|
||||||
|
"async-each": "^1.0.0",
|
||||||
|
"fsevents": "^1.0.0",
|
||||||
|
"glob-parent": "^2.0.0",
|
||||||
|
"inherits": "^2.0.1",
|
||||||
|
"is-binary-path": "^1.0.0",
|
||||||
|
"is-glob": "^2.0.0",
|
||||||
|
"path-is-absolute": "^1.0.0",
|
||||||
|
"readdirp": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"source-map": {
|
||||||
|
"version": "0.5.7",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.5.7.tgz",
|
||||||
|
"integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"babel-code-frame": {
|
"babel-code-frame": {
|
||||||
"version": "6.26.0",
|
"version": "6.26.0",
|
||||||
"resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
|
"resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz",
|
||||||
|
@ -1273,7 +1327,7 @@
|
||||||
},
|
},
|
||||||
"babel-core": {
|
"babel-core": {
|
||||||
"version": "6.26.0",
|
"version": "6.26.0",
|
||||||
"resolved": "https://registry.npmjs.org/babel-core/-/babel-core-6.26.0.tgz",
|
"resolved": "https://registry.npm.taobao.org/babel-core/download/babel-core-6.26.0.tgz",
|
||||||
"integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=",
|
"integrity": "sha1-rzL3izGm/O8RnIew/Y2XU/A6C7g=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-code-frame": "^6.26.0",
|
"babel-code-frame": "^6.26.0",
|
||||||
|
@ -1299,8 +1353,8 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"debug": {
|
"debug": {
|
||||||
"version": "2.6.9",
|
"version": "2.6.9",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
"resolved": "https://registry.npm.taobao.org/debug/download/debug-2.6.9.tgz?cache=0&sync_timestamp=1605791507452&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-2.6.9.tgz",
|
||||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
"integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"ms": "2.0.0"
|
"ms": "2.0.0"
|
||||||
}
|
}
|
||||||
|
@ -1345,6 +1399,17 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"babel-helper-bindify-decorators": {
|
||||||
|
"version": "6.24.1",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/babel-helper-bindify-decorators/download/babel-helper-bindify-decorators-6.24.1.tgz",
|
||||||
|
"integrity": "sha1-FMGeXxQte0fxmlJDHlKxzLxAozA=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"babel-runtime": "^6.22.0",
|
||||||
|
"babel-traverse": "^6.24.1",
|
||||||
|
"babel-types": "^6.24.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"babel-helper-builder-binary-assignment-operator-visitor": {
|
"babel-helper-builder-binary-assignment-operator-visitor": {
|
||||||
"version": "6.24.1",
|
"version": "6.24.1",
|
||||||
"resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz",
|
"resolved": "https://registry.npmjs.org/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz",
|
||||||
|
@ -1397,6 +1462,18 @@
|
||||||
"babel-types": "^6.24.1"
|
"babel-types": "^6.24.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"babel-helper-explode-class": {
|
||||||
|
"version": "6.24.1",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/babel-helper-explode-class/download/babel-helper-explode-class-6.24.1.tgz",
|
||||||
|
"integrity": "sha1-fcKjkQ3uAHBW4eMdZAztPVTqqes=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"babel-helper-bindify-decorators": "^6.24.1",
|
||||||
|
"babel-runtime": "^6.22.0",
|
||||||
|
"babel-traverse": "^6.24.1",
|
||||||
|
"babel-types": "^6.24.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"babel-helper-function-name": {
|
"babel-helper-function-name": {
|
||||||
"version": "6.24.1",
|
"version": "6.24.1",
|
||||||
"resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz",
|
"resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz",
|
||||||
|
@ -1585,11 +1662,23 @@
|
||||||
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz",
|
||||||
"integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU="
|
"integrity": "sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU="
|
||||||
},
|
},
|
||||||
|
"babel-plugin-syntax-async-generators": {
|
||||||
|
"version": "6.13.0",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/babel-plugin-syntax-async-generators/download/babel-plugin-syntax-async-generators-6.13.0.tgz",
|
||||||
|
"integrity": "sha1-a8lj67FuzLrmuStZbrfzXDQqi5o=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"babel-plugin-syntax-class-properties": {
|
"babel-plugin-syntax-class-properties": {
|
||||||
"version": "6.13.0",
|
"version": "6.13.0",
|
||||||
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz",
|
||||||
"integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94="
|
"integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94="
|
||||||
},
|
},
|
||||||
|
"babel-plugin-syntax-decorators": {
|
||||||
|
"version": "6.13.0",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/babel-plugin-syntax-decorators/download/babel-plugin-syntax-decorators-6.13.0.tgz",
|
||||||
|
"integrity": "sha1-MSVjtNvePMgGzuPkFszurd0RrAs=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"babel-plugin-syntax-dynamic-import": {
|
"babel-plugin-syntax-dynamic-import": {
|
||||||
"version": "6.18.0",
|
"version": "6.18.0",
|
||||||
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz",
|
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-dynamic-import/-/babel-plugin-syntax-dynamic-import-6.18.0.tgz",
|
||||||
|
@ -1620,6 +1709,17 @@
|
||||||
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz",
|
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz",
|
||||||
"integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM="
|
"integrity": "sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM="
|
||||||
},
|
},
|
||||||
|
"babel-plugin-transform-async-generator-functions": {
|
||||||
|
"version": "6.24.1",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/babel-plugin-transform-async-generator-functions/download/babel-plugin-transform-async-generator-functions-6.24.1.tgz",
|
||||||
|
"integrity": "sha1-8FiQAUX9PpkHpt3yjaWfIVJYpds=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"babel-helper-remap-async-to-generator": "^6.24.1",
|
||||||
|
"babel-plugin-syntax-async-generators": "^6.5.0",
|
||||||
|
"babel-runtime": "^6.22.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"babel-plugin-transform-async-to-generator": {
|
"babel-plugin-transform-async-to-generator": {
|
||||||
"version": "6.24.1",
|
"version": "6.24.1",
|
||||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz",
|
"resolved": "https://registry.npmjs.org/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz",
|
||||||
|
@ -1641,6 +1741,19 @@
|
||||||
"babel-template": "^6.24.1"
|
"babel-template": "^6.24.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"babel-plugin-transform-decorators": {
|
||||||
|
"version": "6.24.1",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/babel-plugin-transform-decorators/download/babel-plugin-transform-decorators-6.24.1.tgz",
|
||||||
|
"integrity": "sha1-eIAT2PjGtSIr33s0Q5Df13Vp4k0=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"babel-helper-explode-class": "^6.24.1",
|
||||||
|
"babel-plugin-syntax-decorators": "^6.13.0",
|
||||||
|
"babel-runtime": "^6.22.0",
|
||||||
|
"babel-template": "^6.24.1",
|
||||||
|
"babel-types": "^6.24.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"babel-plugin-transform-es2015-arrow-functions": {
|
"babel-plugin-transform-es2015-arrow-functions": {
|
||||||
"version": "6.22.0",
|
"version": "6.22.0",
|
||||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz",
|
"resolved": "https://registry.npmjs.org/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz",
|
||||||
|
@ -1935,7 +2048,7 @@
|
||||||
},
|
},
|
||||||
"babel-plugin-transform-runtime": {
|
"babel-plugin-transform-runtime": {
|
||||||
"version": "6.23.0",
|
"version": "6.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/babel-plugin-transform-runtime/-/babel-plugin-transform-runtime-6.23.0.tgz",
|
"resolved": "https://registry.npm.taobao.org/babel-plugin-transform-runtime/download/babel-plugin-transform-runtime-6.23.0.tgz",
|
||||||
"integrity": "sha1-iEkNRGUC6puOfvsP4J7E2ZR5se4=",
|
"integrity": "sha1-iEkNRGUC6puOfvsP4J7E2ZR5se4=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "^6.22.0"
|
"babel-runtime": "^6.22.0"
|
||||||
|
@ -1950,6 +2063,25 @@
|
||||||
"babel-types": "^6.24.1"
|
"babel-types": "^6.24.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"babel-polyfill": {
|
||||||
|
"version": "6.26.0",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/babel-polyfill/download/babel-polyfill-6.26.0.tgz",
|
||||||
|
"integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"babel-runtime": "^6.26.0",
|
||||||
|
"core-js": "^2.5.0",
|
||||||
|
"regenerator-runtime": "^0.10.5"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"regenerator-runtime": {
|
||||||
|
"version": "0.10.5",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/regenerator-runtime/download/regenerator-runtime-0.10.5.tgz?cache=0&sync_timestamp=1595456367497&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fregenerator-runtime%2Fdownload%2Fregenerator-runtime-0.10.5.tgz",
|
||||||
|
"integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"babel-preset-env": {
|
"babel-preset-env": {
|
||||||
"version": "1.6.1",
|
"version": "1.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/babel-preset-env/-/babel-preset-env-1.6.1.tgz",
|
||||||
|
@ -1987,6 +2119,38 @@
|
||||||
"semver": "^5.3.0"
|
"semver": "^5.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"babel-preset-es2015": {
|
||||||
|
"version": "6.24.1",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/babel-preset-es2015/download/babel-preset-es2015-6.24.1.tgz",
|
||||||
|
"integrity": "sha1-1EBQ1rwsn+6nAqrzjXJ6AhBTiTk=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"babel-plugin-check-es2015-constants": "^6.22.0",
|
||||||
|
"babel-plugin-transform-es2015-arrow-functions": "^6.22.0",
|
||||||
|
"babel-plugin-transform-es2015-block-scoped-functions": "^6.22.0",
|
||||||
|
"babel-plugin-transform-es2015-block-scoping": "^6.24.1",
|
||||||
|
"babel-plugin-transform-es2015-classes": "^6.24.1",
|
||||||
|
"babel-plugin-transform-es2015-computed-properties": "^6.24.1",
|
||||||
|
"babel-plugin-transform-es2015-destructuring": "^6.22.0",
|
||||||
|
"babel-plugin-transform-es2015-duplicate-keys": "^6.24.1",
|
||||||
|
"babel-plugin-transform-es2015-for-of": "^6.22.0",
|
||||||
|
"babel-plugin-transform-es2015-function-name": "^6.24.1",
|
||||||
|
"babel-plugin-transform-es2015-literals": "^6.22.0",
|
||||||
|
"babel-plugin-transform-es2015-modules-amd": "^6.24.1",
|
||||||
|
"babel-plugin-transform-es2015-modules-commonjs": "^6.24.1",
|
||||||
|
"babel-plugin-transform-es2015-modules-systemjs": "^6.24.1",
|
||||||
|
"babel-plugin-transform-es2015-modules-umd": "^6.24.1",
|
||||||
|
"babel-plugin-transform-es2015-object-super": "^6.24.1",
|
||||||
|
"babel-plugin-transform-es2015-parameters": "^6.24.1",
|
||||||
|
"babel-plugin-transform-es2015-shorthand-properties": "^6.24.1",
|
||||||
|
"babel-plugin-transform-es2015-spread": "^6.22.0",
|
||||||
|
"babel-plugin-transform-es2015-sticky-regex": "^6.24.1",
|
||||||
|
"babel-plugin-transform-es2015-template-literals": "^6.22.0",
|
||||||
|
"babel-plugin-transform-es2015-typeof-symbol": "^6.22.0",
|
||||||
|
"babel-plugin-transform-es2015-unicode-regex": "^6.24.1",
|
||||||
|
"babel-plugin-transform-regenerator": "^6.24.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"babel-preset-flow": {
|
"babel-preset-flow": {
|
||||||
"version": "6.23.0",
|
"version": "6.23.0",
|
||||||
"resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz",
|
"resolved": "https://registry.npmjs.org/babel-preset-flow/-/babel-preset-flow-6.23.0.tgz",
|
||||||
|
@ -2005,7 +2169,7 @@
|
||||||
},
|
},
|
||||||
"babel-preset-react": {
|
"babel-preset-react": {
|
||||||
"version": "6.24.1",
|
"version": "6.24.1",
|
||||||
"resolved": "https://registry.npmjs.org/babel-preset-react/-/babel-preset-react-6.24.1.tgz",
|
"resolved": "https://registry.npm.taobao.org/babel-preset-react/download/babel-preset-react-6.24.1.tgz",
|
||||||
"integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=",
|
"integrity": "sha1-umnfrqRfw+xjm2pOzqbhdwLJE4A=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-plugin-syntax-jsx": "^6.3.13",
|
"babel-plugin-syntax-jsx": "^6.3.13",
|
||||||
|
@ -2036,6 +2200,31 @@
|
||||||
"babel-preset-react": "6.24.1"
|
"babel-preset-react": "6.24.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"babel-preset-stage-2": {
|
||||||
|
"version": "6.24.1",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/babel-preset-stage-2/download/babel-preset-stage-2-6.24.1.tgz",
|
||||||
|
"integrity": "sha1-2eKWD7PXEYfw5k7sYrwHdnIZvcE=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"babel-plugin-syntax-dynamic-import": "^6.18.0",
|
||||||
|
"babel-plugin-transform-class-properties": "^6.24.1",
|
||||||
|
"babel-plugin-transform-decorators": "^6.24.1",
|
||||||
|
"babel-preset-stage-3": "^6.24.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"babel-preset-stage-3": {
|
||||||
|
"version": "6.24.1",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/babel-preset-stage-3/download/babel-preset-stage-3-6.24.1.tgz",
|
||||||
|
"integrity": "sha1-g2raCp56f6N8sTj7kyb4eTSkg5U=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"babel-plugin-syntax-trailing-function-commas": "^6.22.0",
|
||||||
|
"babel-plugin-transform-async-generator-functions": "^6.24.1",
|
||||||
|
"babel-plugin-transform-async-to-generator": "^6.24.1",
|
||||||
|
"babel-plugin-transform-exponentiation-operator": "^6.24.1",
|
||||||
|
"babel-plugin-transform-object-rest-spread": "^6.22.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"babel-register": {
|
"babel-register": {
|
||||||
"version": "6.26.0",
|
"version": "6.26.0",
|
||||||
"resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz",
|
"resolved": "https://registry.npmjs.org/babel-register/-/babel-register-6.26.0.tgz",
|
||||||
|
@ -3576,8 +3765,8 @@
|
||||||
},
|
},
|
||||||
"copy-to-clipboard": {
|
"copy-to-clipboard": {
|
||||||
"version": "3.3.1",
|
"version": "3.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz",
|
"resolved": "https://registry.npm.taobao.org/copy-to-clipboard/download/copy-to-clipboard-3.3.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcopy-to-clipboard%2Fdownload%2Fcopy-to-clipboard-3.3.1.tgz",
|
||||||
"integrity": "sha512-i13qo6kIHTTpCm8/Wup+0b1mVWETvu2kIMzKoK8FpkLkFxlt0znUAHcMzox+T8sPlqtZXq3CulEjQHsYiGFJUw==",
|
"integrity": "sha1-EVqhqZmP+rYZb5MHatbaO5E2Yq4=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"toggle-selection": "^1.0.6"
|
"toggle-selection": "^1.0.6"
|
||||||
}
|
}
|
||||||
|
@ -4663,7 +4852,7 @@
|
||||||
},
|
},
|
||||||
"dom-closest": {
|
"dom-closest": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/dom-closest/-/dom-closest-0.2.0.tgz",
|
"resolved": "https://registry.npm.taobao.org/dom-closest/download/dom-closest-0.2.0.tgz",
|
||||||
"integrity": "sha1-69n5HRvyLo1vR3h2u80+yQIWwM8=",
|
"integrity": "sha1-69n5HRvyLo1vR3h2u80+yQIWwM8=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"dom-matches": ">=1.0.1"
|
"dom-matches": ">=1.0.1"
|
||||||
|
@ -4707,7 +4896,7 @@
|
||||||
},
|
},
|
||||||
"dom-matches": {
|
"dom-matches": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/dom-matches/-/dom-matches-2.0.0.tgz",
|
"resolved": "https://registry.npm.taobao.org/dom-matches/download/dom-matches-2.0.0.tgz",
|
||||||
"integrity": "sha1-0nKLQWqHUzmA6wibhI0lPPI6dYw="
|
"integrity": "sha1-0nKLQWqHUzmA6wibhI0lPPI6dYw="
|
||||||
},
|
},
|
||||||
"dom-scroll-into-view": {
|
"dom-scroll-into-view": {
|
||||||
|
@ -4778,6 +4967,11 @@
|
||||||
"domelementtype": "1"
|
"domelementtype": "1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"dompurify": {
|
||||||
|
"version": "2.0.15",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/dompurify/download/dompurify-2.0.15.tgz?cache=0&sync_timestamp=1607352578938&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdompurify%2Fdownload%2Fdompurify-2.0.15.tgz",
|
||||||
|
"integrity": "sha1-gOMA/D6JVHvQrxr/LrqIzhf8neo="
|
||||||
|
},
|
||||||
"domutils": {
|
"domutils": {
|
||||||
"version": "1.5.1",
|
"version": "1.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
|
||||||
|
@ -4824,8 +5018,8 @@
|
||||||
},
|
},
|
||||||
"draft-js": {
|
"draft-js": {
|
||||||
"version": "0.10.5",
|
"version": "0.10.5",
|
||||||
"resolved": "https://registry.npmjs.org/draft-js/-/draft-js-0.10.5.tgz",
|
"resolved": "https://registry.npm.taobao.org/draft-js/download/draft-js-0.10.5.tgz",
|
||||||
"integrity": "sha512-LE6jSCV9nkPhfVX2ggcRLA4FKs6zWq9ceuO/88BpXdNCS7mjRTgs0NsV6piUCJX9YxMsB9An33wnkMmU2sD2Zg==",
|
"integrity": "sha1-v6m+sBj+BTPbsI1mdcNxprCPp0I=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"fbjs": "^0.8.15",
|
"fbjs": "^0.8.15",
|
||||||
"immutable": "~3.7.4",
|
"immutable": "~3.7.4",
|
||||||
|
@ -4955,7 +5149,7 @@
|
||||||
},
|
},
|
||||||
"enquire.js": {
|
"enquire.js": {
|
||||||
"version": "2.1.6",
|
"version": "2.1.6",
|
||||||
"resolved": "https://registry.npmjs.org/enquire.js/-/enquire.js-2.1.6.tgz",
|
"resolved": "https://registry.npm.taobao.org/enquire.js/download/enquire.js-2.1.6.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fenquire.js%2Fdownload%2Fenquire.js-2.1.6.tgz",
|
||||||
"integrity": "sha1-PoeAybi4NQhMP2DhZtvDwqPImBQ="
|
"integrity": "sha1-PoeAybi4NQhMP2DhZtvDwqPImBQ="
|
||||||
},
|
},
|
||||||
"entities": {
|
"entities": {
|
||||||
|
@ -5474,7 +5668,7 @@
|
||||||
},
|
},
|
||||||
"eventlistener": {
|
"eventlistener": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/eventlistener/-/eventlistener-0.0.1.tgz",
|
"resolved": "https://registry.npm.taobao.org/eventlistener/download/eventlistener-0.0.1.tgz",
|
||||||
"integrity": "sha1-7Suqu4UiJ68rz4iRUscsY8pTLrg="
|
"integrity": "sha1-7Suqu4UiJ68rz4iRUscsY8pTLrg="
|
||||||
},
|
},
|
||||||
"events": {
|
"events": {
|
||||||
|
@ -6888,6 +7082,12 @@
|
||||||
"minipass": "^3.0.0"
|
"minipass": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"fs-readdir-recursive": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/fs-readdir-recursive/download/fs-readdir-recursive-1.1.0.tgz",
|
||||||
|
"integrity": "sha1-4y/AMKLM7kSmtTcTCNpUvgs5fSc=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"fs-write-stream-atomic": {
|
"fs-write-stream-atomic": {
|
||||||
"version": "1.0.10",
|
"version": "1.0.10",
|
||||||
"resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz",
|
"resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz",
|
||||||
|
@ -7725,7 +7925,7 @@
|
||||||
},
|
},
|
||||||
"hammerjs": {
|
"hammerjs": {
|
||||||
"version": "2.0.8",
|
"version": "2.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz",
|
"resolved": "https://registry.npm.taobao.org/hammerjs/download/hammerjs-2.0.8.tgz",
|
||||||
"integrity": "sha1-BO93hiz/K7edMPdpIJWTAiK/YPE="
|
"integrity": "sha1-BO93hiz/K7edMPdpIJWTAiK/YPE="
|
||||||
},
|
},
|
||||||
"handle-thing": {
|
"handle-thing": {
|
||||||
|
@ -8566,7 +8766,7 @@
|
||||||
},
|
},
|
||||||
"immutable": {
|
"immutable": {
|
||||||
"version": "3.7.6",
|
"version": "3.7.6",
|
||||||
"resolved": "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz",
|
"resolved": "https://registry.npm.taobao.org/immutable/download/immutable-3.7.6.tgz",
|
||||||
"integrity": "sha1-E7TTyxK++hVIKib+Gy665kAHHks="
|
"integrity": "sha1-E7TTyxK++hVIKib+Gy665kAHHks="
|
||||||
},
|
},
|
||||||
"import-fresh": {
|
"import-fresh": {
|
||||||
|
@ -8980,9 +9180,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"is-mobile": {
|
"is-mobile": {
|
||||||
"version": "2.2.1",
|
"version": "2.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/is-mobile/-/is-mobile-2.2.1.tgz",
|
"resolved": "https://registry.nlark.com/is-mobile/download/is-mobile-2.2.2.tgz",
|
||||||
"integrity": "sha512-6zELsfVFr326eq2CI53yvqq6YBanOxKBybwDT+MbMS2laBnK6Ez8m5XHSuTQQbnKRfpDzCod1CMWW5q3wZYMvA=="
|
"integrity": "sha1-9snF1Q7gElTOBec5vdg18e1OmVQ="
|
||||||
},
|
},
|
||||||
"is-npm": {
|
"is-npm": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
|
@ -10154,7 +10354,7 @@
|
||||||
},
|
},
|
||||||
"lodash.throttle": {
|
"lodash.throttle": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
|
"resolved": "https://registry.npm.taobao.org/lodash.throttle/download/lodash.throttle-4.1.1.tgz",
|
||||||
"integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ="
|
"integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ="
|
||||||
},
|
},
|
||||||
"lodash.uniq": {
|
"lodash.uniq": {
|
||||||
|
@ -11209,8 +11409,8 @@
|
||||||
},
|
},
|
||||||
"omit.js": {
|
"omit.js": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/omit.js/-/omit.js-1.0.2.tgz",
|
"resolved": "https://registry.npm.taobao.org/omit.js/download/omit.js-1.0.2.tgz",
|
||||||
"integrity": "sha512-/QPc6G2NS+8d4L/cQhbk6Yit1WTB6Us2g84A7A/1+w9d/eRGHyEqC5kkQtHVoHZ5NFWGG7tUGgrhVZwgZanKrQ==",
|
"integrity": "sha1-kaFPDrqEBm36AVvzDkdMR/MLyFg=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "^6.23.0"
|
"babel-runtime": "^6.23.0"
|
||||||
}
|
}
|
||||||
|
@ -11339,6 +11539,17 @@
|
||||||
"os-tmpdir": "^1.0.0"
|
"os-tmpdir": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"output-file-sync": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/output-file-sync/download/output-file-sync-1.1.2.tgz",
|
||||||
|
"integrity": "sha1-0KM+7+YaIF+suQCS6CZZjVJFznY=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"graceful-fs": "^4.1.4",
|
||||||
|
"mkdirp": "^0.5.1",
|
||||||
|
"object-assign": "^4.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"p-defer": {
|
"p-defer": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz",
|
||||||
|
@ -14002,9 +14213,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rc-calendar": {
|
"rc-calendar": {
|
||||||
"version": "9.15.10",
|
"version": "9.15.11",
|
||||||
"resolved": "https://registry.npmjs.org/rc-calendar/-/rc-calendar-9.15.10.tgz",
|
"resolved": "https://registry.npm.taobao.org/rc-calendar/download/rc-calendar-9.15.11.tgz",
|
||||||
"integrity": "sha512-xh1A3rYejKskAvkjnd9BcHXFbBnAYsHMGHBdtoAkbwp43B6yEieNL0g0Tzz8s1gApDZV2j5vF1jJ9IIpPYFNLw==",
|
"integrity": "sha1-zh5eqOTXdDW+ZqjHfbEvHw+aNF8=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "6.x",
|
"babel-runtime": "6.x",
|
||||||
"classnames": "2.x",
|
"classnames": "2.x",
|
||||||
|
@ -14017,8 +14228,8 @@
|
||||||
},
|
},
|
||||||
"rc-cascader": {
|
"rc-cascader": {
|
||||||
"version": "0.17.5",
|
"version": "0.17.5",
|
||||||
"resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-0.17.5.tgz",
|
"resolved": "https://registry.npm.taobao.org/rc-cascader/download/rc-cascader-0.17.5.tgz?cache=0&sync_timestamp=1610107054432&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-cascader%2Fdownload%2Frc-cascader-0.17.5.tgz",
|
||||||
"integrity": "sha512-WYMVcxU0+Lj+xLr4YYH0+yXODumvNXDcVEs5i7L1mtpWwYkubPV/zbQpn+jGKFCIW/hOhjkU4J1db8/P/UKE7A==",
|
"integrity": "sha1-T96R0jt2CMQgJjw47unAaH+A99w=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"array-tree-filter": "^2.1.0",
|
"array-tree-filter": "^2.1.0",
|
||||||
"prop-types": "^15.5.8",
|
"prop-types": "^15.5.8",
|
||||||
|
@ -14031,8 +14242,8 @@
|
||||||
},
|
},
|
||||||
"rc-checkbox": {
|
"rc-checkbox": {
|
||||||
"version": "2.1.8",
|
"version": "2.1.8",
|
||||||
"resolved": "https://registry.npmjs.org/rc-checkbox/-/rc-checkbox-2.1.8.tgz",
|
"resolved": "https://registry.npm.taobao.org/rc-checkbox/download/rc-checkbox-2.1.8.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-checkbox%2Fdownload%2Frc-checkbox-2.1.8.tgz",
|
||||||
"integrity": "sha512-6qOgh0/by0nVNASx6LZnhRTy17Etcgav+IrI7kL9V9kcDZ/g7K14JFlqrtJ3NjDq/Kyn+BPI1st1XvbkhfaJeg==",
|
"integrity": "sha1-7t2e+cLzr1s7jlzeUlSqia0aiAo=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "^6.23.0",
|
"babel-runtime": "^6.23.0",
|
||||||
"classnames": "2.x",
|
"classnames": "2.x",
|
||||||
|
@ -14042,8 +14253,8 @@
|
||||||
},
|
},
|
||||||
"rc-collapse": {
|
"rc-collapse": {
|
||||||
"version": "1.11.8",
|
"version": "1.11.8",
|
||||||
"resolved": "https://registry.npmjs.org/rc-collapse/-/rc-collapse-1.11.8.tgz",
|
"resolved": "https://registry.npm.taobao.org/rc-collapse/download/rc-collapse-1.11.8.tgz?cache=0&sync_timestamp=1606217065785&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-collapse%2Fdownload%2Frc-collapse-1.11.8.tgz",
|
||||||
"integrity": "sha512-8EhfPyScTYljkbRuIoHniSwZagD5UPpZ3CToYgoNYWC85L2qCbPYF7+OaC713FOrIkp6NbfNqXsITNxmDAmxog==",
|
"integrity": "sha1-ZqQAidRpUZ6UJACasckn4hQEHYA=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"classnames": "2.x",
|
"classnames": "2.x",
|
||||||
"css-animation": "1.x",
|
"css-animation": "1.x",
|
||||||
|
@ -14056,8 +14267,8 @@
|
||||||
},
|
},
|
||||||
"rc-dialog": {
|
"rc-dialog": {
|
||||||
"version": "7.6.1",
|
"version": "7.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-7.6.1.tgz",
|
"resolved": "https://registry.npm.taobao.org/rc-dialog/download/rc-dialog-7.6.1.tgz?cache=0&sync_timestamp=1614949683544&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-dialog%2Fdownload%2Frc-dialog-7.6.1.tgz",
|
||||||
"integrity": "sha512-KUKf+2eZ4YL+lnXMG3hR4ZtIhC9glfH27NtTVz3gcoDIPAf3uUvaXVRNoDCiSi+OGKLyIb/b6EoidFh6nQC5Wg==",
|
"integrity": "sha1-EVRczAuUWTT6dgeXJuDYU+UtcF8=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "6.x",
|
"babel-runtime": "6.x",
|
||||||
"rc-animate": "2.x",
|
"rc-animate": "2.x",
|
||||||
|
@ -14066,8 +14277,8 @@
|
||||||
},
|
},
|
||||||
"rc-drawer": {
|
"rc-drawer": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/rc-drawer/-/rc-drawer-3.1.3.tgz",
|
"resolved": "https://registry.npm.taobao.org/rc-drawer/download/rc-drawer-3.1.3.tgz?cache=0&sync_timestamp=1614159639291&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-drawer%2Fdownload%2Frc-drawer-3.1.3.tgz",
|
||||||
"integrity": "sha512-2z+RdxmzXyZde/1OhVMfDR1e/GBswFeWSZ7FS3Fdd0qhgVdpV1wSzILzzxRaT481ItB5hOV+e8pZT07vdJE8kg==",
|
"integrity": "sha1-y8sE1MB/C2by7OEdhH9KG9gOoLc=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"rc-util": "^4.16.1",
|
"rc-util": "^4.16.1",
|
||||||
|
@ -14076,8 +14287,8 @@
|
||||||
},
|
},
|
||||||
"rc-dropdown": {
|
"rc-dropdown": {
|
||||||
"version": "2.4.1",
|
"version": "2.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-2.4.1.tgz",
|
"resolved": "https://registry.npm.taobao.org/rc-dropdown/download/rc-dropdown-2.4.1.tgz?cache=0&sync_timestamp=1600332782526&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-dropdown%2Fdownload%2Frc-dropdown-2.4.1.tgz",
|
||||||
"integrity": "sha512-p0XYn0wrOpAZ2fUGE6YJ6U8JBNc5ASijznZ6dkojdaEfQJAeZtV9KMEewhxkVlxGSbbdXe10ptjBlTEW9vEwEg==",
|
"integrity": "sha1-qu9us6UVLN2ZgolcKnjZtfBGzew=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "^6.26.0",
|
"babel-runtime": "^6.26.0",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
|
@ -14088,8 +14299,8 @@
|
||||||
},
|
},
|
||||||
"rc-editor-core": {
|
"rc-editor-core": {
|
||||||
"version": "0.8.10",
|
"version": "0.8.10",
|
||||||
"resolved": "https://registry.npmjs.org/rc-editor-core/-/rc-editor-core-0.8.10.tgz",
|
"resolved": "https://registry.npm.taobao.org/rc-editor-core/download/rc-editor-core-0.8.10.tgz",
|
||||||
"integrity": "sha512-T3aHpeMCIYA1sdAI7ynHHjXy5fqp83uPlD68ovZ0oClTSc3tbHmyCxXlA+Ti4YgmcpCYv7avF6a+TIbAka53kw==",
|
"integrity": "sha1-byFbxd+cM/+p9sWzDKc6favoq3w=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "^6.26.0",
|
"babel-runtime": "^6.26.0",
|
||||||
"classnames": "^2.2.5",
|
"classnames": "^2.2.5",
|
||||||
|
@ -14102,8 +14313,8 @@
|
||||||
},
|
},
|
||||||
"rc-editor-mention": {
|
"rc-editor-mention": {
|
||||||
"version": "1.1.13",
|
"version": "1.1.13",
|
||||||
"resolved": "https://registry.npmjs.org/rc-editor-mention/-/rc-editor-mention-1.1.13.tgz",
|
"resolved": "https://registry.npm.taobao.org/rc-editor-mention/download/rc-editor-mention-1.1.13.tgz",
|
||||||
"integrity": "sha512-3AOmGir91Fi2ogfRRaXLtqlNuIwQpvla7oUnGHS1+3eo7b+fUp5IlKcagqtwUBB5oDNofoySXkLBxzWvSYNp/Q==",
|
"integrity": "sha1-nxyrEGX4awFSOEAyF5DCqxKsXos=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "^6.23.0",
|
"babel-runtime": "^6.23.0",
|
||||||
"classnames": "^2.2.5",
|
"classnames": "^2.2.5",
|
||||||
|
@ -14131,9 +14342,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rc-hammerjs": {
|
"rc-hammerjs": {
|
||||||
"version": "0.6.9",
|
"version": "0.6.10",
|
||||||
"resolved": "https://registry.npmjs.org/rc-hammerjs/-/rc-hammerjs-0.6.9.tgz",
|
"resolved": "https://registry.npm.taobao.org/rc-hammerjs/download/rc-hammerjs-0.6.10.tgz",
|
||||||
"integrity": "sha512-4llgWO3RgLyVbEqUdGsDfzUDqklRlQW5VEhE3x35IvhV+w//VPRG34SBavK3D2mD/UaLKaohgU41V4agiftC8g==",
|
"integrity": "sha1-GDGjvY8hmXAL/MWtayCjVjCuteA=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "6.x",
|
"babel-runtime": "6.x",
|
||||||
"hammerjs": "^2.0.8",
|
"hammerjs": "^2.0.8",
|
||||||
|
@ -14141,9 +14352,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rc-input-number": {
|
"rc-input-number": {
|
||||||
"version": "4.5.6",
|
"version": "4.5.9",
|
||||||
"resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-4.5.6.tgz",
|
"resolved": "https://registry.nlark.com/rc-input-number/download/rc-input-number-4.5.9.tgz?cache=0&sync_timestamp=1619578110950&other_urls=https%3A%2F%2Fregistry.nlark.com%2Frc-input-number%2Fdownload%2Frc-input-number-4.5.9.tgz",
|
||||||
"integrity": "sha512-AXbL4gtQ1mSQnu6v/JtMv3UbGRCzLvQznmf0a7U/SAtZ8+dCEAqD4JpJhkjv73Wog53eRYhw4l7ApdXflc9ymg==",
|
"integrity": "sha1-HL9zXiT+I8TrmkMBAxcguV8qPj0=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "6.x",
|
"babel-runtime": "6.x",
|
||||||
"classnames": "^2.2.0",
|
"classnames": "^2.2.0",
|
||||||
|
@ -14154,8 +14365,8 @@
|
||||||
},
|
},
|
||||||
"rc-mentions": {
|
"rc-mentions": {
|
||||||
"version": "0.4.2",
|
"version": "0.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-0.4.2.tgz",
|
"resolved": "https://registry.npm.taobao.org/rc-mentions/download/rc-mentions-0.4.2.tgz?cache=0&sync_timestamp=1610510822768&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-mentions%2Fdownload%2Frc-mentions-0.4.2.tgz",
|
||||||
"integrity": "sha512-DTZurQzacLXOfVuiHydGzqkq7cFMHXF18l2jZ9PhWUn2cqvOSY3W4osN0Pq29AOMOBpcxdZCzgc7Lb0r/bgkDw==",
|
"integrity": "sha1-wYq3Ae+55LdbOFGgwNLdaYZA4kY=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ant-design/create-react-context": "^0.2.4",
|
"@ant-design/create-react-context": "^0.2.4",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
|
@ -14183,8 +14394,8 @@
|
||||||
},
|
},
|
||||||
"rc-notification": {
|
"rc-notification": {
|
||||||
"version": "3.3.1",
|
"version": "3.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-3.3.1.tgz",
|
"resolved": "https://registry.npm.taobao.org/rc-notification/download/rc-notification-3.3.1.tgz?cache=0&sync_timestamp=1614675471156&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-notification%2Fdownload%2Frc-notification-3.3.1.tgz",
|
||||||
"integrity": "sha512-U5+f4BmBVfMSf3OHSLyRagsJ74yKwlrQAtbbL5ijoA0F2C60BufwnOcHG18tVprd7iaIjzZt1TKMmQSYSvgrig==",
|
"integrity": "sha1-C6o+cPjUCrAVzo+njCYMSQ/HvrQ=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "6.x",
|
"babel-runtime": "6.x",
|
||||||
"classnames": "2.x",
|
"classnames": "2.x",
|
||||||
|
@ -14205,9 +14416,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rc-progress": {
|
"rc-progress": {
|
||||||
"version": "2.5.2",
|
"version": "2.5.3",
|
||||||
"resolved": "https://registry.npmjs.org/rc-progress/-/rc-progress-2.5.2.tgz",
|
"resolved": "https://registry.npm.taobao.org/rc-progress/download/rc-progress-2.5.3.tgz",
|
||||||
"integrity": "sha512-ajI+MJkbBz9zYDuE9GQsY5gsyqPF7HFioZEDZ9Fmc+ebNZoiSeSJsTJImPFCg0dW/5WiRGUy2F69SX1aPtSJgA==",
|
"integrity": "sha1-APAblb2+GFbTpfgiQgUZAui3qOc=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "6.x",
|
"babel-runtime": "6.x",
|
||||||
"prop-types": "^15.5.8"
|
"prop-types": "^15.5.8"
|
||||||
|
@ -14224,8 +14435,8 @@
|
||||||
},
|
},
|
||||||
"rc-resize-observer": {
|
"rc-resize-observer": {
|
||||||
"version": "0.1.3",
|
"version": "0.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-0.1.3.tgz",
|
"resolved": "https://registry.npm.taobao.org/rc-resize-observer/download/rc-resize-observer-0.1.3.tgz?cache=0&sync_timestamp=1608864858155&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-resize-observer%2Fdownload%2Frc-resize-observer-0.1.3.tgz",
|
||||||
"integrity": "sha512-uzOQEwx83xdQSFOkOAM7x7GHIQKYnrDV4dWxtCxyG1BS1pkfJ4EvDeMfsvAJHSYkQXVBu+sgRHGbRtLG3qiuUg==",
|
"integrity": "sha1-CXGR+cOrGG7ZB7VTum71Zd8Rwkk=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"classnames": "^2.2.1",
|
"classnames": "^2.2.1",
|
||||||
"rc-util": "^4.13.0",
|
"rc-util": "^4.13.0",
|
||||||
|
@ -14253,8 +14464,8 @@
|
||||||
},
|
},
|
||||||
"rc-slider": {
|
"rc-slider": {
|
||||||
"version": "8.7.1",
|
"version": "8.7.1",
|
||||||
"resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-8.7.1.tgz",
|
"resolved": "https://registry.npm.taobao.org/rc-slider/download/rc-slider-8.7.1.tgz?cache=0&sync_timestamp=1616675519253&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-slider%2Fdownload%2Frc-slider-8.7.1.tgz",
|
||||||
"integrity": "sha512-WMT5mRFUEcrLWwTxsyS8jYmlaMsTVCZIGENLikHsNv+tE8ThU2lCoPfi/xFNUfJFNFSBFP3MwPez9ZsJmNp13g==",
|
"integrity": "sha1-ntBzYtyTSJo45lSyG4EirXD9PEI=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "6.x",
|
"babel-runtime": "6.x",
|
||||||
"classnames": "^2.2.5",
|
"classnames": "^2.2.5",
|
||||||
|
@ -14268,8 +14479,8 @@
|
||||||
},
|
},
|
||||||
"rc-steps": {
|
"rc-steps": {
|
||||||
"version": "3.5.0",
|
"version": "3.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/rc-steps/-/rc-steps-3.5.0.tgz",
|
"resolved": "https://registry.npm.taobao.org/rc-steps/download/rc-steps-3.5.0.tgz",
|
||||||
"integrity": "sha512-2Vkkrpa7PZbg7qPsqTNzVDov4u78cmxofjjnIHiGB9+9rqKS8oTLPzbW2uiWDr3Lk+yGwh8rbpGO1E6VAgBCOg==",
|
"integrity": "sha1-NrKn8fSZB7DZA2OISxhiPK+ftgA=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "^6.23.0",
|
"babel-runtime": "^6.23.0",
|
||||||
"classnames": "^2.2.3",
|
"classnames": "^2.2.3",
|
||||||
|
@ -14278,9 +14489,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rc-switch": {
|
"rc-switch": {
|
||||||
"version": "1.9.0",
|
"version": "1.9.2",
|
||||||
"resolved": "https://registry.npmjs.org/rc-switch/-/rc-switch-1.9.0.tgz",
|
"resolved": "https://registry.npm.taobao.org/rc-switch/download/rc-switch-1.9.2.tgz?cache=0&sync_timestamp=1603791200779&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-switch%2Fdownload%2Frc-switch-1.9.2.tgz",
|
||||||
"integrity": "sha512-Isas+egaK6qSk64jaEw4GgPStY4umYDbT7ZY93bZF1Af+b/JEsKsJdNOU2qG3WI0Z6tXo2DDq0kJCv8Yhu0zww==",
|
"integrity": "sha1-eSHHZkEf6aZCZRDDQpAi1rpN/eI=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"classnames": "^2.2.1",
|
"classnames": "^2.2.1",
|
||||||
"prop-types": "^15.5.6",
|
"prop-types": "^15.5.6",
|
||||||
|
@ -14289,8 +14500,8 @@
|
||||||
},
|
},
|
||||||
"rc-table": {
|
"rc-table": {
|
||||||
"version": "6.10.15",
|
"version": "6.10.15",
|
||||||
"resolved": "https://registry.npmjs.org/rc-table/-/rc-table-6.10.15.tgz",
|
"resolved": "https://registry.nlark.com/rc-table/download/rc-table-6.10.15.tgz",
|
||||||
"integrity": "sha512-LAr0M/gqt+irOjvPNBLApmQ0CUHNOfKsEBhu1uIuB3OlN1ynA9z+sdoTQyNd9+8NSl0MYnQOOfhtLChAY7nU0A==",
|
"integrity": "sha1-GB9McMT9dPZX7o8jGW5+sIoDZco=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"classnames": "^2.2.5",
|
"classnames": "^2.2.5",
|
||||||
"component-classes": "^1.2.6",
|
"component-classes": "^1.2.6",
|
||||||
|
@ -14304,8 +14515,8 @@
|
||||||
},
|
},
|
||||||
"rc-tabs": {
|
"rc-tabs": {
|
||||||
"version": "9.7.0",
|
"version": "9.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-9.7.0.tgz",
|
"resolved": "https://registry.npm.taobao.org/rc-tabs/download/rc-tabs-9.7.0.tgz?cache=0&sync_timestamp=1608866453009&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-tabs%2Fdownload%2Frc-tabs-9.7.0.tgz",
|
||||||
"integrity": "sha512-kvmgp8/MfLzFZ06hWHignqomFQ5nF7BqKr5O1FfhE4VKsGrep52YSF/1MvS5oe0NPcI9XGNS2p751C5v6cYDpQ==",
|
"integrity": "sha1-rglpW+9ZY9bmTnvBBSHHbf3YRIs=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ant-design/create-react-context": "^0.2.4",
|
"@ant-design/create-react-context": "^0.2.4",
|
||||||
"babel-runtime": "6.x",
|
"babel-runtime": "6.x",
|
||||||
|
@ -14322,8 +14533,8 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"raf": {
|
"raf": {
|
||||||
"version": "3.4.1",
|
"version": "3.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
|
"resolved": "https://registry.npm.taobao.org/raf/download/raf-3.4.1.tgz",
|
||||||
"integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
|
"integrity": "sha1-B0LpmkplUvRF1z4+4DKK8P8e3jk=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"performance-now": "^2.1.0"
|
"performance-now": "^2.1.0"
|
||||||
}
|
}
|
||||||
|
@ -14332,8 +14543,8 @@
|
||||||
},
|
},
|
||||||
"rc-time-picker": {
|
"rc-time-picker": {
|
||||||
"version": "3.7.3",
|
"version": "3.7.3",
|
||||||
"resolved": "https://registry.npmjs.org/rc-time-picker/-/rc-time-picker-3.7.3.tgz",
|
"resolved": "https://registry.npm.taobao.org/rc-time-picker/download/rc-time-picker-3.7.3.tgz?cache=0&sync_timestamp=1576572941972&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-time-picker%2Fdownload%2Frc-time-picker-3.7.3.tgz",
|
||||||
"integrity": "sha512-Lv1Mvzp9fRXhXEnRLO4nW6GLNxUkfAZ3RsiIBsWjGjXXvMNjdr4BX/ayElHAFK0DoJqOhm7c5tjmIYpEOwcUXg==",
|
"integrity": "sha1-ZajekECTJQrpyCsCpJBeD5leI+I=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"classnames": "2.x",
|
"classnames": "2.x",
|
||||||
"moment": "2.x",
|
"moment": "2.x",
|
||||||
|
@ -14345,8 +14556,8 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"raf": {
|
"raf": {
|
||||||
"version": "3.4.1",
|
"version": "3.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
|
"resolved": "https://registry.npm.taobao.org/raf/download/raf-3.4.1.tgz",
|
||||||
"integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
|
"integrity": "sha1-B0LpmkplUvRF1z4+4DKK8P8e3jk=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"performance-now": "^2.1.0"
|
"performance-now": "^2.1.0"
|
||||||
}
|
}
|
||||||
|
@ -14355,8 +14566,8 @@
|
||||||
},
|
},
|
||||||
"rc-tooltip": {
|
"rc-tooltip": {
|
||||||
"version": "3.7.3",
|
"version": "3.7.3",
|
||||||
"resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-3.7.3.tgz",
|
"resolved": "https://registry.npm.taobao.org/rc-tooltip/download/rc-tooltip-3.7.3.tgz?cache=0&sync_timestamp=1614588684791&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-tooltip%2Fdownload%2Frc-tooltip-3.7.3.tgz",
|
||||||
"integrity": "sha512-dE2ibukxxkrde7wH9W8ozHKUO4aQnPZ6qBHtrTH9LoO836PjDdiaWO73fgPB05VfJs9FbZdmGPVEbXCeOP99Ww==",
|
"integrity": "sha1-KArsavyqROjf8EgPuv+eh/wArsw=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "6.x",
|
"babel-runtime": "6.x",
|
||||||
"prop-types": "^15.5.8",
|
"prop-types": "^15.5.8",
|
||||||
|
@ -14404,8 +14615,8 @@
|
||||||
},
|
},
|
||||||
"rc-tree-select": {
|
"rc-tree-select": {
|
||||||
"version": "2.9.4",
|
"version": "2.9.4",
|
||||||
"resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-2.9.4.tgz",
|
"resolved": "https://registry.nlark.com/rc-tree-select/download/rc-tree-select-2.9.4.tgz",
|
||||||
"integrity": "sha512-0HQkXAN4XbfBW20CZYh3G+V+VMrjX42XRtDCpyv6PDUm5vikC0Ob682ZBCVS97Ww2a5Hf6Ajmu0ahWEdIEpwhg==",
|
"integrity": "sha1-aqeU4fDmXGbEBqoKKg50/QpVewk=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"classnames": "^2.2.1",
|
"classnames": "^2.2.1",
|
||||||
"dom-scroll-into-view": "^1.2.1",
|
"dom-scroll-into-view": "^1.2.1",
|
||||||
|
@ -14422,8 +14633,8 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"rc-tree": {
|
"rc-tree": {
|
||||||
"version": "2.1.4",
|
"version": "2.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-2.1.4.tgz",
|
"resolved": "https://registry.npm.taobao.org/rc-tree/download/rc-tree-2.1.4.tgz?cache=0&sync_timestamp=1615350038621&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-tree%2Fdownload%2Frc-tree-2.1.4.tgz",
|
||||||
"integrity": "sha512-Xey794Iavgs8YldFlXcZLOhfcIhlX5Oz/yfKufknBXf2AlZCOkc7aHqSM9uTF7fBPtTGPhPxNEfOqHfY7b7xng==",
|
"integrity": "sha1-73WfPnmaIbQ8Hs+ceU6hwU5wtZs=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ant-design/create-react-context": "^0.2.4",
|
"@ant-design/create-react-context": "^0.2.4",
|
||||||
"classnames": "2.x",
|
"classnames": "2.x",
|
||||||
|
@ -14436,8 +14647,8 @@
|
||||||
},
|
},
|
||||||
"rc-trigger": {
|
"rc-trigger": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-3.0.0.tgz",
|
"resolved": "https://registry.nlark.com/rc-trigger/download/rc-trigger-3.0.0.tgz?cache=0&sync_timestamp=1619590696046&other_urls=https%3A%2F%2Fregistry.nlark.com%2Frc-trigger%2Fdownload%2Frc-trigger-3.0.0.tgz",
|
||||||
"integrity": "sha512-hQxbbJpo23E2QnYczfq3Ec5J5tVl2mUDhkqxrEsQAqk16HfADQg+iKNWzEYXyERSncdxfnzYuaBgy764mNRzTA==",
|
"integrity": "sha1-9tmx2oomsrLR2RKgaHbBpIb1mA8=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "6.x",
|
"babel-runtime": "6.x",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
|
@ -14449,18 +14660,14 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"rc-animate": {
|
"rc-animate": {
|
||||||
"version": "3.0.0-rc.6",
|
"version": "3.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/rc-animate/-/rc-animate-3.0.0-rc.6.tgz",
|
"resolved": "https://registry.npm.taobao.org/rc-animate/download/rc-animate-3.1.1.tgz?cache=0&sync_timestamp=1601018005635&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-animate%2Fdownload%2Frc-animate-3.1.1.tgz",
|
||||||
"integrity": "sha512-oBLPpiT6Q4t6YvD/pkLcmofBP1p01TX0Otse8Q4+Mxt8J+VSDflLZGIgf62EwkvRwsQUkLPjZVFBsldnPKLzjg==",
|
"integrity": "sha1-3v3YY/VoFsIiU05Nxo/t3s0IE4Y=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "6.x",
|
"@ant-design/css-animation": "^1.7.2",
|
||||||
"classnames": "^2.2.5",
|
"classnames": "^2.2.6",
|
||||||
"component-classes": "^1.2.6",
|
|
||||||
"fbjs": "^0.8.16",
|
|
||||||
"prop-types": "15.x",
|
|
||||||
"raf": "^3.4.0",
|
"raf": "^3.4.0",
|
||||||
"rc-util": "^4.5.0",
|
"rc-util": "^4.15.3"
|
||||||
"react-lifecycles-compat": "^3.0.4"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14899,9 +15106,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"react-lazy-load": {
|
"react-lazy-load": {
|
||||||
"version": "3.0.13",
|
"version": "3.1.13",
|
||||||
"resolved": "https://registry.npmjs.org/react-lazy-load/-/react-lazy-load-3.0.13.tgz",
|
"resolved": "https://registry.npm.taobao.org/react-lazy-load/download/react-lazy-load-3.1.13.tgz?cache=0&sync_timestamp=1593654792284&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freact-lazy-load%2Fdownload%2Freact-lazy-load-3.1.13.tgz",
|
||||||
"integrity": "sha1-OwqS0zbUPT8Nc8vm81sXBQsIuCQ=",
|
"integrity": "sha1-I2lD92twhMyEWHFtljKhyYU+pc0=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"eventlistener": "0.0.1",
|
"eventlistener": "0.0.1",
|
||||||
"lodash.debounce": "^4.0.0",
|
"lodash.debounce": "^4.0.0",
|
||||||
|
@ -15039,8 +15246,8 @@
|
||||||
},
|
},
|
||||||
"react-slick": {
|
"react-slick": {
|
||||||
"version": "0.25.2",
|
"version": "0.25.2",
|
||||||
"resolved": "https://registry.npmjs.org/react-slick/-/react-slick-0.25.2.tgz",
|
"resolved": "https://registry.nlark.com/react-slick/download/react-slick-0.25.2.tgz",
|
||||||
"integrity": "sha512-8MNH/NFX/R7zF6W/w+FS5VXNyDusF+XDW1OU0SzODEU7wqYB+ZTGAiNJ++zVNAVqCAHdyCybScaUB+FCZOmBBw==",
|
"integrity": "sha1-VjMbZ9R9i8/i3OtqyrHI/VvR9rw=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"classnames": "^2.2.5",
|
"classnames": "^2.2.5",
|
||||||
"enquire.js": "^2.1.6",
|
"enquire.js": "^2.1.6",
|
||||||
|
@ -15884,8 +16091,8 @@
|
||||||
},
|
},
|
||||||
"rmc-feedback": {
|
"rmc-feedback": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/rmc-feedback/-/rmc-feedback-2.0.0.tgz",
|
"resolved": "https://registry.npm.taobao.org/rmc-feedback/download/rmc-feedback-2.0.0.tgz",
|
||||||
"integrity": "sha512-5PWOGOW7VXks/l3JzlOU9NIxRpuaSS8d9zA3UULUCuTKnpwBHNvv1jSJzxgbbCQeYzROWUpgKI4za3X4C/mKmQ==",
|
"integrity": "sha1-y8bLOuY8emNe7w4l5PuvWsNm7qo=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "6.x",
|
"babel-runtime": "6.x",
|
||||||
"classnames": "^2.2.5"
|
"classnames": "^2.2.5"
|
||||||
|
@ -16468,8 +16675,8 @@
|
||||||
},
|
},
|
||||||
"shallow-equal": {
|
"shallow-equal": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.1.tgz",
|
"resolved": "https://registry.npm.taobao.org/shallow-equal/download/shallow-equal-1.2.1.tgz",
|
||||||
"integrity": "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA=="
|
"integrity": "sha1-TBar+lYEOqINBQMk76aJQLDaedo="
|
||||||
},
|
},
|
||||||
"shallowequal": {
|
"shallowequal": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
|
@ -17010,8 +17217,8 @@
|
||||||
},
|
},
|
||||||
"source-map-support": {
|
"source-map-support": {
|
||||||
"version": "0.4.18",
|
"version": "0.4.18",
|
||||||
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz",
|
"resolved": "https://registry.npm.taobao.org/source-map-support/download/source-map-support-0.4.18.tgz?cache=0&sync_timestamp=1587719517036&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsource-map-support%2Fdownload%2Fsource-map-support-0.4.18.tgz",
|
||||||
"integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==",
|
"integrity": "sha1-Aoam3ovkJkEzhZTpfM6nXwosWF8=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"source-map": "^0.5.6"
|
"source-map": "^0.5.6"
|
||||||
},
|
},
|
||||||
|
@ -18666,6 +18873,12 @@
|
||||||
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
|
||||||
"integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ=="
|
"integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ=="
|
||||||
},
|
},
|
||||||
|
"user-home": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/user-home/download/user-home-1.1.1.tgz",
|
||||||
|
"integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"util": {
|
"util": {
|
||||||
"version": "0.11.1",
|
"version": "0.11.1",
|
||||||
"resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz",
|
"resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz",
|
||||||
|
@ -18717,6 +18930,15 @@
|
||||||
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz",
|
||||||
"integrity": "sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w=="
|
"integrity": "sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w=="
|
||||||
},
|
},
|
||||||
|
"v8flags": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/v8flags/download/v8flags-2.1.1.tgz?cache=0&sync_timestamp=1590964281452&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fv8flags%2Fdownload%2Fv8flags-2.1.1.tgz",
|
||||||
|
"integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"user-home": "^1.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"validate-npm-package-license": {
|
"validate-npm-package-license": {
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
|
||||||
|
@ -20254,6 +20476,16 @@
|
||||||
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
|
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"xterm": {
|
||||||
|
"version": "4.8.1",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/xterm/download/xterm-4.8.1.tgz",
|
||||||
|
"integrity": "sha1-FVoXKaQ+Gom0BlJOIsVjQznjnKE="
|
||||||
|
},
|
||||||
|
"xterm-addon-fit": {
|
||||||
|
"version": "0.4.0",
|
||||||
|
"resolved": "https://registry.npm.taobao.org/xterm-addon-fit/download/xterm-addon-fit-0.4.0.tgz",
|
||||||
|
"integrity": "sha1-BuDF0KaqrPsAnvVl76HIHpPZAZM="
|
||||||
|
},
|
||||||
"y18n": {
|
"y18n": {
|
||||||
"version": "3.2.1",
|
"version": "3.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
|
||||||
|
|
14
package.json
14
package.json
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"name": "educoder",
|
"name": "forge",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -10,7 +10,6 @@
|
||||||
"array-flatten": "^2.1.2",
|
"array-flatten": "^2.1.2",
|
||||||
"autoprefixer": "7.1.6",
|
"autoprefixer": "7.1.6",
|
||||||
"axios": "^0.18.1",
|
"axios": "^0.18.1",
|
||||||
"babel-core": "6.26.0",
|
|
||||||
"babel-eslint": "7.2.3",
|
"babel-eslint": "7.2.3",
|
||||||
"babel-jest": "20.0.3",
|
"babel-jest": "20.0.3",
|
||||||
"babel-loader": "7.1.2",
|
"babel-loader": "7.1.2",
|
||||||
|
@ -27,6 +26,7 @@
|
||||||
"codemirror": "^5.53.0",
|
"codemirror": "^5.53.0",
|
||||||
"connected-react-router": "4.4.1",
|
"connected-react-router": "4.4.1",
|
||||||
"css-loader": "^3.5.2",
|
"css-loader": "^3.5.2",
|
||||||
|
"dompurify": "^2.0.15",
|
||||||
"dotenv": "4.0.0",
|
"dotenv": "4.0.0",
|
||||||
"dotenv-expand": "4.2.0",
|
"dotenv-expand": "4.2.0",
|
||||||
"echarts": "^4.7.0",
|
"echarts": "^4.7.0",
|
||||||
|
@ -111,7 +111,9 @@
|
||||||
"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",
|
||||||
|
@ -182,7 +184,13 @@
|
||||||
"port": "3007",
|
"port": "3007",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/runtime": "7.0.0-beta.51",
|
"@babel/runtime": "7.0.0-beta.51",
|
||||||
|
"babel-cli": "^6.26.0",
|
||||||
|
"babel-core": "^6.26.0",
|
||||||
"babel-plugin-import": "^1.13.0",
|
"babel-plugin-import": "^1.13.0",
|
||||||
|
"babel-plugin-transform-runtime": "^6.23.0",
|
||||||
|
"babel-preset-es2015": "^6.24.1",
|
||||||
|
"babel-preset-react": "^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",
|
||||||
"happypack": "^5.0.1",
|
"happypack": "^5.0.1",
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -2325,6 +2325,9 @@ input::-ms-clear {
|
||||||
background-color: #F5F5F5;
|
background-color: #F5F5F5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ant-modal-close{
|
||||||
|
top:8px!important;
|
||||||
|
}
|
||||||
|
|
||||||
.newContainer {
|
.newContainer {
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
|
@ -2343,7 +2346,6 @@ input::-ms-clear {
|
||||||
/*中间部分宽度固定为1200*/
|
/*中间部分宽度固定为1200*/
|
||||||
.newMain {
|
.newMain {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding-bottom: 110px;
|
|
||||||
min-width: 1200px;
|
min-width: 1200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2658,7 +2660,7 @@ a.color-green:hover {
|
||||||
|
|
||||||
/*百分比宽度*/
|
/*百分比宽度*/
|
||||||
.width100 {
|
.width100 {
|
||||||
width: 100%;
|
width: 100% !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.width89 {
|
.width89 {
|
||||||
|
@ -4105,21 +4107,6 @@ 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;
|
||||||
|
@ -6715,4 +6702,13 @@ ul.count_ul li:not(:last-child):after {
|
||||||
}
|
}
|
||||||
input.ant-input-lg::placeholder{
|
input.ant-input-lg::placeholder{
|
||||||
font-size: 14px !important;
|
font-size: 14px !important;
|
||||||
|
}
|
||||||
|
p{
|
||||||
|
margin-bottom: 0px!important;
|
||||||
|
}
|
||||||
|
.toprightNum{
|
||||||
|
position: absolute;
|
||||||
|
right: 0px;
|
||||||
|
top:4px;
|
||||||
|
color: #999;
|
||||||
}
|
}
|
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 584 KiB After Width: | Height: | Size: 733 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,111 @@
|
||||||
|
|
||||||
|
.CodeMirror-merge {
|
||||||
|
position: relative;
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-merge, .CodeMirror-merge .CodeMirror {
|
||||||
|
min-height:50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-merge-2pane .CodeMirror-merge-pane { width: 48%; }
|
||||||
|
.CodeMirror-merge-2pane .CodeMirror-merge-gap { width: 4%; }
|
||||||
|
.CodeMirror-merge-3pane .CodeMirror-merge-pane { width: 31%; }
|
||||||
|
.CodeMirror-merge-3pane .CodeMirror-merge-gap { width: 3.5%; }
|
||||||
|
|
||||||
|
.CodeMirror-merge-pane {
|
||||||
|
display: inline-block;
|
||||||
|
white-space: normal;
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
.CodeMirror-merge-pane-rightmost {
|
||||||
|
position: absolute;
|
||||||
|
right: 0px;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-merge-gap {
|
||||||
|
z-index: 2;
|
||||||
|
display: inline-block;
|
||||||
|
height: 100%;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
background: #515151;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-merge-scrolllock-wrap {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0; left: 50%;
|
||||||
|
}
|
||||||
|
.CodeMirror-merge-scrolllock {
|
||||||
|
position: relative;
|
||||||
|
left: -50%;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #d8d8d8;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-merge-copybuttons-left, .CodeMirror-merge-copybuttons-right {
|
||||||
|
position: absolute;
|
||||||
|
left: 0; top: 0;
|
||||||
|
right: 0; bottom: 0;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-merge-copy {
|
||||||
|
position: absolute;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #ce374b;
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-merge-copy-reverse {
|
||||||
|
position: absolute;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #44c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-merge-copybuttons-left .CodeMirror-merge-copy { left: 2px; }
|
||||||
|
.CodeMirror-merge-copybuttons-right .CodeMirror-merge-copy { right: 2px; }
|
||||||
|
|
||||||
|
.CodeMirror-merge-r-inserted, .CodeMirror-merge-l-inserted {
|
||||||
|
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAGUlEQVQI12MwuCXy3+CWyH8GBgYGJgYkAABZbAQ9ELXurwAAAABJRU5ErkJggg==);
|
||||||
|
background-position: bottom left;
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-merge-r-deleted, .CodeMirror-merge-l-deleted {
|
||||||
|
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAGUlEQVQI12M4Kyb2/6yY2H8GBgYGJgYkAABURgPz6Ks7wQAAAABJRU5ErkJggg==);
|
||||||
|
background-position: bottom left;
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-merge-r-chunk { background: #9a6868; }
|
||||||
|
.CodeMirror-merge-r-chunk-start { /*border-top: 1px solid #ee8; */}
|
||||||
|
.CodeMirror-merge-r-chunk-end {/* border-bottom: 1px solid #ee8; */}
|
||||||
|
.CodeMirror-merge-r-connect { fill:#9a6868;}
|
||||||
|
|
||||||
|
.CodeMirror-merge-l-chunk { background: #eef; }
|
||||||
|
.CodeMirror-merge-l-chunk-start { border-top: 1px solid #88e; }
|
||||||
|
.CodeMirror-merge-l-chunk-end { border-bottom: 1px solid #88e; }
|
||||||
|
.CodeMirror-merge-l-connect { fill: #eef; stroke: #88e; stroke-width: 1px; }
|
||||||
|
|
||||||
|
.CodeMirror-merge-l-chunk.CodeMirror-merge-r-chunk { background: #dfd; }
|
||||||
|
.CodeMirror-merge-l-chunk-start.CodeMirror-merge-r-chunk-start { border-top: 1px solid #4e4; }
|
||||||
|
.CodeMirror-merge-l-chunk-end.CodeMirror-merge-r-chunk-end { border-bottom: 1px solid #4e4; }
|
||||||
|
|
||||||
|
.CodeMirror-merge-collapsed-widget:before {
|
||||||
|
content: "(...)";
|
||||||
|
}
|
||||||
|
.CodeMirror-merge-collapsed-widget {
|
||||||
|
cursor: pointer;
|
||||||
|
color: #88b;
|
||||||
|
background: #eef;
|
||||||
|
border: 1px solid #ddf;
|
||||||
|
font-size: 90%;
|
||||||
|
padding: 0 3px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
.CodeMirror-merge-collapsed-line .CodeMirror-gutter-elt { display: none; }
|
|
@ -8,18 +8,9 @@
|
||||||
<meta name=”Description” Content=”持续构建协同、共享、可信的软件创建生态开源创作与软件生产相结合,支持大规模群体开展软件协同创新活动”>
|
<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">
|
||||||
<!-- <script type="text/javascript">
|
|
||||||
window.__isR = true;
|
<link rel="stylesheet" type="text/css" href="%PUBLIC_URL%css/iconfont.css">
|
||||||
if (
|
<link rel="stylesheet" type="text/css" href="%PUBLIC_URL%css/edu-purge.css">
|
||||||
(navigator.userAgent.indexOf('MSIE 9') != -1
|
|
||||||
|| navigator.userAgent.indexOf('MSIE 10') != -1)
|
|
||||||
&&
|
|
||||||
location.pathname.indexOf("/compatibility") == -1) {
|
|
||||||
location.href = '/compatibility.html'
|
|
||||||
}
|
|
||||||
</script> -->
|
|
||||||
<link rel=" stylesheet" type="text/css" href="%PUBLIC_URL%css/iconfont.css">
|
|
||||||
<link rel=" stylesheet" type="text/css" href="%PUBLIC_URL%css/edu-purge.css">
|
|
||||||
<link rel="stylesheet" type="text/css" href="%PUBLIC_URL%css/editormd.min.css">
|
<link rel="stylesheet" type="text/css" href="%PUBLIC_URL%css/editormd.min.css">
|
||||||
<link rel="stylesheet" type="text/css" href="%PUBLIC_URL%css/merge.css">
|
<link rel="stylesheet" type="text/css" href="%PUBLIC_URL%css/merge.css">
|
||||||
<%= htmlWebpackPlugin.tags.headTags %>
|
<%= htmlWebpackPlugin.tags.headTags %>
|
||||||
|
@ -30,6 +21,7 @@
|
||||||
<div id="root" class="page -layout-v -fit widthunit"></div>
|
<div id="root" class="page -layout-v -fit widthunit"></div>
|
||||||
<div id="picture_display" style="display: none;"></div>
|
<div id="picture_display" style="display: none;"></div>
|
||||||
<script src="%PUBLIC_URL%js/jquery-1.8.3.min.js"></script>
|
<script src="%PUBLIC_URL%js/jquery-1.8.3.min.js"></script>
|
||||||
|
<script src="%PUBLIC_URL%js/js_min_all.js"></script>
|
||||||
<script src="%PUBLIC_URL%js/codemirror/codemirror.js"></script>
|
<script src="%PUBLIC_URL%js/codemirror/codemirror.js"></script>
|
||||||
<script src="%PUBLIC_URL%js/editormd/editormd.min.js"></script>
|
<script src="%PUBLIC_URL%js/editormd/editormd.min.js"></script>
|
||||||
<script src="%PUBLIC_URL%js/codemirror/merge/merge.js"></script>
|
<script src="%PUBLIC_URL%js/codemirror/merge/merge.js"></script>
|
||||||
|
|
31
src/App.js
31
src/App.js
|
@ -9,13 +9,7 @@ import {
|
||||||
} from 'react-router-dom';
|
} from 'react-router-dom';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import LoginDialog from './modules/login/LoginDialog';
|
import LoginDialog from './modules/login/LoginDialog';
|
||||||
import Notcompletedysl from './modules/user/Notcompletedysl';
|
import 'babel-polyfill';
|
||||||
import Trialapplicationysl from './modules/login/Trialapplicationysl';
|
|
||||||
import Trialapplicationreview from './modules/user/Trialapplicationreview';
|
|
||||||
import AccountProfile from "./modules/user/AccountProfile";
|
|
||||||
import Accountnewprofile from './modules/user/Accountnewprofile';
|
|
||||||
import Certifiedprofessional from './modules/modals/Certifiedprofessional';
|
|
||||||
|
|
||||||
import Loading from './Loading'
|
import Loading from './Loading'
|
||||||
|
|
||||||
import Loadable from 'react-loadable';
|
import Loadable from 'react-loadable';
|
||||||
|
@ -76,6 +70,10 @@ const OrganizeIndex = Loadable({
|
||||||
loader: () => import('./forge/Team/Index'),
|
loader: () => import('./forge/Team/Index'),
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
})
|
})
|
||||||
|
const EducoderLogin = Loadable({
|
||||||
|
loader: () => import('./modules/login/EducoderLogin'),
|
||||||
|
loading: Loading,
|
||||||
|
})
|
||||||
|
|
||||||
class App extends Component {
|
class App extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -213,18 +211,12 @@ class App extends Component {
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<ConfigProvider locale={zhCN}>
|
<ConfigProvider locale={zhCN}>
|
||||||
<MuiThemeProvider theme={theme}>
|
<MuiThemeProvider theme={theme}>
|
||||||
{/* <Accountnewprofile {...this.props}{...this.state} /> */}
|
|
||||||
<LoginDialog {...this.props} {...this.state} Modifyloginvalue={() => this.Modifyloginvalue()}></LoginDialog>
|
<LoginDialog {...this.props} {...this.state} Modifyloginvalue={() => this.Modifyloginvalue()}></LoginDialog>
|
||||||
{/* <Notcompletedysl {...this.props} {...this.state}></Notcompletedysl> */}
|
|
||||||
{/* <Trialapplicationysl {...this.props} {...this.state}></Trialapplicationysl> */}
|
|
||||||
{/* <Trialapplicationreview {...this.props} {...this.state}></Trialapplicationreview> */}
|
|
||||||
{/* <AccountProfile {...this.props} {...this.state} /> */}
|
|
||||||
{/* <Certifiedprofessional {...this.props} {...this.state} ModalCancelsy={this.ModalCancelsy} ModalshowCancelsy={this.ModalshowCancelsy} /> */}
|
|
||||||
<Router>
|
<Router>
|
||||||
<Switch>
|
<Switch>
|
||||||
{/*项目*/}
|
{/*项目*/}
|
||||||
<Route
|
<Route
|
||||||
path={"/projects/:projectId/ops/:opsId/detail"}
|
path={"/projects/:owner/:projectId/devops/:opsId/detail"}
|
||||||
render={
|
render={
|
||||||
(props) => {
|
(props) => {
|
||||||
return (<OpsDetail {...this.props} {...props} {...this.state} />)
|
return (<OpsDetail {...this.props} {...props} {...this.state} />)
|
||||||
|
@ -240,7 +232,14 @@ class App extends Component {
|
||||||
}
|
}
|
||||||
}>
|
}>
|
||||||
</Route>
|
</Route>
|
||||||
|
<Route
|
||||||
|
path="/register"
|
||||||
|
render={
|
||||||
|
(props) => {
|
||||||
|
return (<EducoderLogin {...this.props} {...props} {...this.state} />)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/>
|
||||||
{/*403*/}
|
{/*403*/}
|
||||||
<Route path="/403" component={Shixunauthority} />
|
<Route path="/403" component={Shixunauthority} />
|
||||||
|
|
||||||
|
@ -248,7 +247,7 @@ class App extends Component {
|
||||||
<Route path={"/organize"}
|
<Route path={"/organize"}
|
||||||
render={
|
render={
|
||||||
(props) => {
|
(props) => {
|
||||||
return (<OrganizeIndex {...this.props} {...props} {...this.state} />)
|
return (<OrganizeIndex {...props} {...this.props} {...this.state} />)
|
||||||
}
|
}
|
||||||
}>
|
}>
|
||||||
</Route>
|
</Route>
|
||||||
|
|
|
@ -2,19 +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';
|
|
||||||
let message501 = false;
|
|
||||||
|
|
||||||
|
import './index.css';
|
||||||
|
|
||||||
|
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
|
||||||
} else {
|
|
||||||
window.location.href = list
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO 开发期多个身份切换
|
// TODO 开发期多个身份切换
|
||||||
|
@ -26,56 +24,22 @@ 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) {
|
|
||||||
console.log("123")
|
|
||||||
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()
|
// 判断网络是否连接
|
||||||
// TODO 避免重复的请求 https://github.com/axios/axios#cancellation
|
initOnlineOfflineListener();
|
||||||
var
|
|
||||||
proxy = "http://localhost:3000"
|
|
||||||
proxy = "https://testforgeplus.trustie.net"
|
|
||||||
|
|
||||||
const requestMap = {};
|
var proxy = "https://testforgeplus.trustie.net";
|
||||||
window.setfalseInRequestMap = function (keyName) {
|
|
||||||
requestMap[keyName] = false;
|
|
||||||
}
|
|
||||||
//响应前的设置
|
//响应前的设置
|
||||||
axios.interceptors.request.use(
|
axios.interceptors.request.use(
|
||||||
config => {
|
config => {
|
||||||
setpostcookie()
|
if(config.url.indexOf("http") !== -1) {
|
||||||
clearAllCookie()
|
|
||||||
|
|
||||||
if (config.url.indexOf(proxy) !== -1 || config.url.indexOf(':') !== -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`) {
|
||||||
|
@ -89,18 +53,12 @@ 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;
|
||||||
},
|
},
|
||||||
err => {
|
err => {
|
||||||
return Promise.reject(err);
|
return Promise.reject(err);
|
||||||
});
|
});
|
||||||
|
|
||||||
axios.interceptors.response.use(function (response) {
|
axios.interceptors.response.use(function (response) {
|
||||||
if (response === undefined) {
|
if (response === undefined) {
|
||||||
|
@ -149,8 +107,6 @@ 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,7 +1,4 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
|
|
||||||
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
|
|
||||||
|
|
||||||
import { Spin } from 'antd';
|
import { Spin } from 'antd';
|
||||||
|
|
||||||
class Loading extends Component {
|
class Loading extends Component {
|
||||||
|
@ -12,7 +9,6 @@ class Loading extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
// Loading
|
|
||||||
return (
|
return (
|
||||||
<div className="App" style={{ minHeight: '800px', width: "100%" }}>
|
<div className="App" style={{ minHeight: '800px', width: "100%" }}>
|
||||||
<style>
|
<style>
|
||||||
|
|
|
@ -11,11 +11,26 @@ 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 = 'https://testforgeplus.trustie.net';
|
||||||
if (isDev) {
|
if (isDev) {
|
||||||
return `${local}/${path}`
|
return `${local}/${path}`
|
||||||
}
|
}
|
||||||
return `/${path}`;
|
return `${path}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getImage(path) {
|
||||||
|
// https://www.educoder.net
|
||||||
|
// https://testbdweb.trustie.net
|
||||||
|
// const local = 'http://localhost:3000'
|
||||||
|
const local = 'https://testforgeplus.trustie.net/';
|
||||||
|
if(path.indexOf("http://")===-1){
|
||||||
|
if (isDev) {
|
||||||
|
return `${local}/images/${path}`
|
||||||
|
}
|
||||||
|
return `/${path}`;
|
||||||
|
}else{
|
||||||
|
return path;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getcdnImageUrl(path) {
|
export function getcdnImageUrl(path) {
|
||||||
|
@ -147,28 +162,28 @@ export function getmyUrl(geturl) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getUploadActionUrl(path, goTest) {
|
export function getUploadActionUrl(path, goTest) {
|
||||||
return `${getUrl()}/api/attachments.json?debug=${window._debugType || 'admin'}`;
|
return `${getUrl()}/api/attachments.json${isDev ?`${isDev ?`?debug=${window._debugType || 'admin'}` : ""}` : ""}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getUploadLogoActionUrl() {
|
export function getUploadLogoActionUrl() {
|
||||||
return `${getUrl()}/api/resumes/logo.json?debug=${window._debugType || 'admin'}`;
|
return `${getUrl()}/api/resumes/logo.json${isDev ?`?debug=${window._debugType || 'admin'}` : ""}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getUploadActionUrltwo(id) {
|
export function getUploadActionUrltwo(id) {
|
||||||
return `${getUrlmys()}/api/shixuns/${id}/upload_data_sets.json?debug=${window._debugType || 'admin'}`
|
return `${getUrlmys()}/api/shixuns/${id}/upload_data_sets.json${isDev ?`?debug=${window._debugType || 'admin'}` : ""}`
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getUploadActionUrlthree() {
|
export function getUploadActionUrlthree() {
|
||||||
return `${getUrlmys()}/api/jupyters/import_with_tpm.json?debug=${window._debugType || 'admin'}`
|
return `${getUrlmys()}/api/jupyters/import_with_tpm.json${isDev ?`?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?debug=${window._debugType || 'admin'}`
|
return `${getUrlmys()}/api/shixuns/${id}/upload_git_file.json${isDev ?`?debug=${window._debugType || 'admin'}` : ""}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function getUploadActionUrlOfAuth(id) {
|
export function getUploadActionUrlOfAuth(id) {
|
||||||
return `${getUrl()}/api/users/accounts/${id}/auth_attachment.json?debug=${window._debugType || 'admin'}`
|
return `${getUrl()}/api/users/accounts/${id}/auth_attachment.json${isDev ?`?debug=${window._debugType || 'admin'}` : ""}`
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getRandomNumber(type) {
|
export function getRandomNumber(type) {
|
||||||
|
|
|
@ -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(`images/${author.image_url}`) : 'https://b-ssl.duitang.com/uploads/item/201511/13/20151113110434_kyReJ.jpeg'}
|
src={author.image_url ? getImageUrl(`/${author.image_url}`) : 'https://b-ssl.duitang.com/uploads/item/201511/13/20151113110434_kyReJ.jpeg'}
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
@ -38,13 +38,11 @@ export const formatDelta = (deltas) => {
|
||||||
alt="${alt}"
|
alt="${alt}"
|
||||||
/>
|
/>
|
||||||
`;
|
`;
|
||||||
// text = "<img src="+url+" width='60px' height='30px' onclick='' alt="+alt+"/>";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
formatted.push(text);
|
formatted.push(text);
|
||||||
});
|
});
|
||||||
console.log(formatted);
|
|
||||||
return formatted.join('');
|
return formatted.join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
export {
|
export {
|
||||||
getUploadLogoActionUrl as getUploadLogoActionUrl,
|
getUploadLogoActionUrl as getUploadLogoActionUrl,
|
||||||
getImageUrl as getImageUrl, 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
|
||||||
} from './UrlTool';
|
} from './UrlTool';
|
||||||
|
@ -76,10 +76,4 @@ export { default as AliyunUploader } from './components/media/AliyunUploader'
|
||||||
export { default as ImageLayer2 } from './hooks/ImageLayer2'
|
export { default as ImageLayer2 } from './hooks/ImageLayer2'
|
||||||
|
|
||||||
// 外部
|
// 外部
|
||||||
export { default as CBreadcrumb } from '../modules/courses/common/CBreadcrumb'
|
|
||||||
export { CNotificationHOC as CNotificationHOC } from '../modules/courses/common/CNotificationHOC'
|
export { CNotificationHOC as CNotificationHOC } from '../modules/courses/common/CNotificationHOC'
|
||||||
export { default as ModalWrapper } from '../modules/courses/common/ModalWrapper'
|
|
||||||
export { default as NoneData } from '../modules/courses/coursesPublic/NoneData'
|
|
||||||
|
|
||||||
export { default as WordNumberTextarea } from '../modules/modals/WordNumberTextarea'
|
|
||||||
|
|
||||||
|
|
|
@ -48,15 +48,15 @@ function buildToc(coll, k, level, ctx) {
|
||||||
});
|
});
|
||||||
ctx.push("</ul>")
|
ctx.push("</ul>")
|
||||||
}
|
}
|
||||||
ctx.push("</li>")
|
ctx.push("</li>");
|
||||||
k = buildToc(coll, k, level, ctx)
|
k = buildToc(coll, k, level, ctx)
|
||||||
return k
|
return k
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getTocContent() {
|
export function getTocContent() {
|
||||||
buildToc(toc, 0, 0, ctx)
|
buildToc(toc, 0, 0, ctx);
|
||||||
ctx.push("</ul>")
|
ctx.push("</ul>");
|
||||||
return ctx.join("")
|
return ctx.join("");
|
||||||
}
|
}
|
||||||
|
|
||||||
const tokenizer = {
|
const tokenizer = {
|
||||||
|
@ -157,7 +157,6 @@ renderer.heading = function (text, level, raw) {
|
||||||
})
|
})
|
||||||
return '<h' + level + ' id="' + anchor + '">' + text + '</h' + level + '>'
|
return '<h' + level + ' id="' + anchor + '">' + text + '</h' + level + '>'
|
||||||
}
|
}
|
||||||
|
|
||||||
marked.setOptions({
|
marked.setOptions({
|
||||||
silent: true,
|
silent: true,
|
||||||
smartypants: true,
|
smartypants: true,
|
||||||
|
|
|
@ -1,37 +1,58 @@
|
||||||
import React, { useEffect, useRef, useMemo } from "react";
|
import React, { useEffect, useRef, useMemo } from 'react'
|
||||||
import "katex/dist/katex.min.css";
|
import 'katex/dist/katex.min.css'
|
||||||
import { renderToString } from 'katex';
|
import marked, { getTocContent, cleanToc, getMathExpressions, resetMathExpressions } from '../common/marked';
|
||||||
import marked, { getTocContent, cleanToc, getMathExpressions, resetMathExpressions } from "../common/marked";
|
|
||||||
import 'code-prettify'
|
import 'code-prettify'
|
||||||
|
import dompurify from 'dompurify';
|
||||||
|
|
||||||
|
import { renderToString } from 'katex'
|
||||||
|
|
||||||
const preRegex = /<pre[^>]*>/g
|
const preRegex = /<pre[^>]*>/g
|
||||||
|
|
||||||
function _unescape(str) {
|
function _unescape(str) {
|
||||||
let div = document.createElement('div')
|
let div = document.createElement('div')
|
||||||
div.innerHTML = str
|
div.innerHTML = str
|
||||||
return div.childNodes.length === 0 ? "" : div.childNodes[0].nodeValue;
|
return div.childNodes.length === 0 ? "" : div.childNodes[0].nodeValue
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ({ value = '', className, style = {} }) => {
|
|
||||||
let str = String(value)
|
|
||||||
|
|
||||||
|
|
||||||
|
export default ({
|
||||||
|
value = '',
|
||||||
|
className,
|
||||||
|
style = {},
|
||||||
|
url
|
||||||
|
}) => {
|
||||||
|
let str = String(value);
|
||||||
const html = useMemo(() => {
|
const html = useMemo(() => {
|
||||||
let rs = marked(str)
|
let rs = marked(str);
|
||||||
const math_expressions = getMathExpressions()
|
const math_expressions = getMathExpressions();
|
||||||
if (str.match(/\[TOC\]/)) {
|
if (str.match(/\[TOC\]/)) {
|
||||||
rs = rs.replace("<p>[TOC]</p>", getTocContent())
|
rs = rs.replace("<p>[TOC]</p>", getTocContent())
|
||||||
cleanToc()
|
cleanToc()
|
||||||
}
|
}
|
||||||
rs = rs.replace(/(__special_katext_id_\d+__)/g, (_match, capture) => {
|
rs = rs.replace(/(__special_katext_id_\d+__)/g, (_match, capture) => {
|
||||||
const { type, expression } = math_expressions[capture]
|
const { type, expression } = math_expressions[capture]
|
||||||
return renderToString(_unescape(expression), { displayMode: type === 'block', throwOnError: false, output: 'html' })
|
return renderToString(_unescape(expression) || '', { displayMode: type === 'block', throwOnError: false, output: 'html' })
|
||||||
})
|
})
|
||||||
rs = rs.replace(/▁/g, "▁▁▁")
|
rs = rs.replace(/▁/g, "▁▁▁")
|
||||||
resetMathExpressions()
|
resetMathExpressions()
|
||||||
return rs
|
return dompurify.sanitize(rs)
|
||||||
}, [str])
|
}, [str]);
|
||||||
|
|
||||||
const el = useRef()
|
// 锚点跳转,链接地址里含#对应的id
|
||||||
|
useEffect(()=>{
|
||||||
|
if(url && url.hash && html){
|
||||||
|
let u = url.hash;
|
||||||
|
if(u){
|
||||||
|
let id = decodeURIComponent(u.split("#")[1]);
|
||||||
|
let ele = document.getElementById(id);
|
||||||
|
if(ele){
|
||||||
|
window.scrollTo(0, ele.offsetTop + 220);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},[url])
|
||||||
|
|
||||||
|
const el = useRef();
|
||||||
function onAncherHandler(e) {
|
function onAncherHandler(e) {
|
||||||
let target = e.target
|
let target = e.target
|
||||||
if (target.tagName.toUpperCase() === 'A') {
|
if (target.tagName.toUpperCase() === 'A') {
|
||||||
|
@ -40,7 +61,7 @@ export default ({ value = '', className, style = {} }) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
let viewEl = document.getElementById(ancher.replace('#', ''))
|
let viewEl = document.getElementById(ancher.replace('#', ''))
|
||||||
if (viewEl) {
|
if (viewEl) {
|
||||||
viewEl.parentNode.scrollTop = viewEl.offsetTop
|
viewEl.scrollIntoView(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,6 +82,12 @@ export default ({ value = '', className, style = {} }) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [html, el.current, onAncherHandler])
|
}, [html, el.current, onAncherHandler])
|
||||||
|
return (
|
||||||
return (<div ref={el} style={style} className={`${className ? className : ''} markdown-body`} dangerouslySetInnerHTML={{ __html: html }}></div>)
|
<div
|
||||||
|
ref={el}
|
||||||
|
style={style}
|
||||||
|
className={`${className ? className : ''} markdown-body`}
|
||||||
|
dangerouslySetInnerHTML={{ __html: html }}
|
||||||
|
></div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,18 +67,17 @@ function Index(props){
|
||||||
}
|
}
|
||||||
return(
|
return(
|
||||||
<div className="aboutPanels">
|
<div className="aboutPanels">
|
||||||
|
|
||||||
<div className="aboutContent">
|
<div className="aboutContent">
|
||||||
<AlignCenterBetween style={{padding:"14px 0px"}}>
|
<AlignCenterBetween style={{padding:"14px 20px"}}>
|
||||||
<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 && <a onClick={editContent} className="color-blue">编辑</a> }
|
{ editOpration && !edit && <a onClick={editContent} className="color-blue">编辑</a> }
|
||||||
</AlignCenterBetween>
|
</AlignCenterBetween>
|
||||||
{
|
{
|
||||||
edit ?
|
edit ?
|
||||||
<div>
|
<div className="padding20">
|
||||||
<MDEditor
|
<MDEditor
|
||||||
placeholder={"请输入描述信息"}
|
placeholder={"请输入描述信息"}
|
||||||
height={200}
|
height={500}
|
||||||
mdID={"order-new-description"}
|
mdID={"order-new-description"}
|
||||||
initValue={content}
|
initValue={content}
|
||||||
onChange={onContentChange}
|
onChange={onContentChange}
|
||||||
|
@ -114,11 +113,11 @@ function Index(props){
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
:
|
:
|
||||||
<div style={{padding:"20px 0px"}}>
|
<div className="padding20">
|
||||||
{content ?
|
{content ?
|
||||||
<RenderHtml className="break_word_comments imageLayerParent" value={content} />
|
<RenderHtml className="break_word_comments imageLayerParent" value={content} url={props.history.location}/>
|
||||||
:
|
:
|
||||||
<div>暂无简介~</div>
|
<div>暂无概览~</div>
|
||||||
}
|
}
|
||||||
{attachments && attachments.length > 0 &&
|
{attachments && attachments.length > 0 &&
|
||||||
<Attachments
|
<Attachments
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
.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;
|
||||||
|
|
|
@ -177,7 +177,7 @@ class Activity extends Component{
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
:
|
:
|
||||||
<NoneData _html="暂时还没有相关数据哦!" />
|
<NoneData _html="暂时还没有相关数据!" />
|
||||||
}
|
}
|
||||||
</Spin>
|
</Spin>
|
||||||
{
|
{
|
||||||
|
|
|
@ -32,8 +32,8 @@ class ActivityItem extends Component {
|
||||||
</p >
|
</p >
|
||||||
}
|
}
|
||||||
<p className="itemLine mt10">
|
<p className="itemLine mt10">
|
||||||
<Link to={`/users/${item && item.login}`} className="show-user-link">
|
<Link to={`/users/${item && item.user_login}`} className="show-user-link">
|
||||||
<img alt="" src={getImageUrl(`images/${item.user_avatar}`)} className="createImage" />
|
<img alt="" src={getImageUrl(`/${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>}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import './branch.css';
|
||||||
import { getBranch , getTag } from '../GetData/getData';
|
import { getBranch , getTag } from '../GetData/getData';
|
||||||
|
|
||||||
|
|
||||||
export default (({ projectsId , repo_id , changeBranch , branch , owner })=>{
|
export default (({ projectsId , branch , owner , changeBranch , branchList , tagflag = true })=>{
|
||||||
const [ showValue , setShowValue ] = useState(branch);
|
const [ showValue , setShowValue ] = useState(branch);
|
||||||
const [ inputValue , setInputValue] = useState(undefined);
|
const [ inputValue , setInputValue] = useState(undefined);
|
||||||
const [ nav , setNav ] = useState(0);
|
const [ nav , setNav ] = useState(0);
|
||||||
|
@ -17,10 +17,11 @@ export default (({ projectsId , repo_id , changeBranch , branch , owner })=>{
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
setShowValue(branch);
|
setShowValue(branch);
|
||||||
},[branch])
|
},[branch])
|
||||||
|
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
document.body.addEventListener('click', e => {
|
document.body.addEventListener('click', e => {
|
||||||
let name = e.target.className;
|
let name = e.target.className;
|
||||||
let turn = name == "ant-input OptionsInput" || name == "navli active"|| name == "navli" || name == "padding10 bor-bottom-greyE";
|
let turn = name === "ant-input OptionsInput" || name === "navli active"|| name === "navli" || name === "padding10 bor-bottom-greyE";
|
||||||
if(turn){
|
if(turn){
|
||||||
return;
|
return;
|
||||||
}else{
|
}else{
|
||||||
|
@ -30,8 +31,12 @@ export default (({ projectsId , repo_id , changeBranch , branch , owner })=>{
|
||||||
})
|
})
|
||||||
|
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
getBranchs(projectsId,owner);
|
if(branchList){
|
||||||
},[projectsId])
|
setData(branchList);
|
||||||
|
setDatas(branchList);
|
||||||
|
setIsSpin(false);
|
||||||
|
}
|
||||||
|
},[branchList])
|
||||||
|
|
||||||
|
|
||||||
async function getBranchs(id,owner){
|
async function getBranchs(id,owner){
|
||||||
|
@ -63,7 +68,7 @@ export default (({ projectsId , repo_id , changeBranch , branch , owner })=>{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function chooseitem(value){
|
function chooseitem(value){
|
||||||
setShowValue(value);
|
// setShowValue(value);
|
||||||
changeBranch(value);
|
changeBranch(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,8 +82,8 @@ export default (({ projectsId , repo_id , changeBranch , branch , owner })=>{
|
||||||
onChange={changeInputValue} style={{width:"220px"}}
|
onChange={changeInputValue} style={{width:"220px"}}
|
||||||
/>
|
/>
|
||||||
<ul className="navUl">
|
<ul className="navUl">
|
||||||
<li className={nav==0?"navli active":"navli"} onClick={()=>changeNav(0)}><i className="iconfont icon-fenzhi1 font-14 mr3"></i>分支列表</li>
|
<li className={nav === 0?"navli active":"navli"} onClick={()=>changeNav(0)}><i className="iconfont icon-fenzhi1 font-14 mr3"></i>分支列表</li>
|
||||||
<li className={nav==1?"navli active":"navli"} onClick={()=>changeNav(1)}><i className="iconfont icon-biaoqian3 font-14 mr3"></i>标签列表</li>
|
{ tagflag && <li className={nav === 1?"navli active":"navli"} onClick={()=>changeNav(1)}><i className="iconfont icon-biaoqian3 font-14 mr3"></i>标签列表</li> }
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<Spin spinning={isSpin}>
|
<Spin spinning={isSpin}>
|
||||||
|
@ -97,9 +102,10 @@ export default (({ projectsId , repo_id , changeBranch , branch , owner })=>{
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
return(
|
return(
|
||||||
<Popover placement="bottom" visible={flag} content={menu} onClick={()=>setFlag(!flag)} overlayClassName="branch-tagBox-list">
|
<Popover placement='bottomLeft' visible={flag} content={menu} onClick={()=>setFlag(!flag)} overlayClassName="branch-tagBox-list">
|
||||||
<div className="branch-tagBox">
|
<div className="branch-tagBox">
|
||||||
<span className="color-grey-9 mr3 ml8">{nav === 0 ?"分支":"标签"}:</span>
|
{/* {nav === 0 ?"分支":"标签"} */}
|
||||||
|
<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;
|
||||||
width: 240px;
|
min-width: 140px;
|
||||||
}
|
}
|
||||||
.branch-tagBox-list .ant-popover-arrow{
|
.branch-tagBox-list .ant-popover-arrow{
|
||||||
display: none;
|
display: none;
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { AutoComplete , Button , Icon } from 'antd';
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
const { Option } = AutoComplete;
|
||||||
|
function AddGroup({organizeId,getGroupID}){
|
||||||
|
const [ id , setID ] = useState(undefined);
|
||||||
|
const [ source , setSource ] = useState(undefined);
|
||||||
|
const [ searchKey , setSearchKey ] = useState("");
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
getUserList();
|
||||||
|
},[searchKey])
|
||||||
|
|
||||||
|
function getUserList(e){
|
||||||
|
const url = `/organizations/${organizeId}/teams/search.json`;
|
||||||
|
axios.get(url, {
|
||||||
|
params: {
|
||||||
|
search: searchKey,
|
||||||
|
},
|
||||||
|
}).then((result) => {
|
||||||
|
if (result) {
|
||||||
|
sourceOptions(result.data.teams);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function sourceOptions(userDataSource){
|
||||||
|
const s = userDataSource && userDataSource.map((item, key) => {
|
||||||
|
return (
|
||||||
|
<Option
|
||||||
|
key={key}
|
||||||
|
value={`${item.id}`}
|
||||||
|
name={item.name}
|
||||||
|
>
|
||||||
|
{item.name}
|
||||||
|
</Option>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
setSource(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeInputUser(e){
|
||||||
|
setSearchKey(e || "");
|
||||||
|
};
|
||||||
|
|
||||||
|
// 选择用户
|
||||||
|
function selectInputUser(e, option){
|
||||||
|
setID(e);
|
||||||
|
setSearchKey(option.props.name);
|
||||||
|
};
|
||||||
|
|
||||||
|
function addCollaborator(){
|
||||||
|
getGroupID && getGroupID(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(
|
||||||
|
<div className="addPanel">
|
||||||
|
<AutoComplete
|
||||||
|
dataSource={source}
|
||||||
|
value={searchKey}
|
||||||
|
style={{ width: 300 }}
|
||||||
|
onChange={changeInputUser}
|
||||||
|
onSelect={selectInputUser}
|
||||||
|
placeholder="搜索需要添加的团队..."
|
||||||
|
allowClear
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
ghost
|
||||||
|
onClick={addCollaborator}
|
||||||
|
className="ml15"
|
||||||
|
>
|
||||||
|
<Icon type="plus" size="16"></Icon>
|
||||||
|
添加团队
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default AddGroup;
|
|
@ -0,0 +1,95 @@
|
||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { AutoComplete , Button , Icon } from 'antd';
|
||||||
|
import axios from 'axios';
|
||||||
|
import { getImageUrl } from 'educoder';
|
||||||
|
|
||||||
|
const { Option } = AutoComplete;
|
||||||
|
function AddMember({getID,login}){
|
||||||
|
const [ id , setID ] = useState(undefined);
|
||||||
|
const [ source , setSource ] = useState(undefined);
|
||||||
|
const [ searchKey , setSearchKey ] = useState(undefined);
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
getUserList();
|
||||||
|
},[searchKey])
|
||||||
|
|
||||||
|
function getUserList(e){
|
||||||
|
const url = `/users/list.json`;
|
||||||
|
axios.get(url, {
|
||||||
|
params: {
|
||||||
|
search: searchKey,
|
||||||
|
},
|
||||||
|
}).then((result) => {
|
||||||
|
if (result) {
|
||||||
|
sourceOptions(result.data.users);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function sourceOptions(userDataSource){
|
||||||
|
const s = userDataSource && userDataSource.map((item, key) => {
|
||||||
|
return (
|
||||||
|
<Option
|
||||||
|
key={key}
|
||||||
|
value={`${item.user_id}`}
|
||||||
|
login={`${item.login}`}
|
||||||
|
name={item.username}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
className="user_img radius"
|
||||||
|
width="28"
|
||||||
|
height="28"
|
||||||
|
src={getImageUrl(`/${item && item.image_url}`)}
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
<span className="ml10" style={{ "vertical-align": "middle" }}>
|
||||||
|
{item.username}
|
||||||
|
<span className="color-grey ml10">({item.login})</span>
|
||||||
|
</span>
|
||||||
|
</Option>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
setSource(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeInputUser(e){
|
||||||
|
setSearchKey(e);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 选择用户
|
||||||
|
function selectInputUser(e, option){
|
||||||
|
setID(login ? e : option.props.login);
|
||||||
|
setSearchKey(option.props.name);
|
||||||
|
};
|
||||||
|
|
||||||
|
function addCollaborator(){
|
||||||
|
getID && getID(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(
|
||||||
|
<div className="addPanel">
|
||||||
|
<AutoComplete
|
||||||
|
dataSource={source}
|
||||||
|
value={searchKey}
|
||||||
|
style={{ width: 300 }}
|
||||||
|
onChange={changeInputUser}
|
||||||
|
onSelect={selectInputUser}
|
||||||
|
placeholder="搜索需要添加的用户..."
|
||||||
|
allowClear
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
ghost
|
||||||
|
onClick={addCollaborator}
|
||||||
|
className="ml15"
|
||||||
|
>
|
||||||
|
<Icon type="plus" size="16"></Icon>
|
||||||
|
添加成员
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default AddMember;
|
|
@ -1,19 +1,23 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { getImageUrl } from 'educoder';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
import './Component.scss';
|
import './Component.scss';
|
||||||
|
|
||||||
export default (({img , title, desc , rightBtn})=>{
|
function Cards({img , title, desc , rightBtn , src , bottomInfos}){
|
||||||
return(
|
return(
|
||||||
<div className="cards">
|
<div className="cards">
|
||||||
<div className="img"><img src={img} alt=""/></div>
|
{img &&<div className="img"><img src={getImageUrl(`/${img}`)} alt=""/></div>}
|
||||||
<div className="content">
|
<div className="content">
|
||||||
<p className="titles">
|
<p className="titles">
|
||||||
<span>{title}</span>
|
<Link to={src}>{title}</Link>
|
||||||
{rightBtn}
|
{rightBtn}
|
||||||
</p>
|
</p>
|
||||||
<div className="desc">
|
<div className="desc">
|
||||||
{desc}
|
{desc}
|
||||||
</div>
|
</div>
|
||||||
|
{bottomInfos}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})
|
}
|
||||||
|
export default Cards;
|
|
@ -8,6 +8,10 @@ li.ant-menu-item{
|
||||||
margin:0px!important;
|
margin:0px!important;
|
||||||
border-bottom: 1px solid #eee;
|
border-bottom: 1px solid #eee;
|
||||||
}
|
}
|
||||||
|
.flags{
|
||||||
|
border: 1px solid red;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
// Cards
|
// Cards
|
||||||
.cards{
|
.cards{
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -15,6 +19,8 @@ li.ant-menu-item{
|
||||||
padding:20px 34px;
|
padding:20px 34px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
margin-bottom:18px;
|
margin-bottom:18px;
|
||||||
|
min-height: 130px;
|
||||||
|
border:1px solid #eee;
|
||||||
.img{
|
.img{
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
width: 190px;
|
width: 190px;
|
||||||
|
@ -23,8 +29,10 @@ li.ant-menu-item{
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
overflow: hidden;
|
||||||
img{
|
img{
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
max-height: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.content{
|
.content{
|
||||||
|
@ -35,7 +43,9 @@ li.ant-menu-item{
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin-bottom: 10px!important;
|
margin-bottom: 10px!important;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
&>span{
|
height: 22px;
|
||||||
|
line-height: 22px;;
|
||||||
|
&>a{
|
||||||
font-size:18px ;
|
font-size:18px ;
|
||||||
color: #333;
|
color: #333;
|
||||||
}
|
}
|
||||||
|
@ -46,11 +56,13 @@ li.ant-menu-item{
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
-webkit-box-orient: vertical;
|
-webkit-box-orient: vertical;
|
||||||
-webkit-line-clamp: 2;
|
-webkit-line-clamp: 2;
|
||||||
|
line-height: 20px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 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;
|
||||||
|
@ -72,6 +84,7 @@ li.ant-menu-item{
|
||||||
border-radius:11px;
|
border-radius:11px;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
|
font-size: 12px;
|
||||||
&.running{
|
&.running{
|
||||||
background:#5091FF;
|
background:#5091FF;
|
||||||
color: #F1F8FF;
|
color: #F1F8FF;
|
||||||
|
@ -88,6 +101,10 @@ li.ant-menu-item{
|
||||||
background:#F73030;
|
background:#F73030;
|
||||||
color:#FCEEEE ;
|
color:#FCEEEE ;
|
||||||
}
|
}
|
||||||
|
&.killed{
|
||||||
|
background:#eee;
|
||||||
|
color:#999 ;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.handleBox{
|
.handleBox{
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
@ -95,6 +112,10 @@ 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{
|
||||||
right:190px;
|
right:190px;
|
||||||
|
@ -119,4 +140,56 @@ 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,160 @@
|
||||||
|
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;
|
|
@ -0,0 +1,99 @@
|
||||||
|
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;
|
|
@ -0,0 +1,9 @@
|
||||||
|
.ant-modal-mask{
|
||||||
|
z-index: 1001;
|
||||||
|
}
|
||||||
|
.ant-modal-wrap{
|
||||||
|
z-index: 1002;
|
||||||
|
.ant-form-explain{
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
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));
|
|
@ -5,7 +5,7 @@ import './Component.scss';
|
||||||
export default (()=>{
|
export default (()=>{
|
||||||
return(
|
return(
|
||||||
<div className="handleBox">
|
<div className="handleBox">
|
||||||
<a href="https://www.trustie.net/forums/82/memos/3075" target="_blank" >
|
<a href="https://forum.trustie.net/forums/3075/detail" target="_blank" >
|
||||||
<img src={Handbook} alt=""/>
|
<img src={Handbook} alt=""/>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
export default ({title , value , className})=>{
|
export default ({title , value , className})=>{
|
||||||
const Keys = styled.span`
|
const Keys = styled.span`
|
||||||
display:flex;
|
display:flex;
|
||||||
align-item:center;
|
align-items:center;
|
||||||
& span{
|
& span{
|
||||||
display:block;
|
display:block;
|
||||||
height:20px;
|
height:20px;
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
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;
|
|
@ -19,7 +19,7 @@ export default (({fork,parise})=>{
|
||||||
}`;
|
}`;
|
||||||
const SpanStyleparise = styled.span`{
|
const SpanStyleparise = styled.span`{
|
||||||
display:flex;
|
display:flex;
|
||||||
align-item:center;
|
align-items:center;
|
||||||
margin-left:30px;
|
margin-left:30px;
|
||||||
padding:0px 12px;
|
padding:0px 12px;
|
||||||
border-radius:13px;
|
border-radius:13px;
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import './Component.scss';
|
import './Component.scss';
|
||||||
|
import { Button } from 'antd';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
import FocusButton from "../UsersList/focus_button";
|
||||||
|
import { getImageUrl } from 'educoder';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
const Img = styled.img`{
|
const Img = styled.img`{
|
||||||
border-radius:50%;
|
border-radius:50%;
|
||||||
|
@ -28,26 +32,8 @@ const I = styled.i`{
|
||||||
font-size:13px!important;
|
font-size:13px!important;
|
||||||
color:#60B25E;
|
color:#60B25E;
|
||||||
margin-right:2px;
|
margin-right:2px;
|
||||||
}`
|
height:17px;
|
||||||
const FocusBtn = styled.a`{
|
line-height:17px;
|
||||||
display:inline-block;
|
|
||||||
height:30px;
|
|
||||||
line-height:26px;
|
|
||||||
padding:0px 12px;
|
|
||||||
background-color:#fafafa;
|
|
||||||
border:1px solid #eee;
|
|
||||||
border-radius:2px;
|
|
||||||
color:#888!important;
|
|
||||||
}`
|
|
||||||
const Ifocused = styled.i`{
|
|
||||||
font-size:16px!important;
|
|
||||||
color:#FFA802;
|
|
||||||
margin-right:4px;
|
|
||||||
}`
|
|
||||||
const Ifocus = styled.i`{
|
|
||||||
font-size:16px!important;
|
|
||||||
color:#BBBBBB;
|
|
||||||
margin-right:4px;
|
|
||||||
}`
|
}`
|
||||||
const Div = styled.div`{
|
const Div = styled.div`{
|
||||||
margin-bottom: 18px;
|
margin-bottom: 18px;
|
||||||
|
@ -56,17 +42,18 @@ const Div = styled.div`{
|
||||||
align-items: center;
|
align-items: center;
|
||||||
border:1px solid #eee;
|
border:1px solid #eee;
|
||||||
}`
|
}`
|
||||||
export default (({img,name,time, focusStatus})=>{
|
export default (({ user , img, name, time, focusStatus, is_current_user, login , successFunc }) => {
|
||||||
return(
|
return (
|
||||||
<Div>
|
<Div>
|
||||||
<Img src={img}/>
|
<Link to={`/users/${user && user.login}`}><Img src={getImageUrl(`/${img}`)} /></Link>
|
||||||
<div className="m-infos">
|
<div className="m-infos">
|
||||||
<Name>{name}</Name>
|
<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>
|
||||||
{
|
{
|
||||||
focusStatus ?
|
is_current_user ?
|
||||||
<FocusBtn><Ifocused className="iconfont icon-shixing"></Ifocused>已关注</FocusBtn> :
|
<Button type="default">当前用户</Button>
|
||||||
<FocusBtn><Ifocus className="iconfont icon-kongxing"></Ifocus>关注</FocusBtn>
|
:
|
||||||
|
<FocusButton is_watch={focusStatus} id={login} successFunc={successFunc}/>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</Div>
|
</Div>
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Modal , Button } from 'antd';
|
||||||
|
import './Component.scss';
|
||||||
|
|
||||||
|
function Modals({visible,title,content,onOk,onCancel}){
|
||||||
|
return(
|
||||||
|
<Modal
|
||||||
|
className="modalsStyle"
|
||||||
|
visible={visible}
|
||||||
|
title={title}
|
||||||
|
onCancel={onCancel}
|
||||||
|
closable={true}
|
||||||
|
footer={
|
||||||
|
<div>
|
||||||
|
<Button onClick={onCancel}>取消</Button>
|
||||||
|
<Button type={"primary"} style={{marginLeft:"20px"}} onClick={onOk}>确定</Button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div style={{fontSize:"16px"}}>{content}</div>
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default Modals;
|
|
@ -0,0 +1,61 @@
|
||||||
|
import React , { useState , useEffect } from 'react';
|
||||||
|
import { Select } from 'antd';
|
||||||
|
import { getUrl } from 'educoder';
|
||||||
|
|
||||||
|
import axios from 'axios';
|
||||||
|
const Option = Select.Option;
|
||||||
|
|
||||||
|
export default (({ language , select_language })=>{
|
||||||
|
const [ six , setSix ] = useState(undefined);
|
||||||
|
const [ languages , setLanguage ] = useState(undefined);
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
const url = '/ci/languages.json';
|
||||||
|
axios.get(url).then(result=>{
|
||||||
|
if(result){
|
||||||
|
setLanguage(result.data);
|
||||||
|
}
|
||||||
|
}).catch(error=>{
|
||||||
|
console.log(error);
|
||||||
|
})
|
||||||
|
},[])
|
||||||
|
|
||||||
|
function changelanguage(value){
|
||||||
|
let array = value ? languages.filter(item=>item.name === value) :undefined;
|
||||||
|
select_language(value,array && array[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
const url = '/ci/languages/common.json';
|
||||||
|
axios.get(url).then(result=>{
|
||||||
|
if(result){
|
||||||
|
setSix(result.data);
|
||||||
|
}
|
||||||
|
}).catch(error=>{
|
||||||
|
console.log(error);
|
||||||
|
})
|
||||||
|
},[])
|
||||||
|
|
||||||
|
return(
|
||||||
|
<React.Fragment>
|
||||||
|
{
|
||||||
|
six &&
|
||||||
|
<ul className="language">
|
||||||
|
{
|
||||||
|
six.map((item,key)=>{
|
||||||
|
return(
|
||||||
|
key < 6 ? <li className={language ===item.name ? "active":""} onClick={()=>changelanguage(item.name)}><img alt="" src={item.cover_url && getUrl(item.cover_url)} /></li> : ""
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
}
|
||||||
|
<Select showSearch={true} placeholder={"请选择文本语言"} style={{ width: 200 }} value={language} onChange={changelanguage}>
|
||||||
|
<Option value={undefined}>请选择文本语言</Option>
|
||||||
|
{languages && languages.map((item, key) => {
|
||||||
|
return <Option value={item.name}>{item.name}</Option>;
|
||||||
|
})}
|
||||||
|
</Select>
|
||||||
|
</React.Fragment>
|
||||||
|
)
|
||||||
|
})
|
|
@ -3,42 +3,54 @@ import './Component.scss';
|
||||||
|
|
||||||
export const Tags = (status)=>{
|
export const Tags = (status)=>{
|
||||||
switch(status){
|
switch(status){
|
||||||
case 1:
|
case "running":
|
||||||
return(
|
return(
|
||||||
<span className="statusColor running">运行中</span>
|
<span className="statusColor running">运行中</span>
|
||||||
);
|
);
|
||||||
case 2:
|
case "failure":case"error":
|
||||||
return (
|
return (
|
||||||
<span className="statusColor failed">未通过</span>
|
<span className="statusColor failed">未通过</span>
|
||||||
);
|
);
|
||||||
case 3:
|
case "success":
|
||||||
return (
|
return (
|
||||||
<span className="statusColor pass">已通过</span>
|
<span className="statusColor pass">已通过</span>
|
||||||
);
|
);
|
||||||
default:
|
case "pending":
|
||||||
return (
|
return (
|
||||||
<span className="statusColor Preparing">准备中</span>
|
<span className="statusColor Preparing">准备中</span>
|
||||||
);
|
);
|
||||||
|
case 'killed':
|
||||||
|
return (
|
||||||
|
<span className="statusColor killed">已撤销</span>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TagsLine = (status)=>{
|
export const TagsLine = (status)=>{
|
||||||
switch(status){
|
switch(status){
|
||||||
case 1:
|
case "running":
|
||||||
return(
|
return(
|
||||||
<span className="statuslineColor running">运行中</span>
|
<span className="statuslineColor running">运行中</span>
|
||||||
);
|
);
|
||||||
case 2:
|
case "failure":case "error":
|
||||||
return (
|
return (
|
||||||
<span className="statuslineColor failed">未通过</span>
|
<span className="statuslineColor failed">未通过</span>
|
||||||
);
|
);
|
||||||
case 3:
|
case "success":
|
||||||
return (
|
return (
|
||||||
<span className="statuslineColor pass">已通过</span>
|
<span className="statuslineColor pass">已通过</span>
|
||||||
);
|
);
|
||||||
default:
|
case "pending":
|
||||||
return (
|
return (
|
||||||
<span className="statuslineColor Preparing">准备中</span>
|
<span className="statuslineColor Preparing">准备中</span>
|
||||||
);
|
);
|
||||||
|
case 'killed':
|
||||||
|
return (
|
||||||
|
<span className="statuslineColor killed">已撤销</span>
|
||||||
|
);
|
||||||
|
case 'skipped':
|
||||||
|
return (
|
||||||
|
<span className="statuslineColor skipped">已跳过</span>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
import React ,{ useState } from 'react';
|
||||||
|
import { Modal , Input , Spin } from 'antd';
|
||||||
|
import { AlignCenter } from "./layout";
|
||||||
|
import axios from 'axios';
|
||||||
|
import './Component.scss';
|
||||||
|
|
||||||
|
function PasswordAuthority({ authorityValBox , successFunc , cancelFunc }){
|
||||||
|
const [ authorityVal , setAuthorityVal ] = useState(undefined);
|
||||||
|
const [ authorityValFlag , setAuthorityValFlag ] = useState(false);
|
||||||
|
const [ isSpin , setIsSpin ] = useState(false);
|
||||||
|
|
||||||
|
// 取消授权-登录密码的输入
|
||||||
|
function cancelAuthority(){
|
||||||
|
setAuthorityVal(undefined);
|
||||||
|
cancelFunc();
|
||||||
|
}
|
||||||
|
// 确认授权
|
||||||
|
function okAuthority(){
|
||||||
|
if(!authorityVal){
|
||||||
|
setAuthorityValFlag(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setIsSpin(true);
|
||||||
|
const url = `/users/ci/oauth_grant.json`;
|
||||||
|
axios.get(url,{
|
||||||
|
params:{password:authorityVal}
|
||||||
|
}).then(result=>{
|
||||||
|
setIsSpin(false);
|
||||||
|
if(result){
|
||||||
|
successFunc(result.data.step);
|
||||||
|
}
|
||||||
|
}).catch(error=>{setIsSpin(false);});
|
||||||
|
}
|
||||||
|
return(
|
||||||
|
<Modal visible={authorityValBox} centered={true} title="授权" onCancel={cancelAuthority} onOk={okAuthority}>
|
||||||
|
<Spin spinning={isSpin}>
|
||||||
|
<p style={{textAlign:"center"}}>请输入您的登录密码,确认授权DevOps应用</p>
|
||||||
|
<AlignCenter style={{justifyContent:"center",marginTop:"20px"}}>
|
||||||
|
<span>密码:</span>
|
||||||
|
<Input.Password value={authorityVal} className={authorityValFlag===true && "flags"} onChange={(e)=>setAuthorityVal(e.target.value)} style={{width:"220px"}}></Input.Password>
|
||||||
|
</AlignCenter>
|
||||||
|
</Spin>
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default PasswordAuthority;
|
|
@ -0,0 +1,41 @@
|
||||||
|
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`}>{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;
|
|
@ -2,13 +2,15 @@ import React from "react";
|
||||||
import { Input } from "antd";
|
import { Input } from "antd";
|
||||||
|
|
||||||
const { Search } = Input;
|
const { Search } = Input;
|
||||||
export default ({ placeholder , onSearch }) => {
|
export default ({ placeholder , onSearch , onChange }) => {
|
||||||
return (
|
return (
|
||||||
<Search
|
<Search
|
||||||
|
allowClear
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
enterButton={'搜索'}
|
enterButton={'搜索'}
|
||||||
onSearch={onSearch}
|
onSearch={onSearch}
|
||||||
width="300px"
|
width="300px"
|
||||||
|
onChange={onChange}
|
||||||
></Search>
|
></Search>
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,52 +2,53 @@ import React , { useState , useEffect } from 'react';
|
||||||
import { AutoComplete } from 'antd';
|
import { AutoComplete } from 'antd';
|
||||||
import { getImageUrl } from "educoder";
|
import { getImageUrl } from "educoder";
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
const Option = AutoComplete.Option;
|
const Option = AutoComplete.Option;
|
||||||
|
|
||||||
export default ({ getUser })=>{
|
export default ({ getUser , placeholder, width ,value })=>{
|
||||||
|
const [ source , setSource ] = useState(undefined);
|
||||||
const [ searchKey , setSearchKey ] = useState(undefined);
|
const [ searchKey , setSearchKey ] = useState(undefined);
|
||||||
const [ userDataSource , setUserDataSource ] = useState(undefined);
|
|
||||||
|
useEffect(()=>{
|
||||||
|
if(!value){
|
||||||
|
setSearchKey(undefined);
|
||||||
|
}
|
||||||
|
},[value])
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
getUserList();
|
||||||
|
},[searchKey])
|
||||||
|
|
||||||
function getUserList(e){
|
function getUserList(e){
|
||||||
const url = `/users/list.json`;
|
const url = `/users/list.json`;
|
||||||
axios.get(url, {
|
axios.get(url, {
|
||||||
params: {
|
params: {
|
||||||
search: e,
|
search: searchKey,
|
||||||
},
|
},
|
||||||
})
|
}).then((result) => {
|
||||||
.then((result) => {
|
|
||||||
if (result) {
|
if (result) {
|
||||||
setUserDataSource(result.data.users);
|
sourceOptions(result.data.users);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
function changeInputUser(value){
|
|
||||||
setSearchKey(value);
|
|
||||||
getUserList(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
function selectInputUser(id, option){
|
function sourceOptions(userDataSource){
|
||||||
setSearchKey(option.props.searchValue);
|
const s = userDataSource && userDataSource.map((item, key) => {
|
||||||
getUserList(option.props.searchValue);
|
|
||||||
getUser && getUser(id);
|
|
||||||
}
|
|
||||||
const source =
|
|
||||||
userDataSource && userDataSource.map((item, key) => {
|
|
||||||
return (
|
return (
|
||||||
<Option
|
<Option
|
||||||
key={key}
|
key={key}
|
||||||
value={`${item.user_id}`}
|
value={`${item.user_id}`}
|
||||||
searchValue={`${item.username}`}
|
login={`${item.login}`}
|
||||||
|
name={item.username}
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
className="user_img radius"
|
className="user_img radius"
|
||||||
width="28"
|
width="28"
|
||||||
height="28"
|
height="28"
|
||||||
src={getImageUrl(`images/${item && item.image_url}`)}
|
src={getImageUrl(`/${item && item.image_url}`)}
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
<span className="ml10" style={{ "vertical-align": "middle" }}>
|
<span className="ml10" style={{ "vertical-align": "middle" }}>
|
||||||
|
@ -57,14 +58,31 @@ export default ({ getUser })=>{
|
||||||
</Option>
|
</Option>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
setSource(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeInputUser(e){
|
||||||
|
setSearchKey(e);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 选择用户
|
||||||
|
function selectInputUser(e, option){
|
||||||
|
setSearchKey(option.props.name);
|
||||||
|
getUser(option.props.login);
|
||||||
|
};
|
||||||
|
|
||||||
return(
|
return(
|
||||||
<AutoComplete
|
<div className="addPanel">
|
||||||
dataSource={source}
|
<AutoComplete
|
||||||
value={searchKey}
|
getPopupContainer={trigger => trigger.parentNode}
|
||||||
style={{ width: 300 }}
|
dataSource={source}
|
||||||
onChange={changeInputUser}
|
value={searchKey}
|
||||||
onSelect={selectInputUser}
|
style={{ width: width || 300 }}
|
||||||
placeholder="搜索需要添加的用户..."
|
onChange={changeInputUser}
|
||||||
/>
|
onSelect={selectInputUser}
|
||||||
|
placeholder={placeholder || "搜索需要添加的用户..."}
|
||||||
|
allowClear
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
|
@ -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,8 +19,16 @@ export default ({ url , name , column })=>{
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
return(
|
return(
|
||||||
|
id?
|
||||||
|
<Link to={`/users/${login}`}>
|
||||||
|
<Img>
|
||||||
|
{ url && <img src={url} alt=""/> }
|
||||||
|
<span>{name}</span>
|
||||||
|
</Img>
|
||||||
|
</Link>
|
||||||
|
:
|
||||||
<Img>
|
<Img>
|
||||||
<img src={url} alt=""/>
|
{ url && <img src={url} alt=""/> }
|
||||||
<span>{name}</span>
|
<span>{name}</span>
|
||||||
</Img>
|
</Img>
|
||||||
)
|
)
|
||||||
|
|
|
@ -24,18 +24,33 @@ 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-item:flex-start;
|
align-items: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:72%;
|
width:78%;
|
||||||
|
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`{
|
||||||
width:28%;
|
flex:1;
|
||||||
border-radius:5px;
|
border-radius:5px;
|
||||||
margin-bottom:30px;
|
margin-bottom:30px;
|
||||||
}`
|
}`
|
||||||
|
@ -61,22 +76,24 @@ export const Redline = styled.a`{
|
||||||
line-height:28px;
|
line-height:28px;
|
||||||
border-radius:2px;
|
border-radius:2px;
|
||||||
border:1px solid #F73030;
|
border:1px solid #F73030;
|
||||||
color:#F73030;
|
color:${props => (props.bold ? "#fff" : "#F73030")} !important;
|
||||||
padding:0px 12px;
|
padding:0px 12px;
|
||||||
display:inline-block;
|
display:inline-block;
|
||||||
min-width:80px;
|
min-width:80px;
|
||||||
text-align:center;
|
text-align:center;
|
||||||
|
background:${props => (props.bold ? "#F73030" : "#fff")};
|
||||||
}`
|
}`
|
||||||
export const Greenline = styled.a`{
|
export const Greenline = styled.a`{
|
||||||
height:30px;
|
height:30px;
|
||||||
line-height:28px;
|
line-height:28px;
|
||||||
border-radius:2px;
|
border-radius:2px;
|
||||||
border:1px solid #28BD6C;
|
border:1px solid #28BD6C;
|
||||||
color:#28BD6C;
|
color:${props => (props.bold ? "#fff" : "#28BD6C")} !important;
|
||||||
padding:0px 12px;
|
padding:0px 12px;
|
||||||
display:inline-block;
|
display:inline-block;
|
||||||
min-width:80px;
|
min-width:80px;
|
||||||
text-align:center;
|
text-align:center;
|
||||||
|
background:${props => (props.bold ? "#28BD6C" : "#fff")};
|
||||||
}`
|
}`
|
||||||
export const Greenback = styled.a`{
|
export const Greenback = styled.a`{
|
||||||
height:30px;
|
height:30px;
|
||||||
|
@ -94,7 +111,7 @@ export const Blueback = styled.a`{
|
||||||
line-height:30px;
|
line-height:30px;
|
||||||
border-radius:2px;
|
border-radius:2px;
|
||||||
background-color:rgba(80,145,255,1);
|
background-color:rgba(80,145,255,1);
|
||||||
color:#fff;
|
color:#fff!important;
|
||||||
padding:0px 12px;
|
padding:0px 12px;
|
||||||
display:inline-block;
|
display:inline-block;
|
||||||
min-width:80px;
|
min-width:80px;
|
||||||
|
@ -154,3 +171,9 @@ export const Content = styled.div`{
|
||||||
background-color:#fff;
|
background-color:#fff;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}`
|
}`
|
||||||
|
export const GroupProjectBackgroup = styled.div`{
|
||||||
|
background:#fafafa;
|
||||||
|
padding:20px 30px;
|
||||||
|
width:100%;
|
||||||
|
}`
|
||||||
|
|
||||||
|
|
|
@ -1,27 +1,71 @@
|
||||||
import React , { forwardRef , useCallback } from 'react';
|
import React, { forwardRef, useCallback, useState , useEffect } from "react";
|
||||||
import activate from '../Images/activate.png';
|
import activate from "../Images/activate.png";
|
||||||
import { Blueback } from '../Component/layout';
|
import { AlignCenter, Blueback } from "../Component/layout";
|
||||||
import styled from 'styled-components';
|
import PasswordAuthority from "../Component/PasswordAuthority";
|
||||||
import { Link } from 'react-router-dom';
|
import styled from "styled-components";
|
||||||
import { Form , Input } from 'antd';
|
import { Form, Input , Spin , Button } from "antd";
|
||||||
import axios from 'axios';
|
import ServiceModal from './ServiceModal';
|
||||||
|
import axios from "axios";
|
||||||
|
|
||||||
const P = styled.p`{
|
const P = styled.p`
|
||||||
width:200px;
|
{
|
||||||
line-height:30px;
|
width: 230px;
|
||||||
font-size:16px;
|
line-height: 30px;
|
||||||
color:#333;
|
font-size: 16px;
|
||||||
text-align:center;
|
color: #333;
|
||||||
margin-top:30px;
|
text-align: center;
|
||||||
margin-bottom:30px!important;
|
margin-top: 30px;
|
||||||
}`;
|
margin-bottom: 30px !important;
|
||||||
function About( props , ref){
|
}
|
||||||
const { form: { getFieldDecorator , validateFields } } = props;
|
`;
|
||||||
|
function About(props, ref) {
|
||||||
|
const { form: { getFieldDecorator, validateFields , setFieldsValue } } = props;
|
||||||
|
const [isSpining, setIsSpining] = useState(true);
|
||||||
|
|
||||||
|
// 认证密码
|
||||||
|
const [ authorityVal , setAuthorityVal ] = useState(undefined);
|
||||||
|
const [ authorityValFlag , setAuthorityValFlag ] = useState(false);
|
||||||
|
|
||||||
|
//0: 标识未开启devops
|
||||||
|
//1: 标识用户已填写了云服务器相关信息,但并未开启认证
|
||||||
|
const [step, setStep] = useState(0);
|
||||||
|
|
||||||
|
const owner = props.match.params.owner;
|
||||||
|
const { user } = props;
|
||||||
|
const projectsId = props.match.params.projectsId;
|
||||||
|
const [ disabled, setDisabled ] = useState(false);
|
||||||
|
const [ typeFlag, setTypeFlag] = useState(false);
|
||||||
|
|
||||||
|
const AuthorLogin = props.projectDetail && props.projectDetail.author && props.projectDetail.author.login;
|
||||||
|
const CurrentLogin = props.current_user && props.current_user.login;
|
||||||
|
useEffect(()=>{
|
||||||
|
if(CurrentLogin === AuthorLogin){
|
||||||
|
auth('get');
|
||||||
|
}else{
|
||||||
|
setIsSpining(false);
|
||||||
|
}
|
||||||
|
},[AuthorLogin,CurrentLogin])
|
||||||
|
|
||||||
|
function auth(type){
|
||||||
|
const url = `/${owner}/${projectsId}/ci_authorize.json`;
|
||||||
|
axios({
|
||||||
|
method:`${type}`,
|
||||||
|
url
|
||||||
|
}).then(result=>{
|
||||||
|
setIsSpining(false);
|
||||||
|
if(result && result.data ){
|
||||||
|
setStep(result.data.step);
|
||||||
|
}
|
||||||
|
}).catch(error=>{
|
||||||
|
setIsSpining(false);
|
||||||
|
console.log(error);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const helper = useCallback(
|
const helper = useCallback(
|
||||||
(label, name, rules, widget, isRequired) => (
|
(label, name, rules, widget, isRequired) => (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<span className={isRequired?"required":""}>{label}</span>
|
<span className={isRequired ? "required" : ""}>{label}</span>
|
||||||
<Form.Item>
|
<Form.Item>
|
||||||
{getFieldDecorator(name, { rules, validateFirst: true })(widget)}
|
{getFieldDecorator(name, { rules, validateFirst: true })(widget)}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
@ -29,52 +73,181 @@ function About( props , ref){
|
||||||
),
|
),
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
// 下一步
|
||||||
function startActive(){
|
function goStep() {
|
||||||
let projectsId = props.match.params.projectsId;
|
validateFields((error, values) => {
|
||||||
validateFields((error,values)=>{
|
if (!error) {
|
||||||
if(!error){
|
if(disabled){
|
||||||
const url = `/dev_ops/cloud_accounts.json`;
|
setStep(1);
|
||||||
axios.post(url,{
|
}else{
|
||||||
...values,
|
setIsSpining(true);
|
||||||
project_id:projectsId
|
const url = `/${owner}/${projectsId}/cloud_accounts.json`;
|
||||||
}).then(result=>{
|
axios.post(url, {...values,ip_num:values.ip}).then((result) => {
|
||||||
if(result && result.data.redirect_url){
|
setIsSpining(false);
|
||||||
window.location.href = result.data.redirect_url;
|
if (result && result.data.redirect_url) {
|
||||||
}
|
props.showNotification("服务器信息配置完成!");
|
||||||
}).catch(error=>{
|
setStep(1);
|
||||||
console.log(error);
|
}
|
||||||
})
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log(error);
|
||||||
|
setIsSpining(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 选择服务器后调用接口,点击下一步(1是自有服务器,2是trustie服务器)
|
||||||
|
function sureModal(type){
|
||||||
|
if(type === 2){
|
||||||
|
setTypeFlag(false);
|
||||||
|
setIsSpining(true);
|
||||||
|
const url = `/users/ci/cloud_account/trustie_bind.json`;
|
||||||
|
axios.post(url,{
|
||||||
|
account:user && user.login
|
||||||
|
}).then(result=>{
|
||||||
|
setIsSpining(false);
|
||||||
|
if(result && result.data){
|
||||||
|
setStep(result.data.step);
|
||||||
|
}
|
||||||
|
}).catch(error=>{setIsSpining(false)})
|
||||||
|
}else{
|
||||||
|
setTypeFlag(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上一步
|
||||||
|
function goUpStep(step){
|
||||||
|
setTypeFlag(false);
|
||||||
|
setStep(step);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 输入用户密码后下一步
|
||||||
|
function authStep(){
|
||||||
|
if(!authorityVal){
|
||||||
|
setAuthorityValFlag(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setAuthorityValFlag(false);
|
||||||
|
setIsSpining(true);
|
||||||
|
const url = `/users/ci/oauth_grant.json`;
|
||||||
|
axios.get(url,{
|
||||||
|
params:{password:authorityVal}
|
||||||
|
}).then(result=>{
|
||||||
|
setIsSpining(false);
|
||||||
|
if(result){
|
||||||
|
setStep(result.data.step);
|
||||||
|
}
|
||||||
|
}).catch(error=>{setIsSpining(false)});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 开始激活
|
||||||
|
function startActive(){
|
||||||
|
setIsSpining(true);
|
||||||
|
const url = `/${owner}/${projectsId}/activate.json`;
|
||||||
|
axios.post(url).then(result=>{
|
||||||
|
setIsSpining(false);
|
||||||
|
if(result && result.data.status === 0){
|
||||||
|
props.history.push(`/projects/${owner}/${projectsId}/devops/dispose`);
|
||||||
|
// 需要将顶部的open_devops修改
|
||||||
|
let { changeOpenDevops } = props;
|
||||||
|
changeOpenDevops && changeOpenDevops(true);
|
||||||
|
}
|
||||||
|
}).catch(error=>{
|
||||||
|
console.log(error);
|
||||||
|
setIsSpining(false);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return(
|
|
||||||
<div className="activatePanel">
|
return (
|
||||||
<img src={activate} alt="" width="250px"/>
|
<Spin spinning={isSpining}>
|
||||||
<P>定义DevOps工作流,帮助您检测bug、发布代码…</P>
|
{/* <PasswordAuthority authorityValBox={authorityValBox} successFunc={okAuthority} cancelFunc={cancelAuthority}></PasswordAuthority> */}
|
||||||
<Link to={""} style={{color:"#5091FF",marginBottom:"20px"}}>了解什么是DevOps?</Link>
|
<div className="activatePanel">
|
||||||
<Form>
|
<img src={activate} alt="" width="250px" />
|
||||||
{helper(
|
<P>定义DevOps工作流,帮助您检测bug、发布代码…</P>
|
||||||
"服务器IP地址:",
|
{
|
||||||
"ip_num",
|
CurrentLogin !== AuthorLogin ?
|
||||||
[{ required: true, message: "请输入服务器IP地址" }],
|
<div className="noOperation">DevOps开启功能暂未对项目创建者以外的角色开放,可以联系项目创建者进行开启,开启后便可查看构建信息。</div>:""
|
||||||
<Input placeholder="请输入服务器IP地址" style={{width:"368px"}} size="large" />,true
|
}
|
||||||
)}
|
<a href={"https://forum.trustie.net/forums/3110/detail"} target="_blank" style={{ color: "#5091FF"}}>
|
||||||
{helper(
|
了解什么是DevOps?
|
||||||
"服务器用户名:",
|
</a>
|
||||||
"account",
|
<a href={"https://forum.trustie.net/forums/3080/detail"} target="_blank" style={{ color: "#5091FF"}}>
|
||||||
[{ required: true, message: "请输入服务器用户名" }],
|
如何使用DevOps?
|
||||||
<Input placeholder="请输入服务器用户名" size="large" />,true
|
</a>
|
||||||
)}
|
{
|
||||||
{helper(
|
AuthorLogin === CurrentLogin ?
|
||||||
"服务器密码:",
|
<React.Fragment>
|
||||||
"secret",
|
{
|
||||||
[{ required: true, message: "请输入服务器密码" }],
|
step === 0 && !typeFlag ?
|
||||||
<Input.Password placeholder="请输入服务器密码" size="large" />,true
|
<ServiceModal sureModal={sureModal}></ServiceModal>
|
||||||
)}
|
:""
|
||||||
</Form>
|
}
|
||||||
<Blueback onClick={startActive}>开始激活</Blueback>
|
{ step === 0 && typeFlag ?
|
||||||
</div>
|
<React.Fragment>
|
||||||
)
|
<Input.Password style={{display:'none'}} size="large" />
|
||||||
|
<Form style={{marginTop:"20px"}}>
|
||||||
|
<p className="mb20" style={{width:"370px"}}>请仔细核对您的服务器信息,一旦确认提交将无法修改</p>
|
||||||
|
{helper(
|
||||||
|
"服务器IP地址:",
|
||||||
|
"ip",
|
||||||
|
[{ required: true, message: "请输入服务器IP地址" }],
|
||||||
|
<Input
|
||||||
|
placeholder="请输入服务器IP地址"
|
||||||
|
style={{ width: "368px" }}
|
||||||
|
size="large"
|
||||||
|
disabled={disabled}
|
||||||
|
/>,
|
||||||
|
true
|
||||||
|
)}
|
||||||
|
{helper(
|
||||||
|
"服务器用户名:",
|
||||||
|
"account",
|
||||||
|
[{ required: true, message: "请输入服务器用户名" }],
|
||||||
|
<Input placeholder="请输入服务器用户名" size="large" disabled={disabled}/>,
|
||||||
|
true
|
||||||
|
)}
|
||||||
|
{helper(
|
||||||
|
"服务器密码:",
|
||||||
|
"secret",
|
||||||
|
[{ required: true, message: "请输入服务器密码" }],
|
||||||
|
<Input.Password placeholder="请输入服务器密码" size="large" disabled={disabled}/>,
|
||||||
|
true
|
||||||
|
)}
|
||||||
|
</Form>
|
||||||
|
<AlignCenter>
|
||||||
|
{ !disabled && <Button className="mr20" onClick={()=>goUpStep(0)}>上一步</Button>}
|
||||||
|
<Blueback onClick={goStep}>下一步</Blueback>
|
||||||
|
</AlignCenter>
|
||||||
|
</React.Fragment>
|
||||||
|
:""
|
||||||
|
}
|
||||||
|
{
|
||||||
|
step === 1 ?
|
||||||
|
<div>
|
||||||
|
<AlignCenter style={{justifyContent:"center",marginTop:"20px"}}>
|
||||||
|
<span style={{marginBottom:"42px"}}>密码:</span>
|
||||||
|
<div>
|
||||||
|
<Input.Password value={authorityVal} className={authorityValFlag===true && "flags"} onChange={(e)=>setAuthorityVal(e.target.value)} style={{width:"220px"}}></Input.Password>
|
||||||
|
<p className="color-grey-9" style={{textAlign:"left",lineHeight:'21px'}}>您已保存相关服务器信息,请输入密码,<br/>确认授权DevOps应用</p>
|
||||||
|
</div>
|
||||||
|
</AlignCenter>
|
||||||
|
<AlignCenter style={{justifyContent:'center'}}>
|
||||||
|
<Blueback onClick={authStep} className="mt20">下一步</Blueback>
|
||||||
|
</AlignCenter>
|
||||||
|
</div>:""
|
||||||
|
}
|
||||||
|
{ step === 2 ?
|
||||||
|
<div style={{textAlign:'center',marginTop:"20px"}}>
|
||||||
|
<Blueback onClick={startActive} className="mt20">开始激活</Blueback>
|
||||||
|
</div>:""
|
||||||
|
}
|
||||||
|
</React.Fragment>
|
||||||
|
:""
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</Spin>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
export default Form.create()(forwardRef(About));
|
export default Form.create()(forwardRef(About));
|
||||||
|
|
|
@ -1,140 +1,167 @@
|
||||||
import React , { useState , useEffect } from 'react';
|
import React , { useState , useEffect } from 'react';
|
||||||
|
import { Spin , Pagination } from 'antd';
|
||||||
import { Blueback } from '../Component/layout';
|
import { Blueback } from '../Component/layout';
|
||||||
import Editor from "react-monaco-editor";
|
import List from './Dispose/List';
|
||||||
import Modals from './DisposeModal';
|
import Head from './Dispose/head';
|
||||||
import FileLanguage from '../Component/FileLanguage';
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
import PipelineName from './Dispose/PipelineName';
|
||||||
|
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
const Div = styled.div`{
|
||||||
|
padding:24px 30px;
|
||||||
|
}`;
|
||||||
|
const limit = 15;
|
||||||
function Dispose(props){
|
function Dispose(props){
|
||||||
const [ info , setInfo ] = useState(undefined);
|
const [ spining , setSpining ] = useState(true);
|
||||||
|
const [ updateInfo , setUpdateInfo ] = useState(undefined);
|
||||||
|
const [ list , setList ] = useState(undefined);
|
||||||
|
const [ permission , setPermission ] = useState(undefined);
|
||||||
const [ visible , setVisible ] = useState(false);
|
const [ visible , setVisible ] = useState(false);
|
||||||
const [ ymlValue , setYmlValue ] = useState("");
|
const [ page , setPage ] = useState(1);
|
||||||
const [ six , setSix ] = useState(undefined);
|
const [ totalCount , setTotalCount ] = useState(0);
|
||||||
const [ fileLanguage , setFileLanguage ] = useState(undefined);
|
const [ branchList , setBranchList ] =useState(undefined);
|
||||||
const [ first , setFirst ] = useState(false);
|
|
||||||
|
|
||||||
|
|
||||||
|
const projectDetail = props.projectDetail;
|
||||||
|
const current_user = props.current_user;
|
||||||
let projectsId = props.match.params.projectsId;
|
let projectsId = props.match.params.projectsId;
|
||||||
let owner = props.match.params.owner;
|
let owner = props.match.params.owner;
|
||||||
|
|
||||||
|
// 获取用户的身份角色
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
if(projectsId){
|
if(projectDetail){
|
||||||
const url = '/dev_ops/builds/get_trustie_pipeline.json';
|
setPermission(props.projectDetail.permission);
|
||||||
axios.get(url,{
|
|
||||||
params:{
|
|
||||||
project_id:projectsId
|
|
||||||
}
|
|
||||||
}).then(result=>{
|
|
||||||
if(result && result.data.content){
|
|
||||||
setInfo(result.data);
|
|
||||||
setYmlValue(result.data.content);
|
|
||||||
setFirst(true);
|
|
||||||
}else{
|
|
||||||
setFirst(false);
|
|
||||||
}
|
|
||||||
}).catch(error=>{
|
|
||||||
console.log(error);
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
},[])
|
},[projectDetail])
|
||||||
|
|
||||||
useEffect(()=>{
|
function Init(){
|
||||||
const url = '/dev_ops/languages/common.json';
|
const url = `/ci/pipelines/list.json`;
|
||||||
axios.get(url).then(result=>{
|
axios.get(url,{
|
||||||
if(result){
|
params:{
|
||||||
setSix(result.data);
|
identifier:projectsId,owner,
|
||||||
|
page,limit
|
||||||
}
|
}
|
||||||
}).catch(error=>{
|
}).then(result=>{
|
||||||
console.log(error);
|
if(result && result.data){
|
||||||
})
|
setList(result.data.pipelines);
|
||||||
},[])
|
}
|
||||||
|
setSpining(false);
|
||||||
// 修改文件内容
|
}).catch(error=>{setSpining(false);})
|
||||||
function changeEditor(value){
|
|
||||||
setYmlValue(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 切换语言
|
useEffect(()=>{
|
||||||
function select_language(value,array){
|
Init();
|
||||||
setFileLanguage(value);
|
},[page])
|
||||||
// console.log(array);
|
|
||||||
setYmlValue( array && array.content);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 确定提交
|
useEffect(()=>{
|
||||||
function submit(){
|
if(owner && projectsId){
|
||||||
let url = '';
|
const url = `/${owner}/${projectsId}/branches.json`;
|
||||||
let params = {
|
axios.get(url).then(result=>{
|
||||||
branch: "master",
|
if(result && result.data){
|
||||||
content:ymlValue,
|
setBranchList(result.data);
|
||||||
filepath:info && info.name,
|
|
||||||
message:''
|
|
||||||
}
|
|
||||||
if(first){
|
|
||||||
// 为true,则是编辑否则是新建
|
|
||||||
url = `/${owner}/${projectsId}/update_file.json`;
|
|
||||||
axios.put(url,{
|
|
||||||
...params,
|
|
||||||
sha:info && info.sha
|
|
||||||
}).then(result=>{
|
|
||||||
if(result){
|
|
||||||
setVisible(true);
|
|
||||||
}
|
}
|
||||||
}).catch(error=>{
|
}).catch(error=>{})
|
||||||
console.log(error);
|
}
|
||||||
})
|
},[owner,projectsId])
|
||||||
|
|
||||||
|
// 新增/编辑流水线
|
||||||
|
function addNew(pipeline_name,id,branch,event){
|
||||||
|
setVisible(true);
|
||||||
|
setUpdateInfo(undefined);
|
||||||
|
if(pipeline_name){
|
||||||
|
let eventA = event.split(",");
|
||||||
|
let l = {pipeline_name,id,branch,event:eventA}
|
||||||
|
setUpdateInfo(l);
|
||||||
}else{
|
}else{
|
||||||
url = `/${owner}/${projectsId}/create_file.json`;
|
setUpdateInfo(undefined);
|
||||||
axios.post(url,params).then(result=>{
|
|
||||||
if(result){
|
|
||||||
setVisible(true);
|
|
||||||
}
|
|
||||||
}).catch(error=>{
|
|
||||||
console.log(error);
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function suresubmit(){
|
|
||||||
props.history.push(`/projects/${owner}/${projectsId}/ops/list`);
|
function onOk(pipeline_name,updateId,branch,event){
|
||||||
}
|
if(pipeline_name){
|
||||||
|
let eventStr = "";
|
||||||
return(
|
for(var i = 0;i<event.length;i++){
|
||||||
<React.Fragment>
|
eventStr +=event[i]+",";
|
||||||
<Modals visible={visible} closeFunc={(flag)=>setVisible(flag)} sureFunc={suresubmit}></Modals>
|
|
||||||
<p>编程语言:</p>
|
|
||||||
{
|
|
||||||
six &&
|
|
||||||
<ul className="language">
|
|
||||||
{
|
|
||||||
six && six.map((item,key)=>{
|
|
||||||
return(
|
|
||||||
key < 6 ? <li><img alt="" src={item.cover_url} /></li> : ""
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</ul>
|
|
||||||
}
|
}
|
||||||
<div className="mt20 mb20">
|
eventStr = eventStr.substring(0,eventStr.length-1);
|
||||||
<FileLanguage language={fileLanguage} select_language={select_language}/>
|
if(!updateId){
|
||||||
|
// 新增
|
||||||
|
const url = `/ci/pipelines.json`;
|
||||||
|
axios.post(url,{
|
||||||
|
pipeline_name,
|
||||||
|
file_name:".trustie-pipeline.yml",
|
||||||
|
repo:projectsId,branch,event:eventStr,owner
|
||||||
|
}).then(result=>{
|
||||||
|
setVisible(false);
|
||||||
|
if(result && result.data){
|
||||||
|
props.showNotification("流水线新增成功,请进行工作流配置!");
|
||||||
|
props.history.push(`/projects/${owner}/${projectsId}/devops/dispose/${result.data.id}`);
|
||||||
|
}else{
|
||||||
|
props.showNotification("流水线新增失败,请稍后再试!");
|
||||||
|
}
|
||||||
|
}).catch(error=>{})
|
||||||
|
}else{
|
||||||
|
// 修改
|
||||||
|
const url = `/ci/pipelines/${updateId}.json`;
|
||||||
|
axios.put(url,{
|
||||||
|
pipeline_name,repo:projectsId,branch,event:eventStr,owner
|
||||||
|
}).then(result=>{
|
||||||
|
if(result && result.data){
|
||||||
|
setVisible(false);
|
||||||
|
Init();
|
||||||
|
props.showNotification("流水线名称更新成功!");
|
||||||
|
}else{
|
||||||
|
props.showNotification("流水线名称更新失败,请稍后再试!");
|
||||||
|
}
|
||||||
|
}).catch(error=>{})
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
props.showNotification("请输入流水线名称!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除
|
||||||
|
function deleteFunc(id){
|
||||||
|
const url = `/ci/pipelines/${id}.json`;
|
||||||
|
axios.delete(url).then(result=>{
|
||||||
|
if(result && result.data){
|
||||||
|
props.showNotification("流水线删除成功!");
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
}).catch(error=>{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 模板管理
|
||||||
|
function toModalManage(){
|
||||||
|
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");
|
||||||
|
return(
|
||||||
|
<Spin spinning={spining}>
|
||||||
|
<PipelineName branchList={branchList} visible={visible} value={updateInfo} onCancel={()=>setVisible(false)} onOk={onOk}/>
|
||||||
|
<div className="disposePanel">
|
||||||
|
<Head manager={ operate ? toModalManage : undefined} parameter={operate ? toparameter :undefined}/>
|
||||||
|
<Div>
|
||||||
|
{ operate && <Blueback onClick={()=>addNew(undefined,undefined)}>新增流水线</Blueback> }
|
||||||
|
<div className="mt20 disposeList">
|
||||||
|
<List list={list} operate={operate} projectsId={projectsId} owner={owner} showModal={addNew} deleteFunc={deleteFunc}/>
|
||||||
|
{
|
||||||
|
totalCount > limit &&
|
||||||
|
<div className="mt20 pb20" style={{textAlign:'center'}}>
|
||||||
|
<Pagination simple current={page} pageSize={limit} total={totalCount} onChange={(page)=>setPage(page)}/>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</Div>
|
||||||
</div>
|
</div>
|
||||||
<p>配置脚本:</p>
|
</Spin>
|
||||||
<div className="editorBody">
|
|
||||||
<p className="editorHead">
|
|
||||||
<span>{info && info.name}</span>
|
|
||||||
<a><i className="iconfont icon-bianji6 font-14"></i></a>
|
|
||||||
</p>
|
|
||||||
<Editor
|
|
||||||
height="300px"
|
|
||||||
language={"java"}
|
|
||||||
theme={"vs-grey"}
|
|
||||||
defaultValue="请输入内容"
|
|
||||||
value={ymlValue}
|
|
||||||
options={"editor_options"}
|
|
||||||
onChange={changeEditor}
|
|
||||||
></Editor>
|
|
||||||
</div>
|
|
||||||
<Blueback onClick={submit}>确定提交</Blueback>
|
|
||||||
</React.Fragment>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
export default Dispose;
|
export default Dispose;
|
|
@ -0,0 +1,100 @@
|
||||||
|
import React , { useEffect , useState } from 'react';
|
||||||
|
|
||||||
|
function Choosen({ chooseFunc, temp , templateId , category }){
|
||||||
|
const [ tempId, setTemId ] = useState(undefined);
|
||||||
|
const [ cate , setCate ]= useState(undefined);
|
||||||
|
const [ templates , setTemplates ] = useState(undefined);
|
||||||
|
const [ categories , setCategories ] = useState(undefined);
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
if(templateId){
|
||||||
|
setTemId(templateId);
|
||||||
|
}
|
||||||
|
},[templateId])
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
if(category){
|
||||||
|
setCate(category);
|
||||||
|
}
|
||||||
|
},[category])
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
if(temp && temp.length > 0){
|
||||||
|
if(temp[0].category !== "初始化"){
|
||||||
|
setCategories(temp);
|
||||||
|
}else{
|
||||||
|
setCategories(undefined);
|
||||||
|
}
|
||||||
|
if(category && temp[0].category !== "初始化" && category !== "初始化"){
|
||||||
|
let c = temp.filter(item=>item.category === category);
|
||||||
|
let t = c && c.length > 0 && c[0].templates;
|
||||||
|
setTemplates(t);
|
||||||
|
setCate(category);
|
||||||
|
}else{
|
||||||
|
setTemplates(temp[0].templates);
|
||||||
|
setCate(temp[0].category);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
setTemplates(undefined);
|
||||||
|
setCate(undefined);
|
||||||
|
setCategories(undefined);
|
||||||
|
}
|
||||||
|
},[temp,category])
|
||||||
|
|
||||||
|
// 选择类别
|
||||||
|
function changeCate(cate){
|
||||||
|
setCate(cate);
|
||||||
|
let c = categories && categories.filter(item=>item.category === cate);
|
||||||
|
let t = c && c[0].templates;
|
||||||
|
setTemplates(t);
|
||||||
|
let m_t_id = t && t.length>0 && t[0].id;
|
||||||
|
let m_t_content = t && t.length>0 && t[0].content;
|
||||||
|
setTemId(m_t_id);
|
||||||
|
chooseFunc && chooseFunc(m_t_content,m_t_id,cate);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 选择模板
|
||||||
|
function chooseOption(id){
|
||||||
|
let item = templates.filter(item=>item.id === id);
|
||||||
|
let content = item && item.length >0 && item[0].content;
|
||||||
|
chooseFunc && chooseFunc(content,id,cate);
|
||||||
|
setTemId(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(
|
||||||
|
<React.Fragment>
|
||||||
|
{
|
||||||
|
categories && categories.length > 0 &&
|
||||||
|
<div className="choosenList">
|
||||||
|
<span>模板类别:</span>
|
||||||
|
<ul>
|
||||||
|
{
|
||||||
|
categories.map((item,key)=>{
|
||||||
|
return(
|
||||||
|
<li className={cate === item.category ?"active":""} onClick={()=>changeCate(item.category)}>{item.category}</li>)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
{
|
||||||
|
templates && templates.length> 0 &&
|
||||||
|
<div className="choosenList">
|
||||||
|
<span>模板选择:</span>
|
||||||
|
<ul>
|
||||||
|
{
|
||||||
|
templates.map((item,key)=>{
|
||||||
|
return(
|
||||||
|
<li className={tempId === item.id ? "active":""} onClick={()=>chooseOption(item.id)}>{item.template_name}</li>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</React.Fragment>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default Choosen;
|
|
@ -0,0 +1,37 @@
|
||||||
|
import React from 'react';
|
||||||
|
import Editor from 'react-monaco-editor';
|
||||||
|
|
||||||
|
function Editors({value,onChange,theme,height,visible,width="100%",Numbers="on"}){
|
||||||
|
const editor_options = {
|
||||||
|
lineNumbers: Numbers,
|
||||||
|
wordWrap: true, //强制换行
|
||||||
|
selectOnLineNumbers: true,
|
||||||
|
lineHeight: 24,
|
||||||
|
renderLineHighlight: "line",
|
||||||
|
revealHorizontalRightPadding: 5,
|
||||||
|
placeholder:"请输入内容",
|
||||||
|
readOnly: visible,
|
||||||
|
cursorStyle: visible ? "underline-thin" : "line",
|
||||||
|
folding: true,
|
||||||
|
foldingStrategy: "indentation", // 代码可分小段折叠
|
||||||
|
automaticLayout: true, // 自适应布局
|
||||||
|
minimap: {
|
||||||
|
// 不要小地图
|
||||||
|
enabled: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return(
|
||||||
|
<Editor
|
||||||
|
height={height}
|
||||||
|
width={width}
|
||||||
|
language={"yaml"}
|
||||||
|
theme={theme}
|
||||||
|
placeholder="请输入内容"
|
||||||
|
value={value}
|
||||||
|
options={editor_options}
|
||||||
|
onChange={(value)=>onChange(value)}
|
||||||
|
disabled={true}
|
||||||
|
></Editor>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default Editors;
|
|
@ -0,0 +1,66 @@
|
||||||
|
import React , { useEffect , useState } from 'react';
|
||||||
|
import { Button } from 'antd';
|
||||||
|
import Choosen from './Choosen';
|
||||||
|
import Editors from './Editors';
|
||||||
|
|
||||||
|
function Init({ datas , templates , saveFunc , saveDatas}){
|
||||||
|
const [ templateId , setTemplateId ] = useState(undefined);
|
||||||
|
const [ ymlValue , setYmlValue ] = useState(undefined);
|
||||||
|
const [ temp , setTemp ] = useState(undefined);
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
if(templates && templates.length > 0){
|
||||||
|
setTemp(templates)
|
||||||
|
}
|
||||||
|
},[templates])
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
if(datas && datas.length > 0){
|
||||||
|
setTemplateId(datas[0].template_id);
|
||||||
|
setYmlValue(datas[0].content);
|
||||||
|
}
|
||||||
|
},[datas])
|
||||||
|
|
||||||
|
// 选择模板
|
||||||
|
function chooseFunc(content,id,cate){
|
||||||
|
setTemplateId(id);
|
||||||
|
setYmlValue(content);
|
||||||
|
recieveData(id,content);
|
||||||
|
}
|
||||||
|
|
||||||
|
function recieveData(id,content){
|
||||||
|
let steps = datas;
|
||||||
|
if(datas && datas.length>0){
|
||||||
|
steps[0].content = content || ymlValue;
|
||||||
|
steps[0].template_id = id || templateId ;
|
||||||
|
}else{
|
||||||
|
steps =
|
||||||
|
[{
|
||||||
|
step_name:"初始化",
|
||||||
|
show_index:1,
|
||||||
|
content:content || ymlValue,
|
||||||
|
template_id:id || templateId
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
saveDatas(steps);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 点击下一步时
|
||||||
|
function nextStep(){
|
||||||
|
recieveData();
|
||||||
|
saveFunc(undefined,undefined,undefined,undefined,"next");
|
||||||
|
}
|
||||||
|
|
||||||
|
return(
|
||||||
|
<div>
|
||||||
|
<Choosen chooseFunc={chooseFunc} templateId={templateId} temp={temp}/>
|
||||||
|
<div className="mt15">
|
||||||
|
<Editors value={ymlValue} onChange={setYmlValue} theme={"vs-dark"} height={"400px"}/>
|
||||||
|
</div>
|
||||||
|
<div className="mt20">
|
||||||
|
<Button type={"primary"} onClick={nextStep}>下一步</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default Init;
|
|
@ -0,0 +1,131 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Table , Popconfirm } from 'antd';
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
|
// const STATUS = {
|
||||||
|
// running:"运行中",
|
||||||
|
// failure:"未通过",
|
||||||
|
// error:"未通过",
|
||||||
|
// success:"已通过",
|
||||||
|
// killed:"已撤销",
|
||||||
|
// 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 }){
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
title:"流水线名称",
|
||||||
|
dataIndex:"pipeline_name",
|
||||||
|
key:1,
|
||||||
|
ellipsis:true,
|
||||||
|
render:(txt,item)=>{
|
||||||
|
return(
|
||||||
|
<span onDoubleClick={()=>showModal(txt,item.id,item.branch,item.event)} style={{display:"block",cursor:"pointer"}}>{txt}</span>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title:"文件名称",
|
||||||
|
dataIndex:"file_name",
|
||||||
|
key:1,
|
||||||
|
width:"15%",
|
||||||
|
ellipsis:true,
|
||||||
|
render:(value,item)=>{
|
||||||
|
return(
|
||||||
|
<Link to={`/projects/${owner}/${projectsId}/tree/${item.branch}/${value}`} className="color-blue">{value}</Link>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title:"触发分支",
|
||||||
|
dataIndex:"branch",
|
||||||
|
key:1,
|
||||||
|
width:"10%",
|
||||||
|
ellipsis:true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title:"触发事件",
|
||||||
|
dataIndex:"event",
|
||||||
|
key:1,
|
||||||
|
width:"10%",
|
||||||
|
ellipsis:true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title:"最近构建时间",
|
||||||
|
dataIndex:"last_build_time",
|
||||||
|
key:1,
|
||||||
|
width:"15%",
|
||||||
|
ellipsis:true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title:"最近构建状态",
|
||||||
|
dataIndex:"pipeline_status",
|
||||||
|
key:1,
|
||||||
|
width:"12%",
|
||||||
|
ellipsis:true,
|
||||||
|
render:(txt)=>{
|
||||||
|
return renderTableStatus(txt)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title:"操作",
|
||||||
|
dataIndex:"operation",
|
||||||
|
key:1,
|
||||||
|
width:"21%",
|
||||||
|
render:(txt,item)=>{
|
||||||
|
return(
|
||||||
|
<span>
|
||||||
|
{ operate ?
|
||||||
|
<Link to={`/projects/${owner}/${projectsId}/devops/dispose/${item.id}`} className="mr10 color-grey-6">
|
||||||
|
<i className="iconfont icon-zaibianji font-13 mr3"></i>编辑</Link> :""
|
||||||
|
}
|
||||||
|
{ operate ?
|
||||||
|
<Popconfirm title={"确定要删除此流水线?"} onConfirm={()=>deleteFunc(item.id)} okText="确定" cancelText={"取消"}>
|
||||||
|
<a className="mr10 color-grey-6"><i className="iconfont icon-lajitong font-13 mr3"></i>删除</a>
|
||||||
|
</Popconfirm>:""
|
||||||
|
}
|
||||||
|
<Link to={`/projects/${owner}/${projectsId}/devops/list/${item.branch}`} className="color-grey-6"><i className="iconfont icon-yunhang font-13 mr3"></i>查看运行记录</Link>
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
return(
|
||||||
|
<Table size="small" columns={columns} dataSource={list} rowKey={(row)=>row.id} pagination={false}></Table>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default List;
|
|
@ -0,0 +1,67 @@
|
||||||
|
import React , { useEffect , useState } from 'react';
|
||||||
|
import { Modal , Input , Select } from 'antd';
|
||||||
|
const { Option }= Select;
|
||||||
|
|
||||||
|
const EVENT = ["push","pull_request","tag","cron","custom","promote","rollback"]
|
||||||
|
function PipelineName({visible,onCancel,onOk,value ,branchList}){
|
||||||
|
const [ name , setName ] = useState(undefined);
|
||||||
|
const [ branchValue , setBranchValue ] = useState(undefined);
|
||||||
|
const [ eventValue , setEventValue ] = useState([EVENT[0]]);
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
if(branchList && branchList.length>0){
|
||||||
|
setBranchValue(branchList[0].name);
|
||||||
|
}
|
||||||
|
},[branchList])
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
if(value){
|
||||||
|
setName(value.pipeline_name);
|
||||||
|
setBranchValue(value.branch);
|
||||||
|
setEventValue(value.event);
|
||||||
|
}else{
|
||||||
|
setName(undefined);
|
||||||
|
}
|
||||||
|
},[value])
|
||||||
|
|
||||||
|
function onSure(){
|
||||||
|
onOk(name,value && value.id,branchValue,eventValue);
|
||||||
|
}
|
||||||
|
return(
|
||||||
|
<Modal
|
||||||
|
visible={visible}
|
||||||
|
title="流水线名称"
|
||||||
|
width={"500px"}
|
||||||
|
onCancel={onCancel}
|
||||||
|
onOk={onSure}
|
||||||
|
centered={true}
|
||||||
|
>
|
||||||
|
<div className="choosenList">
|
||||||
|
<span>流水线名称:</span>
|
||||||
|
<Input value={name} onChange={(e)=>setName(e.target.value)} placeholder="请输入名称" style={{width:"340px",margin:"6px 0px"}}/>
|
||||||
|
</div>
|
||||||
|
<div className="choosenList mt20">
|
||||||
|
<span>触发条件:</span>
|
||||||
|
<Select value={branchValue} style={{width:"150px"}} onChange={(e)=>setBranchValue(e)}>
|
||||||
|
{
|
||||||
|
branchList && branchList.length>0 && branchList.map((item,key)=>{
|
||||||
|
return(
|
||||||
|
<Option value={item.name} key={key}>{item.name}</Option>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</Select>
|
||||||
|
<Select mode="multiple" allowClear value={eventValue} style={{width:"180px",marginLeft:"10px"}} onChange={(e)=>{console.log(e);setEventValue(e)}}>
|
||||||
|
{
|
||||||
|
EVENT.map((item,key)=>{
|
||||||
|
return(
|
||||||
|
<Option value={item} key={key}>{item}</Option>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default PipelineName;
|
|
@ -0,0 +1,102 @@
|
||||||
|
import React , { useEffect , useState } from 'react';
|
||||||
|
import { Button , Popconfirm } from 'antd';
|
||||||
|
import { Cancel } from '../../Component/layout';
|
||||||
|
import Item from './StageItem';
|
||||||
|
|
||||||
|
function Stage({
|
||||||
|
templates ,
|
||||||
|
datas ,
|
||||||
|
saveDatas ,
|
||||||
|
saveFunc ,
|
||||||
|
stepName ,
|
||||||
|
deleteStep ,
|
||||||
|
deleteFunc ,
|
||||||
|
deleteFlag
|
||||||
|
}){
|
||||||
|
const [ stepList , setStepList ] = useState(undefined);
|
||||||
|
const [ temp , setTemp ] = useState(undefined);
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
if(templates && templates.length > 0){
|
||||||
|
setTemp(templates);
|
||||||
|
}
|
||||||
|
},[templates])
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
if(datas){
|
||||||
|
if(datas.length > 0 && stepList !== datas){
|
||||||
|
setStepList(datas);
|
||||||
|
}else if(datas.length === 0){
|
||||||
|
let list = [];
|
||||||
|
setStepList(list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},[datas])
|
||||||
|
|
||||||
|
// 添加步骤
|
||||||
|
function addFunc(){
|
||||||
|
let list = stepList;
|
||||||
|
let length = list ? list.length : 0;
|
||||||
|
let pre = temp && temp.length > 0 && temp[0];
|
||||||
|
let c = pre && pre.category;
|
||||||
|
let child = pre && pre.templates && pre.templates.length > 0 && pre.templates[0];
|
||||||
|
let step =
|
||||||
|
{
|
||||||
|
"category":c,
|
||||||
|
"step_name": stepName+`${length + 1}`,
|
||||||
|
"show_index": length + 1,
|
||||||
|
"content":child.content,
|
||||||
|
"template_id":child.id,
|
||||||
|
"hide":false
|
||||||
|
}
|
||||||
|
list.push(step);
|
||||||
|
saveDatas(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将修改的对应项保存在数组中
|
||||||
|
function saveItems(content,id,cate,key){
|
||||||
|
let item = stepList;
|
||||||
|
item[key].content = content;
|
||||||
|
item[key].template_id = id;
|
||||||
|
item[key].category = cate;
|
||||||
|
saveDatas([...item]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function slideItems(key,hide){
|
||||||
|
let item = stepList;
|
||||||
|
item[key].hide = !hide;
|
||||||
|
setStepList([...item]);
|
||||||
|
saveDatas(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteItem(id,key){
|
||||||
|
deleteStep(id,key);
|
||||||
|
}
|
||||||
|
// 点击下一步时
|
||||||
|
function nextStep(btn){
|
||||||
|
saveFunc(undefined,undefined,undefined,undefined,btn);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(
|
||||||
|
<div>
|
||||||
|
{
|
||||||
|
stepList && stepList.length > 0 && stepList.map((item,key)=>{
|
||||||
|
return(
|
||||||
|
<Item item={item} templates={temp} k={key} saveItems={saveItems} slideItems={slideItems} deleteStep={deleteItem}/>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
<a className="addStageBtn" onClick={addFunc}>+ 添加步骤</a>
|
||||||
|
<div className="mt20">
|
||||||
|
<Button type="primary" onClick={()=>nextStep("last")}>上一步</Button>
|
||||||
|
<Button className="ml20" type="primary" onClick={()=>nextStep("next")}>下一步</Button>
|
||||||
|
{!deleteFlag &&
|
||||||
|
<Popconfirm title={'确定要删除当前阶段吗'} okText="是" cancelText="否" onConfirm={deleteFunc}>
|
||||||
|
<Cancel className="ml20">删除</Cancel>
|
||||||
|
</Popconfirm>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default Stage;
|
|
@ -0,0 +1,41 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { FlexAJ } from '../../Component/layout';
|
||||||
|
import Editors from './Editors';
|
||||||
|
import Choosen from './Choosen';
|
||||||
|
import { Popconfirm } from 'antd';
|
||||||
|
|
||||||
|
|
||||||
|
function StageItem({item, templates,saveItems,k, slideItems , deleteStep}){
|
||||||
|
|
||||||
|
function onChangevalue(value){
|
||||||
|
saveItems(value,item.template_id,item.category,k);
|
||||||
|
}
|
||||||
|
// 选择模板
|
||||||
|
function chooseFunc(content,id,cate){
|
||||||
|
saveItems(content,id,cate,k);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(
|
||||||
|
<div className="stepsItem">
|
||||||
|
<FlexAJ className="stepsHead">
|
||||||
|
<span>{item.step_name}</span>
|
||||||
|
<span className="color-grey-9">
|
||||||
|
<Popconfirm
|
||||||
|
title={"确定要删除这个步骤吗?"}
|
||||||
|
okText="是"
|
||||||
|
cancelText="否"
|
||||||
|
onConfirm={() => deleteStep(item.id,k)}
|
||||||
|
><a>
|
||||||
|
<i className="iconfont icon-lajitong1 font-14"></i></a>
|
||||||
|
</Popconfirm>
|
||||||
|
<a onClick={()=>slideItems(k,item.hide)}><i className={ (!item.hide || item.hide === false) ? "iconfont icon-sanjiaoxing-down font-14" :"iconfont icon-triangle font-14"}></i></a>
|
||||||
|
</span>
|
||||||
|
</FlexAJ>
|
||||||
|
<div className={(!item.hide || item.hide === false) ? "stepsBody active" : "stepsBody"}>
|
||||||
|
<Choosen chooseFunc={chooseFunc} category={item.category} templateId={item.template_id} temp={templates}/>
|
||||||
|
<Editors value={item.content} onChange={onChangevalue} theme="vs-dark" height="270px" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default StageItem;
|
|
@ -0,0 +1,32 @@
|
||||||
|
import React ,{useEffect , useState} from 'react';
|
||||||
|
import { Button } from 'antd';
|
||||||
|
import Editors from './Editors';
|
||||||
|
|
||||||
|
function Sure({datas , name , saveFunc , sureSubmit , loading}){
|
||||||
|
const [ value , setValue ] = useState(undefined);
|
||||||
|
useEffect(()=>{
|
||||||
|
if(datas && datas.content){
|
||||||
|
setValue(datas.content)
|
||||||
|
}
|
||||||
|
},[datas]);
|
||||||
|
|
||||||
|
function sure(){
|
||||||
|
sureSubmit();
|
||||||
|
}
|
||||||
|
|
||||||
|
return(
|
||||||
|
<div>
|
||||||
|
<div style={{padding:"0px 15px 15px 15px"}}>
|
||||||
|
工作流名称:{name}
|
||||||
|
</div>
|
||||||
|
<div className="editorBody" style={{marginTop:"0px"}}>
|
||||||
|
<Editors value={value} theme={"vs-grey"} height={"600px"} visible/>
|
||||||
|
</div>
|
||||||
|
<div className="mt20">
|
||||||
|
<Button type={"primary"} onClick={()=>saveFunc(undefined,undefined,undefined,undefined,"last")}>上一步</Button>
|
||||||
|
{ value && <Button type={"primary"} loading={loading} className="ml20" onClick={sure}>确定提交</Button> }
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default Sure;
|
|
@ -0,0 +1,21 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { AlignCenterBetween , Blueline , FlexAJ } from '../../Component/layout';
|
||||||
|
|
||||||
|
|
||||||
|
function head({manager , parameter}){
|
||||||
|
return(
|
||||||
|
<AlignCenterBetween>
|
||||||
|
<span className="font-20">工作流配置</span>
|
||||||
|
<FlexAJ>
|
||||||
|
{
|
||||||
|
parameter && <Blueline onClick={parameter}>参数管理</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>
|
||||||
|
</AlignCenterBetween>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default head;
|
|
@ -0,0 +1,40 @@
|
||||||
|
import React from 'react';
|
||||||
|
import MenusRename from './menusRename';
|
||||||
|
import MenusAdd from './menusAdd';
|
||||||
|
|
||||||
|
const typeIcon = {
|
||||||
|
init:"icon-initialize",build:"icon-structure",deploy:"icon-arrange",customize:"icon-newStage",confirm:'icon-sure'
|
||||||
|
}
|
||||||
|
|
||||||
|
function Menus({step,changeStep, menuList , renameFunc , checkDatas , addFunc }){
|
||||||
|
|
||||||
|
function InitActive(key,stage_type,stage_id,stage_name){
|
||||||
|
changeStep(key,stage_type,stage_id,stage_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增阶段
|
||||||
|
function getName(name,index){
|
||||||
|
addFunc && addFunc(name,index);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(
|
||||||
|
<ul className="menus">
|
||||||
|
{
|
||||||
|
menuList && menuList.length > 0 && menuList.map((item,key)=>{
|
||||||
|
return(
|
||||||
|
<React.Fragment key={item.id} >
|
||||||
|
<li onClick={()=>InitActive(item.show_index,item.stage_type,item.id,item.stage_name)} className={item.show_index === step ?"active":""}>
|
||||||
|
<i className={`iconfont ${typeIcon[`${item.stage_type}`]}`}></i>
|
||||||
|
<MenusRename renameFunc={renameFunc} id={item.id} name={item.stage_name} edit={item.stage_type !== "init" && item.stage_type !== "confirm"}/>
|
||||||
|
</li>
|
||||||
|
{ key !== (menuList.length-1) && menuList.length < 7 ?
|
||||||
|
<MenusAdd checkDatas={checkDatas} k={key+2} getName={getName}/>:""
|
||||||
|
}
|
||||||
|
</React.Fragment>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default Menus;
|
|
@ -0,0 +1,55 @@
|
||||||
|
import React , { useState , useEffect } from 'react';
|
||||||
|
import { Input } from 'antd';
|
||||||
|
|
||||||
|
function menusAdd ({ getName , checkDatas , k }){
|
||||||
|
const [ show, setShow ] = useState(false);
|
||||||
|
const [ value , setValue ] = useState(undefined);
|
||||||
|
const [ index , setIndex ] = useState(undefined);
|
||||||
|
const [ref, setRef ] = useState(undefined);
|
||||||
|
const [put, setPut ] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (put && ref) {
|
||||||
|
ref.focus();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
useEffect(() => {
|
||||||
|
if (k) {
|
||||||
|
setIndex(k);
|
||||||
|
}
|
||||||
|
},[k])
|
||||||
|
|
||||||
|
|
||||||
|
function blurInput(){
|
||||||
|
if(value){
|
||||||
|
getName(value , index);
|
||||||
|
}
|
||||||
|
setValue(undefined);
|
||||||
|
setShow(false);
|
||||||
|
setPut(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function showInput(){
|
||||||
|
let c = checkDatas();
|
||||||
|
if(c || c === "" ){
|
||||||
|
setShow(true);
|
||||||
|
setPut(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return(
|
||||||
|
<li className="menuAdd">
|
||||||
|
{ !show && <i className="iconfont icon-tianjia" onClick={showInput}></i> }
|
||||||
|
<Input
|
||||||
|
ref={(el) => setRef(el)}
|
||||||
|
size={"small"}
|
||||||
|
maxLength={8}
|
||||||
|
style={{width:"75px",display : `${show?"block":'none'}`}}
|
||||||
|
placeholder="新阶段名称"
|
||||||
|
value={value}
|
||||||
|
onChange={(e)=>setValue(e.target.value)} onBlur={blurInput}
|
||||||
|
/>
|
||||||
|
</li>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default menusAdd;
|
|
@ -0,0 +1,53 @@
|
||||||
|
import React , { useEffect , useState } from 'react';
|
||||||
|
import { Input } from 'antd';
|
||||||
|
|
||||||
|
function menusRename({ name , edit , id , renameFunc }){
|
||||||
|
const [ n , setN ] = useState(undefined);
|
||||||
|
const [ show , setShow ] = useState(false);
|
||||||
|
const [ref, setRef ] = useState(undefined);
|
||||||
|
const [put, setPut ] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (edit && ref) {
|
||||||
|
ref.focus();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
if(name){
|
||||||
|
setN(name)
|
||||||
|
}
|
||||||
|
},[name])
|
||||||
|
|
||||||
|
// 显示input框编辑
|
||||||
|
function changeShow(e){
|
||||||
|
e.stopPropagation();
|
||||||
|
setShow(true);
|
||||||
|
setPut(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function blurInput(e){
|
||||||
|
renameFunc(e.target.value,id);
|
||||||
|
setPut(false);
|
||||||
|
setShow(false);
|
||||||
|
}
|
||||||
|
return(
|
||||||
|
<div className="aboutEdit">
|
||||||
|
<span className="operateName">
|
||||||
|
{ !show && n }
|
||||||
|
<Input
|
||||||
|
ref={(el) => setRef(el)}
|
||||||
|
value={n}
|
||||||
|
size="small"
|
||||||
|
maxLength={8}
|
||||||
|
onClick={(e)=>e.stopPropagation()}
|
||||||
|
onBlur={blurInput}
|
||||||
|
style={{width:"75px",display : `${show?"block":'none'}`}}
|
||||||
|
onChange={(e)=>setN(e.target.value)}
|
||||||
|
/>
|
||||||
|
{ !show && edit && <i className="iconfont icon-editUnder font-16 color-grey-9" onClick={changeShow}></i> }
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default menusRename
|
|
@ -8,7 +8,7 @@ const Div = styled.div`{
|
||||||
text-align:center;
|
text-align:center;
|
||||||
color:#333;
|
color:#333;
|
||||||
}`
|
}`
|
||||||
export default (({visible , closeFunc , suresubmit})=>{
|
export default (({visible , closeFunc , sureFunc})=>{
|
||||||
return(
|
return(
|
||||||
<Modal
|
<Modal
|
||||||
title="提示"
|
title="提示"
|
||||||
|
@ -17,7 +17,7 @@ export default (({visible , closeFunc , suresubmit})=>{
|
||||||
footer={
|
footer={
|
||||||
<div>
|
<div>
|
||||||
<Button onClick={()=>closeFunc(false)}>取消</Button>
|
<Button onClick={()=>closeFunc(false)}>取消</Button>
|
||||||
<Button type={"primary"} onClick={suresubmit} style={{marginLeft:"20px"}}>确定</Button>
|
<Button type={"primary"} onClick={()=>sureFunc()} style={{marginLeft:"20px"}}>确定</Button>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
onCancel={()=>closeFunc(false)}
|
onCancel={()=>closeFunc(false)}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React from 'react';
|
import React , { useEffect } from 'react';
|
||||||
import { WhiteBack } from '../Component/layout';
|
import { WhiteBack } from '../Component/layout';
|
||||||
import './ops.scss';
|
import './ops.scss';
|
||||||
|
|
||||||
|
@ -10,27 +10,65 @@ const About = Loadable({
|
||||||
loader: () => import('./About'),
|
loader: () => import('./About'),
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
})
|
})
|
||||||
const Infos = Loadable({
|
const New = Loadable({
|
||||||
loader: () => import('./Infos'),
|
loader: () => import('./disposePipeline'),
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
})
|
})
|
||||||
|
const Dispose = Loadable({
|
||||||
|
loader: () => import('./Dispose'),
|
||||||
|
loading: Loading,
|
||||||
|
})
|
||||||
|
const Stucture = Loadable({
|
||||||
|
loader: () => import('./Structure'),
|
||||||
|
loading: Loading,
|
||||||
|
})
|
||||||
|
const Mould = Loadable({
|
||||||
|
loader: () => import('./Mould'),
|
||||||
|
loading: Loading,
|
||||||
|
})
|
||||||
|
const Params = Loadable({
|
||||||
|
loader: () => import('./Manage/Params'),
|
||||||
|
loading: Loading,
|
||||||
|
})
|
||||||
|
|
||||||
export default ((props)=>{
|
export default ((props)=>{
|
||||||
|
|
||||||
return(
|
return(
|
||||||
<WhiteBack className="opsPanel">
|
<WhiteBack className="opsPanel">
|
||||||
<Switch {...props}>
|
<Switch {...props}>
|
||||||
<Route path="/projects/:projectsId/ops/dispose"
|
<Route path="/projects/:owner/:projectsId/devops/dispose/:disposeId"
|
||||||
render={
|
render={
|
||||||
() => (<Infos {...props} />)
|
(p) => (<New {...props} {...p}/>)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
<Route path="/projects/:projectsId/ops/list"
|
<Route path="/projects/:owner/:projectsId/devops/params"
|
||||||
render={
|
render={
|
||||||
() => (<Infos {...props} />)
|
(p) => (<Params {...props} {...p}/>)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
<Route path="/projects/:projectsId/ops"
|
<Route path="/projects/:owner/:projectsId/devops/mould"
|
||||||
render={
|
render={
|
||||||
() => (<About {...props} />)
|
(p) => (<Mould {...props} {...p}/>)
|
||||||
|
}
|
||||||
|
></Route>
|
||||||
|
<Route path="/projects/:owner/:projectsId/devops/dispose/new"
|
||||||
|
render={
|
||||||
|
(p) => (<New {...props} {...p}/>)
|
||||||
|
}
|
||||||
|
></Route>
|
||||||
|
<Route path="/projects/:owner/:projectsId/devops/dispose"
|
||||||
|
render={
|
||||||
|
(p) => (<Dispose {...props} {...p}/>)
|
||||||
|
}
|
||||||
|
></Route>
|
||||||
|
<Route path="/projects/:owner/:projectsId/devops/list/:branch"
|
||||||
|
render={
|
||||||
|
(p) => (<Stucture {...props} {...p}/>)
|
||||||
|
}
|
||||||
|
></Route>
|
||||||
|
<Route path="/projects/:owner/:projectsId/devops"
|
||||||
|
render={
|
||||||
|
(p) => (<About {...props} {...p}/>)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
</Switch>
|
</Switch>
|
||||||
|
|
|
@ -3,7 +3,6 @@ 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';
|
||||||
|
|
||||||
|
@ -11,27 +10,26 @@ const Div = styled.div`{
|
||||||
padding:24px 30px;
|
padding:24px 30px;
|
||||||
}`;
|
}`;
|
||||||
export default ((props)=>{
|
export default ((props)=>{
|
||||||
const [ menu , setMenu ] = useState(undefined);
|
const [ permission , setPermission ] = useState("");
|
||||||
|
|
||||||
|
const owner = props.match.params.owner;
|
||||||
|
|
||||||
|
const projectDetail = props.projectDetail;
|
||||||
|
|
||||||
const path = props.location.pathname;
|
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
// console.log(props.match.params.projectsId)
|
if(projectDetail){
|
||||||
if(path === `/projects/${props.match.params.projectsId}/ops/list`){
|
setPermission(props.projectDetail.permission);
|
||||||
setMenu(true);
|
|
||||||
}else{
|
|
||||||
setMenu(false);
|
|
||||||
}
|
}
|
||||||
},[path])
|
},[projectDetail])
|
||||||
|
|
||||||
|
|
||||||
return(
|
return(
|
||||||
<div className="disposePanel">
|
<div className="disposePanel">
|
||||||
<Banner>
|
<Banner>
|
||||||
<Link to={`/projects/${props.match.params.projectsId}/ops/dispose`}>工作流配置</Link>
|
{ permission !=="Reporter" && <Link to={`/projects/${owner}/${props.match.params.projectsId}/devops/dispose`}>工作流配置</Link>}
|
||||||
{ menu ? <Link to={`/projects/${props.match.params.projectsId}/ops/list`} style={{ marginLeft:"66px",color:"#5091FF" }}>构建列表</Link>:""}
|
|
||||||
</Banner>
|
</Banner>
|
||||||
<Div>
|
<Div>
|
||||||
{ menu && menu === true && <Structure {...props}/> }
|
<Dispost {...props}/>
|
||||||
{ menu && menu === false && <Dispost {...props}/> }
|
|
||||||
</Div>
|
</Div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,119 @@
|
||||||
|
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;
|
|
@ -0,0 +1,73 @@
|
||||||
|
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));
|
|
@ -0,0 +1,4 @@
|
||||||
|
.ant-form-explain{
|
||||||
|
position: absolute;
|
||||||
|
bottom: -15px;
|
||||||
|
}
|
|
@ -0,0 +1,160 @@
|
||||||
|
import React , { useEffect , useState , useRef } from 'react';
|
||||||
|
import { Banner , Blueback , FlexAJ } from '../Component/layout';
|
||||||
|
import { Input , Table ,Pagination , Select , Popconfirm } from 'antd';
|
||||||
|
import { Link } from 'react-router-dom'
|
||||||
|
import styled from 'styled-components';
|
||||||
|
import axios from 'axios';
|
||||||
|
import New from './MouldNew';
|
||||||
|
|
||||||
|
const { Option } = Select;
|
||||||
|
|
||||||
|
const Div = styled.div`{
|
||||||
|
padding:24px 30px;
|
||||||
|
min-height:420px;
|
||||||
|
}`;
|
||||||
|
const STAGE = [
|
||||||
|
{stage_name:"所有",stage_type:"all"},
|
||||||
|
{stage_name:"初始化",stage_type:"init"},
|
||||||
|
{stage_name:"编译构建",stage_type:"build"},
|
||||||
|
{stage_name:"部署",stage_type:"deploy"},
|
||||||
|
{stage_name:"其他",stage_type:"customize"}
|
||||||
|
]
|
||||||
|
const limit = 15;
|
||||||
|
function Mould(props){
|
||||||
|
const [ visible ,setVisible ] = useState(false);
|
||||||
|
const [ list ,setList ] = useState(undefined);
|
||||||
|
const [ page ,setPage ] = useState(1);
|
||||||
|
const [ totalCount ,setTotalCount ] = useState(0);
|
||||||
|
const [ stageType ,setStageType ] = useState("all");
|
||||||
|
const [ search ,setSearch ] = useState(undefined);
|
||||||
|
const childRef = useRef();
|
||||||
|
let projectsId = props.match.params.projectsId;
|
||||||
|
let owner = props.match.params.owner;
|
||||||
|
useEffect(()=>{
|
||||||
|
Init(page,stageType);
|
||||||
|
},[page,stageType])
|
||||||
|
|
||||||
|
function Init(page,stageType,searchvalue){
|
||||||
|
const url = `/ci/templates/list.json`;
|
||||||
|
axios.get(url,{
|
||||||
|
params:{
|
||||||
|
page,limit,stage_type:stageType,name:searchvalue
|
||||||
|
}
|
||||||
|
}).then(result=>{
|
||||||
|
if(result && result.data){
|
||||||
|
setList(result.data.templates);
|
||||||
|
setTotalCount(result.data.total_count);
|
||||||
|
}
|
||||||
|
}).catch(error=>{})
|
||||||
|
}
|
||||||
|
|
||||||
|
const columns=[
|
||||||
|
{
|
||||||
|
title:"名称",
|
||||||
|
dataIndex:"template_name",
|
||||||
|
key:1,
|
||||||
|
ellipsis:true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title:"所属阶段",
|
||||||
|
dataIndex:"stage_type",
|
||||||
|
key:2,
|
||||||
|
ellipsis:true,
|
||||||
|
render:(txt,item)=>{
|
||||||
|
let i = STAGE.filter(item=>item.stage_type === txt);
|
||||||
|
return i && i.length>0 && i[0].stage_name
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title:"模板类型",
|
||||||
|
dataIndex:"category",
|
||||||
|
key:3,
|
||||||
|
ellipsis:true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title:"操作",
|
||||||
|
dataIndex:"operation",
|
||||||
|
key:4,
|
||||||
|
ellipsis:true,
|
||||||
|
render:(txt,item)=>{
|
||||||
|
return(
|
||||||
|
<span>
|
||||||
|
<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)} okText="确定" cancelText={"取消"}>
|
||||||
|
<a className="mr10 color-grey-6"><i className="iconfont icon-lajitong font-13 mr3"></i>删除</a>
|
||||||
|
</Popconfirm>
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
// 编辑模板
|
||||||
|
function editMouldFunc(item){
|
||||||
|
if (childRef.current) {
|
||||||
|
childRef.current.setEditInfo(item);
|
||||||
|
}
|
||||||
|
setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除模板
|
||||||
|
function deleteMouldFunc(id){
|
||||||
|
const url = `/ci/templates/${id}.json`;
|
||||||
|
axios.delete(url).then(result=>{
|
||||||
|
if(result && result.data){
|
||||||
|
props.showNotification("模板删除成功!");
|
||||||
|
Init(page,stageType,search);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function searchValue(){
|
||||||
|
Init(page,stageType,search);
|
||||||
|
}
|
||||||
|
|
||||||
|
function newMouldFunc(){
|
||||||
|
if (childRef.current) {
|
||||||
|
childRef.current.setEditInfo(undefined);
|
||||||
|
}
|
||||||
|
setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onOk(){
|
||||||
|
Init(page,stageType);
|
||||||
|
}
|
||||||
|
return(
|
||||||
|
<div>
|
||||||
|
<New wrappedComponentRef={(f) => childRef.current = f} ref={childRef} visible={visible} onCancel={()=>setVisible(false)} onOk={onOk}></New>
|
||||||
|
<Banner>
|
||||||
|
<FlexAJ><span>工作流 - 模板管理</span><Link to={`/projects/${owner}/${projectsId}/devops/dispose`} className="font-14 color-grey-9">返回</Link></FlexAJ>
|
||||||
|
</Banner>
|
||||||
|
<Div className="disposeList">
|
||||||
|
<FlexAJ>
|
||||||
|
<Blueback onClick={newMouldFunc}>新建模板</Blueback>
|
||||||
|
<FlexAJ>
|
||||||
|
<span className="mr10">阶段:</span>
|
||||||
|
<Select onChange={e=>setStageType(e)} value={stageType} style={{width:"180px"}}>
|
||||||
|
{
|
||||||
|
STAGE.map((item,key)=>{
|
||||||
|
return(
|
||||||
|
<Option value={item.stage_type}>{item.stage_name}</Option>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</Select>
|
||||||
|
<Input placeholder="请输入模板名称" value={search} onChange={(e)=>setSearch(e.target.value)} allowClear style={{width:"160px",marginLeft:"15px"}}/>
|
||||||
|
<Blueback className="ml15" onClick={searchValue}>搜索</Blueback>
|
||||||
|
</FlexAJ>
|
||||||
|
</FlexAJ>
|
||||||
|
<Table className="mt20" size="small" columns={columns} dataSource={list} rowKey={(row)=>row.id} pagination={false}></Table>
|
||||||
|
{
|
||||||
|
totalCount > limit &&
|
||||||
|
<div className="mt20 pb20" style={{textAlign:'center'}}>
|
||||||
|
<Pagination simple current={page} pageSize={limit} total={totalCount} onChange={(page)=>setPage(page)}/>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</Div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default Mould;
|
|
@ -0,0 +1,166 @@
|
||||||
|
import React , { useImperativeHandle , useState , forwardRef , useCallback } from 'react';
|
||||||
|
import { Form , Modal , Input , Select , Spin } from 'antd';
|
||||||
|
import Editor from './Dispose/Editors';
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
const { Option } = Select;
|
||||||
|
const TYPE = ["Java","C","C++","Python","Go","Ruby","R","PHP",
|
||||||
|
"Perl","Node","Docker","Rust","Swift","Erlang","Other"]
|
||||||
|
|
||||||
|
function MouldNew({ form , visible , onCancel , onOk }, ref){
|
||||||
|
const [value , setValue ] = useState(undefined);
|
||||||
|
const [isSpin , setIsSpin ] = useState(false);
|
||||||
|
const [valueFlag , setValueFlag ] = useState(false);
|
||||||
|
const [ id , setId ] = useState(false);
|
||||||
|
const [ buildFlag , setBuildFlag ] = useState(false);
|
||||||
|
|
||||||
|
const { getFieldDecorator, validateFields , setFieldsValue } = form;
|
||||||
|
|
||||||
|
useImperativeHandle(ref, () => ({
|
||||||
|
setEditInfo: (info) => {
|
||||||
|
if(info){
|
||||||
|
setFieldsValue({
|
||||||
|
...info
|
||||||
|
})
|
||||||
|
if(info.stage_type === "build"){
|
||||||
|
setBuildFlag(true);
|
||||||
|
setFieldsValue({
|
||||||
|
category:TYPE[0]
|
||||||
|
})
|
||||||
|
}else{
|
||||||
|
removeCate();
|
||||||
|
}
|
||||||
|
setValue(info.content);
|
||||||
|
setId(info.id);
|
||||||
|
}else{
|
||||||
|
removeCate();
|
||||||
|
clear();
|
||||||
|
setId(undefined);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
const helper = useCallback(
|
||||||
|
(label, name, rules, widget, className, isRequired,flag) => (
|
||||||
|
<Form.Item label={label} className={className}>
|
||||||
|
{getFieldDecorator(name, { rules, validateFirst: true , valuePropName:flag ? "checked":"value" })(widget)}
|
||||||
|
</Form.Item>
|
||||||
|
),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
function changeContent(v){
|
||||||
|
if(v){
|
||||||
|
setValue(v);
|
||||||
|
setValueFlag(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function cancel(){
|
||||||
|
clear();
|
||||||
|
onCancel();
|
||||||
|
}
|
||||||
|
function sure(){
|
||||||
|
if(!value){
|
||||||
|
setValueFlag(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
validateFields((error,values)=>{
|
||||||
|
if(!error){
|
||||||
|
setIsSpin(true);
|
||||||
|
const url = `/ci/templates.json`;
|
||||||
|
axios.post(url,{
|
||||||
|
...values,id,content:value,category:buildFlag ? values.category:""
|
||||||
|
}).then(result=>{
|
||||||
|
if(result && result.data){
|
||||||
|
setIsSpin(false);
|
||||||
|
cancel();
|
||||||
|
onOk();
|
||||||
|
}
|
||||||
|
}).catch(error=>{})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
function clear(){
|
||||||
|
setFieldsValue({
|
||||||
|
stage_type:"init",
|
||||||
|
template_name:undefined,
|
||||||
|
category:"Java",
|
||||||
|
})
|
||||||
|
setValue("");
|
||||||
|
setValueFlag(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeStage(e){
|
||||||
|
if(e === "build"){
|
||||||
|
setBuildFlag(true);
|
||||||
|
setFieldsValue({
|
||||||
|
category:TYPE[0]
|
||||||
|
})
|
||||||
|
}else{
|
||||||
|
removeCate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeCate(){
|
||||||
|
setBuildFlag(false);
|
||||||
|
setFieldsValue({
|
||||||
|
category:""
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return(
|
||||||
|
<Modal
|
||||||
|
visible={visible}
|
||||||
|
width="500px"
|
||||||
|
title={"新建/编辑模板"}
|
||||||
|
onCancel={cancel}
|
||||||
|
onOk={sure}
|
||||||
|
centered={true}
|
||||||
|
>
|
||||||
|
<Spin spinning={isSpin}>
|
||||||
|
<Form layout={"inline"}>
|
||||||
|
{helper(
|
||||||
|
"所属阶段",
|
||||||
|
"stage_type",
|
||||||
|
[{required:true,message:"请选择所属阶段"}],
|
||||||
|
<Select placeholder="请选择所属阶段" style={{width:"350px"}} onChange={(e)=>{changeStage(e)}}>
|
||||||
|
<Option value="init">初始化</Option>
|
||||||
|
<Option value="build">编译构建</Option>
|
||||||
|
<Option value="deploy">部署</Option>
|
||||||
|
<Option value="customize">其他</Option>
|
||||||
|
</Select>
|
||||||
|
)}
|
||||||
|
{helper(
|
||||||
|
"模板名称",
|
||||||
|
"template_name",
|
||||||
|
[{required:true,message:"请输入模板名称"}],
|
||||||
|
<Input placeholder="请输入模板名称" style={{width:"350px"}}/>
|
||||||
|
)}
|
||||||
|
{helper(
|
||||||
|
"模板分类",
|
||||||
|
"category",
|
||||||
|
[{required:buildFlag,message:"请选择模板分类"}],
|
||||||
|
<Select placeholder="请选择模板分类" style={{width:"350px"}}>
|
||||||
|
{
|
||||||
|
TYPE.map((item,key)=>{
|
||||||
|
return(
|
||||||
|
<Option value={item}>{item}</Option>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</Select>,buildFlag===true ? "" :"hide"
|
||||||
|
)}
|
||||||
|
<div style={{display:'flex',justifyContent:"flex-start"}}>
|
||||||
|
<span><span className="color-red">* </span>模板内容:</span>
|
||||||
|
<div>
|
||||||
|
<div className="editorPanel">
|
||||||
|
<Editor Numbers={"off"} width={"350px"} value={value} height="200px" theme="vs-grey" onChange={changeContent}/>
|
||||||
|
</div>
|
||||||
|
{ valueFlag && <span className="color-red">请输入模板内容</span>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Form>
|
||||||
|
</Spin>
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default Form.create()(forwardRef(MouldNew));
|
||||||
|
|
|
@ -1,42 +1,127 @@
|
||||||
import React from 'react';
|
import React, { useEffect, useState } from "react";
|
||||||
import { FlexAJ , Blueline , AlignCenter } from '../Component/layout';
|
import { FlexAJ, Blueline, AlignCenter } from "../Component/layout";
|
||||||
import styled from 'styled-components';
|
import styled from "styled-components";
|
||||||
import { Menu } from 'antd';
|
import { Menu, Popconfirm } from "antd";
|
||||||
import { TagsLine } from '../Component/OpsStatus';
|
import { TagsLine } from "../Component/OpsStatus";
|
||||||
|
import { Time } from "../Utils/Time";
|
||||||
|
import { truncateCommitId } from "../common/util";
|
||||||
|
import { getUrl } from 'educoder';
|
||||||
|
|
||||||
const SubMenu = Menu.SubMenu;
|
const SubMenu = Menu.SubMenu;
|
||||||
const Img = styled.img`{
|
const Img = styled.img`
|
||||||
width:25px;
|
{
|
||||||
height:25px;
|
width: 25px;
|
||||||
border-radius:50%;
|
height: 25px;
|
||||||
margin-right:10px;
|
border-radius: 50%;
|
||||||
}`
|
margin-right: 10px;
|
||||||
export default (()=>{
|
}
|
||||||
return(
|
`;
|
||||||
|
export default ({ data, repeatSet , chooseSteps }) => {
|
||||||
|
const [tamp, setTamp] = useState(undefined);
|
||||||
|
const [sha, setSha] = useState(undefined);
|
||||||
|
useEffect(() => {
|
||||||
|
if (data && data.started) {
|
||||||
|
let t = parseInt(data.started) * 1000;
|
||||||
|
let time = Time(t);
|
||||||
|
setTamp(time);
|
||||||
|
}
|
||||||
|
if (data && data.after) {
|
||||||
|
setSha(truncateCommitId(data.after));
|
||||||
|
}
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
function renderStatusBtn() {
|
||||||
|
let status = data && data.status;
|
||||||
|
let number = data && data.number;
|
||||||
|
if (status === "failure" || status === "error" || status === "success") {
|
||||||
|
return "";
|
||||||
|
}else if(status === "killed"){
|
||||||
|
return(
|
||||||
|
<Popconfirm
|
||||||
|
title="确认重新构建?"
|
||||||
|
onConfirm={(e) => repeatSet(e,'repeat',number)}
|
||||||
|
onCancel={(e)=>{e.stopPropagation()}}
|
||||||
|
cancelText="取消"
|
||||||
|
okText="确定"
|
||||||
|
>
|
||||||
|
<Blueline onClick={(e)=>{e.stopPropagation()}}>重新构建</Blueline>
|
||||||
|
</Popconfirm>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<Popconfirm
|
||||||
|
title="确认撤销构建?"
|
||||||
|
onConfirm={(e) => repeatSet(e,'cancel',number)}
|
||||||
|
onCancel={(e)=>{e.stopPropagation()}}
|
||||||
|
cancelText="取消"
|
||||||
|
okText="确定"
|
||||||
|
>
|
||||||
|
<Blueline onClick={(e)=>{e.stopPropagation()}}>撤销构建</Blueline>
|
||||||
|
</Popconfirm>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function clickSub(e,stageN,stepN){
|
||||||
|
chooseSteps(stageN,stepN);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
<div>
|
<div>
|
||||||
<FlexAJ className="leftheader">
|
<FlexAJ className="leftheader">
|
||||||
<AlignCenter>
|
<AlignCenter>
|
||||||
<Img src="https://dss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=2091711702,2468700162&fm=111&gp=0.jpg"/>
|
<Img src={getUrl(`/images/${data && data.author && data.author.image_url}`)} />
|
||||||
<span className="nest">开始时间:<span>2020.07.10 15:30</span></span>
|
{data && data.started &&
|
||||||
<span className="nest">运行时间:<span>20s</span></span>
|
<span className="nest">
|
||||||
|
开始时间:<span> {data.started}</span>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
{
|
||||||
|
data && data.duration_time &&
|
||||||
|
<span className="nest">
|
||||||
|
运行时间:<span>{data.duration_time}</span>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
</AlignCenter>
|
</AlignCenter>
|
||||||
<Blueline>重新创建</Blueline>
|
{renderStatusBtn()}
|
||||||
</FlexAJ>
|
</FlexAJ>
|
||||||
<div className="leftMainContent">
|
<div className="leftMainContent">
|
||||||
<AlignCenter className="contentBranch">
|
<AlignCenter className="contentBranch">
|
||||||
<i className="iconfont icon-fenzhi1"></i>
|
<i className="iconfont icon-fenzhi1"></i>
|
||||||
<span>分支:</span>
|
<span>分支:</span>
|
||||||
<span className="branchname">master</span>
|
<span className="branchname">{data && data.branch_target}</span>
|
||||||
<span className="branchsha">8b3476f5</span>
|
<span className="branchsha">{data && truncateCommitId(data.build_after_sha)}</span>
|
||||||
</AlignCenter>
|
</AlignCenter>
|
||||||
</div>
|
</div>
|
||||||
<Menu mode='inline' className="leftMenu">
|
<Menu mode="inline" className="leftMenu" defaultOpenKeys={[`0`]} defaultSelectedKeys={[`0`]}>
|
||||||
<SubMenu title={<div><i className="iconfont icon-gongzuoliu font-14 mr4"></i><span>CI</span></div>}>
|
{data && data.stages ? data.stages.map((item, key) => {
|
||||||
<Menu.Item>
|
return item.steps && item.steps.length > 0 ?
|
||||||
<FlexAJ><span>Build setup 01 {TagsLine(1)}</span><span>20s</span></FlexAJ>
|
<SubMenu
|
||||||
</Menu.Item>
|
title={
|
||||||
</SubMenu>
|
<div>
|
||||||
|
<i className="iconfont icon-gongzuoliu font-14 mr4"></i>
|
||||||
|
<span>{item.name}</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
key={`${key}`}
|
||||||
|
>
|
||||||
|
{item.steps.map((i, k) => {
|
||||||
|
return (
|
||||||
|
<Menu.Item key={`${k}`} onClick={(e)=>clickSub(e,item.number,i.id)}>
|
||||||
|
<FlexAJ>
|
||||||
|
<span>
|
||||||
|
{i.name} {i.status ? TagsLine(i.status) : ""}
|
||||||
|
</span>
|
||||||
|
<span>{i.duration_time}</span>
|
||||||
|
</FlexAJ>
|
||||||
|
</Menu.Item>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</SubMenu>
|
||||||
|
: "";
|
||||||
|
})
|
||||||
|
: ""}
|
||||||
</Menu>
|
</Menu>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
})
|
};
|
||||||
|
|
|
@ -1,21 +1,123 @@
|
||||||
import React from 'react';
|
import React, { useState, useEffect } from "react";
|
||||||
import { FlexAJ , AlignCenter } from '../Component/layout';
|
import { Spin , Menu } from "antd";
|
||||||
|
import { FlexAJ, AlignCenter } from "../Component/layout";
|
||||||
|
import axios from "axios";
|
||||||
|
import CodeSSH from './ssh/Index';
|
||||||
|
|
||||||
export default (()=>{
|
export default ({
|
||||||
return(
|
data,
|
||||||
<div className="rightMainContent">
|
stepN,
|
||||||
<div>
|
stageN,
|
||||||
<FlexAJ className="items">
|
projectId,
|
||||||
<span>Build setup 01</span>
|
owner,
|
||||||
<AlignCenter>20<i className="iconfont icon-triangle"></i></AlignCenter>
|
opsId,
|
||||||
</FlexAJ>
|
rightSpin,
|
||||||
</div>
|
}) => {
|
||||||
<div>
|
const [coders, setCoders] = useState(undefined);
|
||||||
<FlexAJ className="items"></FlexAJ>
|
const [empty, setEmpty] = useState(false);
|
||||||
</div>
|
const [spining, setSpining] = useState(true);
|
||||||
<div>
|
const [stage, setStage] = useState(undefined);
|
||||||
<FlexAJ className="items"></FlexAJ>
|
const [step, setStep] = useState(undefined);
|
||||||
</div>
|
const [nav, setNav] = useState("0");
|
||||||
</div>
|
|
||||||
)
|
useEffect(() => {
|
||||||
})
|
setSpining(rightSpin);
|
||||||
|
}, [rightSpin]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (data) {
|
||||||
|
let stages = data.stages;
|
||||||
|
if (stages && stages.length > 0) {
|
||||||
|
let pre = stageN
|
||||||
|
? stages.filter((item) => item.number === stageN)[0]
|
||||||
|
: stages[0];
|
||||||
|
setStage(pre);
|
||||||
|
let p = pre && pre.steps;
|
||||||
|
let sub = stepN
|
||||||
|
? p && p.length > 0 && p.filter((item) => item.id === stepN)[0]
|
||||||
|
: p[0];
|
||||||
|
|
||||||
|
setStep(sub);
|
||||||
|
setNav("0");
|
||||||
|
if (sub && sub.status !== "skipped") {
|
||||||
|
getStep(pre.number, sub.number);
|
||||||
|
}
|
||||||
|
// 如果状态是skipped就不用去调用接口查询对应的out信息了
|
||||||
|
if(sub.status === "skipped"){
|
||||||
|
setCoders(undefined);
|
||||||
|
setEmpty(true);
|
||||||
|
setSpining(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setSpining(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [data, stageN, stepN]);
|
||||||
|
|
||||||
|
function getStep(stageN, stepN) {
|
||||||
|
if (stageN && stepN) {
|
||||||
|
const url = `/${owner}/${projectId}/builds/${opsId}/logs/${stageN}/${stepN}.json`;
|
||||||
|
axios.get(url).then((result) => {
|
||||||
|
if (result) {
|
||||||
|
setCoders(result.data);
|
||||||
|
setSpining(false);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
{/* <Menu className="devopsNav" onClick={(e)=>{setNav(e.key)}} selectedKeys={[nav]} mode="horizontal">
|
||||||
|
<Menu.Item key={'0'} value="0">开发流水线</Menu.Item>
|
||||||
|
<Menu.Item key={'1'} value="1">命令行</Menu.Item>
|
||||||
|
</Menu> */}
|
||||||
|
{
|
||||||
|
nav === "0" &&
|
||||||
|
<Spin spinning={spining}>
|
||||||
|
<div className="rightMainContent">
|
||||||
|
{data && data.status !== "error" ? (
|
||||||
|
<div>
|
||||||
|
<FlexAJ className="items">
|
||||||
|
<span>{step && step.name}</span>
|
||||||
|
<AlignCenter>
|
||||||
|
{step && step.duration_time}
|
||||||
|
<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">
|
||||||
|
<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>
|
||||||
|
</Spin>
|
||||||
|
}
|
||||||
|
{
|
||||||
|
nav === "1" && <CodeSSH />
|
||||||
|
}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import { Radio , Button } from 'antd';
|
||||||
|
|
||||||
|
function ServiceModal({sureModal}){
|
||||||
|
const [ type , setType ] = useState(1);
|
||||||
|
|
||||||
|
function changeType(e){
|
||||||
|
setType(e.target.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(
|
||||||
|
<div className="mt30" style={{textAlign:"center"}}>
|
||||||
|
<Radio.Group value={type} onChange={changeType}>
|
||||||
|
<Radio value={1}>自有服务器</Radio>
|
||||||
|
<Radio value={2}>Trustie服务器</Radio>
|
||||||
|
</Radio.Group>
|
||||||
|
<p className="mt30"><Button type="primary" onClick={()=>sureModal(type)}>下一步</Button></p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default ServiceModal;
|
|
@ -1,240 +1,331 @@
|
||||||
import React , { useState , useEffect } from 'react';
|
import React, { useState, useEffect , useImperativeHandle ,forwardRef } from "react";
|
||||||
import { FlexAJ , AlignCenter , Blueback } from '../Component/layout';
|
import { FlexAJ, AlignCenter , Banner } from "../Component/layout";
|
||||||
import { Table , Pagination } from 'antd';
|
import { Table, Pagination, Popconfirm } from "antd";
|
||||||
import { truncateCommitId } from '../common/util';
|
import { truncateCommitId } from "../common/util";
|
||||||
|
import {getUrl} from 'educoder';
|
||||||
|
import axios from "axios";
|
||||||
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import axios from 'axios';
|
|
||||||
|
|
||||||
|
const Div = styled.div`{
|
||||||
|
padding:24px 30px;
|
||||||
|
}`;
|
||||||
const STATUS = [
|
const STATUS = [
|
||||||
{name:"所有",value:"1"},
|
{ name: "所有"},
|
||||||
{name:"准备中",value:"2"},
|
{ name: "运行中", value: "running" },
|
||||||
{name:"运行中",value:"3"},
|
{ name: "已撤销", value: "killed" },
|
||||||
{name:"已完成",value:"4"}
|
{ name: "构建失败", value: "failure" },
|
||||||
]
|
{ name: "已完成", value: "success" },
|
||||||
const LIMIT = 15;
|
|
||||||
const datasource = [
|
|
||||||
{
|
|
||||||
status:2,
|
|
||||||
author:"caishi",
|
|
||||||
message:{
|
|
||||||
branch:"master",
|
|
||||||
sha:"8b3476f5",
|
|
||||||
image:"https://dss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=2034740944,4251903193&fm=26&gp=0.jpg",
|
|
||||||
message:"将分支“ 221063-improve-buy-ci-minutes-link”"
|
|
||||||
},
|
|
||||||
begin:"2020-07-08",
|
|
||||||
run:"20s"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
status:1,
|
|
||||||
author:"caishi",
|
|
||||||
message:{
|
|
||||||
branch:"master",
|
|
||||||
sha:"8b3476f5",
|
|
||||||
image:"https://dss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=2034740944,4251903193&fm=26&gp=0.jpg",
|
|
||||||
message:"将分支“ 221063-improve-buy-ci-minutes-link”"
|
|
||||||
},
|
|
||||||
begin:"2020-07-08",
|
|
||||||
run:""
|
|
||||||
}
|
|
||||||
];
|
];
|
||||||
|
const LIMIT = 15;
|
||||||
|
function Structure(props,ref){
|
||||||
|
const [status, setStatus] = useState(undefined);
|
||||||
|
const [page, setPage] = useState(1);
|
||||||
|
const [total, setTotal] = useState(0);
|
||||||
|
const [data, setData] = useState(undefined);
|
||||||
|
const [tableLoading, setTableLoading] = useState(true);
|
||||||
|
|
||||||
const Img = styled.img`{
|
let projectsId = props.match.params.projectsId;
|
||||||
border-radius:50%;
|
let owner = props.match.params.owner;
|
||||||
margin-rigth:10px;
|
let branch = props.match.params.branch;
|
||||||
width:25px;
|
const permission = props.projectDetail && props.projectDetail.permission;
|
||||||
height:25px;
|
|
||||||
}`
|
|
||||||
export default ((props)=>{
|
|
||||||
const [ status ,setStatus ] = useState("1");
|
|
||||||
const [ page ,setPage ] = useState(1);
|
|
||||||
const [ total ,setTotal ] = useState(10);
|
|
||||||
const [ data , setData ] = useState(undefined);
|
|
||||||
|
|
||||||
let projectsId = props.match.params.projectsId;
|
useImperativeHandle(ref, () => ({
|
||||||
|
changeVal: () => {
|
||||||
useEffect(()=>{
|
setTableLoading(true);
|
||||||
if(projectsId){
|
Init();
|
||||||
const url ='/dev_ops/builds.json';
|
|
||||||
axios.get(url,{
|
|
||||||
params:{
|
|
||||||
project_id:projectsId
|
|
||||||
}
|
|
||||||
}).then(result=>{
|
|
||||||
if(result){
|
|
||||||
let list = result.data && result.data.map((item,key)=>{
|
|
||||||
return {
|
|
||||||
status:item.status,
|
|
||||||
author:item.sender,
|
|
||||||
message:{
|
|
||||||
branch:item.source,
|
|
||||||
image:item.author_avatar,
|
|
||||||
message:item.message,
|
|
||||||
sha:truncateCommitId(item.after)
|
|
||||||
},
|
|
||||||
started:item.started,
|
|
||||||
timestamp:item.timestamp
|
|
||||||
}
|
|
||||||
})
|
|
||||||
setData(list);
|
|
||||||
}
|
|
||||||
}).catch(error=>{
|
|
||||||
console.log(error);
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
},[])
|
}))
|
||||||
|
|
||||||
function ChangeStatus(value){
|
useEffect(() => {
|
||||||
setStatus(value)
|
if (projectsId) {
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
}, [page]);
|
||||||
|
|
||||||
|
let current_user = props.current_user;
|
||||||
|
function Init(status) {
|
||||||
|
const url = `/${owner}/${projectsId}/builds.json`;
|
||||||
|
axios.get(url,{
|
||||||
|
params:{
|
||||||
|
search:status,
|
||||||
|
page,limit:LIMIT,branch
|
||||||
|
}
|
||||||
|
}).then((result) => {
|
||||||
|
if (result && result.data) {
|
||||||
|
let list = result.data.builds && result.data.builds.map((item, key) => {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
author:item.author && item.author.name,
|
||||||
|
image_url:item.author && item.author.image_url,
|
||||||
|
message: {
|
||||||
|
branch: item.branch_target,
|
||||||
|
message: item.message,
|
||||||
|
sha: truncateCommitId(item.build_after_sha),
|
||||||
|
},
|
||||||
|
started: item.started || "--"
|
||||||
|
};
|
||||||
|
});
|
||||||
|
setTotal(result.data.total_count);
|
||||||
|
setData(list);
|
||||||
|
setTableLoading(false);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function ChangeStatus(value) {
|
||||||
|
setStatus(value);
|
||||||
|
Init(value);
|
||||||
}
|
}
|
||||||
// 切换分页
|
// 切换分页
|
||||||
function ChangePage(page){
|
function ChangePage(page) {
|
||||||
setPage(page)
|
setPage(page);
|
||||||
}
|
}
|
||||||
function renderStatus() {
|
function renderStatus() {
|
||||||
return(
|
return (
|
||||||
<ul className="listNav">
|
<ul className="listNav">
|
||||||
{
|
{STATUS.map((item, key) => {
|
||||||
STATUS.map((item,key)=>{
|
return (
|
||||||
return <li onClick={()=>ChangeStatus(item.value)} className={ status === item.value ? "active":""}>{item.name}</li>
|
<li
|
||||||
})
|
onClick={() => ChangeStatus(item.value)}
|
||||||
}
|
className={status === item.value ? "active" : ""}
|
||||||
|
>
|
||||||
|
{item.name}
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
function renderStatusBtn(status){
|
function renderStatusBtn(status, number) {
|
||||||
if(status === "failure" || status ==="success"){
|
if (status === "error" || status === "success") {
|
||||||
|
return "";
|
||||||
|
}else if(status === "killed" || status === "failure"){
|
||||||
return(
|
return(
|
||||||
<a className="color-blue">重新构建</a>
|
<Popconfirm
|
||||||
)
|
title="确认重新构建?"
|
||||||
}else{
|
onConfirm={(e) => repeatSet(e,number)}
|
||||||
return(
|
onCancel={(e)=>{e.stopPropagation()}}
|
||||||
<a className="color-red">撤销构建</a>
|
cancelText="取消"
|
||||||
)
|
okText="确定"
|
||||||
|
>
|
||||||
|
<a className="color-blue" onClick={(e)=>{e.stopPropagation()}}>重新构建</a>
|
||||||
|
</Popconfirm>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<Popconfirm
|
||||||
|
title="确认撤销构建?"
|
||||||
|
onConfirm={(e) => cancelSet(e,number)}
|
||||||
|
onCancel={(e)=>{e.stopPropagation()}}
|
||||||
|
cancelText="取消"
|
||||||
|
okText="确定"
|
||||||
|
>
|
||||||
|
<a className="color-red" onClick={(e)=>{e.stopPropagation()}}>撤销构建</a>
|
||||||
|
</Popconfirm>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function renderTableStatus (status){
|
// 重新构建
|
||||||
switch (status){
|
function repeatSet(e,number) {
|
||||||
|
e.stopPropagation();
|
||||||
|
setTableLoading(true);
|
||||||
|
const url = `/${owner}/${projectsId}/builds/${number}/restart.json`;
|
||||||
|
axios.post(url).then((result) => {
|
||||||
|
if (result) {
|
||||||
|
props.showNotification("工作流正在重新构建!");
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 撤销构建
|
||||||
|
function cancelSet(e,number) {
|
||||||
|
e.stopPropagation();
|
||||||
|
setTableLoading(true);
|
||||||
|
const url = `/${owner}/${projectsId}/builds/${number}/stop.json`;
|
||||||
|
axios.delete(url).then((result) => {
|
||||||
|
if (result) {
|
||||||
|
props.showNotification("撤销构建成功!");
|
||||||
|
Init(projectsId);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderTableStatus(status) {
|
||||||
|
switch (status) {
|
||||||
case "running":
|
case "running":
|
||||||
return(
|
|
||||||
<span className="statusTag running"><i className="iconfont icon-yunhangzhong"></i>运行中</span>
|
|
||||||
);
|
|
||||||
case "failure":
|
|
||||||
return (
|
return (
|
||||||
<span className="statusTag failed"><i className="iconfont icon-weitongguo"></i>未通过</span>
|
<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":
|
case "success":
|
||||||
return (
|
return (
|
||||||
<span className="statusTag pass"><i className="iconfont icon-yitongguo"></i>已通过</span>
|
<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:
|
default:
|
||||||
return (
|
return (
|
||||||
<span className="statusTag Preparing"><i className="iconfont icon-zhunbeizhong"></i>准备中</span>
|
<span className="statusTag Preparing">
|
||||||
|
<i className="iconfont icon-zhunbeizhong"></i>准备中
|
||||||
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function clickRows(event,e){
|
||||||
|
props.history.push(`/projects/${owner}/${projectsId}/devops/${e.number}/detail`);
|
||||||
|
}
|
||||||
const column = [
|
const column = [
|
||||||
{
|
{
|
||||||
title:'序号',
|
title: "序号",
|
||||||
dataIndex:"No",
|
dataIndex: "number",
|
||||||
key:"No",
|
key: "number",
|
||||||
width:"8%",
|
width: "8%",
|
||||||
render:(item,value,key)=>{
|
render: ( value, item, key) => {
|
||||||
return(
|
return <span>#{value}</span>;
|
||||||
<span>#{key+1}</span>
|
},
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title:'状态',
|
title: "状态",
|
||||||
dataIndex:"status",
|
dataIndex: "status",
|
||||||
key:"status",
|
key: "status",
|
||||||
width:"12%",
|
width: "12%",
|
||||||
render:(value,item,key)=>{
|
render: (value, item, key) => {
|
||||||
return(renderTableStatus(value))
|
return renderTableStatus(value);
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title:'构建人',
|
title: "构建人",
|
||||||
dataIndex:"author",
|
dataIndex: "author",
|
||||||
key:"author",
|
key: "author",
|
||||||
width:"12%",
|
width: "12%",
|
||||||
align:"center"
|
align: "center",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title:'提交信息',
|
title: "提交信息",
|
||||||
dataIndex:"message",
|
dataIndex: "message",
|
||||||
key:"message",
|
key: "message",
|
||||||
width:"30%",
|
width: "30%",
|
||||||
render:(value,item,key)=>{
|
render: (value, item, key) => {
|
||||||
let meg = item.message;
|
let meg = item.message;
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<div>
|
<div>
|
||||||
{ meg.branch && <span className="mr10 color-grey-8"><i className="iconfont icon-fenzhi1 font-16 mr5"></i>分支{meg.branch}</span>}
|
{meg.branch && (
|
||||||
{ meg.sha && <span className="color-orange">{meg.sha}</span>}
|
<span className="mr10 color-grey-8">
|
||||||
|
<i className="iconfont icon-fenzhi1 font-16 mr5"></i>分支
|
||||||
|
{meg.branch}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{meg.sha && <span className="color-orange">{meg.sha}</span>}
|
||||||
</div>
|
</div>
|
||||||
<AlignCenter>
|
<AlignCenter>
|
||||||
<Img src={meg.image} />
|
<img style={{borderRadius:"50%",marginRight:"10px",width:"25px",height:"25px"}} alt="" src={`${item.image_url && getUrl(`/images/${item.image_url}`)}`} />
|
||||||
<div className="task-hide ml5" style={{maxWidth:"300px"}}>{meg.message}</div>
|
<div className="task-hide ml5" style={{ maxWidth: "300px" }}>
|
||||||
|
{meg.message}
|
||||||
|
</div>
|
||||||
</AlignCenter>
|
</AlignCenter>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
)
|
);
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title:'开始时间',
|
title: "开始时间",
|
||||||
dataIndex:"started",
|
dataIndex: "started",
|
||||||
key:"started",
|
key: "started",
|
||||||
width:"15%",
|
width: "15%",
|
||||||
render:(value,item,key)=>{
|
render: (value, item, key) => {
|
||||||
return (
|
return <span>{value || "--"}</span>;
|
||||||
<span>{value || "--"}</span>
|
},
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title:'运行时间',
|
title: "运行时间",
|
||||||
dataIndex:"timestamp",
|
dataIndex: "duration_time",
|
||||||
key:"timestamp",
|
key: "duration_time",
|
||||||
width:"15%",
|
width: "15%",
|
||||||
render:(value,item,key)=>{
|
render: (value, item, key) => {
|
||||||
return (
|
return <span>{value || "--"}</span>;
|
||||||
<span>{value || value === 0 ? `${value}s` : "--"}</span>
|
},
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title:'操作',
|
title: "操作",
|
||||||
dataIndex:"operation",
|
dataIndex: "operation",
|
||||||
key:"operation",
|
key: "operation",
|
||||||
render:(value,item,key)=>{
|
render: (value, item, key) => {
|
||||||
return(renderStatusBtn(item.status));
|
if(permission === "Admin" || permission === "Owner"){
|
||||||
}
|
return renderStatusBtn(item.status, item.number);
|
||||||
}
|
}else{
|
||||||
]
|
return "--";
|
||||||
return(
|
}
|
||||||
<div className="listPart">
|
},
|
||||||
<FlexAJ>
|
},
|
||||||
{renderStatus()}
|
];
|
||||||
<span>
|
return (
|
||||||
<Blueback className="mr30">手动创建</Blueback>
|
<div className="disposePanel">
|
||||||
<span className="mr30"><i className="iconfont icon-fenzhi1 font-16 mr5 color-blue"></i>分支</span>
|
<Banner>
|
||||||
<span><i className="iconfont icon-biaoqian3 font-16 mr5 color-blue"></i>标签</span>
|
<FlexAJ>
|
||||||
</span>
|
<span>构建列表</span>
|
||||||
</FlexAJ>
|
<Link to={`/projects/${owner}/${projectsId}/devops/dispose`} className="font-15 color-grey-9">返回</Link>
|
||||||
<Table
|
</FlexAJ>
|
||||||
columns={column}
|
</Banner>
|
||||||
className="normalTable"
|
<Div>
|
||||||
dataSource={data}
|
<div className="listPart">
|
||||||
pagination={false}
|
<FlexAJ>
|
||||||
></Table>
|
{renderStatus()}
|
||||||
{
|
<a onClick={()=>Init(status)} className="color-red font-16">刷新</a>
|
||||||
total > LIMIT ?
|
</FlexAJ>
|
||||||
<div style={{textAlign:'center',margin:"30px 50px"}}>
|
<Table
|
||||||
<Pagination showQuickJumper defaultCurrent={page} total={total} pageSize={LIMIT} onChange={ChangePage}></Pagination>
|
onRow={(record,index)=>{
|
||||||
</div>:""
|
return{
|
||||||
}
|
onClick:(event)=>clickRows(event,record)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
columns={column}
|
||||||
|
className="normalTable"
|
||||||
|
dataSource={data}
|
||||||
|
pagination={false}
|
||||||
|
loading={tableLoading}
|
||||||
|
></Table>
|
||||||
|
{total > LIMIT ?
|
||||||
|
<div style={{ textAlign: "center", margin: "30px 50px" }}>
|
||||||
|
<Pagination
|
||||||
|
showQuickJumper
|
||||||
|
defaultCurrent={page}
|
||||||
|
total={total}
|
||||||
|
pageSize={LIMIT}
|
||||||
|
onChange={ChangePage}
|
||||||
|
></Pagination>
|
||||||
|
</div>
|
||||||
|
:
|
||||||
|
"" }
|
||||||
|
</div>
|
||||||
|
</Div>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
})
|
};
|
||||||
|
export default forwardRef(Structure);
|
||||||
|
|
|
@ -0,0 +1,317 @@
|
||||||
|
import React , { useEffect , useState } from 'react';
|
||||||
|
import { WhiteBack } from '../Component/layout';
|
||||||
|
import { Spin } from 'antd';
|
||||||
|
import Head from './Dispose/head';
|
||||||
|
import Menus from './Dispose/menus';
|
||||||
|
import Init from './Dispose/Init';
|
||||||
|
import Sure from './Dispose/Sure';
|
||||||
|
import Stage from './Dispose/Stage';
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
function disposePipeline(props){
|
||||||
|
const [ spining , setSpining ] = useState(true);
|
||||||
|
const [ stage , setStage ] = useState(1);
|
||||||
|
const [ pipeLineName , setPipeLineName ] = useState(undefined);
|
||||||
|
const [ stepName , setStepName ] = useState(undefined);
|
||||||
|
const [ stageId , setStageId ] =useState(undefined);
|
||||||
|
const [ menuList , setMenuList ] = useState(undefined);
|
||||||
|
const [ stageType , setStageType ] = useState("init");
|
||||||
|
const [ datas , setDatas ] = useState(undefined);
|
||||||
|
const [ templates , setTemplates] = useState(undefined);
|
||||||
|
const [ datasUpdataFlag , setDatasUpdataFlag ] = useState(false);
|
||||||
|
const [ loading ,setLoading ] = useState(false);
|
||||||
|
|
||||||
|
const { disposeId } = props.match.params;
|
||||||
|
let projectsId = props.match.params.projectsId;
|
||||||
|
let owner = props.match.params.owner;
|
||||||
|
useEffect(()=>{
|
||||||
|
if(stageType && stageType !=="confirm"){
|
||||||
|
InitTemplates();
|
||||||
|
}
|
||||||
|
},[stageType])
|
||||||
|
|
||||||
|
// 获取模板
|
||||||
|
function InitTemplates(){
|
||||||
|
const url = `/ci/templates/templates_by_stage.json`;
|
||||||
|
axios.get(url,{
|
||||||
|
params:{ stage_type:stageType, id:disposeId }
|
||||||
|
}).then(result=>{
|
||||||
|
if(result && result.data){
|
||||||
|
setTemplates(result.data);
|
||||||
|
}
|
||||||
|
}).catch(error=>{})
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
if(disposeId && (stageType && stageType !=="confirm")){
|
||||||
|
getData(0);
|
||||||
|
}
|
||||||
|
},[disposeId])
|
||||||
|
// 获取所有阶段默认第一个阶段的数据
|
||||||
|
function getData(index){
|
||||||
|
const url = `/ci/pipelines/${disposeId}/stages.json`;
|
||||||
|
axios.get(url).then(result=>{
|
||||||
|
if(result && result.data){
|
||||||
|
setMenuList(result.data.stages);
|
||||||
|
if(index || index === 0){
|
||||||
|
let first = result.data.stages[index];
|
||||||
|
setStage(first.show_index);
|
||||||
|
setStageId(first.id);
|
||||||
|
setPipeLineName(`${first.pipeline_name}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
if(stageId){
|
||||||
|
getStageStep(stageId);
|
||||||
|
}
|
||||||
|
},[stageId])
|
||||||
|
// 切换阶段时获取阶段步骤数据(第一次默认查询”初始化“阶段的数据)
|
||||||
|
function getStageStep(stageId){
|
||||||
|
let url = "";
|
||||||
|
if(stageType && stageType === "confirm"){
|
||||||
|
url = `/ci/pipelines/${disposeId}/content.json`;
|
||||||
|
axios.get(url,{
|
||||||
|
params:{
|
||||||
|
owner,repo:projectsId
|
||||||
|
}
|
||||||
|
}).then(result=>{
|
||||||
|
if(result && result.data){
|
||||||
|
setDatas(result.data);
|
||||||
|
}
|
||||||
|
}).catch(error=>{})
|
||||||
|
}else{
|
||||||
|
url = `/ci/pipelines/${disposeId}/${stageId}/steps.json`;
|
||||||
|
axios.get(url).then(result=>{
|
||||||
|
if(result && result.data){
|
||||||
|
let step = result.data.steps;
|
||||||
|
setDatas(step);
|
||||||
|
let flag = !step || (step && step.length === 0);
|
||||||
|
setDatasUpdataFlag(flag);
|
||||||
|
}
|
||||||
|
}).catch(error=>{})
|
||||||
|
}
|
||||||
|
setSpining(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 切换阶段:s:show_index,stage_type:stage_type
|
||||||
|
function changestage(show_index,stage_type,stage_id,stage_name){
|
||||||
|
if(show_index !== stage){
|
||||||
|
saveFunc(show_index,stage_type,stage_id,stage_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取子组件传过来的数据
|
||||||
|
function saveDatas(steps){
|
||||||
|
setDatas([...steps]);
|
||||||
|
setDatasUpdataFlag(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查数组里面是否有空数据
|
||||||
|
function checkDatas(){
|
||||||
|
if(datas && datas.length > 0){
|
||||||
|
for(let i= 0;i< datas.length;i++){
|
||||||
|
if(datas[i] && (!datas[i].content || !datas[i].template_id)){
|
||||||
|
props.showNotification("请先选择模板!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if(stageType === "init" ){
|
||||||
|
props.showNotification("请先选择模板!");
|
||||||
|
return false;
|
||||||
|
}else if(stageType === "confirm" ){
|
||||||
|
return true;
|
||||||
|
}else{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存步骤
|
||||||
|
function saveFunc(show_index,stage_type,stage_id,stageName,btn){
|
||||||
|
setSpining(true);
|
||||||
|
// 判断数据是否有过更新
|
||||||
|
if(datasUpdataFlag && stageType !== "confirm"){
|
||||||
|
// 先判断子组件传过来的数据是否有undefined --datas
|
||||||
|
let f = checkDatas();
|
||||||
|
if(f && (datas && datas.length !== 0)){
|
||||||
|
// 数据没问题后先保存数据再切换阶段
|
||||||
|
saveDataFunc(btn,show_index,stage_type,stage_id,stageName);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
setSpining(false);
|
||||||
|
f === "" && elseFunc(btn,show_index,stage_type,stage_id,stageName);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
elseFunc(btn,show_index,stage_type,stage_id,stageName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveDataFunc(btn,show_index,stage_type,stage_id,stageName){
|
||||||
|
const url = `/ci/pipelines/${disposeId}/${stageId}/stage_step.json`;
|
||||||
|
axios.post(url,{
|
||||||
|
steps:datas
|
||||||
|
}).then(result=>{
|
||||||
|
if(result && result.data){
|
||||||
|
setDatasUpdataFlag(false);
|
||||||
|
if(!btn){
|
||||||
|
setStage(show_index);
|
||||||
|
setStageType(stage_type);
|
||||||
|
setStageId(stage_id);
|
||||||
|
setStepName(pipeLineName+`-`+stageName);
|
||||||
|
}else{
|
||||||
|
enters(btn);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
props.showNotification("阶段更新失败,请稍微重试!");
|
||||||
|
}
|
||||||
|
}).catch(error=>{})
|
||||||
|
}
|
||||||
|
|
||||||
|
function elseFunc(btn,show_index,stage_type,stage_id,stageName){
|
||||||
|
if(btn){
|
||||||
|
enters(btn);
|
||||||
|
}else{
|
||||||
|
setStage(show_index);
|
||||||
|
setStageType(stage_type);
|
||||||
|
setStageId(stage_id);
|
||||||
|
setStepName(pipeLineName+`-`+stageName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 上一步、下一步
|
||||||
|
function enters(btn){
|
||||||
|
let s = stage;
|
||||||
|
if(btn === "next"){
|
||||||
|
// 点击阶段里面的下一步
|
||||||
|
s = s+1;
|
||||||
|
}else{
|
||||||
|
// 上一步
|
||||||
|
s = s-1;
|
||||||
|
}
|
||||||
|
let item = menuList && menuList.filter(i=>i.show_index === (s));
|
||||||
|
setStage(s);
|
||||||
|
setStageType(item[0].stage_type);
|
||||||
|
setStageId(item[0].id);
|
||||||
|
setStepName(pipeLineName+`-`+item[0].stage_name);
|
||||||
|
}
|
||||||
|
// 删除步骤
|
||||||
|
function deleteStep(id,index){
|
||||||
|
if(id){
|
||||||
|
const url = `/ci/pipelines/${disposeId}/${stageId}/${id}/delete_step.json`;
|
||||||
|
axios.delete(url).then(result=>{
|
||||||
|
if(result && result.data){
|
||||||
|
getStageStep(stageId);
|
||||||
|
props.showNotification("阶段步骤删除成功!");
|
||||||
|
}
|
||||||
|
}).catch(error=>{})
|
||||||
|
}else{
|
||||||
|
let d = datas.filter(s=>s.show_index !== (index+1));
|
||||||
|
setDatas(d);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function renameFunc(value,id){
|
||||||
|
const url = `/ci/pipelines/${disposeId}/${id}/update_stage.json`;
|
||||||
|
axios.put(url,{
|
||||||
|
stage_name:value
|
||||||
|
}).then(result=>{
|
||||||
|
if(result && result.data){
|
||||||
|
getData();
|
||||||
|
}
|
||||||
|
}).catch(error=>{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增阶段
|
||||||
|
function addMenuFunc(name,index){
|
||||||
|
const url = `/ci/pipelines/${disposeId}/create_stage.json`;
|
||||||
|
axios.post(url,{
|
||||||
|
show_index:index,
|
||||||
|
stage_name:name
|
||||||
|
}).then(result=>{
|
||||||
|
if(result && result.data){
|
||||||
|
getData(index-1);
|
||||||
|
setStageType("customize");
|
||||||
|
}else{
|
||||||
|
props.showNotification("阶段新增失败!");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除阶段
|
||||||
|
function deleteStageFunc(){
|
||||||
|
let next = menuList && menuList.filter(item=>item.show_index === (stage+1));
|
||||||
|
let nextStageType = next && next.length>0 && next[0].stage_type;
|
||||||
|
const url = `/ci/pipelines/${disposeId}/${stageId}/delete_stage.json`;
|
||||||
|
axios.delete(url,{
|
||||||
|
params:{show_index:stage}
|
||||||
|
}).then(result=>{
|
||||||
|
if(result && result.data){
|
||||||
|
getData(stage-1);
|
||||||
|
setStageType(nextStageType);
|
||||||
|
}else{
|
||||||
|
props.showNotification("阶段删除失败!");
|
||||||
|
}
|
||||||
|
}).catch(error=>{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确认提交
|
||||||
|
function sureSubmit(){
|
||||||
|
setLoading(true);
|
||||||
|
let params = {
|
||||||
|
branch: datas.branch,
|
||||||
|
content:datas.content,
|
||||||
|
filepath:'.trustie-pipeline.yml',
|
||||||
|
message:'',
|
||||||
|
sha:datas.sha || undefined,
|
||||||
|
owner:owner,
|
||||||
|
repo:projectsId
|
||||||
|
}
|
||||||
|
let url = `/${owner}/${projectsId}/update_trustie_pipeline.json`;
|
||||||
|
axios.put(url,{
|
||||||
|
...params
|
||||||
|
}).then(result=>{
|
||||||
|
if(result){
|
||||||
|
props.history.push(`/projects/${owner}/${projectsId}/devops/dispose`);
|
||||||
|
}
|
||||||
|
setLoading(false);
|
||||||
|
}).catch(error=>{
|
||||||
|
console.log(error);
|
||||||
|
setLoading(false);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return(
|
||||||
|
<div className="disposePanel">
|
||||||
|
<Head />
|
||||||
|
<WhiteBack style={{padding:"24px 30px"}}>
|
||||||
|
<Spin spinning={spining}>
|
||||||
|
<div style={{minHeight:"450px"}}>
|
||||||
|
<Menus step={stage} checkDatas={checkDatas} changeStep={changestage} menuList={menuList} renameFunc={renameFunc} addFunc={addMenuFunc}/>
|
||||||
|
{
|
||||||
|
stageType === "init" ? <Init stage_type={stageType} templates={templates} datas={datas} saveDatas={saveDatas} saveFunc={saveFunc}/>
|
||||||
|
:
|
||||||
|
stageType === "confirm" ? <Sure sureSubmit={sureSubmit} name={pipeLineName} datas={datas} saveFunc={saveFunc} loading={loading}/>
|
||||||
|
:
|
||||||
|
<Stage {...props}
|
||||||
|
stepName={stepName}
|
||||||
|
deleteStep={deleteStep}
|
||||||
|
stage_type={stageType}
|
||||||
|
templates={templates}
|
||||||
|
datas={datas}
|
||||||
|
deleteFunc={deleteStageFunc}
|
||||||
|
saveDatas={saveDatas}
|
||||||
|
saveFunc={saveFunc}
|
||||||
|
deleteFlag={menuList && menuList.length === 3}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</Spin>
|
||||||
|
</WhiteBack>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default disposePipeline;
|
|
@ -10,10 +10,17 @@
|
||||||
padding:60px 0px;
|
padding:60px 0px;
|
||||||
}
|
}
|
||||||
.disposePanel{
|
.disposePanel{
|
||||||
|
border:1px solid #eee;
|
||||||
.language{
|
.language{
|
||||||
display: flex;
|
display: flex;
|
||||||
|
margin-bottom: 20px;
|
||||||
li{
|
li{
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
border:1px solid #fff;
|
||||||
|
&.active{
|
||||||
|
border:1px solid #5091FF;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.editorBody{
|
.editorBody{
|
||||||
|
@ -36,6 +43,7 @@
|
||||||
top:7px;
|
top:7px;
|
||||||
}
|
}
|
||||||
.listPart{
|
.listPart{
|
||||||
|
min-height: 400px;
|
||||||
.listNav{
|
.listNav{
|
||||||
display: flex;
|
display: flex;
|
||||||
li{
|
li{
|
||||||
|
@ -63,6 +71,7 @@
|
||||||
.ant-table-thead > tr > th, .ant-table-tbody > tr > td{
|
.ant-table-thead > tr > th, .ant-table-tbody > tr > td{
|
||||||
padding:10px 5px;
|
padding:10px 5px;
|
||||||
color:#333;
|
color:#333;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.ant-table-thead{
|
.ant-table-thead{
|
||||||
border:1px solid rgba(238,238,238,1)
|
border:1px solid rgba(238,238,238,1)
|
||||||
|
@ -70,43 +79,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 列表
|
.ant-modal-close{
|
||||||
.listPart{
|
top:7px;
|
||||||
.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 ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// ops详情
|
// ops详情
|
||||||
.opsDetailPanel{
|
.opsDetailPanel{
|
||||||
|
@ -205,13 +181,35 @@
|
||||||
border:1px solid rgba(255,110,33,1);
|
border:1px solid rgba(255,110,33,1);
|
||||||
color:rgba(255,110,33,1);
|
color:rgba(255,110,33,1);
|
||||||
}
|
}
|
||||||
|
&.killed{
|
||||||
|
border:1px solid #999;
|
||||||
|
color:#999;
|
||||||
|
}
|
||||||
|
&.skipped{
|
||||||
|
border:1px solid #d4d9de;
|
||||||
|
color:#798390;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&.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;
|
||||||
|
overflow-y: auto;
|
||||||
& > div{
|
& > div{
|
||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
.items{
|
.items{
|
||||||
|
@ -264,4 +262,260 @@
|
||||||
cursor: col-resize;
|
cursor: col-resize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
.opsDetailOut{
|
||||||
|
display: flex;
|
||||||
|
color: #fff;
|
||||||
|
line-height: 22px;
|
||||||
|
align-items: flex-start;
|
||||||
|
margin-top: 5px;
|
||||||
|
&>span{
|
||||||
|
margin-right: 10px;
|
||||||
|
min-width: 20px;
|
||||||
|
text-align: left;
|
||||||
|
padding-left: 3px;
|
||||||
|
}
|
||||||
|
&>p{
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.noOperation{
|
||||||
|
margin-bottom:20px;
|
||||||
|
width:380px;
|
||||||
|
text-align:center;
|
||||||
|
line-height:22px;
|
||||||
|
color:#666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.disposeList{
|
||||||
|
min-height: 450px;
|
||||||
|
.ant-table-body{
|
||||||
|
margin:0px!important;
|
||||||
|
.ant-table-thead{
|
||||||
|
background-color: #fafafa;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.txtright{
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
.menus{
|
||||||
|
display: flex;
|
||||||
|
box-shadow: 0px 0px 6px rgba(0,3,8,0.1);
|
||||||
|
padding:20px 0px 10px 0px;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
& > li{
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column;
|
||||||
|
align-items:center;
|
||||||
|
justify-content: flex-start;
|
||||||
|
text-align: center;
|
||||||
|
color: #787878;
|
||||||
|
font-size: 16px;
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
max-width: 122px;
|
||||||
|
flex:2;
|
||||||
|
&>i{
|
||||||
|
font-size: 30px!important;
|
||||||
|
height: 30px;
|
||||||
|
width: 30px;
|
||||||
|
line-height: 30px;
|
||||||
|
}
|
||||||
|
&:hover,&.active{
|
||||||
|
& > i{
|
||||||
|
color: #1890FF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.active::after{
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
margin-left: -25px;
|
||||||
|
bottom:-10px;
|
||||||
|
width: 50px;
|
||||||
|
height: 2px;
|
||||||
|
background-color: #1890FF;
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
.aboutEdit{
|
||||||
|
width: 100%;
|
||||||
|
.operateName{
|
||||||
|
position: relative;
|
||||||
|
line-height: 22px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0px 15px;
|
||||||
|
min-height: 40px;
|
||||||
|
& > i{
|
||||||
|
position: absolute;
|
||||||
|
right:0px;
|
||||||
|
top:10px;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&:hover i{
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
& > li.menuAdd{
|
||||||
|
position: relative;
|
||||||
|
flex: 1;
|
||||||
|
&:hover{
|
||||||
|
& > i{
|
||||||
|
color: #787878;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
& > i{
|
||||||
|
font-size: 18px!important;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
top:0px;
|
||||||
|
}
|
||||||
|
& > input{
|
||||||
|
position: absolute;
|
||||||
|
z-index: 1;
|
||||||
|
top:3px;
|
||||||
|
}
|
||||||
|
&::before{
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
border-bottom: 1px dashed #eee;
|
||||||
|
content: "";
|
||||||
|
top:15px;
|
||||||
|
margin-top: -1px;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.choosenList{
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
line-height: 35px;
|
||||||
|
align-items: center;
|
||||||
|
& > span{
|
||||||
|
display: block;
|
||||||
|
min-width: 75px;
|
||||||
|
text-align: right;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #333;
|
||||||
|
height: 35px;
|
||||||
|
margin-right: 12px;
|
||||||
|
}
|
||||||
|
& > ul{
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
li{
|
||||||
|
padding:0px 12px;
|
||||||
|
height: 35px;
|
||||||
|
line-height: 35px;
|
||||||
|
border:1px solid #e1e4e8;
|
||||||
|
background-color: #fff;
|
||||||
|
margin:6px 0px;
|
||||||
|
margin-right: 12px;
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
li.active{
|
||||||
|
color: #fff;
|
||||||
|
background-color: #1890FF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ant-select-selection.ant-select-selection--multiple{
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
height: 35px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.addStageBtn{
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
border:1px solid #e1e4e8;
|
||||||
|
height: 48px;
|
||||||
|
line-height: 48px;
|
||||||
|
color: #1890FF;
|
||||||
|
font-size: 16px;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 0px 20px;
|
||||||
|
}
|
||||||
|
.stepsItem{
|
||||||
|
border:1px solid #e1e4e8;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
.stepsHead{
|
||||||
|
padding:8px 15px;
|
||||||
|
span > a > i{
|
||||||
|
margin-left: 8px;
|
||||||
|
color: #666!important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.stepsBody{
|
||||||
|
padding:10px 15px;
|
||||||
|
border-top: 1px solid #e1e4e8;
|
||||||
|
background-color: rgb(251, 251, 251);
|
||||||
|
display: none;
|
||||||
|
transition: 0.3s;
|
||||||
|
}
|
||||||
|
.stepsBody.active{
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.editorPanel{
|
||||||
|
border:1px solid #eee;
|
||||||
|
.margin{
|
||||||
|
width: 0px;
|
||||||
|
}
|
||||||
|
.monaco-scrollable-element.editor-scrollable{
|
||||||
|
left: 0px!important;
|
||||||
|
width: 100%!important;
|
||||||
|
.view-lines{
|
||||||
|
width: 336px!important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.hide{
|
||||||
|
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,33 +1,114 @@
|
||||||
import React from 'react';
|
import React, { useEffect, useState, useRef, useContext } from "react";
|
||||||
import './ops.scss';
|
import "./ops.scss";
|
||||||
import { FlexAJ, AlignCenter } from '../Component/layout';
|
import { FlexAJ, AlignCenter } from "../Component/layout";
|
||||||
import { Tags } from '../Component/OpsStatus';
|
import { Tags } from "../Component/OpsStatus";
|
||||||
import SplitPane from 'react-split-pane';
|
import SplitPane from "react-split-pane";
|
||||||
import LeftPanel from './OpsDetailLeftpanel';
|
import LeftPanel from "./OpsDetailLeftpanel";
|
||||||
import RightPanel from './OpsDetailRightpanel';
|
import RightPanel from "./OpsDetailRightpanel";
|
||||||
|
import axios from "axios";
|
||||||
|
import { Spin } from "antd";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
|
||||||
|
export default (props) => {
|
||||||
|
const [data, setData] = useState(undefined);
|
||||||
|
const [stageN, setStageN] = useState(undefined);
|
||||||
|
const [stepN, setStepN] = useState(undefined);
|
||||||
|
const [rightSpin, setRightSpin] = useState(false);
|
||||||
|
const [spinning, setSpinning] = useState(true);
|
||||||
|
|
||||||
export default (()=>{
|
let projectId = props.match.params.projectId;
|
||||||
return(
|
let owner = props.match.params.owner;
|
||||||
<div className="opsDetailPanel">
|
let opsId = props.match.params.opsId;
|
||||||
<FlexAJ className="opsInfos">
|
|
||||||
<AlignCenter>
|
useEffect(() => {
|
||||||
<span>#1</span>
|
if (opsId && projectId) {
|
||||||
<span className="ml10">将分支“221063-improve-buy-ci-minutes-link”合并到“221063-improve-buy-ci-minutes-link"</span>
|
Init();
|
||||||
{Tags(1)}
|
}
|
||||||
</AlignCenter>
|
}, [opsId]);
|
||||||
<a style={{color:"#ddd"}}><i className="iconfont icon-yiguanbi font-15 mr5"></i>退出</a>
|
|
||||||
</FlexAJ>
|
function Init() {
|
||||||
<div className="opsSection">
|
const url = `/${owner}/${projectId}/builds/${opsId}.json`;
|
||||||
<SplitPane className="outer-split-pane" split="vertical" minSize={468} maxSize={-350} defaultSize="40%">
|
axios.get(url).then((result) => {
|
||||||
<section className="leftSection">
|
if (result && result.data) {
|
||||||
<LeftPanel />
|
setSpinning(false);
|
||||||
</section>
|
setData(result.data);
|
||||||
<section className="rightSection">
|
}
|
||||||
<RightPanel />
|
})
|
||||||
</section>
|
.catch((error) => {
|
||||||
</SplitPane>
|
console.log(error);
|
||||||
|
setSpinning(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重新构建
|
||||||
|
function repeatSet(e,type,number) {
|
||||||
|
if(type==="repeat"){
|
||||||
|
// 重新构建
|
||||||
|
const url = `/${owner}/${projectId}/builds/${number}/restart.json`;
|
||||||
|
axios.post(url).then((result) => {
|
||||||
|
if (result && result.data) {
|
||||||
|
props.showNotification("工作流正在重新构建!");
|
||||||
|
props.history.push(`/projects/${owner}/${projectId}/devops/${result.data.number}/detail`);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
// 撤销构建
|
||||||
|
const url = `/${owner}/${projectId}/builds/${number}/stop.json`;
|
||||||
|
axios.delete(url).then((result) => {
|
||||||
|
if (result) {
|
||||||
|
props.showNotification("撤销构建成功!");
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function chooseSteps(pre,sub){
|
||||||
|
if(pre && sub){
|
||||||
|
setStepN(sub);
|
||||||
|
setStageN(pre);
|
||||||
|
setRightSpin(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Spin spinning={spinning}>
|
||||||
|
<div className="opsDetailPanel">
|
||||||
|
<FlexAJ className="opsInfos">
|
||||||
|
<AlignCenter>
|
||||||
|
<span>#{data && data.number}</span>
|
||||||
|
<span className="ml10">{data && data.message}</span>
|
||||||
|
{Tags(`${data && data.status}`)}
|
||||||
|
</AlignCenter>
|
||||||
|
<Link
|
||||||
|
style={{ color: "#ddd" }}
|
||||||
|
to={`/projects/${owner}/${projectId}/devops/dispose`}
|
||||||
|
>
|
||||||
|
<i className="iconfont icon-yiguanbi font-15 mr5"></i>退出
|
||||||
|
</Link>
|
||||||
|
</FlexAJ>
|
||||||
|
<div className="opsSection">
|
||||||
|
<SplitPane
|
||||||
|
className="outer-split-pane"
|
||||||
|
split="vertical"
|
||||||
|
minSize={468}
|
||||||
|
maxSize={-350}
|
||||||
|
defaultSize="40%"
|
||||||
|
>
|
||||||
|
<section className="leftSection">
|
||||||
|
<LeftPanel data={data} repeatSet={repeatSet} chooseSteps={chooseSteps} />
|
||||||
|
</section>
|
||||||
|
<section className="rightSection">
|
||||||
|
<RightPanel data={data} rightSpin={rightSpin} stepN={stepN} stageN={stageN} owner={owner} projectId={projectId} opsId={opsId} />
|
||||||
|
</section>
|
||||||
|
</SplitPane>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Spin>
|
||||||
)
|
);
|
||||||
});
|
};
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
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;
|
|
@ -0,0 +1,219 @@
|
||||||
|
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>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,46 @@
|
||||||
|
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;
|
|
@ -0,0 +1,174 @@
|
||||||
|
import React ,{ forwardRef, useEffect, useState } from 'react';
|
||||||
|
import { Modal , Form , Input , Radio , Select } from 'antd';
|
||||||
|
import SearchUser from '../Component/SearchUser';
|
||||||
|
import './Index.scss';
|
||||||
|
import Axios from 'axios';
|
||||||
|
|
||||||
|
const { Option } = Select;
|
||||||
|
function DivertModal({form , visible , onSuccess , onCancel,owner,repo}){
|
||||||
|
const { getFieldDecorator, validateFields , setFieldsValue } = form;
|
||||||
|
const [ cate , setCate ] = useState(0);
|
||||||
|
const [ value , setValue ] = useState(undefined);
|
||||||
|
|
||||||
|
const [ organizations , setOrganizations ] = useState(undefined);
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
setFieldsValue({goal:cate})
|
||||||
|
},[])
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
if(owner && repo && visible===true){
|
||||||
|
getTeam();
|
||||||
|
}
|
||||||
|
if(!visible){
|
||||||
|
setFieldsValue({
|
||||||
|
owner_name:undefined,
|
||||||
|
identifier:undefined
|
||||||
|
})
|
||||||
|
setValue(undefined)
|
||||||
|
}
|
||||||
|
},[repo,owner,visible])
|
||||||
|
|
||||||
|
function getTeam(){
|
||||||
|
const url = `/${owner}/${repo}/applied_transfer_projects/organizations.json`;
|
||||||
|
Axios.get(url).then(result=>{
|
||||||
|
if(result){
|
||||||
|
setOrganizations(result.data.organizations);
|
||||||
|
}
|
||||||
|
}).catch(error=>{})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确认转移
|
||||||
|
function onOk(){
|
||||||
|
validateFields((error,values)=>{
|
||||||
|
console.log(...values);
|
||||||
|
if(!error){
|
||||||
|
const url = `/${owner}/${repo}/applied_transfer_projects.json`;
|
||||||
|
Axios.post(url,{
|
||||||
|
...values
|
||||||
|
}).then(result=>{
|
||||||
|
if(result){
|
||||||
|
onSuccess(result.data && result.data.owner);
|
||||||
|
}
|
||||||
|
}).catch(error=>{})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
function changeType(e){
|
||||||
|
setCate(e.target.value);
|
||||||
|
setFieldsValue({
|
||||||
|
owner_name:undefined
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkIdentifier(rule, value, callback){
|
||||||
|
if(!value){
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
if (repo && value !== repo) {
|
||||||
|
callback("请输入当前项目的标识!");
|
||||||
|
}
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
const layout = {
|
||||||
|
labelCol: { span: 5 },
|
||||||
|
wrapperCol: { span: 18 },
|
||||||
|
};
|
||||||
|
|
||||||
|
function getUser(id){
|
||||||
|
setValue(id);
|
||||||
|
setFieldsValue({
|
||||||
|
owner_name:id
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return(
|
||||||
|
<Modal
|
||||||
|
width="620px"
|
||||||
|
visible={visible}
|
||||||
|
title="转移仓库"
|
||||||
|
onCancel={onCancel}
|
||||||
|
onOk={onOk}
|
||||||
|
okText="确认转移"
|
||||||
|
cancelText={"取消"}
|
||||||
|
centered
|
||||||
|
>
|
||||||
|
<div className="diverModal">
|
||||||
|
{
|
||||||
|
cate === 0 ?
|
||||||
|
<ul className="descUl">
|
||||||
|
<li>转移需对方确认接受,转移成功后你将被移出仓库,其他已有成员权限不变</li>
|
||||||
|
<li>转移成功后,仓库的地址将变更至目标用户的命名空间下</li>
|
||||||
|
<li>已有成员如需继续操作仓库,需更新本地仓库的remote,使之指向新的地址</li>
|
||||||
|
</ul>
|
||||||
|
:
|
||||||
|
<ul className="descUl">
|
||||||
|
<li>仓库仅可以转移到您已经加入的组织中,不可以转移到未加入的组织中</li>
|
||||||
|
<li>涉及到仓库改名操作,请提前做好仓库备份并且在转移后对本地仓库的remote进行修改</li>
|
||||||
|
<li>转移仓库到组织后,你和组织创建者/管理员同时拥有对该仓库的管理操作</li>
|
||||||
|
</ul>
|
||||||
|
}
|
||||||
|
<Form {...layout} colon={false} layout={"horizontal"}>
|
||||||
|
<Form.Item label="转移给:" style={{marginBottom:"0px"}}>
|
||||||
|
{getFieldDecorator("goal",{
|
||||||
|
rules:[]
|
||||||
|
})(
|
||||||
|
<Radio.Group onChange={changeType}>
|
||||||
|
<Radio value={0}>个人</Radio>
|
||||||
|
<Radio value={1}>组织</Radio>
|
||||||
|
</Radio.Group>
|
||||||
|
)}
|
||||||
|
</Form.Item>
|
||||||
|
{
|
||||||
|
cate === 0 &&
|
||||||
|
<Form.Item label=" ">
|
||||||
|
{getFieldDecorator("owner_name",{
|
||||||
|
rules:[{required:true,message:"请输入目标用户名"}]
|
||||||
|
})(
|
||||||
|
// <Input placeholder="请输入目标用户" autoComplete={"off"}/>
|
||||||
|
<SearchUser getUser={getUser} width={"100%"} placeholder="请输入目标用户" value={value}/>
|
||||||
|
)}
|
||||||
|
</Form.Item>
|
||||||
|
}
|
||||||
|
{
|
||||||
|
cate === 1 &&
|
||||||
|
<Form.Item label=" ">
|
||||||
|
{getFieldDecorator("owner_name",
|
||||||
|
{rules:[{required:true,message:"请选择目标组织"}]}
|
||||||
|
)(
|
||||||
|
<Select placeholder="请选择目标组织" getPopupContainer={trigger => trigger.parentNode}>
|
||||||
|
{
|
||||||
|
organizations && organizations.length > 0 ?
|
||||||
|
organizations.map((i,k)=>{
|
||||||
|
return(
|
||||||
|
<Option value={i.name}>{i.nickname}</Option>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
:""
|
||||||
|
}
|
||||||
|
</Select>
|
||||||
|
)}
|
||||||
|
</Form.Item>
|
||||||
|
}
|
||||||
|
|
||||||
|
<Form.Item label="仓库名称:">
|
||||||
|
{getFieldDecorator("identifier",
|
||||||
|
{
|
||||||
|
rules:[
|
||||||
|
{required:true,message:"请输入仓库名称"},
|
||||||
|
{
|
||||||
|
validator:checkIdentifier
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
)(
|
||||||
|
<Input placeholder="请输入仓库名称" autoComplete={"off"}/>
|
||||||
|
)}
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default Form.create()(forwardRef(DivertModal));
|
|
@ -0,0 +1,12 @@
|
||||||
|
.diverModal{
|
||||||
|
.descUl{
|
||||||
|
background-color: #fffae6;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding:10px 15px;
|
||||||
|
color: #efc16b;
|
||||||
|
border:1px solid #efc16b;
|
||||||
|
}
|
||||||
|
.ant-form-item-required::before{
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,4 +10,12 @@ 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;
|
||||||
}
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
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;
|
|
@ -0,0 +1,728 @@
|
||||||
|
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 } from 'antd';
|
||||||
|
|
||||||
|
import LoginDialog from '../../modules/login/LoginDialog';
|
||||||
|
import GotoQQgroup from '../../modal/GotoQQgroup'
|
||||||
|
|
||||||
|
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;
|
|
@ -0,0 +1,68 @@
|
||||||
|
|
||||||
|
.dropdownFlex{
|
||||||
|
display:flex;
|
||||||
|
padding:5px;
|
||||||
|
background:#fff;
|
||||||
|
border-radius: 3px;
|
||||||
|
.ant-menu-vertical > .ant-menu-item{
|
||||||
|
border:none;
|
||||||
|
height: 35px;
|
||||||
|
line-height: 35px;
|
||||||
|
margin:0px;
|
||||||
|
}
|
||||||
|
.ant-menu-vertical{
|
||||||
|
border:none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.newFooter {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
background: #323232;
|
||||||
|
clear: both;
|
||||||
|
min-width: 1200px;
|
||||||
|
z-index: 8;
|
||||||
|
left: 0px;
|
||||||
|
p {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom:0px !important;
|
||||||
|
}
|
||||||
|
.footerInfos{
|
||||||
|
display: flex;
|
||||||
|
max-width: 1200px;
|
||||||
|
margin:0px auto;
|
||||||
|
justify-content: space-around;
|
||||||
|
padding:60px 0px;
|
||||||
|
& >ul{
|
||||||
|
padding:0px 40px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
max-width: 25%;
|
||||||
|
text-align: left;
|
||||||
|
li{
|
||||||
|
color: #fff;
|
||||||
|
font-weight: 300;
|
||||||
|
&:first-child{
|
||||||
|
font-size: 17px;
|
||||||
|
}
|
||||||
|
&>a,&>span{
|
||||||
|
color: #bbb;
|
||||||
|
}
|
||||||
|
&>a:hover{
|
||||||
|
color: #4cacff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.footerCopy{
|
||||||
|
color: #bbb;
|
||||||
|
border-top: 1px solid #4e4e4e;
|
||||||
|
padding:10px 0px;
|
||||||
|
a{
|
||||||
|
color: #bbb;
|
||||||
|
&:hover{
|
||||||
|
color: #4cacff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 590 KiB |
Binary file not shown.
After Width: | Height: | Size: 64 KiB |
|
@ -6,7 +6,6 @@ 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";
|
||||||
|
@ -31,20 +30,29 @@ const Infos = Loadable({
|
||||||
loader: () => import("./users/Infos"),
|
loader: () => import("./users/Infos"),
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
});
|
});
|
||||||
|
|
||||||
class Index extends Component {
|
class Index extends Component {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className="newMain clearfix">
|
<div className="newMain clearfix">
|
||||||
<Handbook />
|
|
||||||
<Switch {...this.props}>
|
<Switch {...this.props}>
|
||||||
|
<Route
|
||||||
|
path="/projects/:projectsType/new/:OIdentifier"
|
||||||
|
render={(props) => (
|
||||||
|
<ProjectNew {...this.props} {...props} />
|
||||||
|
)}
|
||||||
|
></Route>
|
||||||
<Route
|
<Route
|
||||||
path="/projects/:projectsType/new"
|
path="/projects/:projectsType/new"
|
||||||
render={(props) => (
|
render={(props) => (
|
||||||
<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) => (
|
||||||
|
|
|
@ -0,0 +1,449 @@
|
||||||
|
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" trigger={['click']}>
|
||||||
|
<Button type="default">文件 <i className="iconfont icon-sanjiaoxing-down ml3 font-14 color-grey-9"></i></Button>
|
||||||
|
</Dropdown>
|
||||||
|
}
|
||||||
|
|
||||||
|
<Dropdown overlay={downloadMenu} placement="bottomRight" trigger={['click']}>
|
||||||
|
<Button type={'primary'}>下载 <i className="iconfont icon-sanjiaoxing-down ml3 font-14 color-white"></i></Button>
|
||||||
|
</Dropdown>
|
||||||
|
</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"}><pre id="ptxt">{lastCommit && lastCommit.message}</pre></div>
|
||||||
|
{ hideBtn && <span className="ellipsis" onClick={()=>changeHide(hide)}><i className="iconfont icon-shenglvehao"></i></span> }
|
||||||
|
|
||||||
|
<span className="ml12 color-grey-9 mt3">{lastCommit && lastCommit.time_from_now}</span>
|
||||||
|
{ commitCount ? <Link to={`/projects/${owner}/${projectsId}/commits`} className="ml12 color-grey-9"><i className="iconfont icon-tijiao mr3 font-17 color-grey-9"></i>{commitCount}次提交</Link>:"" }
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
<ul className="listtablebody">
|
||||||
|
{
|
||||||
|
treeValuePath && treeValuePath.length > 0 &&
|
||||||
|
<Path
|
||||||
|
identifier={projectDetail && projectDetail.identifier}
|
||||||
|
treeValuePath={treeValuePath}
|
||||||
|
returnUlr={returnUlr}
|
||||||
|
returnMain={returnMain}
|
||||||
|
getPathUrl={getPathUrl}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
{
|
||||||
|
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;
|
|
@ -0,0 +1,22 @@
|
||||||
|
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;
|
|
@ -0,0 +1,30 @@
|
||||||
|
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;
|
|
@ -0,0 +1,62 @@
|
||||||
|
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;
|
|
@ -3,7 +3,7 @@ import { Link } from "react-router-dom";
|
||||||
import { Dropdown , Menu , Icon , Tooltip , Spin } from 'antd';
|
import { Dropdown , Menu , Icon , Tooltip , Spin } from 'antd';
|
||||||
import { truncateCommitId } from '../common/util';
|
import { truncateCommitId } from '../common/util';
|
||||||
import { getBranch } from '../GetData/getData';
|
import { getBranch } from '../GetData/getData';
|
||||||
|
import Nodata from '../Nodata';
|
||||||
import './list.css';
|
import './list.css';
|
||||||
|
|
||||||
export default ((props)=>{
|
export default ((props)=>{
|
||||||
|
@ -32,9 +32,9 @@ export default ((props)=>{
|
||||||
return(
|
return(
|
||||||
<li key={key}>
|
<li key={key}>
|
||||||
<div>
|
<div>
|
||||||
<Link to={`/projects/${owner}/${projectsId}?branch=${item.name}`} className="color-blue font-15" style={{"maxWidth":"100px"}}>{item.name}</Link>
|
<Link to={`/projects/${owner}/${projectsId}/tree/${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">
|
||||||
<span className="mr5 commitKey" style={{marginLeft:0}}>{item.last_commit && truncateCommitId(item.last_commit.sha)}</span>
|
<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>
|
||||||
<span className="color-grey-8 ml30">最后更新于{item.last_commit && item.last_commit.time_from_now}</span>
|
<span className="color-grey-8 ml30">最后更新于{item.last_commit && item.last_commit.time_from_now}</span>
|
||||||
</p>
|
</p>
|
||||||
|
@ -54,6 +54,8 @@ export default ((props)=>{
|
||||||
</ul>
|
</ul>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
)
|
)
|
||||||
|
}else if(data && data.length === 0){
|
||||||
|
return ( <Nodata _html="暂无数据"/>)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const menu =(zip_url,tar_url)=> (
|
const menu =(zip_url,tar_url)=> (
|
||||||
|
@ -68,7 +70,7 @@ export default ((props)=>{
|
||||||
<Spin spinning={isSpin}>
|
<Spin spinning={isSpin}>
|
||||||
<div className="branchTable">
|
<div className="branchTable">
|
||||||
<p className="branchTitle bor-bottom-greyE">分支列表</p>
|
<p className="branchTitle bor-bottom-greyE">分支列表</p>
|
||||||
{list()}
|
<div style={{minHeight:"400px"}}>{list()}</div>
|
||||||
</div>
|
</div>
|
||||||
</Spin>
|
</Spin>
|
||||||
</div>
|
</div>
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue