forked from Gitlink/forgeplus-react
Compare commits
1 Commits
master
...
dev_assist
| Author | SHA1 | Date |
|---|---|---|
|
|
fa55253398 |
16
.babelrc
16
.babelrc
|
|
@ -1,16 +0,0 @@
|
||||||
{
|
|
||||||
"presets": [
|
|
||||||
"es2015",
|
|
||||||
"react",
|
|
||||||
"stage-2"
|
|
||||||
],
|
|
||||||
"plugins": [[
|
|
||||||
"transform-runtime",
|
|
||||||
{
|
|
||||||
"helpers": false,
|
|
||||||
"polyfill": false,
|
|
||||||
"regenerator": true,
|
|
||||||
"moduleName": "babel-runtime"
|
|
||||||
}
|
|
||||||
]]
|
|
||||||
}
|
|
||||||
16
README.md
16
README.md
|
|
@ -1,16 +0,0 @@
|
||||||
<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,7 +17,16 @@ 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);
|
||||||
|
|
@ -132,6 +141,7 @@ 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,
|
||||||
|
|
@ -151,8 +161,10 @@ module.exports = {
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
test: /\.css$/,
|
test: /\.css$/,
|
||||||
|
|
||||||
use: [
|
use: [
|
||||||
{
|
{
|
||||||
loader: MiniCssExtractPlugin.loader,
|
loader: MiniCssExtractPlugin.loader,
|
||||||
|
|
|
||||||
|
|
@ -1,40 +1,35 @@
|
||||||
{
|
{
|
||||||
"name": "forge",
|
"name": "educoder",
|
||||||
"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.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",
|
"resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-3.2.2.tgz",
|
||||||
"integrity": "sha1-WtQ9YZ6RHzSI66wwPWBuZqhCOQM=",
|
"integrity": "sha512-YKgNbG2dlzqMhA9NtI3/pbY16m3Yl/EeWBRa+lB1X1YaYxHrxNexiQYCLTWO/uDvAjLFMEDU+zR901waBtMtjQ==",
|
||||||
"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.npm.taobao.org/@ant-design/create-react-context/download/@ant-design/create-react-context-0.2.5.tgz",
|
"resolved": "https://registry.npmjs.org/@ant-design/create-react-context/-/create-react-context-0.2.5.tgz",
|
||||||
"integrity": "sha1-9fWpFjtHcgl3EoNzl60w4i55+Fg=",
|
"integrity": "sha512-1rMAa4qgP2lfl/QBH9i78+Gjxtj9FTMpMyDGZsEBW5Kih72EuUo9958mV8PgpRkh4uwPSQ7vVZWXeyNZXVAFDg==",
|
||||||
"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.npm.taobao.org/@ant-design/icons/download/@ant-design/icons-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-2.1.1.tgz",
|
||||||
"integrity": "sha1-e5wI3/1PXUHbZn2dvl4BB9C9mko="
|
"integrity": "sha512-jCH+k2Vjlno4YWl6g535nHR09PwCEmTBKAG6VqF+rhkrSPRLfgpU2maagwbZPLjaHuU5Jd1DFQ2KJpQuI6uG8w=="
|
||||||
},
|
},
|
||||||
"@ant-design/icons-react": {
|
"@ant-design/icons-react": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npm.taobao.org/@ant-design/icons-react/download/@ant-design/icons-react-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/@ant-design/icons-react/-/icons-react-2.0.1.tgz",
|
||||||
"integrity": "sha1-F6JRNXGrMXrKKSfljOol3THlNvs=",
|
"integrity": "sha512-r1QfoltMuruJZqdiKcbPim3d8LNsVPB733U0gZEUSxBLuqilwsW28K2rCTWSMTjmFX7Mfpf+v/wdiFe/XCqThw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ant-design/colors": "^3.1.0",
|
"@ant-design/colors": "^3.1.0",
|
||||||
"babel-runtime": "^6.26.0"
|
"babel-runtime": "^6.26.0"
|
||||||
|
|
@ -451,8 +446,8 @@
|
||||||
},
|
},
|
||||||
"@types/react-slick": {
|
"@types/react-slick": {
|
||||||
"version": "0.23.4",
|
"version": "0.23.4",
|
||||||
"resolved": "https://registry.npm.taobao.org/@types/react-slick/download/@types/react-slick-0.23.4.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-slick/-/react-slick-0.23.4.tgz",
|
||||||
"integrity": "sha1-yX4qnn49GTPGhZO46CdS+rHozlM=",
|
"integrity": "sha512-vXoIy4GUfB7/YgqubR4H7RALo+pRdMYCeLgWwV3MPwl5pggTlEkFBTF19R7u+LJc85uMqC7RfsbkqPLMQ4ab+A==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/react": "*"
|
"@types/react": "*"
|
||||||
}
|
}
|
||||||
|
|
@ -868,9 +863,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"antd": {
|
"antd": {
|
||||||
"version": "3.26.20",
|
"version": "3.26.16",
|
||||||
"resolved": "https://registry.nlark.com/antd/download/antd-3.26.20.tgz",
|
"resolved": "https://registry.npmjs.org/antd/-/antd-3.26.16.tgz",
|
||||||
"integrity": "sha1-8/Vw76qllQoUSULyHrKqqgiOlAc=",
|
"integrity": "sha512-EYRwlEf8FCPCVRk5yDcgjSZOC0exu+m75SwlSQU+Mh17f9wGhLeL2/DV7/Sra1r+BZlfiahFdkgrLY7UgMMBEQ==",
|
||||||
"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",
|
||||||
|
|
@ -930,16 +925,16 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"raf": {
|
"raf": {
|
||||||
"version": "3.4.1",
|
"version": "3.4.1",
|
||||||
"resolved": "https://registry.npm.taobao.org/raf/download/raf-3.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
|
||||||
"integrity": "sha1-B0LpmkplUvRF1z4+4DKK8P8e3jk=",
|
"integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"performance-now": "^2.1.0"
|
"performance-now": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rc-pagination": {
|
"rc-pagination": {
|
||||||
"version": "1.20.15",
|
"version": "1.20.14",
|
||||||
"resolved": "https://registry.npm.taobao.org/rc-pagination/download/rc-pagination-1.20.15.tgz",
|
"resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-1.20.14.tgz",
|
||||||
"integrity": "sha1-zLTNDpvU5H9y8p6kMsA1C/ez2Ac=",
|
"integrity": "sha512-sNKwbFrxiqATqcIIShfrFs8BT03n4UUwTAMYae+JhHTmILQmXdvimEnZbVuWcno6G02DAJcLrFpmkn1h2tmEJw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "6.x",
|
"babel-runtime": "6.x",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
|
|
@ -949,8 +944,8 @@
|
||||||
},
|
},
|
||||||
"rc-rate": {
|
"rc-rate": {
|
||||||
"version": "2.5.1",
|
"version": "2.5.1",
|
||||||
"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",
|
"resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.5.1.tgz",
|
||||||
"integrity": "sha1-Vfxf0j6p3MciULmoiYA0efSEKWE=",
|
"integrity": "sha512-3iJkNJT8xlHklPCdeZtUZmJmRVUbr6AHRlfSsztfYTXVlHrv2TcPn3XkHsH+12j812WVB7gvilS2j3+ffjUHXg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"classnames": "^2.2.5",
|
"classnames": "^2.2.5",
|
||||||
"prop-types": "^15.5.8",
|
"prop-types": "^15.5.8",
|
||||||
|
|
@ -960,8 +955,8 @@
|
||||||
},
|
},
|
||||||
"rc-select": {
|
"rc-select": {
|
||||||
"version": "9.2.3",
|
"version": "9.2.3",
|
||||||
"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",
|
"resolved": "https://registry.npmjs.org/rc-select/-/rc-select-9.2.3.tgz",
|
||||||
"integrity": "sha1-ZDQOLW72TovDz8b0aP/ShiVYmsI=",
|
"integrity": "sha512-WhswxOMWiNnkXRbxyrj0kiIvyCfo/BaRPaYbsDetSIAU2yEDwKHF798blCP5u86KLOBKBvtxWLFCkSsQw1so5w==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "^6.23.0",
|
"babel-runtime": "^6.23.0",
|
||||||
"classnames": "2.x",
|
"classnames": "2.x",
|
||||||
|
|
@ -979,8 +974,8 @@
|
||||||
},
|
},
|
||||||
"rc-tree": {
|
"rc-tree": {
|
||||||
"version": "2.1.4",
|
"version": "2.1.4",
|
||||||
"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",
|
"resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-2.1.4.tgz",
|
||||||
"integrity": "sha1-73WfPnmaIbQ8Hs+ceU6hwU5wtZs=",
|
"integrity": "sha512-Xey794Iavgs8YldFlXcZLOhfcIhlX5Oz/yfKufknBXf2AlZCOkc7aHqSM9uTF7fBPtTGPhPxNEfOqHfY7b7xng==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ant-design/create-react-context": "^0.2.4",
|
"@ant-design/create-react-context": "^0.2.4",
|
||||||
"classnames": "2.x",
|
"classnames": "2.x",
|
||||||
|
|
@ -1088,8 +1083,8 @@
|
||||||
},
|
},
|
||||||
"array-tree-filter": {
|
"array-tree-filter": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npm.taobao.org/array-tree-filter/download/array-tree-filter-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/array-tree-filter/-/array-tree-filter-2.1.0.tgz",
|
||||||
"integrity": "sha1-hzrAD+yDdJ8lWsjdCDgUtPYykZA="
|
"integrity": "sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw=="
|
||||||
},
|
},
|
||||||
"array-union": {
|
"array-union": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
|
|
@ -1259,55 +1254,6 @@
|
||||||
"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",
|
||||||
|
|
@ -1327,7 +1273,7 @@
|
||||||
},
|
},
|
||||||
"babel-core": {
|
"babel-core": {
|
||||||
"version": "6.26.0",
|
"version": "6.26.0",
|
||||||
"resolved": "https://registry.npm.taobao.org/babel-core/download/babel-core-6.26.0.tgz",
|
"resolved": "https://registry.npmjs.org/babel-core/-/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",
|
||||||
|
|
@ -1353,8 +1299,8 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"debug": {
|
"debug": {
|
||||||
"version": "2.6.9",
|
"version": "2.6.9",
|
||||||
"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",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||||
"integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=",
|
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"ms": "2.0.0"
|
"ms": "2.0.0"
|
||||||
}
|
}
|
||||||
|
|
@ -1399,17 +1345,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"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",
|
||||||
|
|
@ -1462,18 +1397,6 @@
|
||||||
"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",
|
||||||
|
|
@ -1662,23 +1585,11 @@
|
||||||
"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",
|
||||||
|
|
@ -1709,17 +1620,6 @@
|
||||||
"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",
|
||||||
|
|
@ -1741,19 +1641,6 @@
|
||||||
"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",
|
||||||
|
|
@ -2048,7 +1935,7 @@
|
||||||
},
|
},
|
||||||
"babel-plugin-transform-runtime": {
|
"babel-plugin-transform-runtime": {
|
||||||
"version": "6.23.0",
|
"version": "6.23.0",
|
||||||
"resolved": "https://registry.npm.taobao.org/babel-plugin-transform-runtime/download/babel-plugin-transform-runtime-6.23.0.tgz",
|
"resolved": "https://registry.npmjs.org/babel-plugin-transform-runtime/-/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"
|
||||||
|
|
@ -2063,25 +1950,6 @@
|
||||||
"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",
|
||||||
|
|
@ -2119,38 +1987,6 @@
|
||||||
"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",
|
||||||
|
|
@ -2169,7 +2005,7 @@
|
||||||
},
|
},
|
||||||
"babel-preset-react": {
|
"babel-preset-react": {
|
||||||
"version": "6.24.1",
|
"version": "6.24.1",
|
||||||
"resolved": "https://registry.npm.taobao.org/babel-preset-react/download/babel-preset-react-6.24.1.tgz",
|
"resolved": "https://registry.npmjs.org/babel-preset-react/-/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",
|
||||||
|
|
@ -2200,31 +2036,6 @@
|
||||||
"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",
|
||||||
|
|
@ -3765,8 +3576,8 @@
|
||||||
},
|
},
|
||||||
"copy-to-clipboard": {
|
"copy-to-clipboard": {
|
||||||
"version": "3.3.1",
|
"version": "3.3.1",
|
||||||
"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",
|
"resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz",
|
||||||
"integrity": "sha1-EVqhqZmP+rYZb5MHatbaO5E2Yq4=",
|
"integrity": "sha512-i13qo6kIHTTpCm8/Wup+0b1mVWETvu2kIMzKoK8FpkLkFxlt0znUAHcMzox+T8sPlqtZXq3CulEjQHsYiGFJUw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"toggle-selection": "^1.0.6"
|
"toggle-selection": "^1.0.6"
|
||||||
}
|
}
|
||||||
|
|
@ -4852,7 +4663,7 @@
|
||||||
},
|
},
|
||||||
"dom-closest": {
|
"dom-closest": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npm.taobao.org/dom-closest/download/dom-closest-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/dom-closest/-/dom-closest-0.2.0.tgz",
|
||||||
"integrity": "sha1-69n5HRvyLo1vR3h2u80+yQIWwM8=",
|
"integrity": "sha1-69n5HRvyLo1vR3h2u80+yQIWwM8=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"dom-matches": ">=1.0.1"
|
"dom-matches": ">=1.0.1"
|
||||||
|
|
@ -4896,7 +4707,7 @@
|
||||||
},
|
},
|
||||||
"dom-matches": {
|
"dom-matches": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npm.taobao.org/dom-matches/download/dom-matches-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/dom-matches/-/dom-matches-2.0.0.tgz",
|
||||||
"integrity": "sha1-0nKLQWqHUzmA6wibhI0lPPI6dYw="
|
"integrity": "sha1-0nKLQWqHUzmA6wibhI0lPPI6dYw="
|
||||||
},
|
},
|
||||||
"dom-scroll-into-view": {
|
"dom-scroll-into-view": {
|
||||||
|
|
@ -4967,11 +4778,6 @@
|
||||||
"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",
|
||||||
|
|
@ -5018,8 +4824,8 @@
|
||||||
},
|
},
|
||||||
"draft-js": {
|
"draft-js": {
|
||||||
"version": "0.10.5",
|
"version": "0.10.5",
|
||||||
"resolved": "https://registry.npm.taobao.org/draft-js/download/draft-js-0.10.5.tgz",
|
"resolved": "https://registry.npmjs.org/draft-js/-/draft-js-0.10.5.tgz",
|
||||||
"integrity": "sha1-v6m+sBj+BTPbsI1mdcNxprCPp0I=",
|
"integrity": "sha512-LE6jSCV9nkPhfVX2ggcRLA4FKs6zWq9ceuO/88BpXdNCS7mjRTgs0NsV6piUCJX9YxMsB9An33wnkMmU2sD2Zg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"fbjs": "^0.8.15",
|
"fbjs": "^0.8.15",
|
||||||
"immutable": "~3.7.4",
|
"immutable": "~3.7.4",
|
||||||
|
|
@ -5149,7 +4955,7 @@
|
||||||
},
|
},
|
||||||
"enquire.js": {
|
"enquire.js": {
|
||||||
"version": "2.1.6",
|
"version": "2.1.6",
|
||||||
"resolved": "https://registry.npm.taobao.org/enquire.js/download/enquire.js-2.1.6.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fenquire.js%2Fdownload%2Fenquire.js-2.1.6.tgz",
|
"resolved": "https://registry.npmjs.org/enquire.js/-/enquire.js-2.1.6.tgz",
|
||||||
"integrity": "sha1-PoeAybi4NQhMP2DhZtvDwqPImBQ="
|
"integrity": "sha1-PoeAybi4NQhMP2DhZtvDwqPImBQ="
|
||||||
},
|
},
|
||||||
"entities": {
|
"entities": {
|
||||||
|
|
@ -5668,7 +5474,7 @@
|
||||||
},
|
},
|
||||||
"eventlistener": {
|
"eventlistener": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"resolved": "https://registry.npm.taobao.org/eventlistener/download/eventlistener-0.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/eventlistener/-/eventlistener-0.0.1.tgz",
|
||||||
"integrity": "sha1-7Suqu4UiJ68rz4iRUscsY8pTLrg="
|
"integrity": "sha1-7Suqu4UiJ68rz4iRUscsY8pTLrg="
|
||||||
},
|
},
|
||||||
"events": {
|
"events": {
|
||||||
|
|
@ -7082,12 +6888,6 @@
|
||||||
"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",
|
||||||
|
|
@ -7925,7 +7725,7 @@
|
||||||
},
|
},
|
||||||
"hammerjs": {
|
"hammerjs": {
|
||||||
"version": "2.0.8",
|
"version": "2.0.8",
|
||||||
"resolved": "https://registry.npm.taobao.org/hammerjs/download/hammerjs-2.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz",
|
||||||
"integrity": "sha1-BO93hiz/K7edMPdpIJWTAiK/YPE="
|
"integrity": "sha1-BO93hiz/K7edMPdpIJWTAiK/YPE="
|
||||||
},
|
},
|
||||||
"handle-thing": {
|
"handle-thing": {
|
||||||
|
|
@ -8766,7 +8566,7 @@
|
||||||
},
|
},
|
||||||
"immutable": {
|
"immutable": {
|
||||||
"version": "3.7.6",
|
"version": "3.7.6",
|
||||||
"resolved": "https://registry.npm.taobao.org/immutable/download/immutable-3.7.6.tgz",
|
"resolved": "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz",
|
||||||
"integrity": "sha1-E7TTyxK++hVIKib+Gy665kAHHks="
|
"integrity": "sha1-E7TTyxK++hVIKib+Gy665kAHHks="
|
||||||
},
|
},
|
||||||
"import-fresh": {
|
"import-fresh": {
|
||||||
|
|
@ -9180,9 +8980,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"is-mobile": {
|
"is-mobile": {
|
||||||
"version": "2.2.2",
|
"version": "2.2.1",
|
||||||
"resolved": "https://registry.nlark.com/is-mobile/download/is-mobile-2.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/is-mobile/-/is-mobile-2.2.1.tgz",
|
||||||
"integrity": "sha1-9snF1Q7gElTOBec5vdg18e1OmVQ="
|
"integrity": "sha512-6zELsfVFr326eq2CI53yvqq6YBanOxKBybwDT+MbMS2laBnK6Ez8m5XHSuTQQbnKRfpDzCod1CMWW5q3wZYMvA=="
|
||||||
},
|
},
|
||||||
"is-npm": {
|
"is-npm": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
|
|
@ -10354,7 +10154,7 @@
|
||||||
},
|
},
|
||||||
"lodash.throttle": {
|
"lodash.throttle": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npm.taobao.org/lodash.throttle/download/lodash.throttle-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
|
||||||
"integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ="
|
"integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ="
|
||||||
},
|
},
|
||||||
"lodash.uniq": {
|
"lodash.uniq": {
|
||||||
|
|
@ -11409,8 +11209,8 @@
|
||||||
},
|
},
|
||||||
"omit.js": {
|
"omit.js": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npm.taobao.org/omit.js/download/omit.js-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/omit.js/-/omit.js-1.0.2.tgz",
|
||||||
"integrity": "sha1-kaFPDrqEBm36AVvzDkdMR/MLyFg=",
|
"integrity": "sha512-/QPc6G2NS+8d4L/cQhbk6Yit1WTB6Us2g84A7A/1+w9d/eRGHyEqC5kkQtHVoHZ5NFWGG7tUGgrhVZwgZanKrQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "^6.23.0"
|
"babel-runtime": "^6.23.0"
|
||||||
}
|
}
|
||||||
|
|
@ -11539,17 +11339,6 @@
|
||||||
"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",
|
||||||
|
|
@ -14213,9 +14002,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rc-calendar": {
|
"rc-calendar": {
|
||||||
"version": "9.15.11",
|
"version": "9.15.10",
|
||||||
"resolved": "https://registry.npm.taobao.org/rc-calendar/download/rc-calendar-9.15.11.tgz",
|
"resolved": "https://registry.npmjs.org/rc-calendar/-/rc-calendar-9.15.10.tgz",
|
||||||
"integrity": "sha1-zh5eqOTXdDW+ZqjHfbEvHw+aNF8=",
|
"integrity": "sha512-xh1A3rYejKskAvkjnd9BcHXFbBnAYsHMGHBdtoAkbwp43B6yEieNL0g0Tzz8s1gApDZV2j5vF1jJ9IIpPYFNLw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "6.x",
|
"babel-runtime": "6.x",
|
||||||
"classnames": "2.x",
|
"classnames": "2.x",
|
||||||
|
|
@ -14228,8 +14017,8 @@
|
||||||
},
|
},
|
||||||
"rc-cascader": {
|
"rc-cascader": {
|
||||||
"version": "0.17.5",
|
"version": "0.17.5",
|
||||||
"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",
|
"resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-0.17.5.tgz",
|
||||||
"integrity": "sha1-T96R0jt2CMQgJjw47unAaH+A99w=",
|
"integrity": "sha512-WYMVcxU0+Lj+xLr4YYH0+yXODumvNXDcVEs5i7L1mtpWwYkubPV/zbQpn+jGKFCIW/hOhjkU4J1db8/P/UKE7A==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"array-tree-filter": "^2.1.0",
|
"array-tree-filter": "^2.1.0",
|
||||||
"prop-types": "^15.5.8",
|
"prop-types": "^15.5.8",
|
||||||
|
|
@ -14242,8 +14031,8 @@
|
||||||
},
|
},
|
||||||
"rc-checkbox": {
|
"rc-checkbox": {
|
||||||
"version": "2.1.8",
|
"version": "2.1.8",
|
||||||
"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",
|
"resolved": "https://registry.npmjs.org/rc-checkbox/-/rc-checkbox-2.1.8.tgz",
|
||||||
"integrity": "sha1-7t2e+cLzr1s7jlzeUlSqia0aiAo=",
|
"integrity": "sha512-6qOgh0/by0nVNASx6LZnhRTy17Etcgav+IrI7kL9V9kcDZ/g7K14JFlqrtJ3NjDq/Kyn+BPI1st1XvbkhfaJeg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "^6.23.0",
|
"babel-runtime": "^6.23.0",
|
||||||
"classnames": "2.x",
|
"classnames": "2.x",
|
||||||
|
|
@ -14253,8 +14042,8 @@
|
||||||
},
|
},
|
||||||
"rc-collapse": {
|
"rc-collapse": {
|
||||||
"version": "1.11.8",
|
"version": "1.11.8",
|
||||||
"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",
|
"resolved": "https://registry.npmjs.org/rc-collapse/-/rc-collapse-1.11.8.tgz",
|
||||||
"integrity": "sha1-ZqQAidRpUZ6UJACasckn4hQEHYA=",
|
"integrity": "sha512-8EhfPyScTYljkbRuIoHniSwZagD5UPpZ3CToYgoNYWC85L2qCbPYF7+OaC713FOrIkp6NbfNqXsITNxmDAmxog==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"classnames": "2.x",
|
"classnames": "2.x",
|
||||||
"css-animation": "1.x",
|
"css-animation": "1.x",
|
||||||
|
|
@ -14267,8 +14056,8 @@
|
||||||
},
|
},
|
||||||
"rc-dialog": {
|
"rc-dialog": {
|
||||||
"version": "7.6.1",
|
"version": "7.6.1",
|
||||||
"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",
|
"resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-7.6.1.tgz",
|
||||||
"integrity": "sha1-EVRczAuUWTT6dgeXJuDYU+UtcF8=",
|
"integrity": "sha512-KUKf+2eZ4YL+lnXMG3hR4ZtIhC9glfH27NtTVz3gcoDIPAf3uUvaXVRNoDCiSi+OGKLyIb/b6EoidFh6nQC5Wg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "6.x",
|
"babel-runtime": "6.x",
|
||||||
"rc-animate": "2.x",
|
"rc-animate": "2.x",
|
||||||
|
|
@ -14277,8 +14066,8 @@
|
||||||
},
|
},
|
||||||
"rc-drawer": {
|
"rc-drawer": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"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",
|
"resolved": "https://registry.npmjs.org/rc-drawer/-/rc-drawer-3.1.3.tgz",
|
||||||
"integrity": "sha1-y8sE1MB/C2by7OEdhH9KG9gOoLc=",
|
"integrity": "sha512-2z+RdxmzXyZde/1OhVMfDR1e/GBswFeWSZ7FS3Fdd0qhgVdpV1wSzILzzxRaT481ItB5hOV+e8pZT07vdJE8kg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
"rc-util": "^4.16.1",
|
"rc-util": "^4.16.1",
|
||||||
|
|
@ -14287,8 +14076,8 @@
|
||||||
},
|
},
|
||||||
"rc-dropdown": {
|
"rc-dropdown": {
|
||||||
"version": "2.4.1",
|
"version": "2.4.1",
|
||||||
"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",
|
"resolved": "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-2.4.1.tgz",
|
||||||
"integrity": "sha1-qu9us6UVLN2ZgolcKnjZtfBGzew=",
|
"integrity": "sha512-p0XYn0wrOpAZ2fUGE6YJ6U8JBNc5ASijznZ6dkojdaEfQJAeZtV9KMEewhxkVlxGSbbdXe10ptjBlTEW9vEwEg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "^6.26.0",
|
"babel-runtime": "^6.26.0",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
|
|
@ -14299,8 +14088,8 @@
|
||||||
},
|
},
|
||||||
"rc-editor-core": {
|
"rc-editor-core": {
|
||||||
"version": "0.8.10",
|
"version": "0.8.10",
|
||||||
"resolved": "https://registry.npm.taobao.org/rc-editor-core/download/rc-editor-core-0.8.10.tgz",
|
"resolved": "https://registry.npmjs.org/rc-editor-core/-/rc-editor-core-0.8.10.tgz",
|
||||||
"integrity": "sha1-byFbxd+cM/+p9sWzDKc6favoq3w=",
|
"integrity": "sha512-T3aHpeMCIYA1sdAI7ynHHjXy5fqp83uPlD68ovZ0oClTSc3tbHmyCxXlA+Ti4YgmcpCYv7avF6a+TIbAka53kw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "^6.26.0",
|
"babel-runtime": "^6.26.0",
|
||||||
"classnames": "^2.2.5",
|
"classnames": "^2.2.5",
|
||||||
|
|
@ -14313,8 +14102,8 @@
|
||||||
},
|
},
|
||||||
"rc-editor-mention": {
|
"rc-editor-mention": {
|
||||||
"version": "1.1.13",
|
"version": "1.1.13",
|
||||||
"resolved": "https://registry.npm.taobao.org/rc-editor-mention/download/rc-editor-mention-1.1.13.tgz",
|
"resolved": "https://registry.npmjs.org/rc-editor-mention/-/rc-editor-mention-1.1.13.tgz",
|
||||||
"integrity": "sha1-nxyrEGX4awFSOEAyF5DCqxKsXos=",
|
"integrity": "sha512-3AOmGir91Fi2ogfRRaXLtqlNuIwQpvla7oUnGHS1+3eo7b+fUp5IlKcagqtwUBB5oDNofoySXkLBxzWvSYNp/Q==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "^6.23.0",
|
"babel-runtime": "^6.23.0",
|
||||||
"classnames": "^2.2.5",
|
"classnames": "^2.2.5",
|
||||||
|
|
@ -14342,9 +14131,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rc-hammerjs": {
|
"rc-hammerjs": {
|
||||||
"version": "0.6.10",
|
"version": "0.6.9",
|
||||||
"resolved": "https://registry.npm.taobao.org/rc-hammerjs/download/rc-hammerjs-0.6.10.tgz",
|
"resolved": "https://registry.npmjs.org/rc-hammerjs/-/rc-hammerjs-0.6.9.tgz",
|
||||||
"integrity": "sha1-GDGjvY8hmXAL/MWtayCjVjCuteA=",
|
"integrity": "sha512-4llgWO3RgLyVbEqUdGsDfzUDqklRlQW5VEhE3x35IvhV+w//VPRG34SBavK3D2mD/UaLKaohgU41V4agiftC8g==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "6.x",
|
"babel-runtime": "6.x",
|
||||||
"hammerjs": "^2.0.8",
|
"hammerjs": "^2.0.8",
|
||||||
|
|
@ -14352,9 +14141,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rc-input-number": {
|
"rc-input-number": {
|
||||||
"version": "4.5.9",
|
"version": "4.5.6",
|
||||||
"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",
|
"resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-4.5.6.tgz",
|
||||||
"integrity": "sha1-HL9zXiT+I8TrmkMBAxcguV8qPj0=",
|
"integrity": "sha512-AXbL4gtQ1mSQnu6v/JtMv3UbGRCzLvQznmf0a7U/SAtZ8+dCEAqD4JpJhkjv73Wog53eRYhw4l7ApdXflc9ymg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "6.x",
|
"babel-runtime": "6.x",
|
||||||
"classnames": "^2.2.0",
|
"classnames": "^2.2.0",
|
||||||
|
|
@ -14365,8 +14154,8 @@
|
||||||
},
|
},
|
||||||
"rc-mentions": {
|
"rc-mentions": {
|
||||||
"version": "0.4.2",
|
"version": "0.4.2",
|
||||||
"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",
|
"resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-0.4.2.tgz",
|
||||||
"integrity": "sha1-wYq3Ae+55LdbOFGgwNLdaYZA4kY=",
|
"integrity": "sha512-DTZurQzacLXOfVuiHydGzqkq7cFMHXF18l2jZ9PhWUn2cqvOSY3W4osN0Pq29AOMOBpcxdZCzgc7Lb0r/bgkDw==",
|
||||||
"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",
|
||||||
|
|
@ -14394,8 +14183,8 @@
|
||||||
},
|
},
|
||||||
"rc-notification": {
|
"rc-notification": {
|
||||||
"version": "3.3.1",
|
"version": "3.3.1",
|
||||||
"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",
|
"resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-3.3.1.tgz",
|
||||||
"integrity": "sha1-C6o+cPjUCrAVzo+njCYMSQ/HvrQ=",
|
"integrity": "sha512-U5+f4BmBVfMSf3OHSLyRagsJ74yKwlrQAtbbL5ijoA0F2C60BufwnOcHG18tVprd7iaIjzZt1TKMmQSYSvgrig==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "6.x",
|
"babel-runtime": "6.x",
|
||||||
"classnames": "2.x",
|
"classnames": "2.x",
|
||||||
|
|
@ -14416,9 +14205,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rc-progress": {
|
"rc-progress": {
|
||||||
"version": "2.5.3",
|
"version": "2.5.2",
|
||||||
"resolved": "https://registry.npm.taobao.org/rc-progress/download/rc-progress-2.5.3.tgz",
|
"resolved": "https://registry.npmjs.org/rc-progress/-/rc-progress-2.5.2.tgz",
|
||||||
"integrity": "sha1-APAblb2+GFbTpfgiQgUZAui3qOc=",
|
"integrity": "sha512-ajI+MJkbBz9zYDuE9GQsY5gsyqPF7HFioZEDZ9Fmc+ebNZoiSeSJsTJImPFCg0dW/5WiRGUy2F69SX1aPtSJgA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "6.x",
|
"babel-runtime": "6.x",
|
||||||
"prop-types": "^15.5.8"
|
"prop-types": "^15.5.8"
|
||||||
|
|
@ -14435,8 +14224,8 @@
|
||||||
},
|
},
|
||||||
"rc-resize-observer": {
|
"rc-resize-observer": {
|
||||||
"version": "0.1.3",
|
"version": "0.1.3",
|
||||||
"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",
|
"resolved": "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-0.1.3.tgz",
|
||||||
"integrity": "sha1-CXGR+cOrGG7ZB7VTum71Zd8Rwkk=",
|
"integrity": "sha512-uzOQEwx83xdQSFOkOAM7x7GHIQKYnrDV4dWxtCxyG1BS1pkfJ4EvDeMfsvAJHSYkQXVBu+sgRHGbRtLG3qiuUg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"classnames": "^2.2.1",
|
"classnames": "^2.2.1",
|
||||||
"rc-util": "^4.13.0",
|
"rc-util": "^4.13.0",
|
||||||
|
|
@ -14464,8 +14253,8 @@
|
||||||
},
|
},
|
||||||
"rc-slider": {
|
"rc-slider": {
|
||||||
"version": "8.7.1",
|
"version": "8.7.1",
|
||||||
"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",
|
"resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-8.7.1.tgz",
|
||||||
"integrity": "sha1-ntBzYtyTSJo45lSyG4EirXD9PEI=",
|
"integrity": "sha512-WMT5mRFUEcrLWwTxsyS8jYmlaMsTVCZIGENLikHsNv+tE8ThU2lCoPfi/xFNUfJFNFSBFP3MwPez9ZsJmNp13g==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "6.x",
|
"babel-runtime": "6.x",
|
||||||
"classnames": "^2.2.5",
|
"classnames": "^2.2.5",
|
||||||
|
|
@ -14479,8 +14268,8 @@
|
||||||
},
|
},
|
||||||
"rc-steps": {
|
"rc-steps": {
|
||||||
"version": "3.5.0",
|
"version": "3.5.0",
|
||||||
"resolved": "https://registry.npm.taobao.org/rc-steps/download/rc-steps-3.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/rc-steps/-/rc-steps-3.5.0.tgz",
|
||||||
"integrity": "sha1-NrKn8fSZB7DZA2OISxhiPK+ftgA=",
|
"integrity": "sha512-2Vkkrpa7PZbg7qPsqTNzVDov4u78cmxofjjnIHiGB9+9rqKS8oTLPzbW2uiWDr3Lk+yGwh8rbpGO1E6VAgBCOg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "^6.23.0",
|
"babel-runtime": "^6.23.0",
|
||||||
"classnames": "^2.2.3",
|
"classnames": "^2.2.3",
|
||||||
|
|
@ -14489,9 +14278,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rc-switch": {
|
"rc-switch": {
|
||||||
"version": "1.9.2",
|
"version": "1.9.0",
|
||||||
"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",
|
"resolved": "https://registry.npmjs.org/rc-switch/-/rc-switch-1.9.0.tgz",
|
||||||
"integrity": "sha1-eSHHZkEf6aZCZRDDQpAi1rpN/eI=",
|
"integrity": "sha512-Isas+egaK6qSk64jaEw4GgPStY4umYDbT7ZY93bZF1Af+b/JEsKsJdNOU2qG3WI0Z6tXo2DDq0kJCv8Yhu0zww==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"classnames": "^2.2.1",
|
"classnames": "^2.2.1",
|
||||||
"prop-types": "^15.5.6",
|
"prop-types": "^15.5.6",
|
||||||
|
|
@ -14500,8 +14289,8 @@
|
||||||
},
|
},
|
||||||
"rc-table": {
|
"rc-table": {
|
||||||
"version": "6.10.15",
|
"version": "6.10.15",
|
||||||
"resolved": "https://registry.nlark.com/rc-table/download/rc-table-6.10.15.tgz",
|
"resolved": "https://registry.npmjs.org/rc-table/-/rc-table-6.10.15.tgz",
|
||||||
"integrity": "sha1-GB9McMT9dPZX7o8jGW5+sIoDZco=",
|
"integrity": "sha512-LAr0M/gqt+irOjvPNBLApmQ0CUHNOfKsEBhu1uIuB3OlN1ynA9z+sdoTQyNd9+8NSl0MYnQOOfhtLChAY7nU0A==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"classnames": "^2.2.5",
|
"classnames": "^2.2.5",
|
||||||
"component-classes": "^1.2.6",
|
"component-classes": "^1.2.6",
|
||||||
|
|
@ -14515,8 +14304,8 @@
|
||||||
},
|
},
|
||||||
"rc-tabs": {
|
"rc-tabs": {
|
||||||
"version": "9.7.0",
|
"version": "9.7.0",
|
||||||
"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",
|
"resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-9.7.0.tgz",
|
||||||
"integrity": "sha1-rglpW+9ZY9bmTnvBBSHHbf3YRIs=",
|
"integrity": "sha512-kvmgp8/MfLzFZ06hWHignqomFQ5nF7BqKr5O1FfhE4VKsGrep52YSF/1MvS5oe0NPcI9XGNS2p751C5v6cYDpQ==",
|
||||||
"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",
|
||||||
|
|
@ -14533,8 +14322,8 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"raf": {
|
"raf": {
|
||||||
"version": "3.4.1",
|
"version": "3.4.1",
|
||||||
"resolved": "https://registry.npm.taobao.org/raf/download/raf-3.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
|
||||||
"integrity": "sha1-B0LpmkplUvRF1z4+4DKK8P8e3jk=",
|
"integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"performance-now": "^2.1.0"
|
"performance-now": "^2.1.0"
|
||||||
}
|
}
|
||||||
|
|
@ -14543,8 +14332,8 @@
|
||||||
},
|
},
|
||||||
"rc-time-picker": {
|
"rc-time-picker": {
|
||||||
"version": "3.7.3",
|
"version": "3.7.3",
|
||||||
"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",
|
"resolved": "https://registry.npmjs.org/rc-time-picker/-/rc-time-picker-3.7.3.tgz",
|
||||||
"integrity": "sha1-ZajekECTJQrpyCsCpJBeD5leI+I=",
|
"integrity": "sha512-Lv1Mvzp9fRXhXEnRLO4nW6GLNxUkfAZ3RsiIBsWjGjXXvMNjdr4BX/ayElHAFK0DoJqOhm7c5tjmIYpEOwcUXg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"classnames": "2.x",
|
"classnames": "2.x",
|
||||||
"moment": "2.x",
|
"moment": "2.x",
|
||||||
|
|
@ -14556,8 +14345,8 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"raf": {
|
"raf": {
|
||||||
"version": "3.4.1",
|
"version": "3.4.1",
|
||||||
"resolved": "https://registry.npm.taobao.org/raf/download/raf-3.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
|
||||||
"integrity": "sha1-B0LpmkplUvRF1z4+4DKK8P8e3jk=",
|
"integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"performance-now": "^2.1.0"
|
"performance-now": "^2.1.0"
|
||||||
}
|
}
|
||||||
|
|
@ -14566,8 +14355,8 @@
|
||||||
},
|
},
|
||||||
"rc-tooltip": {
|
"rc-tooltip": {
|
||||||
"version": "3.7.3",
|
"version": "3.7.3",
|
||||||
"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",
|
"resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-3.7.3.tgz",
|
||||||
"integrity": "sha1-KArsavyqROjf8EgPuv+eh/wArsw=",
|
"integrity": "sha512-dE2ibukxxkrde7wH9W8ozHKUO4aQnPZ6qBHtrTH9LoO836PjDdiaWO73fgPB05VfJs9FbZdmGPVEbXCeOP99Ww==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "6.x",
|
"babel-runtime": "6.x",
|
||||||
"prop-types": "^15.5.8",
|
"prop-types": "^15.5.8",
|
||||||
|
|
@ -14615,8 +14404,8 @@
|
||||||
},
|
},
|
||||||
"rc-tree-select": {
|
"rc-tree-select": {
|
||||||
"version": "2.9.4",
|
"version": "2.9.4",
|
||||||
"resolved": "https://registry.nlark.com/rc-tree-select/download/rc-tree-select-2.9.4.tgz",
|
"resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-2.9.4.tgz",
|
||||||
"integrity": "sha1-aqeU4fDmXGbEBqoKKg50/QpVewk=",
|
"integrity": "sha512-0HQkXAN4XbfBW20CZYh3G+V+VMrjX42XRtDCpyv6PDUm5vikC0Ob682ZBCVS97Ww2a5Hf6Ajmu0ahWEdIEpwhg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"classnames": "^2.2.1",
|
"classnames": "^2.2.1",
|
||||||
"dom-scroll-into-view": "^1.2.1",
|
"dom-scroll-into-view": "^1.2.1",
|
||||||
|
|
@ -14633,8 +14422,8 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"rc-tree": {
|
"rc-tree": {
|
||||||
"version": "2.1.4",
|
"version": "2.1.4",
|
||||||
"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",
|
"resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-2.1.4.tgz",
|
||||||
"integrity": "sha1-73WfPnmaIbQ8Hs+ceU6hwU5wtZs=",
|
"integrity": "sha512-Xey794Iavgs8YldFlXcZLOhfcIhlX5Oz/yfKufknBXf2AlZCOkc7aHqSM9uTF7fBPtTGPhPxNEfOqHfY7b7xng==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ant-design/create-react-context": "^0.2.4",
|
"@ant-design/create-react-context": "^0.2.4",
|
||||||
"classnames": "2.x",
|
"classnames": "2.x",
|
||||||
|
|
@ -14647,8 +14436,8 @@
|
||||||
},
|
},
|
||||||
"rc-trigger": {
|
"rc-trigger": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"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",
|
"resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-3.0.0.tgz",
|
||||||
"integrity": "sha1-9tmx2oomsrLR2RKgaHbBpIb1mA8=",
|
"integrity": "sha512-hQxbbJpo23E2QnYczfq3Ec5J5tVl2mUDhkqxrEsQAqk16HfADQg+iKNWzEYXyERSncdxfnzYuaBgy764mNRzTA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "6.x",
|
"babel-runtime": "6.x",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
|
|
@ -14660,14 +14449,18 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"rc-animate": {
|
"rc-animate": {
|
||||||
"version": "3.1.1",
|
"version": "3.0.0-rc.6",
|
||||||
"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",
|
"resolved": "https://registry.npmjs.org/rc-animate/-/rc-animate-3.0.0-rc.6.tgz",
|
||||||
"integrity": "sha1-3v3YY/VoFsIiU05Nxo/t3s0IE4Y=",
|
"integrity": "sha512-oBLPpiT6Q4t6YvD/pkLcmofBP1p01TX0Otse8Q4+Mxt8J+VSDflLZGIgf62EwkvRwsQUkLPjZVFBsldnPKLzjg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@ant-design/css-animation": "^1.7.2",
|
"babel-runtime": "6.x",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.5",
|
||||||
|
"component-classes": "^1.2.6",
|
||||||
|
"fbjs": "^0.8.16",
|
||||||
|
"prop-types": "15.x",
|
||||||
"raf": "^3.4.0",
|
"raf": "^3.4.0",
|
||||||
"rc-util": "^4.15.3"
|
"rc-util": "^4.5.0",
|
||||||
|
"react-lifecycles-compat": "^3.0.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -15106,9 +14899,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"react-lazy-load": {
|
"react-lazy-load": {
|
||||||
"version": "3.1.13",
|
"version": "3.0.13",
|
||||||
"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",
|
"resolved": "https://registry.npmjs.org/react-lazy-load/-/react-lazy-load-3.0.13.tgz",
|
||||||
"integrity": "sha1-I2lD92twhMyEWHFtljKhyYU+pc0=",
|
"integrity": "sha1-OwqS0zbUPT8Nc8vm81sXBQsIuCQ=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"eventlistener": "0.0.1",
|
"eventlistener": "0.0.1",
|
||||||
"lodash.debounce": "^4.0.0",
|
"lodash.debounce": "^4.0.0",
|
||||||
|
|
@ -15246,8 +15039,8 @@
|
||||||
},
|
},
|
||||||
"react-slick": {
|
"react-slick": {
|
||||||
"version": "0.25.2",
|
"version": "0.25.2",
|
||||||
"resolved": "https://registry.nlark.com/react-slick/download/react-slick-0.25.2.tgz",
|
"resolved": "https://registry.npmjs.org/react-slick/-/react-slick-0.25.2.tgz",
|
||||||
"integrity": "sha1-VjMbZ9R9i8/i3OtqyrHI/VvR9rw=",
|
"integrity": "sha512-8MNH/NFX/R7zF6W/w+FS5VXNyDusF+XDW1OU0SzODEU7wqYB+ZTGAiNJ++zVNAVqCAHdyCybScaUB+FCZOmBBw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"classnames": "^2.2.5",
|
"classnames": "^2.2.5",
|
||||||
"enquire.js": "^2.1.6",
|
"enquire.js": "^2.1.6",
|
||||||
|
|
@ -16091,8 +15884,8 @@
|
||||||
},
|
},
|
||||||
"rmc-feedback": {
|
"rmc-feedback": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npm.taobao.org/rmc-feedback/download/rmc-feedback-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/rmc-feedback/-/rmc-feedback-2.0.0.tgz",
|
||||||
"integrity": "sha1-y8bLOuY8emNe7w4l5PuvWsNm7qo=",
|
"integrity": "sha512-5PWOGOW7VXks/l3JzlOU9NIxRpuaSS8d9zA3UULUCuTKnpwBHNvv1jSJzxgbbCQeYzROWUpgKI4za3X4C/mKmQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"babel-runtime": "6.x",
|
"babel-runtime": "6.x",
|
||||||
"classnames": "^2.2.5"
|
"classnames": "^2.2.5"
|
||||||
|
|
@ -16675,8 +16468,8 @@
|
||||||
},
|
},
|
||||||
"shallow-equal": {
|
"shallow-equal": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npm.taobao.org/shallow-equal/download/shallow-equal-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.1.tgz",
|
||||||
"integrity": "sha1-TBar+lYEOqINBQMk76aJQLDaedo="
|
"integrity": "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA=="
|
||||||
},
|
},
|
||||||
"shallowequal": {
|
"shallowequal": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
|
|
@ -17217,8 +17010,8 @@
|
||||||
},
|
},
|
||||||
"source-map-support": {
|
"source-map-support": {
|
||||||
"version": "0.4.18",
|
"version": "0.4.18",
|
||||||
"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",
|
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz",
|
||||||
"integrity": "sha1-Aoam3ovkJkEzhZTpfM6nXwosWF8=",
|
"integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"source-map": "^0.5.6"
|
"source-map": "^0.5.6"
|
||||||
},
|
},
|
||||||
|
|
@ -18873,12 +18666,6 @@
|
||||||
"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",
|
||||||
|
|
@ -18930,15 +18717,6 @@
|
||||||
"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",
|
||||||
|
|
@ -20476,16 +20254,6 @@
|
||||||
"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": "forge",
|
"name": "educoder",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
"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",
|
||||||
|
|
@ -26,7 +27,6 @@
|
||||||
"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,9 +111,7 @@
|
||||||
"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",
|
||||||
|
|
@ -184,13 +182,7 @@
|
||||||
"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
|
|
@ -2346,6 +2346,7 @@ input::-ms-clear {
|
||||||
/*中间部分宽度固定为1200*/
|
/*中间部分宽度固定为1200*/
|
||||||
.newMain {
|
.newMain {
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
padding-bottom: 110px;
|
||||||
min-width: 1200px;
|
min-width: 1200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4107,6 +4108,21 @@ em.vertical-line {
|
||||||
|
|
||||||
/* 右侧内容宽度变化的话,需要调整posi-search right的值*/
|
/* 右侧内容宽度变化的话,需要调整posi-search right的值*/
|
||||||
|
|
||||||
|
/*底部*/
|
||||||
|
.newFooter {
|
||||||
|
max-height: 110px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.newFooter {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
background: #323232;
|
||||||
|
clear: both;
|
||||||
|
min-width: 1200px;
|
||||||
|
z-index: 8;
|
||||||
|
left: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
.footercon {
|
.footercon {
|
||||||
border-bottom: 1px solid #47494d;
|
border-bottom: 1px solid #47494d;
|
||||||
|
|
@ -6702,13 +6718,4 @@ 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: 733 KiB After Width: | Height: | Size: 584 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,111 +0,0 @@
|
||||||
|
|
||||||
.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,9 +8,18 @@
|
||||||
<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">
|
||||||
<link rel="stylesheet" type="text/css" href="%PUBLIC_URL%css/iconfont.css">
|
window.__isR = true;
|
||||||
<link rel="stylesheet" type="text/css" href="%PUBLIC_URL%css/edu-purge.css">
|
if (
|
||||||
|
(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 %>
|
||||||
|
|
@ -21,7 +30,6 @@
|
||||||
<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>
|
||||||
|
|
|
||||||
25
src/App.js
25
src/App.js
|
|
@ -9,7 +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 'babel-polyfill';
|
|
||||||
import Loading from './Loading'
|
import Loading from './Loading'
|
||||||
|
|
||||||
import Loadable from 'react-loadable';
|
import Loadable from 'react-loadable';
|
||||||
|
|
@ -70,10 +70,6 @@ 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) {
|
||||||
|
|
@ -149,7 +145,7 @@ class App extends Component {
|
||||||
this.setState({
|
this.setState({
|
||||||
mygetHelmetapi: undefined
|
mygetHelmetapi: undefined
|
||||||
});
|
});
|
||||||
document.title = "Forge";
|
document.title = "实践教学";
|
||||||
var link = document.createElement('link'),
|
var link = document.createElement('link'),
|
||||||
oldLink = document.getElementById('dynamic-favicon');
|
oldLink = document.getElementById('dynamic-favicon');
|
||||||
link.id = 'dynamic-favicon';
|
link.id = 'dynamic-favicon';
|
||||||
|
|
@ -211,7 +207,13 @@ 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>
|
||||||
{/*项目*/}
|
{/*项目*/}
|
||||||
|
|
@ -232,14 +234,7 @@ 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} />
|
||||||
|
|
||||||
|
|
@ -247,7 +242,7 @@ class App extends Component {
|
||||||
<Route path={"/organize"}
|
<Route path={"/organize"}
|
||||||
render={
|
render={
|
||||||
(props) => {
|
(props) => {
|
||||||
return (<OrganizeIndex {...props} {...this.props} {...this.state} />)
|
return (<OrganizeIndex {...this.props} {...props} {...this.state} />)
|
||||||
}
|
}
|
||||||
}>
|
}>
|
||||||
</Route>
|
</Route>
|
||||||
|
|
|
||||||
|
|
@ -2,17 +2,19 @@ import axios from 'axios';
|
||||||
import { requestProxy } from "./indexEduplus2RequestProxy";
|
import { requestProxy } from "./indexEduplus2RequestProxy";
|
||||||
import { broadcastChannelOnmessage, isDev, queryString } from 'educoder';
|
import { broadcastChannelOnmessage, isDev, queryString } from 'educoder';
|
||||||
import { notification } from 'antd';
|
import { notification } from 'antd';
|
||||||
|
import cookie from 'react-cookies';
|
||||||
import './index.css';
|
import './index.css';
|
||||||
|
|
||||||
let message501 = false;
|
let message501 = false;
|
||||||
|
|
||||||
broadcastChannelOnmessage('refreshPage', () => {
|
broadcastChannelOnmessage('refreshPage', () => {
|
||||||
window.location.reload();
|
window.location.reload()
|
||||||
})
|
})
|
||||||
|
|
||||||
function locationurl(list) {
|
function locationurl(list) {
|
||||||
if (window.location.port !== "3007") {
|
if (window.location.port === "3007") {
|
||||||
window.location.href = list
|
|
||||||
|
} else {
|
||||||
|
window.location.href = list
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO 开发期多个身份切换
|
// TODO 开发期多个身份切换
|
||||||
|
|
@ -24,22 +26,55 @@ if (isDev) {
|
||||||
parsed = queryString.parse(_search);
|
parsed = queryString.parse(_search);
|
||||||
}
|
}
|
||||||
debugType = window.location.search.indexOf('debug=t') !== -1 ? 'teacher' :
|
debugType = window.location.search.indexOf('debug=t') !== -1 ? 'teacher' :
|
||||||
window.location.search.indexOf('debug=s') !== -1 ? 'student' :
|
window.location.search.indexOf('debug=s') !== -1 ? 'student' :
|
||||||
window.location.search.indexOf('debug=a') !== -1 ? 'admin' : parsed.debug || 'admin'
|
window.location.search.indexOf('debug=a') !== -1 ? 'admin' : parsed.debug || 'admin'
|
||||||
}
|
}
|
||||||
|
function clearAllCookie() {
|
||||||
|
cookie.remove('_educoder_session', { path: '/' });
|
||||||
|
cookie.remove('autologin_trustie', { path: '/' });
|
||||||
|
setpostcookie()
|
||||||
|
}
|
||||||
|
clearAllCookie();
|
||||||
|
function setpostcookie() {
|
||||||
|
const str = window.location.pathname;
|
||||||
|
if (str.indexOf("/wxcode") !== -1) {
|
||||||
|
cookie.remove('_educoder_session', { path: '/' });
|
||||||
|
cookie.remove('autologin_trustie', { path: '/' });
|
||||||
|
const _params = window.location.search;
|
||||||
|
if (_params) {
|
||||||
|
let _search = _params.split('?')[1];
|
||||||
|
let _educoder_sessions = _search.split('&')[0].split('=');
|
||||||
|
cookie.save('_educoder_session', _educoder_sessions[1], { domain: '.educoder.net', path: '/' });
|
||||||
|
let autologin_trusties = _search.split('&')[1].split('=');
|
||||||
|
cookie.save('autologin_trustie', autologin_trusties[1], { domain: '.educoder.net', path: '/' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setpostcookie();
|
||||||
|
|
||||||
window._debugType = debugType;
|
window._debugType = debugType;
|
||||||
export function initAxiosInterceptors(props) {
|
export function initAxiosInterceptors(props) {
|
||||||
// 判断网络是否连接
|
initOnlineOfflineListener()
|
||||||
initOnlineOfflineListener();
|
// TODO 避免重复的请求 https://github.com/axios/axios#cancellation
|
||||||
|
var
|
||||||
|
proxy = "http://localhost:3000";
|
||||||
|
proxy = "https://testforgeplus.trustie.net";
|
||||||
|
|
||||||
var proxy = "https://testforgeplus.trustie.net";
|
const requestMap = {};
|
||||||
|
window.setfalseInRequestMap = function (keyName) {
|
||||||
|
requestMap[keyName] = false;
|
||||||
|
}
|
||||||
//响应前的设置
|
//响应前的设置
|
||||||
axios.interceptors.request.use(
|
axios.interceptors.request.use(
|
||||||
config => {
|
config => {
|
||||||
if(config.url.indexOf("http") !== -1) {
|
setpostcookie()
|
||||||
|
clearAllCookie()
|
||||||
|
|
||||||
|
if (config.url.indexOf(proxy) !== -1) {
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
requestProxy(config);
|
requestProxy(config)
|
||||||
|
|
||||||
let url = `/api${config.url}`;
|
let url = `/api${config.url}`;
|
||||||
|
|
||||||
if (`${config[0]}` !== `true`) {
|
if (`${config[0]}` !== `true`) {
|
||||||
|
|
@ -53,12 +88,18 @@ 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) {
|
||||||
|
|
@ -107,6 +148,8 @@ export function initAxiosInterceptors(props) {
|
||||||
message501 = false
|
message501 = false
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
|
requestMap[response.config.url] = false;
|
||||||
|
setpostcookie();
|
||||||
return response;
|
return response;
|
||||||
}, function (error) {
|
}, function (error) {
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ export function getImageUrl(path) {
|
||||||
if (isDev) {
|
if (isDev) {
|
||||||
return `${local}/${path}`
|
return `${local}/${path}`
|
||||||
}
|
}
|
||||||
return `${path}`;
|
return `/${path}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getImage(path) {
|
export function getImage(path) {
|
||||||
|
|
@ -162,28 +162,28 @@ export function getmyUrl(geturl) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getUploadActionUrl(path, goTest) {
|
export function getUploadActionUrl(path, goTest) {
|
||||||
return `${getUrl()}/api/attachments.json${isDev ?`${isDev ?`?debug=${window._debugType || 'admin'}` : ""}` : ""}`;
|
return `${getUrl()}/api/attachments.json?debug=${window._debugType || 'admin'}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getUploadLogoActionUrl() {
|
export function getUploadLogoActionUrl() {
|
||||||
return `${getUrl()}/api/resumes/logo.json${isDev ?`?debug=${window._debugType || 'admin'}` : ""}`;
|
return `${getUrl()}/api/resumes/logo.json?debug=${window._debugType || 'admin'}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getUploadActionUrltwo(id) {
|
export function getUploadActionUrltwo(id) {
|
||||||
return `${getUrlmys()}/api/shixuns/${id}/upload_data_sets.json${isDev ?`?debug=${window._debugType || 'admin'}` : ""}`
|
return `${getUrlmys()}/api/shixuns/${id}/upload_data_sets.json?debug=${window._debugType || 'admin'}`
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getUploadActionUrlthree() {
|
export function getUploadActionUrlthree() {
|
||||||
return `${getUrlmys()}/api/jupyters/import_with_tpm.json${isDev ?`?debug=${window._debugType || 'admin'}` : ""}`
|
return `${getUrlmys()}/api/jupyters/import_with_tpm.json?debug=${window._debugType || 'admin'}`
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getupload_git_file(id) {
|
export function getupload_git_file(id) {
|
||||||
return `${getUrlmys()}/api/shixuns/${id}/upload_git_file.json${isDev ?`?debug=${window._debugType || 'admin'}` : ""}`
|
return `${getUrlmys()}/api/shixuns/${id}/upload_git_file.json?debug=${window._debugType || 'admin'}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function getUploadActionUrlOfAuth(id) {
|
export function getUploadActionUrlOfAuth(id) {
|
||||||
return `${getUrl()}/api/users/accounts/${id}/auth_attachment.json${isDev ?`?debug=${window._debugType || 'admin'}` : ""}`
|
return `${getUrl()}/api/users/accounts/${id}/auth_attachment.json?debug=${window._debugType || 'admin'}`
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getRandomNumber(type) {
|
export function getRandomNumber(type) {
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ function CommentItem({
|
||||||
const commentAvatar = (author) => (
|
const commentAvatar = (author) => (
|
||||||
<img
|
<img
|
||||||
className="item-flex flex-image"
|
className="item-flex flex-image"
|
||||||
src={author.image_url ? getImageUrl(`/${author.image_url}`) : 'https://b-ssl.duitang.com/uploads/item/201511/13/20151113110434_kyReJ.jpeg'}
|
src={author.image_url ? getImageUrl(`images/${author.image_url}`) : 'https://b-ssl.duitang.com/uploads/item/201511/13/20151113110434_kyReJ.jpeg'}
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -76,4 +76,10 @@ 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,6 +157,7 @@ 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,58 +1,37 @@
|
||||||
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 marked, { getTocContent, cleanToc, getMathExpressions, resetMathExpressions } from '../common/marked';
|
import { renderToString } from 'katex';
|
||||||
|
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 dompurify.sanitize(rs)
|
return rs
|
||||||
}, [str]);
|
}, [str])
|
||||||
|
|
||||||
// 锚点跳转,链接地址里含#对应的id
|
const el = useRef()
|
||||||
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') {
|
||||||
|
|
@ -61,7 +40,7 @@ export default ({
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
let viewEl = document.getElementById(ancher.replace('#', ''))
|
let viewEl = document.getElementById(ancher.replace('#', ''))
|
||||||
if (viewEl) {
|
if (viewEl) {
|
||||||
viewEl.scrollIntoView(true)
|
viewEl.parentNode.scrollTop = viewEl.offsetTop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -82,12 +61,6 @@ export default ({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [html, el.current, onAncherHandler])
|
}, [html, el.current, onAncherHandler])
|
||||||
return (
|
|
||||||
<div
|
return (<div ref={el} style={style} className={`${className ? className : ''} markdown-body`} dangerouslySetInnerHTML={{ __html: html }}></div>)
|
||||||
ref={el}
|
|
||||||
style={style}
|
|
||||||
className={`${className ? className : ''} markdown-body`}
|
|
||||||
dangerouslySetInnerHTML={{ __html: html }}
|
|
||||||
></div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,17 +67,18 @@ function Index(props){
|
||||||
}
|
}
|
||||||
return(
|
return(
|
||||||
<div className="aboutPanels">
|
<div className="aboutPanels">
|
||||||
|
|
||||||
<div className="aboutContent">
|
<div className="aboutContent">
|
||||||
<AlignCenterBetween style={{padding:"14px 20px"}}>
|
<AlignCenterBetween style={{padding:"14px 0px"}}>
|
||||||
<span className="font-16"><i className="iconfont icon-xiangmujianjie mr5 font-16 color-blue"></i>项目概览</span>
|
<span className="font-16"><i className="iconfont icon-xiangmujianjie mr5 font-16 color-blue"></i>项目简介</span>
|
||||||
{ editOpration && !edit && <a onClick={editContent} className="color-blue">编辑</a> }
|
{ editOpration && !edit && <a onClick={editContent} className="color-blue">编辑</a> }
|
||||||
</AlignCenterBetween>
|
</AlignCenterBetween>
|
||||||
{
|
{
|
||||||
edit ?
|
edit ?
|
||||||
<div className="padding20">
|
<div>
|
||||||
<MDEditor
|
<MDEditor
|
||||||
placeholder={"请输入描述信息"}
|
placeholder={"请输入描述信息"}
|
||||||
height={500}
|
height={200}
|
||||||
mdID={"order-new-description"}
|
mdID={"order-new-description"}
|
||||||
initValue={content}
|
initValue={content}
|
||||||
onChange={onContentChange}
|
onChange={onContentChange}
|
||||||
|
|
@ -113,11 +114,11 @@ function Index(props){
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
:
|
:
|
||||||
<div className="padding20">
|
<div style={{padding:"20px 0px"}}>
|
||||||
{content ?
|
{content ?
|
||||||
<RenderHtml className="break_word_comments imageLayerParent" value={content} url={props.history.location}/>
|
<RenderHtml className="break_word_comments imageLayerParent" value={content} />
|
||||||
:
|
:
|
||||||
<div>暂无概览~</div>
|
<div>暂无简介~</div>
|
||||||
}
|
}
|
||||||
{attachments && attachments.length > 0 &&
|
{attachments && attachments.length > 0 &&
|
||||||
<Attachments
|
<Attachments
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
.aboutContent{
|
.aboutContent{
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
border: 1px solid #EEEEEE;
|
border: 1px solid #EEEEEE;
|
||||||
|
padding:0px 30px;
|
||||||
width:100%;
|
width:100%;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
margin-top:20px;
|
margin-top:20px;
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,8 @@ class ActivityItem extends Component {
|
||||||
</p >
|
</p >
|
||||||
}
|
}
|
||||||
<p className="itemLine mt10">
|
<p className="itemLine mt10">
|
||||||
<Link to={`/users/${item && item.user_login}`} className="show-user-link">
|
<Link to={`/users/${item && item.login}`} className="show-user-link">
|
||||||
<img alt="" src={getImageUrl(`/${item.user_avatar}`)} className="createImage" />
|
<img alt="" src={getImageUrl(`images/${item.user_avatar}`)} className="createImage" />
|
||||||
<span className="mr20">{item.user_name}</span>
|
<span className="mr20">{item.user_name}</span>
|
||||||
</Link>
|
</Link>
|
||||||
{item.created_at && <span className="color-grey-9">创建于<span className="ml2 color-grey-6">{item.created_at}</span></span>}
|
{item.created_at && <span className="color-grey-9">创建于<span className="ml2 color-grey-6">{item.created_at}</span></span>}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import './branch.css';
|
||||||
import { getBranch , getTag } from '../GetData/getData';
|
import { getBranch , getTag } from '../GetData/getData';
|
||||||
|
|
||||||
|
|
||||||
export default (({ projectsId , branch , owner , changeBranch , branchList , tagflag = true })=>{
|
export default (({ projectsId , repo_id , changeBranch , branch , owner })=>{
|
||||||
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,7 +17,6 @@ export default (({ projectsId , branch , owner , changeBranch , branchList , tag
|
||||||
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;
|
||||||
|
|
@ -31,12 +30,8 @@ export default (({ projectsId , branch , owner , changeBranch , branchList , tag
|
||||||
})
|
})
|
||||||
|
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
if(branchList){
|
getBranchs(projectsId,owner);
|
||||||
setData(branchList);
|
},[owner])
|
||||||
setDatas(branchList);
|
|
||||||
setIsSpin(false);
|
|
||||||
}
|
|
||||||
},[branchList])
|
|
||||||
|
|
||||||
|
|
||||||
async function getBranchs(id,owner){
|
async function getBranchs(id,owner){
|
||||||
|
|
@ -68,7 +63,7 @@ export default (({ projectsId , branch , owner , changeBranch , branchList , tag
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function chooseitem(value){
|
function chooseitem(value){
|
||||||
// setShowValue(value);
|
setShowValue(value);
|
||||||
changeBranch(value);
|
changeBranch(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -82,8 +77,8 @@ export default (({ projectsId , branch , owner , changeBranch , branchList , tag
|
||||||
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>
|
||||||
{ tagflag && <li className={nav === 1?"navli active":"navli"} onClick={()=>changeNav(1)}><i className="iconfont icon-biaoqian3 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>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<Spin spinning={isSpin}>
|
<Spin spinning={isSpin}>
|
||||||
|
|
@ -102,10 +97,9 @@ export default (({ projectsId , branch , owner , changeBranch , branchList , tag
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
return(
|
return(
|
||||||
<Popover placement='bottomLeft' visible={flag} content={menu} onClick={()=>setFlag(!flag)} overlayClassName="branch-tagBox-list">
|
<Popover placement="bottom" visible={flag} content={menu} onClick={()=>setFlag(!flag)} overlayClassName="branch-tagBox-list">
|
||||||
<div className="branch-tagBox">
|
<div className="branch-tagBox">
|
||||||
{/* {nav === 0 ?"分支":"标签"} */}
|
<span className="color-grey-9 mr3 ml8">{nav === 0 ?"分支":"标签"}:</span>
|
||||||
<span className="color-grey-9 mr3 ml8"><i className="iconfont icon-fenzhi2 font-18"></i></span>
|
|
||||||
<a className="ant-dropdown-link">
|
<a className="ant-dropdown-link">
|
||||||
{showValue}
|
{showValue}
|
||||||
</a>
|
</a>
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
min-width: 140px;
|
min-width: 240px;
|
||||||
}
|
}
|
||||||
.branch-tagBox-list .ant-popover-arrow{
|
.branch-tagBox-list .ant-popover-arrow{
|
||||||
display: none;
|
display: none;
|
||||||
|
|
|
||||||
|
|
@ -1,83 +0,0 @@
|
||||||
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;
|
|
||||||
|
|
@ -1,95 +0,0 @@
|
||||||
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,23 +1,19 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { getImageUrl } from 'educoder';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import './Component.scss';
|
import './Component.scss';
|
||||||
|
|
||||||
function Cards({img , title, desc , rightBtn , src , bottomInfos}){
|
export default (({img , title, desc , rightBtn})=>{
|
||||||
return(
|
return(
|
||||||
<div className="cards">
|
<div className="cards">
|
||||||
{img &&<div className="img"><img src={getImageUrl(`/${img}`)} alt=""/></div>}
|
<div className="img"><img src={img} alt=""/></div>
|
||||||
<div className="content">
|
<div className="content">
|
||||||
<p className="titles">
|
<p className="titles">
|
||||||
<Link to={src}>{title}</Link>
|
<span>{title}</span>
|
||||||
{rightBtn}
|
{rightBtn}
|
||||||
</p>
|
</p>
|
||||||
<div className="desc">
|
<div className="desc">
|
||||||
{desc}
|
{desc}
|
||||||
</div>
|
</div>
|
||||||
{bottomInfos}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
})
|
||||||
export default Cards;
|
|
||||||
|
|
@ -19,8 +19,6 @@ 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;
|
||||||
|
|
@ -29,10 +27,8 @@ 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{
|
||||||
|
|
@ -43,9 +39,7 @@ 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;
|
||||||
height: 22px;
|
&>span{
|
||||||
line-height: 22px;;
|
|
||||||
&>a{
|
|
||||||
font-size:18px ;
|
font-size:18px ;
|
||||||
color: #333;
|
color: #333;
|
||||||
}
|
}
|
||||||
|
|
@ -56,13 +50,11 @@ 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;
|
||||||
|
|
@ -112,9 +104,6 @@ li.ant-menu-item{
|
||||||
right:240px;
|
right:240px;
|
||||||
z-index: 10000;
|
z-index: 10000;
|
||||||
}
|
}
|
||||||
.laterest{
|
|
||||||
color: #05690d;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (max-width: 1800px){
|
@media screen and (max-width: 1800px){
|
||||||
.handleBox{
|
.handleBox{
|
||||||
|
|
@ -140,56 +129,4 @@ li.ant-menu-item{
|
||||||
.handleBox{
|
.handleBox{
|
||||||
right:0px;
|
right:0px;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
.ant-drawer{
|
|
||||||
z-index: 10000!important;
|
|
||||||
}
|
|
||||||
.ant-drawer-body{
|
|
||||||
padding:0px!important;
|
|
||||||
.drawerHead{
|
|
||||||
background-color: #333;
|
|
||||||
color: #fff;
|
|
||||||
padding:15px 20px;
|
|
||||||
}
|
|
||||||
.ant-tree{
|
|
||||||
margin:0px 20px!important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.menuPanels{
|
|
||||||
width: 240px;
|
|
||||||
height: 180px;
|
|
||||||
.ant-popover-content,.ant-popover-inner{
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.halfs{
|
|
||||||
margin-top: 24px;
|
|
||||||
padding:24px 0px 0px 0px;
|
|
||||||
border-top: 1px solid #e8e8e8;
|
|
||||||
.attrPerson{
|
|
||||||
padding-bottom: 24px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.menuinfos{
|
|
||||||
padding:15px 0px;
|
|
||||||
&>a{
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
border-right: 1px solid #eee;
|
|
||||||
flex: 1;
|
|
||||||
& >span:first-child{
|
|
||||||
font-size: 18px;
|
|
||||||
font-weight: 400;
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
& >span:last-child{
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
&:last-child{
|
|
||||||
border-right: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,160 +0,0 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
|
||||||
import { AlignCenter , FlexAJ } from '../Component/layout';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import { Popover , Spin } from 'antd';
|
|
||||||
import { getImageUrl } from 'educoder';
|
|
||||||
import './Component.scss';
|
|
||||||
import { getUser } from '../GetData/getData';
|
|
||||||
import axios from 'axios';
|
|
||||||
|
|
||||||
function Contributors({contributors,owner,projectsId}){
|
|
||||||
const [ menuList ,setMenuList ]= useState([]);
|
|
||||||
const [ list , setList ]= useState(undefined);
|
|
||||||
const [ total , setTotal ]= useState(0);
|
|
||||||
const [ menu , setMenu ] = useState("");
|
|
||||||
const [ login , setLogin ] = useState(undefined);
|
|
||||||
const [ isSpin , setIsSpin ] = useState(false);
|
|
||||||
|
|
||||||
useEffect(()=>{
|
|
||||||
if(contributors && contributors.total_count>0){
|
|
||||||
setTotal(contributors.total_count);
|
|
||||||
setList(contributors.list);
|
|
||||||
}
|
|
||||||
},[contributors])
|
|
||||||
|
|
||||||
useEffect(()=>{
|
|
||||||
if(login){
|
|
||||||
getUsers(login);
|
|
||||||
}else{
|
|
||||||
setMenu(undefined);
|
|
||||||
}
|
|
||||||
},[login])
|
|
||||||
|
|
||||||
async function getUsers(login){
|
|
||||||
setIsSpin(true);
|
|
||||||
let a = menuList && menuList.filter(i=>i.login === login);
|
|
||||||
if(a.length === 0){
|
|
||||||
let result = await getUser(login);
|
|
||||||
let arr = menuList;
|
|
||||||
arr.push({...result});
|
|
||||||
setMenuList(arr);
|
|
||||||
setMenusFunc(result);
|
|
||||||
setIsSpin(false);
|
|
||||||
}else{
|
|
||||||
setMenusFunc(a[0]);
|
|
||||||
setIsSpin(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function setMenusFunc(data){
|
|
||||||
if(data){
|
|
||||||
let ele = (
|
|
||||||
<Spin spinning={isSpin}>
|
|
||||||
<FlexAJ>
|
|
||||||
<AlignCenter>
|
|
||||||
<Link to={`/users/${data.login}`}><img src={getImageUrl(`/${data.image_url}`)} alt="" className="radius" width="38px" height="38px"/></Link>
|
|
||||||
<Link to={`/users/${data.login}`} className="ml10">{data.name}</Link>
|
|
||||||
</AlignCenter>
|
|
||||||
{
|
|
||||||
data.is_watch ? <a className="color-grey-9" onClick={()=>FocusFunc(false,data.login)}>取消关注</a>:<a className="color-blue" onClick={()=>FocusFunc(true,data.login)}>关注</a>
|
|
||||||
}
|
|
||||||
</FlexAJ>
|
|
||||||
<AlignCenter className="menuinfos">
|
|
||||||
<a href={data.projects_url}>
|
|
||||||
<span>{data.projects_count}</span>
|
|
||||||
<span>项目数</span>
|
|
||||||
</a>
|
|
||||||
<a href={data.followers_url}>
|
|
||||||
<span>{data.followers_count}</span>
|
|
||||||
<span>粉丝数</span>
|
|
||||||
</a>
|
|
||||||
<a href={data.following_url}>
|
|
||||||
<span>{data.following_count}</span>
|
|
||||||
<span>关注数</span>
|
|
||||||
</a>
|
|
||||||
</AlignCenter>
|
|
||||||
{
|
|
||||||
data.organizations && data.organizations.length > 0 ?
|
|
||||||
<AlignCenter className="font-12 pt4 pb4">
|
|
||||||
<span>所属组织:</span>
|
|
||||||
<div className="task-hide flex1">
|
|
||||||
{renderArray(data.organizations)}
|
|
||||||
</div>
|
|
||||||
</AlignCenter>
|
|
||||||
:""
|
|
||||||
}
|
|
||||||
{
|
|
||||||
data.location && <AlignCenter className="font-12 pt4 pb4"><span>所在地址:</span><span className="ml5">{data.location}</span></AlignCenter>
|
|
||||||
}
|
|
||||||
</Spin>
|
|
||||||
)
|
|
||||||
setMenu(ele);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function FocusFunc(flag,login){
|
|
||||||
axios({
|
|
||||||
method: flag ? 'post' : 'delete',
|
|
||||||
url: `/watchers/${flag ? 'follow' : 'unfollow'}.json`,
|
|
||||||
params: {target_type: "user",id:login}
|
|
||||||
}).then(result => {
|
|
||||||
if (result && (result.data.status === 0 || result.data.status === 2)) {
|
|
||||||
let a = menuList && menuList.filter(i=>i.login === login);
|
|
||||||
if(a){
|
|
||||||
a[0].is_watch = flag;
|
|
||||||
}
|
|
||||||
setMenusFunc(a[0]);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderArray(array){
|
|
||||||
let str = "";
|
|
||||||
for(var i = 0;i<array.length;i++){
|
|
||||||
str += array[i].name +"、";
|
|
||||||
}
|
|
||||||
let substr = str.substr(0,str.length-1);
|
|
||||||
return (<span title={substr}>{substr}</span>)
|
|
||||||
}
|
|
||||||
|
|
||||||
function setVisibleFunc(flag,l,index){
|
|
||||||
if(l !== login){
|
|
||||||
setLogin(l);
|
|
||||||
}
|
|
||||||
var lx = list.concat();
|
|
||||||
lx.map(i=>i.visible =false);
|
|
||||||
if(flag){
|
|
||||||
lx[index].visible = flag;
|
|
||||||
}
|
|
||||||
lx.splice();
|
|
||||||
setList(lx);
|
|
||||||
}
|
|
||||||
|
|
||||||
return(
|
|
||||||
<div className="halfs">
|
|
||||||
<FlexAJ>
|
|
||||||
<AlignCenter><span className="font-16 color-grey-6">贡献者</span>{ contributors && contributors.total_count > 0 && <span className="infoCount">{contributors.total_count}</span>}</AlignCenter>
|
|
||||||
<Link className="font-12 color-grey-9" to={`/projects/${owner}/${projectsId}/contribute`}>全部</Link>
|
|
||||||
</FlexAJ>
|
|
||||||
<div className="attrPerson" onMouseLeave={()=>setVisibleFunc(false)}>
|
|
||||||
{
|
|
||||||
total > 0 ?
|
|
||||||
list.map((item,key)=>{
|
|
||||||
return(
|
|
||||||
<Popover content={menu} visible={item.visible} overlayClassName="menuPanels" placement="top">
|
|
||||||
<Link key={key} to={`/users/${item.login}`}>
|
|
||||||
<img src={getImageUrl(`/${item.image_url}`)} alt="" onMouseOver={()=>setVisibleFunc(true,item.login,key)}/>
|
|
||||||
</Link>
|
|
||||||
</Popover>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
:""
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export default Contributors;
|
|
||||||
|
|
@ -1,99 +0,0 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
|
||||||
import { Drawer , Tree , Spin } from 'antd';
|
|
||||||
import './Component.scss';
|
|
||||||
import axios from 'axios';
|
|
||||||
const { TreeNode , DirectoryTree } = Tree;
|
|
||||||
|
|
||||||
function DrawerPanel({visible,onClose,branch,owner,projectsId,history, name , list}){
|
|
||||||
const [ treeData , setTreeData ] = useState(undefined);
|
|
||||||
const [ isSpin , setIsSpin ] = useState(true);
|
|
||||||
const [first , setFirst ] = useState(true);
|
|
||||||
useEffect(()=>{
|
|
||||||
if(visible && first){
|
|
||||||
if(list){
|
|
||||||
setTreeData(list);
|
|
||||||
setIsSpin(false);
|
|
||||||
}else{
|
|
||||||
getMenulist();
|
|
||||||
}
|
|
||||||
setFirst(false);
|
|
||||||
}
|
|
||||||
},[visible])
|
|
||||||
|
|
||||||
function getMenulist(){
|
|
||||||
const url = `/${owner}/${projectsId}/entries.json`;
|
|
||||||
axios.get(url,{ params: { ref: branch } }).then(result=>{
|
|
||||||
if(result){
|
|
||||||
setTreeData(result.data.entries);
|
|
||||||
}
|
|
||||||
setIsSpin(false);
|
|
||||||
}).catch(error=>{})
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderTreeNodes(data) {
|
|
||||||
return data && data.length > 0 && data.map((item) => {
|
|
||||||
return (
|
|
||||||
<TreeNode title={item.name} key={item.key} dataRef={item} isLeaf={item.type === "file"}>
|
|
||||||
{renderTreeNodes(item.children)}
|
|
||||||
</TreeNode>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function onLoadData(tr){
|
|
||||||
return new Promise((resolve) => {
|
|
||||||
if (tr.props.children) {
|
|
||||||
resolve();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let en = [];
|
|
||||||
const url = `/${owner}/${projectsId}/sub_entries.json`;
|
|
||||||
axios.get(url, {
|
|
||||||
params:{
|
|
||||||
filepath:tr.props.dataRef.path,
|
|
||||||
ref:branch,
|
|
||||||
type:"dir"
|
|
||||||
}
|
|
||||||
}).then((result) => {
|
|
||||||
if(result){
|
|
||||||
en = result.data.entries;
|
|
||||||
}
|
|
||||||
}).catch(error=>{})
|
|
||||||
setTimeout(() => {
|
|
||||||
tr.props.dataRef.children = en;
|
|
||||||
setTreeData([...treeData]);
|
|
||||||
resolve();
|
|
||||||
}, 2000);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function selectTree(keys,event){
|
|
||||||
let dataref = event.node.props.dataRef;
|
|
||||||
if(dataref.type==="file"){
|
|
||||||
onClose();
|
|
||||||
history.push(`/projects/${owner}/${projectsId}/tree/${branch}/${dataref.path}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return(
|
|
||||||
<Drawer
|
|
||||||
placement="left"
|
|
||||||
visible={visible}
|
|
||||||
closable={false}
|
|
||||||
onClose={onClose}
|
|
||||||
width={"320px"}
|
|
||||||
maskStyle={{backgroundColor:'rgba(0,0,0,0.09)'}}
|
|
||||||
>
|
|
||||||
<Spin spinning={isSpin}>
|
|
||||||
<div className="drawerHead">
|
|
||||||
<p className="font-20">{name}</p>
|
|
||||||
<p><i class="iconfont icon-fenzhi2 font-18 color-grey-9 mr3"></i>{branch}</p>
|
|
||||||
</div>
|
|
||||||
<DirectoryTree loadData={onLoadData} onSelect={selectTree}>
|
|
||||||
{treeData && renderTreeNodes(treeData)}
|
|
||||||
</DirectoryTree>
|
|
||||||
</Spin>
|
|
||||||
</Drawer>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export default DrawerPanel;
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
.ant-modal-mask{
|
|
||||||
z-index: 1001;
|
|
||||||
}
|
|
||||||
.ant-modal-wrap{
|
|
||||||
z-index: 1002;
|
|
||||||
.ant-form-explain{
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,60 +0,0 @@
|
||||||
import React , {forwardRef, useEffect} from 'react';
|
|
||||||
import { Modal , Form , Input , Button } from 'antd';
|
|
||||||
import './EAccount.scss';
|
|
||||||
|
|
||||||
function EducoderAccount({form , visible , onOk , email}){
|
|
||||||
const { getFieldDecorator, validateFields , setFieldsValue } = form;
|
|
||||||
|
|
||||||
useEffect(()=>{
|
|
||||||
if(email){
|
|
||||||
setFieldsValue({email})
|
|
||||||
}
|
|
||||||
},[email])
|
|
||||||
|
|
||||||
function onSure(){
|
|
||||||
validateFields((error,values)=>{
|
|
||||||
if(!error){
|
|
||||||
onOk(values);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
const layout = {
|
|
||||||
labelCol: { span: 5 },
|
|
||||||
wrapperCol: { span: 18 },
|
|
||||||
};
|
|
||||||
return(
|
|
||||||
<Modal
|
|
||||||
visible={visible}
|
|
||||||
title="提示"
|
|
||||||
width="500px"
|
|
||||||
closable={false}
|
|
||||||
footer={
|
|
||||||
<Button type="primary" onClick={onSure}>确定</Button>
|
|
||||||
}
|
|
||||||
centered
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<p className="mb15 edu-txt-center" style={{maxWidth:"350px",margin:"0px auto"}}>
|
|
||||||
为确保您能正常使用平台功能,请确认以下信息:
|
|
||||||
</p>
|
|
||||||
<Form {...layout}>
|
|
||||||
<Form.Item label="邮箱">
|
|
||||||
{getFieldDecorator("email",{
|
|
||||||
rules:[{required:true,message:"请输入邮箱账号"}]
|
|
||||||
})(
|
|
||||||
<Input placeholder="请输入您的邮箱账号" width="220px"/>
|
|
||||||
)}
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="密码">
|
|
||||||
{getFieldDecorator("password",{
|
|
||||||
rules:[{required:true,message:"请输入邮箱密码"}]
|
|
||||||
})(
|
|
||||||
<Input.Password placeholder="请输入您的邮箱密码" width="220px"/>
|
|
||||||
)}
|
|
||||||
</Form.Item>
|
|
||||||
</Form>
|
|
||||||
</div>
|
|
||||||
</Modal>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export default Form.create()(forwardRef(EducoderAccount));
|
|
||||||
|
|
@ -5,7 +5,7 @@ import './Component.scss';
|
||||||
export default (()=>{
|
export default (()=>{
|
||||||
return(
|
return(
|
||||||
<div className="handleBox">
|
<div className="handleBox">
|
||||||
<a href="https://forum.trustie.net/forums/3075/detail" target="_blank" >
|
<a href="https://www.trustie.net/forums/82/memos/3075" target="_blank" >
|
||||||
<img src={Handbook} alt=""/>
|
<img src={Handbook} alt=""/>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
|
||||||
import { FlexAJ } from '../Component/layout';
|
|
||||||
|
|
||||||
function LanguagePower({languages}){
|
|
||||||
const [ array , setArray ] = useState(undefined);
|
|
||||||
|
|
||||||
useEffect(()=>{
|
|
||||||
if(languages){
|
|
||||||
let arr = [];
|
|
||||||
Object.keys(languages).map((item,key)=>{
|
|
||||||
arr.push({name:item,percent:languages[item],color:getColor()});
|
|
||||||
})
|
|
||||||
setArray(arr);
|
|
||||||
}
|
|
||||||
},[languages])
|
|
||||||
|
|
||||||
function getColor(){
|
|
||||||
let str = "#";
|
|
||||||
let arr = ["1","2","3","4","4","5","6","7","8","9","a","b","c","d","e","f"];
|
|
||||||
for(var i=0;i<6;i++){
|
|
||||||
let num = parseInt(Math.random() * 16);
|
|
||||||
str+=arr[num];
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
return(
|
|
||||||
<div>
|
|
||||||
<p className="font-16 color-grey-6">开发语言</p>
|
|
||||||
<div className="progress">
|
|
||||||
{
|
|
||||||
array && array.map((item,key)=>{
|
|
||||||
return(
|
|
||||||
<span style={{width:item.percent,backgroundColor:item.color}}></span>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
{
|
|
||||||
array && array.length > 0 &&
|
|
||||||
<FlexAJ className="progresstip">
|
|
||||||
{
|
|
||||||
array.map((item,key)=>{
|
|
||||||
return(
|
|
||||||
<span><i className="zero" style={{backgroundColor:`${item.color}`}}></i><span>{item.name}</span><span>{item.percent}</span></span>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</FlexAJ>
|
|
||||||
}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export default LanguagePower;
|
|
||||||
|
|
@ -19,7 +19,7 @@ export default (({fork,parise})=>{
|
||||||
}`;
|
}`;
|
||||||
const SpanStyleparise = styled.span`{
|
const SpanStyleparise = styled.span`{
|
||||||
display:flex;
|
display:flex;
|
||||||
align-items:center;
|
align-item:center;
|
||||||
margin-left:30px;
|
margin-left:30px;
|
||||||
padding:0px 12px;
|
padding:0px 12px;
|
||||||
border-radius:13px;
|
border-radius:13px;
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,6 @@
|
||||||
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%;
|
||||||
|
|
@ -32,8 +28,26 @@ const I = styled.i`{
|
||||||
font-size:13px!important;
|
font-size:13px!important;
|
||||||
color:#60B25E;
|
color:#60B25E;
|
||||||
margin-right:2px;
|
margin-right:2px;
|
||||||
height:17px;
|
}`
|
||||||
line-height:17px;
|
const FocusBtn = styled.a`{
|
||||||
|
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;
|
||||||
|
|
@ -42,18 +56,17 @@ const Div = styled.div`{
|
||||||
align-items: center;
|
align-items: center;
|
||||||
border:1px solid #eee;
|
border:1px solid #eee;
|
||||||
}`
|
}`
|
||||||
export default (({ user , img, name, time, focusStatus, is_current_user, login , successFunc }) => {
|
export default (({img,name,time, focusStatus})=>{
|
||||||
return (
|
return(
|
||||||
<Div>
|
<Div>
|
||||||
<Link to={`/users/${user && user.login}`}><Img src={getImageUrl(`/${img}`)} /></Link>
|
<Img src={img}/>
|
||||||
<div className="m-infos">
|
<div className="m-infos">
|
||||||
<Link to={`/users/${user && user.login}`}><Name>{name}</Name></Link>
|
<Name>{name}</Name>
|
||||||
<Time><I className="iconfont icon-shijian"></I>加入时间:{time}</Time>
|
<Time><I className="iconfont icon-shijian"></I>加入时间:{time}</Time>
|
||||||
{
|
{
|
||||||
is_current_user ?
|
focusStatus ?
|
||||||
<Button type="default">当前用户</Button>
|
<FocusBtn><Ifocused className="iconfont icon-shixing"></Ifocused>已关注</FocusBtn> :
|
||||||
:
|
<FocusBtn><Ifocus className="iconfont icon-kongxing"></Ifocus>关注</FocusBtn>
|
||||||
<FocusButton is_watch={focusStatus} id={login} successFunc={successFunc}/>
|
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</Div>
|
</Div>
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ function PasswordAuthority({ authorityValBox , successFunc , cancelFunc }){
|
||||||
|
|
||||||
// 取消授权-登录密码的输入
|
// 取消授权-登录密码的输入
|
||||||
function cancelAuthority(){
|
function cancelAuthority(){
|
||||||
setAuthorityVal(undefined);
|
|
||||||
cancelFunc();
|
cancelFunc();
|
||||||
}
|
}
|
||||||
// 确认授权
|
// 确认授权
|
||||||
|
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { AlignCenter , AlignTop , FlexAJ } from '../Component/layout';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
|
|
||||||
function Releases({owner,projectsId,releaseVersions}){
|
|
||||||
|
|
||||||
return(
|
|
||||||
<div>
|
|
||||||
<FlexAJ>
|
|
||||||
<AlignCenter><span className="font-16 color-grey-6">发行版</span>
|
|
||||||
{ releaseVersions && releaseVersions.total_count > 0 && <span className="infoCount">{releaseVersions.total_count}</span>}
|
|
||||||
</AlignCenter>
|
|
||||||
{ releaseVersions && releaseVersions.total_count > 0 ?
|
|
||||||
<Link className="font-12 color-grey-9" to={`/projects/${owner}/${projectsId}/releases`}>全部</Link>
|
|
||||||
:
|
|
||||||
<Link className="font-12 color-blue" to={`/projects/${owner}/${projectsId}/releases/new`}>新建</Link>
|
|
||||||
}
|
|
||||||
</FlexAJ>
|
|
||||||
{
|
|
||||||
releaseVersions && releaseVersions.total_count>0 ?
|
|
||||||
releaseVersions.list.map((item,key)=>{
|
|
||||||
return(
|
|
||||||
key === 0 &&<AlignTop className="mt10">
|
|
||||||
<i className="iconfont icon-biaoqian3 color-grey-6 font-18 mr10"></i>
|
|
||||||
<div>
|
|
||||||
<p className="font-16 color-grey-6">
|
|
||||||
<Link to={`/projects/${owner}/${projectsId}/releases`}>{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,15 +2,13 @@ import React from "react";
|
||||||
import { Input } from "antd";
|
import { Input } from "antd";
|
||||||
|
|
||||||
const { Search } = Input;
|
const { Search } = Input;
|
||||||
export default ({ placeholder , onSearch , onChange }) => {
|
export default ({ placeholder , onSearch }) => {
|
||||||
return (
|
return (
|
||||||
<Search
|
<Search
|
||||||
allowClear
|
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
enterButton={'搜索'}
|
enterButton={'搜索'}
|
||||||
onSearch={onSearch}
|
onSearch={onSearch}
|
||||||
width="300px"
|
width="300px"
|
||||||
onChange={onChange}
|
|
||||||
></Search>
|
></Search>
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,53 +2,52 @@ 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 , placeholder, width ,value })=>{
|
export default ({ getUser })=>{
|
||||||
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: searchKey,
|
search: e,
|
||||||
},
|
},
|
||||||
}).then((result) => {
|
})
|
||||||
|
.then((result) => {
|
||||||
if (result) {
|
if (result) {
|
||||||
sourceOptions(result.data.users);
|
setUserDataSource(result.data.users);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function changeInputUser(value){
|
||||||
|
setSearchKey(value);
|
||||||
|
getUserList(value);
|
||||||
|
}
|
||||||
|
|
||||||
function sourceOptions(userDataSource){
|
function selectInputUser(id, option){
|
||||||
const s = userDataSource && userDataSource.map((item, key) => {
|
setSearchKey(option.props.searchValue);
|
||||||
|
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}`}
|
||||||
login={`${item.login}`}
|
searchValue={`${item.username}`}
|
||||||
name={item.username}
|
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
className="user_img radius"
|
className="user_img radius"
|
||||||
width="28"
|
width="28"
|
||||||
height="28"
|
height="28"
|
||||||
src={getImageUrl(`/${item && item.image_url}`)}
|
src={getImageUrl(`images/${item && item.image_url}`)}
|
||||||
alt=""
|
alt=""
|
||||||
/>
|
/>
|
||||||
<span className="ml10" style={{ "vertical-align": "middle" }}>
|
<span className="ml10" style={{ "vertical-align": "middle" }}>
|
||||||
|
|
@ -58,31 +57,14 @@ export default ({ getUser , placeholder, width ,value })=>{
|
||||||
</Option>
|
</Option>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
setSource(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
function changeInputUser(e){
|
|
||||||
setSearchKey(e);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 选择用户
|
|
||||||
function selectInputUser(e, option){
|
|
||||||
setSearchKey(option.props.name);
|
|
||||||
getUser(option.props.login);
|
|
||||||
};
|
|
||||||
|
|
||||||
return(
|
return(
|
||||||
<div className="addPanel">
|
<AutoComplete
|
||||||
<AutoComplete
|
dataSource={source}
|
||||||
getPopupContainer={trigger => trigger.parentNode}
|
value={searchKey}
|
||||||
dataSource={source}
|
style={{ width: 300 }}
|
||||||
value={searchKey}
|
onChange={changeInputUser}
|
||||||
style={{ width: width || 300 }}
|
onSelect={selectInputUser}
|
||||||
onChange={changeInputUser}
|
placeholder="搜索需要添加的用户..."
|
||||||
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,16 +19,8 @@ export default ({ url , name , column , id , login })=>{
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
return(
|
return(
|
||||||
id?
|
|
||||||
<Link to={`/users/${login}`}>
|
|
||||||
<Img>
|
|
||||||
{ url && <img src={url} alt=""/> }
|
|
||||||
<span>{name}</span>
|
|
||||||
</Img>
|
|
||||||
</Link>
|
|
||||||
:
|
|
||||||
<Img>
|
<Img>
|
||||||
{ url && <img src={url} alt=""/> }
|
<img src={url} alt=""/>
|
||||||
<span>{name}</span>
|
<span>{name}</span>
|
||||||
</Img>
|
</Img>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -24,33 +24,18 @@ export const AlignCenter = styled.div`{
|
||||||
display:flex;
|
display:flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}`
|
}`
|
||||||
export const AlignTop = styled.div`{
|
|
||||||
display:flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
}`
|
|
||||||
// 左右结构
|
// 左右结构
|
||||||
export const Box = styled.div`{
|
export const Box = styled.div`{
|
||||||
display:flex;
|
display:flex;
|
||||||
align-items:flex-start;
|
align-item:flex-start;
|
||||||
}`
|
|
||||||
export const LongWidth = styled.div`{
|
|
||||||
flex:1;
|
|
||||||
width:0;
|
|
||||||
border-radius:5px;
|
|
||||||
margin-bottom:30px;
|
|
||||||
}`
|
}`
|
||||||
export const Long = styled.div`{
|
export const Long = styled.div`{
|
||||||
width:78%;
|
width:72%;
|
||||||
border-radius:5px;
|
|
||||||
margin-bottom:30px;
|
|
||||||
}`
|
|
||||||
export const ShortWidth = styled.div`{
|
|
||||||
width:300px;
|
|
||||||
border-radius:5px;
|
border-radius:5px;
|
||||||
margin-bottom:30px;
|
margin-bottom:30px;
|
||||||
}`
|
}`
|
||||||
export const Short = styled.div`{
|
export const Short = styled.div`{
|
||||||
flex:1;
|
width:28%;
|
||||||
border-radius:5px;
|
border-radius:5px;
|
||||||
margin-bottom:30px;
|
margin-bottom:30px;
|
||||||
}`
|
}`
|
||||||
|
|
@ -76,24 +61,22 @@ 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:${props => (props.bold ? "#fff" : "#F73030")} !important;
|
color:#F73030;
|
||||||
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:${props => (props.bold ? "#fff" : "#28BD6C")} !important;
|
color:#28BD6C;
|
||||||
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;
|
||||||
|
|
@ -111,7 +94,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!important;
|
color:#fff;
|
||||||
padding:0px 12px;
|
padding:0px 12px;
|
||||||
display:inline-block;
|
display:inline-block;
|
||||||
min-width:80px;
|
min-width:80px;
|
||||||
|
|
@ -171,9 +154,3 @@ 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,15 +1,14 @@
|
||||||
import React, { forwardRef, useCallback, useState , useEffect } from "react";
|
import React, { forwardRef, useCallback, useState , useEffect } from "react";
|
||||||
import activate from "../Images/activate.png";
|
import activate from "../Images/activate.png";
|
||||||
import { AlignCenter, Blueback } from "../Component/layout";
|
import { Blueback , AlignCenter } from "../Component/layout";
|
||||||
import PasswordAuthority from "../Component/PasswordAuthority";
|
import PasswordAuthority from "../Component/PasswordAuthority";
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { Form, Input , Spin , Button } from "antd";
|
import { Form, Input , Spin , Modal } from "antd";
|
||||||
import ServiceModal from './ServiceModal';
|
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
|
||||||
const P = styled.p`
|
const P = styled.p`
|
||||||
{
|
{
|
||||||
width: 230px;
|
width: 200px;
|
||||||
line-height: 30px;
|
line-height: 30px;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
color: #333;
|
color: #333;
|
||||||
|
|
@ -21,23 +20,20 @@ const P = styled.p`
|
||||||
function About(props, ref) {
|
function About(props, ref) {
|
||||||
const { form: { getFieldDecorator, validateFields , setFieldsValue } } = props;
|
const { form: { getFieldDecorator, validateFields , setFieldsValue } } = props;
|
||||||
const [isSpining, setIsSpining] = useState(true);
|
const [isSpining, setIsSpining] = useState(true);
|
||||||
|
const [ authorityValBox , setAuthorityValBox ] = useState(false);
|
||||||
// 认证密码
|
|
||||||
const [ authorityVal , setAuthorityVal ] = useState(undefined);
|
const [ authorityVal , setAuthorityVal ] = useState(undefined);
|
||||||
const [ authorityValFlag , setAuthorityValFlag ] = useState(false);
|
const [ authorityValFlag , setAuthorityValFlag ] = useState(false);
|
||||||
|
|
||||||
//0: 标识未开启devops
|
//0: 标识未开启devops
|
||||||
//1: 标识用户已填写了云服务器相关信息,但并未开启认证
|
//1: 标识用户已填写了云服务器相关信息,但并未开启认证
|
||||||
const [step, setStep] = useState(0);
|
const [step, setStep] = useState(undefined);
|
||||||
|
// step大于1时:为true,不能再修改服务器信息
|
||||||
const owner = props.match.params.owner;
|
const owner = props.match.params.owner;
|
||||||
const { user } = props;
|
|
||||||
const projectsId = props.match.params.projectsId;
|
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 AuthorLogin = props.author && props.author.login;
|
||||||
const CurrentLogin = props.current_user && props.current_user.login;
|
const CurrentLogin = props.current_user && props.current_user.login;
|
||||||
|
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
if(CurrentLogin === AuthorLogin){
|
if(CurrentLogin === AuthorLogin){
|
||||||
auth('get');
|
auth('get');
|
||||||
|
|
@ -52,12 +48,12 @@ function About(props, ref) {
|
||||||
method:`${type}`,
|
method:`${type}`,
|
||||||
url
|
url
|
||||||
}).then(result=>{
|
}).then(result=>{
|
||||||
setIsSpining(false);
|
|
||||||
if(result && result.data ){
|
if(result && result.data ){
|
||||||
|
setIsSpining(false);
|
||||||
setStep(result.data.step);
|
setStep(result.data.step);
|
||||||
|
setFieldsValue({...result.data.cloud_account});
|
||||||
}
|
}
|
||||||
}).catch(error=>{
|
}).catch(error=>{
|
||||||
setIsSpining(false);
|
|
||||||
console.log(error);
|
console.log(error);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -77,8 +73,8 @@ function About(props, ref) {
|
||||||
function goStep() {
|
function goStep() {
|
||||||
validateFields((error, values) => {
|
validateFields((error, values) => {
|
||||||
if (!error) {
|
if (!error) {
|
||||||
if(disabled){
|
if(step > 0){
|
||||||
setStep(1);
|
setAuthorityValBox(true);
|
||||||
}else{
|
}else{
|
||||||
setIsSpining(true);
|
setIsSpining(true);
|
||||||
const url = `/${owner}/${projectsId}/cloud_accounts.json`;
|
const url = `/${owner}/${projectsId}/cloud_accounts.json`;
|
||||||
|
|
@ -87,6 +83,7 @@ function About(props, ref) {
|
||||||
if (result && result.data.redirect_url) {
|
if (result && result.data.redirect_url) {
|
||||||
props.showNotification("服务器信息配置完成!");
|
props.showNotification("服务器信息配置完成!");
|
||||||
setStep(1);
|
setStep(1);
|
||||||
|
setAuthorityValBox(true);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
|
|
@ -98,50 +95,6 @@ function About(props, ref) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 选择服务器后调用接口,点击下一步(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(){
|
function startActive(){
|
||||||
setIsSpining(true);
|
setIsSpining(true);
|
||||||
|
|
@ -159,89 +112,66 @@ function About(props, ref) {
|
||||||
setIsSpining(false);
|
setIsSpining(false);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
// 取消授权-登录密码的输入
|
||||||
|
function cancelAuthority(){
|
||||||
|
setAuthorityValBox(false);
|
||||||
|
}
|
||||||
|
// 确认授权
|
||||||
|
function okAuthority(step){
|
||||||
|
setAuthorityValBox(false);
|
||||||
|
setStep(step);
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<Spin spinning={isSpining}>
|
<Spin spinning={isSpining}>
|
||||||
{/* <PasswordAuthority authorityValBox={authorityValBox} successFunc={okAuthority} cancelFunc={cancelAuthority}></PasswordAuthority> */}
|
<PasswordAuthority authorityValBox={authorityValBox} successFunc={okAuthority} cancelFunc={cancelAuthority}></PasswordAuthority>
|
||||||
<div className="activatePanel">
|
<div className="activatePanel">
|
||||||
<img src={activate} alt="" width="250px" />
|
<img src={activate} alt="" width="250px" />
|
||||||
<P>定义DevOps工作流,帮助您检测bug、发布代码…</P>
|
<P>定义DevOps工作流,帮助您检测bug、发布代码…</P>
|
||||||
{
|
|
||||||
CurrentLogin !== AuthorLogin ?
|
|
||||||
<div className="noOperation">DevOps开启功能暂未对项目创建者以外的角色开放,可以联系项目创建者进行开启,开启后便可查看构建信息。</div>:""
|
|
||||||
}
|
|
||||||
<a href={"https://forum.trustie.net/forums/3110/detail"} target="_blank" style={{ color: "#5091FF"}}>
|
|
||||||
了解什么是DevOps?
|
|
||||||
</a>
|
|
||||||
<a href={"https://forum.trustie.net/forums/3080/detail"} target="_blank" style={{ color: "#5091FF"}}>
|
<a href={"https://forum.trustie.net/forums/3080/detail"} target="_blank" style={{ color: "#5091FF"}}>
|
||||||
如何使用DevOps?
|
了解什么是DevOps?
|
||||||
</a>
|
</a>
|
||||||
{
|
{
|
||||||
AuthorLogin === CurrentLogin ?
|
AuthorLogin === CurrentLogin ?
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
{
|
{ step <=1 ?
|
||||||
step === 0 && !typeFlag ?
|
<React.Fragment>
|
||||||
<ServiceModal sureModal={sureModal}></ServiceModal>
|
<Input.Password style={{display:'none'}} size="large" />
|
||||||
:""
|
<Form style={{marginTop:"20px"}}>
|
||||||
}
|
<p className="mb20" style={{width:"370px"}}>请仔细核对您的服务器信息,一旦确认提交将无法修改</p>
|
||||||
{ step === 0 && typeFlag ?
|
{helper(
|
||||||
<React.Fragment>
|
"服务器IP地址:",
|
||||||
<Input.Password style={{display:'none'}} size="large" />
|
"ip",
|
||||||
<Form style={{marginTop:"20px"}}>
|
[{ required: true, message: "请输入服务器IP地址" }],
|
||||||
<p className="mb20" style={{width:"370px"}}>请仔细核对您的服务器信息,一旦确认提交将无法修改</p>
|
<Input
|
||||||
{helper(
|
placeholder="请输入服务器IP地址"
|
||||||
"服务器IP地址:",
|
style={{ width: "368px" }}
|
||||||
"ip",
|
size="large"
|
||||||
[{ required: true, message: "请输入服务器IP地址" }],
|
disabled={step > 0}
|
||||||
<Input
|
/>,
|
||||||
placeholder="请输入服务器IP地址"
|
true
|
||||||
style={{ width: "368px" }}
|
)}
|
||||||
size="large"
|
{helper(
|
||||||
disabled={disabled}
|
"服务器用户名:",
|
||||||
/>,
|
"account",
|
||||||
true
|
[{ required: true, message: "请输入服务器用户名" }],
|
||||||
)}
|
<Input placeholder="请输入服务器用户名" size="large" disabled={step > 0}/>,
|
||||||
{helper(
|
true
|
||||||
"服务器用户名:",
|
)}
|
||||||
"account",
|
{helper(
|
||||||
[{ required: true, message: "请输入服务器用户名" }],
|
"服务器密码:",
|
||||||
<Input placeholder="请输入服务器用户名" size="large" disabled={disabled}/>,
|
"secret",
|
||||||
true
|
[{ required: true, message: "请输入服务器密码" }],
|
||||||
)}
|
<Input.Password placeholder="请输入服务器密码" size="large" disabled={step > 0}/>,
|
||||||
{helper(
|
true
|
||||||
"服务器密码:",
|
)}
|
||||||
"secret",
|
</Form>
|
||||||
[{ required: true, message: "请输入服务器密码" }],
|
<Blueback onClick={goStep}>下一步</Blueback>
|
||||||
<Input.Password placeholder="请输入服务器密码" size="large" disabled={disabled}/>,
|
</React.Fragment>
|
||||||
true
|
:""}
|
||||||
)}
|
{step > 1 &&
|
||||||
</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"}}>
|
<div style={{textAlign:'center',marginTop:"20px"}}>
|
||||||
<Blueback onClick={startActive} className="mt20">开始激活</Blueback>
|
<Blueback onClick={startActive} className="mt20">开始激活</Blueback>
|
||||||
</div>:""
|
</div>
|
||||||
}
|
}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
:""
|
:""
|
||||||
|
|
|
||||||
|
|
@ -1,166 +1,117 @@
|
||||||
import React , { useState , useEffect } from 'react';
|
import React , { useState , useEffect } from 'react';
|
||||||
import { Spin , Pagination } from 'antd';
|
import { Spin } from 'antd';
|
||||||
import { Blueback } from '../Component/layout';
|
import { Blueback } from '../Component/layout';
|
||||||
import List from './Dispose/List';
|
import Editor from "react-monaco-editor";
|
||||||
import Head from './Dispose/head';
|
import Modals from './DisposeModal';
|
||||||
|
import FileLanguage from '../Component/OpsFileLanguage';
|
||||||
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 [ spining , setSpining ] = useState(true);
|
const [ spining , setSpining ] = useState(true);
|
||||||
const [ updateInfo , setUpdateInfo ] = useState(undefined);
|
const [ info , setInfo ] = useState('.trustie-pipeline.yml');
|
||||||
const [ list , setList ] = useState(undefined);
|
|
||||||
const [ permission , setPermission ] = useState(undefined);
|
|
||||||
const [ visible , setVisible ] = useState(false);
|
const [ visible , setVisible ] = useState(false);
|
||||||
const [ page , setPage ] = useState(1);
|
const [ ymlValue , setYmlValue ] = useState("");
|
||||||
const [ totalCount , setTotalCount ] = useState(0);
|
const [ sha , setSha ] = useState(undefined);
|
||||||
const [ branchList , setBranchList ] =useState(undefined);
|
const [ fileLanguage , setFileLanguage ] = 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(projectDetail){
|
if(projectsId){
|
||||||
setPermission(props.projectDetail.permission);
|
const url = `/${owner}/${projectsId}/get_trustie_pipeline.json`;
|
||||||
}
|
axios.get(url,{
|
||||||
},[projectDetail])
|
params:{
|
||||||
|
project_id:projectsId
|
||||||
function Init(){
|
|
||||||
const url = `/ci/pipelines/list.json`;
|
|
||||||
axios.get(url,{
|
|
||||||
params:{
|
|
||||||
identifier:projectsId,owner,
|
|
||||||
page,limit
|
|
||||||
}
|
|
||||||
}).then(result=>{
|
|
||||||
if(result && result.data){
|
|
||||||
setList(result.data.pipelines);
|
|
||||||
}
|
|
||||||
setSpining(false);
|
|
||||||
}).catch(error=>{setSpining(false);})
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(()=>{
|
|
||||||
Init();
|
|
||||||
},[page])
|
|
||||||
|
|
||||||
useEffect(()=>{
|
|
||||||
if(owner && projectsId){
|
|
||||||
const url = `/${owner}/${projectsId}/branches.json`;
|
|
||||||
axios.get(url).then(result=>{
|
|
||||||
if(result && result.data){
|
|
||||||
setBranchList(result.data);
|
|
||||||
}
|
}
|
||||||
}).catch(error=>{})
|
}).then(result=>{
|
||||||
|
if(result && result.data.content){
|
||||||
|
setInfo(result.data.name);
|
||||||
|
setYmlValue(result.data.content);
|
||||||
|
setFirst(true);
|
||||||
|
setSha(result.data.sha);
|
||||||
|
}else{
|
||||||
|
setFirst(false);
|
||||||
|
}
|
||||||
|
setSpining(false);
|
||||||
|
}).catch(error=>{
|
||||||
|
console.log(error);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},[owner,projectsId])
|
},[projectsId])
|
||||||
|
|
||||||
// 新增/编辑流水线
|
// 修改文件内容
|
||||||
function addNew(pipeline_name,id,branch,event){
|
function changeEditor(value){
|
||||||
setVisible(true);
|
setYmlValue(value);
|
||||||
setUpdateInfo(undefined);
|
}
|
||||||
if(pipeline_name){
|
|
||||||
let eventA = event.split(",");
|
// 切换语言
|
||||||
let l = {pipeline_name,id,branch,event:eventA}
|
function select_language(value,array){
|
||||||
setUpdateInfo(l);
|
setFileLanguage(value);
|
||||||
|
setYmlValue( array && array.content);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确定提交
|
||||||
|
function submit(){
|
||||||
|
let url = '';
|
||||||
|
let params = {
|
||||||
|
branch: "master",
|
||||||
|
content:ymlValue,
|
||||||
|
filepath:info,
|
||||||
|
message:''
|
||||||
|
}
|
||||||
|
if(first){
|
||||||
|
// 为true,则是编辑否则是新建
|
||||||
|
url = `/${owner}/${projectsId}/update_trustie_pipeline.json`;
|
||||||
|
axios.put(url,{
|
||||||
|
...params,
|
||||||
|
sha
|
||||||
|
}).then(result=>{
|
||||||
|
if(result){
|
||||||
|
setVisible(true);
|
||||||
|
}
|
||||||
|
}).catch(error=>{
|
||||||
|
console.log(error);
|
||||||
|
})
|
||||||
}else{
|
}else{
|
||||||
setUpdateInfo(undefined);
|
url = `/${owner}/${projectsId}/create_file.json`;
|
||||||
|
axios.post(url,params).then(result=>{
|
||||||
|
if(result){
|
||||||
|
setVisible(true);
|
||||||
|
}
|
||||||
|
}).catch(error=>{
|
||||||
|
console.log(error);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
function suresubmit(){
|
||||||
function onOk(pipeline_name,updateId,branch,event){
|
setVisible(false);
|
||||||
if(pipeline_name){
|
props.history.push(`/projects/${owner}/${projectsId}/devops/list`);
|
||||||
let eventStr = "";
|
|
||||||
for(var i = 0;i<event.length;i++){
|
|
||||||
eventStr +=event[i]+",";
|
|
||||||
}
|
|
||||||
eventStr = eventStr.substring(0,eventStr.length-1);
|
|
||||||
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(
|
return(
|
||||||
<Spin spinning={spining}>
|
<Spin spinning={spining}>
|
||||||
<PipelineName branchList={branchList} visible={visible} value={updateInfo} onCancel={()=>setVisible(false)} onOk={onOk}/>
|
<Modals visible={visible} closeFunc={(flag)=>setVisible(flag)} sureFunc={suresubmit}></Modals>
|
||||||
<div className="disposePanel">
|
<p>编程语言:</p>
|
||||||
<Head manager={ operate ? toModalManage : undefined} parameter={operate ? toparameter :undefined}/>
|
|
||||||
<Div>
|
<div className="mt20 mb20">
|
||||||
{ operate && <Blueback onClick={()=>addNew(undefined,undefined)}>新增流水线</Blueback> }
|
<FileLanguage language={fileLanguage} select_language={select_language}/>
|
||||||
<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>
|
||||||
|
<div className="editorBody">
|
||||||
|
<p className="editorHead">{info}</p>
|
||||||
|
<Editor
|
||||||
|
height="300px"
|
||||||
|
language={"yml"}
|
||||||
|
theme={"vs-grey"}
|
||||||
|
defaultValue="请输入内容"
|
||||||
|
value={ymlValue}
|
||||||
|
options={"editor_options"}
|
||||||
|
onChange={changeEditor}
|
||||||
|
></Editor>
|
||||||
|
</div>
|
||||||
|
<Blueback onClick={submit}>确定提交</Blueback>
|
||||||
</Spin>
|
</Spin>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,100 +0,0 @@
|
||||||
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;
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
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;
|
|
||||||
|
|
@ -1,66 +0,0 @@
|
||||||
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;
|
|
||||||
|
|
@ -1,131 +0,0 @@
|
||||||
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;
|
|
||||||
|
|
@ -1,67 +0,0 @@
|
||||||
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;
|
|
||||||
|
|
@ -1,102 +0,0 @@
|
||||||
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;
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
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;
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
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;
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
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;
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
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;
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
||||||
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;
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
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
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React , { useEffect } from 'react';
|
import React from 'react';
|
||||||
import { WhiteBack } from '../Component/layout';
|
import { WhiteBack } from '../Component/layout';
|
||||||
import './ops.scss';
|
import './ops.scss';
|
||||||
|
|
||||||
|
|
@ -10,65 +10,27 @@ const About = Loadable({
|
||||||
loader: () => import('./About'),
|
loader: () => import('./About'),
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
})
|
})
|
||||||
const New = Loadable({
|
const Infos = Loadable({
|
||||||
loader: () => import('./disposePipeline'),
|
loader: () => import('./Infos'),
|
||||||
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/:owner/:projectsId/devops/dispose/:disposeId"
|
|
||||||
render={
|
|
||||||
(p) => (<New {...props} {...p}/>)
|
|
||||||
}
|
|
||||||
></Route>
|
|
||||||
<Route path="/projects/:owner/:projectsId/devops/params"
|
|
||||||
render={
|
|
||||||
(p) => (<Params {...props} {...p}/>)
|
|
||||||
}
|
|
||||||
></Route>
|
|
||||||
<Route path="/projects/:owner/:projectsId/devops/mould"
|
|
||||||
render={
|
|
||||||
(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"
|
<Route path="/projects/:owner/:projectsId/devops/dispose"
|
||||||
render={
|
render={
|
||||||
(p) => (<Dispose {...props} {...p}/>)
|
() => (<Infos {...props} />)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
<Route path="/projects/:owner/:projectsId/devops/list/:branch"
|
<Route path="/projects/:owner/:projectsId/devops/list"
|
||||||
render={
|
render={
|
||||||
(p) => (<Stucture {...props} {...p}/>)
|
() => (<Infos {...props} />)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
<Route path="/projects/:owner/:projectsId/devops"
|
<Route path="/projects/:owner/:projectsId/devops"
|
||||||
render={
|
render={
|
||||||
(p) => (<About {...props} {...p}/>)
|
() => (<About {...props} />)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
</Switch>
|
</Switch>
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import React , { useEffect , useState } from 'react';
|
import React , { useEffect , useState , useRef } from 'react';
|
||||||
import { Banner } from '../Component/layout';
|
import { Banner } from '../Component/layout';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
import Dispost from './Dispose';
|
import Dispost from './Dispose';
|
||||||
|
import Structure from './Structure';
|
||||||
|
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
|
@ -10,11 +11,22 @@ const Div = styled.div`{
|
||||||
padding:24px 30px;
|
padding:24px 30px;
|
||||||
}`;
|
}`;
|
||||||
export default ((props)=>{
|
export default ((props)=>{
|
||||||
|
const [ menu , setMenu ] = useState(false);
|
||||||
const [ permission , setPermission ] = useState("");
|
const [ permission , setPermission ] = useState("");
|
||||||
|
const childRef = useRef();
|
||||||
|
|
||||||
|
const path = props.location.pathname;
|
||||||
const owner = props.match.params.owner;
|
const owner = props.match.params.owner;
|
||||||
|
const projectsId = props.match.params.projectsId;
|
||||||
|
|
||||||
const projectDetail = props.projectDetail;
|
const projectDetail = props.projectDetail;
|
||||||
|
useEffect(()=>{
|
||||||
|
if(path === `/projects/${owner}/${projectsId}/devops/list`){
|
||||||
|
setMenu(true);
|
||||||
|
}else{
|
||||||
|
setMenu(false);
|
||||||
|
}
|
||||||
|
},[path])
|
||||||
|
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
if(projectDetail){
|
if(projectDetail){
|
||||||
|
|
@ -22,14 +34,23 @@ export default ((props)=>{
|
||||||
}
|
}
|
||||||
},[projectDetail])
|
},[projectDetail])
|
||||||
|
|
||||||
|
const updateChildState = () => {
|
||||||
|
// changeVal就是子组件暴露给父组件的方法
|
||||||
|
if (childRef.current) {
|
||||||
|
childRef.current.changeVal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return(
|
return(
|
||||||
<div className="disposePanel">
|
<div className="disposePanel">
|
||||||
<Banner>
|
<Banner>
|
||||||
{ permission !=="Reporter" && <Link to={`/projects/${owner}/${props.match.params.projectsId}/devops/dispose`}>工作流配置</Link>}
|
{ permission !=="Reporter" && <Link to={`/projects/${owner}/${props.match.params.projectsId}/devops/dispose`} className={menu===false && "color-blue"} style={{ marginRight:"66px"}}>工作流配置</Link>}
|
||||||
|
<Link to={`/projects/${owner}/${props.match.params.projectsId}/devops/list`}className={menu===true && "color-blue"}>构建列表</Link>
|
||||||
|
{ menu===true && <a onClick={updateChildState} style={{float:"right",fontSize:"14px",color:"#FF6E21",marginTop:"5px"}}>刷新</a>}
|
||||||
</Banner>
|
</Banner>
|
||||||
<Div>
|
<Div>
|
||||||
<Dispost {...props}/>
|
{ menu === true && <Structure {...props} wrappedComponentRef={(form) => childRef.current = form} ref={childRef}/> }
|
||||||
|
{ menu === false && permission !=="Reporter" && <Dispost {...props}/> }
|
||||||
</Div>
|
</Div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,119 +0,0 @@
|
||||||
import React , { useEffect , useState , useRef } from 'react';
|
|
||||||
import { Banner , Blueback , FlexAJ , AlignCenter } from '../../Component/layout';
|
|
||||||
import { Input , Table , Popconfirm , Pagination } from 'antd';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import styled from 'styled-components';
|
|
||||||
import New from './ParamsNew';
|
|
||||||
import "./manage.scss";
|
|
||||||
import axios from 'axios';
|
|
||||||
import { result } from 'lodash';
|
|
||||||
|
|
||||||
const Div = styled.div`{
|
|
||||||
padding:24px 30px;
|
|
||||||
min-height:420px;
|
|
||||||
}`;
|
|
||||||
function Params(props){
|
|
||||||
const [ list ,setList ] = useState(undefined);
|
|
||||||
const [ editList ,setEditList ] = useState(undefined);
|
|
||||||
const [ visible ,setVisible ] = useState(false);
|
|
||||||
|
|
||||||
let projectsId = props.match.params.projectsId;
|
|
||||||
let owner = props.match.params.owner;
|
|
||||||
|
|
||||||
useEffect(()=>{
|
|
||||||
Init()
|
|
||||||
},[])
|
|
||||||
|
|
||||||
function Init(){
|
|
||||||
const url = `/ci/secrets.json`;
|
|
||||||
axios.get(url,{
|
|
||||||
params:{
|
|
||||||
owner,repo:projectsId
|
|
||||||
}
|
|
||||||
}).then(result=>{
|
|
||||||
if(result){
|
|
||||||
setList(result.data);
|
|
||||||
}
|
|
||||||
}).catch(error=>{})
|
|
||||||
}
|
|
||||||
|
|
||||||
const columns=[
|
|
||||||
{
|
|
||||||
title:"参数名",
|
|
||||||
dataIndex:"name",
|
|
||||||
key:1,
|
|
||||||
ellipsis:true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title:"操作",
|
|
||||||
dataIndex:"operation",
|
|
||||||
key:4,
|
|
||||||
render:(txt,item)=>{
|
|
||||||
return(
|
|
||||||
<React.Fragment>
|
|
||||||
<a className="mr10 color-grey-6" onClick={()=>editMouldFunc(item)}><i className="iconfont icon-zaibianji font-13 mr3"></i>编辑</a>
|
|
||||||
<Popconfirm title={"确定要删除此模板?"} onConfirm={()=>deleteMouldFunc(item.id,item.name)} okText="确定" cancelText={"取消"}>
|
|
||||||
<a className="mr10 color-grey-6"><i className="iconfont icon-lajitong font-13 mr3"></i>删除</a>
|
|
||||||
</Popconfirm>
|
|
||||||
</React.Fragment>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
// 编辑
|
|
||||||
function editMouldFunc(item){
|
|
||||||
setEditList(item);
|
|
||||||
setVisible(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除
|
|
||||||
function deleteMouldFunc(id,name){
|
|
||||||
if(id && name){
|
|
||||||
const url = `/ci/secrets/${id}.json`;
|
|
||||||
axios.delete(url,{
|
|
||||||
params:{owner,repo:projectsId,name}
|
|
||||||
}).then(result=>{
|
|
||||||
if(result){
|
|
||||||
Init();
|
|
||||||
props.showNotification(`参数删除成功!`);
|
|
||||||
}
|
|
||||||
}).catch(error=>{})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function successFunc(values,id){
|
|
||||||
const url = `/ci/secrets.json?owner=${owner}&repo=${projectsId}`;
|
|
||||||
axios.post(url,{
|
|
||||||
...values,id
|
|
||||||
}).then(result=>{
|
|
||||||
if(result){
|
|
||||||
props.showNotification(`${id ? '参数编辑':"新增参数"}成功!`);
|
|
||||||
Init();
|
|
||||||
}
|
|
||||||
}).catch(error=>{})
|
|
||||||
}
|
|
||||||
|
|
||||||
function CancelFunc(){
|
|
||||||
setVisible(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
return(
|
|
||||||
<div>
|
|
||||||
<New visble={visible} successFunc={successFunc} CancelFunc={CancelFunc} editList={editList}/>
|
|
||||||
<Banner>
|
|
||||||
<FlexAJ>
|
|
||||||
<span className="font-18">工作流 - 参数管理</span>
|
|
||||||
<Link to={`/projects/${owner}/${projectsId}/devops/dispose`} className="font-14 color-grey-9 ml20">返回</Link>
|
|
||||||
</FlexAJ>
|
|
||||||
</Banner>
|
|
||||||
<Div className="disposeList">
|
|
||||||
<div style={{textAlign:"right"}}>
|
|
||||||
<Blueback onClick={()=>setVisible(true)}>新建</Blueback>
|
|
||||||
</div>
|
|
||||||
<Table className="mt20" size="small" columns={columns} dataSource={list} rowKey={(row)=>row.id} pagination={false}></Table>
|
|
||||||
</Div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export default Params;
|
|
||||||
|
|
@ -1,73 +0,0 @@
|
||||||
import React , { useEffect , useState , useRef , forwardRef } from 'react';
|
|
||||||
import { Modal , Input , Form } from 'antd';
|
|
||||||
|
|
||||||
const { TextArea } = Input;
|
|
||||||
|
|
||||||
function ParamsNew({ form , visble,successFunc,CancelFunc ,editList }){
|
|
||||||
const { getFieldDecorator, validateFields , setFieldsValue } = form;
|
|
||||||
const layout = {
|
|
||||||
labelCol: { span: 5 },
|
|
||||||
wrapperCol: { span: 18 },
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(()=>{
|
|
||||||
if(editList && editList.id){
|
|
||||||
setFieldsValue({
|
|
||||||
name:editList.name,
|
|
||||||
data:editList.data
|
|
||||||
})
|
|
||||||
}else{
|
|
||||||
setFieldsValue({
|
|
||||||
name:undefined,
|
|
||||||
data:undefined
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},[editList])
|
|
||||||
|
|
||||||
// 确定
|
|
||||||
function onConfirmFunc(){
|
|
||||||
validateFields((error,values)=>{
|
|
||||||
if(!error){
|
|
||||||
successFunc(values,editList && editList.id);
|
|
||||||
onCancelFunc();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
function onCancelFunc(){
|
|
||||||
setFieldsValue({
|
|
||||||
name:undefined,
|
|
||||||
data:undefined
|
|
||||||
})
|
|
||||||
CancelFunc();
|
|
||||||
}
|
|
||||||
return(
|
|
||||||
<Modal
|
|
||||||
visible={visble}
|
|
||||||
okText={"确定"}
|
|
||||||
cancelText={"取消"}
|
|
||||||
onCancel={onCancelFunc}
|
|
||||||
onOk={onConfirmFunc}
|
|
||||||
title={"新建"}
|
|
||||||
closable={false}
|
|
||||||
width="500px"
|
|
||||||
>
|
|
||||||
<Form {...layout}>
|
|
||||||
<Form.Item label="参数名称">
|
|
||||||
{getFieldDecorator("name",{
|
|
||||||
rules:[{required:true,message:"请输入参数名称"}]
|
|
||||||
})(
|
|
||||||
<Input placeholder="请输入参数名称" width="220px"/>
|
|
||||||
)}
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="参数值">
|
|
||||||
{getFieldDecorator("data",{
|
|
||||||
rules:[{required:true,message:"请输入参数值"}]
|
|
||||||
})(
|
|
||||||
<TextArea placeholder="请输入参数值" width="220px" autoSize={{ minRows: 4, maxRows: 4 }}/>
|
|
||||||
)}
|
|
||||||
</Form.Item>
|
|
||||||
</Form>
|
|
||||||
</Modal>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export default Form.create()(forwardRef(ParamsNew));
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
.ant-form-explain{
|
|
||||||
position: absolute;
|
|
||||||
bottom: -15px;
|
|
||||||
}
|
|
||||||
|
|
@ -1,160 +0,0 @@
|
||||||
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;
|
|
||||||
|
|
@ -1,166 +0,0 @@
|
||||||
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,8 +1,7 @@
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { Spin , Menu } from "antd";
|
import { Spin } from "antd";
|
||||||
import { FlexAJ, AlignCenter } from "../Component/layout";
|
import { FlexAJ, AlignCenter } from "../Component/layout";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import CodeSSH from './ssh/Index';
|
|
||||||
|
|
||||||
export default ({
|
export default ({
|
||||||
data,
|
data,
|
||||||
|
|
@ -18,8 +17,6 @@ export default ({
|
||||||
const [spining, setSpining] = useState(true);
|
const [spining, setSpining] = useState(true);
|
||||||
const [stage, setStage] = useState(undefined);
|
const [stage, setStage] = useState(undefined);
|
||||||
const [step, setStep] = useState(undefined);
|
const [step, setStep] = useState(undefined);
|
||||||
const [nav, setNav] = useState("0");
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setSpining(rightSpin);
|
setSpining(rightSpin);
|
||||||
}, [rightSpin]);
|
}, [rightSpin]);
|
||||||
|
|
@ -38,7 +35,6 @@ export default ({
|
||||||
: p[0];
|
: p[0];
|
||||||
|
|
||||||
setStep(sub);
|
setStep(sub);
|
||||||
setNav("0");
|
|
||||||
if (sub && sub.status !== "skipped") {
|
if (sub && sub.status !== "skipped") {
|
||||||
getStep(pre.number, sub.number);
|
getStep(pre.number, sub.number);
|
||||||
}
|
}
|
||||||
|
|
@ -69,55 +65,43 @@ export default ({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<Spin spinning={spining}>
|
||||||
{/* <Menu className="devopsNav" onClick={(e)=>{setNav(e.key)}} selectedKeys={[nav]} mode="horizontal">
|
<div className="rightMainContent">
|
||||||
<Menu.Item key={'0'} value="0">开发流水线</Menu.Item>
|
{data && data.status !== "error" ? (
|
||||||
<Menu.Item key={'1'} value="1">命令行</Menu.Item>
|
<div>
|
||||||
</Menu> */}
|
<FlexAJ className="items">
|
||||||
{
|
<span>{step && step.name}</span>
|
||||||
nav === "0" &&
|
<AlignCenter>
|
||||||
<Spin spinning={spining}>
|
{step && step.duration_time}
|
||||||
<div className="rightMainContent">
|
<i className="iconfont icon-sanjiaoxing-down"></i>
|
||||||
{data && data.status !== "error" ? (
|
</AlignCenter>
|
||||||
<div>
|
</FlexAJ>
|
||||||
<FlexAJ className="items">
|
<div>
|
||||||
<span>{step && step.name}</span>
|
{coders && coders.length > 0 ? (
|
||||||
<AlignCenter>
|
coders.map((item, key) => {
|
||||||
{step && step.duration_time}
|
return (
|
||||||
<i className="iconfont icon-sanjiaoxing-down"></i>
|
|
||||||
</AlignCenter>
|
|
||||||
</FlexAJ>
|
|
||||||
<div>
|
|
||||||
{coders && coders.length > 0 ? (
|
|
||||||
coders.map((item, key) => {
|
|
||||||
return (
|
|
||||||
<div className="opsDetailOut">
|
|
||||||
<span>{key + 1}</span>
|
|
||||||
<p>{item.out}</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})
|
|
||||||
) : empty ? (
|
|
||||||
<div className="opsDetailOut">
|
<div className="opsDetailOut">
|
||||||
<span>1</span>
|
<span>{key + 1}</span>
|
||||||
<p>
|
<p>{item.out}</p>
|
||||||
{stage && stage.name} – {step && step.name}: Skipped
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
) : (
|
);
|
||||||
""
|
})
|
||||||
)}
|
) : empty ? (
|
||||||
|
<div className="opsDetailOut">
|
||||||
|
<span>1</span>
|
||||||
|
<p>
|
||||||
|
{stage && stage.name} – {step && step.name}: Skipped
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
) : (
|
||||||
) : (
|
""
|
||||||
<div style={{ color: "red" }}>error:{data && data.error}</div>
|
)}
|
||||||
)}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Spin>
|
) : (
|
||||||
}
|
<div style={{ color: "red" }}>error:{data && data.error}</div>
|
||||||
{
|
)}
|
||||||
nav === "1" && <CodeSSH />
|
</div>
|
||||||
}
|
</Spin>
|
||||||
</React.Fragment>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
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,16 +1,10 @@
|
||||||
import React, { useState, useEffect , useImperativeHandle ,forwardRef } from "react";
|
import React, { useState, useEffect , useImperativeHandle ,forwardRef } from "react";
|
||||||
import { FlexAJ, AlignCenter , Banner } from "../Component/layout";
|
import { FlexAJ, AlignCenter } from "../Component/layout";
|
||||||
import { Table, Pagination, Popconfirm } from "antd";
|
import { Table, Pagination, Popconfirm } from "antd";
|
||||||
import { truncateCommitId } from "../common/util";
|
import { truncateCommitId } from "../common/util";
|
||||||
import {getUrl} from 'educoder';
|
import {getUrl} from 'educoder';
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
|
|
||||||
import styled from 'styled-components';
|
|
||||||
|
|
||||||
const Div = styled.div`{
|
|
||||||
padding:24px 30px;
|
|
||||||
}`;
|
|
||||||
const STATUS = [
|
const STATUS = [
|
||||||
{ name: "所有"},
|
{ name: "所有"},
|
||||||
{ name: "运行中", value: "running" },
|
{ name: "运行中", value: "running" },
|
||||||
|
|
@ -28,7 +22,6 @@ function Structure(props,ref){
|
||||||
|
|
||||||
let projectsId = props.match.params.projectsId;
|
let projectsId = props.match.params.projectsId;
|
||||||
let owner = props.match.params.owner;
|
let owner = props.match.params.owner;
|
||||||
let branch = props.match.params.branch;
|
|
||||||
const permission = props.projectDetail && props.projectDetail.permission;
|
const permission = props.projectDetail && props.projectDetail.permission;
|
||||||
|
|
||||||
useImperativeHandle(ref, () => ({
|
useImperativeHandle(ref, () => ({
|
||||||
|
|
@ -42,7 +35,7 @@ function Structure(props,ref){
|
||||||
if (projectsId) {
|
if (projectsId) {
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
}, [page]);
|
}, []);
|
||||||
|
|
||||||
let current_user = props.current_user;
|
let current_user = props.current_user;
|
||||||
function Init(status) {
|
function Init(status) {
|
||||||
|
|
@ -50,7 +43,7 @@ function Structure(props,ref){
|
||||||
axios.get(url,{
|
axios.get(url,{
|
||||||
params:{
|
params:{
|
||||||
search:status,
|
search:status,
|
||||||
page,limit:LIMIT,branch
|
page,limit:LIMIT
|
||||||
}
|
}
|
||||||
}).then((result) => {
|
}).then((result) => {
|
||||||
if (result && result.data) {
|
if (result && result.data) {
|
||||||
|
|
@ -58,7 +51,6 @@ function Structure(props,ref){
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
author:item.author && item.author.name,
|
author:item.author && item.author.name,
|
||||||
image_url:item.author && item.author.image_url,
|
|
||||||
message: {
|
message: {
|
||||||
branch: item.branch_target,
|
branch: item.branch_target,
|
||||||
message: item.message,
|
message: item.message,
|
||||||
|
|
@ -188,7 +180,7 @@ function Structure(props,ref){
|
||||||
<i className="iconfont icon-weitongguo"></i>已撤销
|
<i className="iconfont icon-weitongguo"></i>已撤销
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
default:
|
case 'pending':
|
||||||
return (
|
return (
|
||||||
<span className="statusTag Preparing">
|
<span className="statusTag Preparing">
|
||||||
<i className="iconfont icon-zhunbeizhong"></i>准备中
|
<i className="iconfont icon-zhunbeizhong"></i>准备中
|
||||||
|
|
@ -245,7 +237,7 @@ function Structure(props,ref){
|
||||||
{meg.sha && <span className="color-orange">{meg.sha}</span>}
|
{meg.sha && <span className="color-orange">{meg.sha}</span>}
|
||||||
</div>
|
</div>
|
||||||
<AlignCenter>
|
<AlignCenter>
|
||||||
<img style={{borderRadius:"50%",marginRight:"10px",width:"25px",height:"25px"}} alt="" src={`${item.image_url && getUrl(`/images/${item.image_url}`)}`} />
|
<img style={{borderRadius:"50%",marginRight:"10px",width:"25px",height:"25px"}} src={`${current_user && getUrl(`/images/${current_user.image_url}`)}`} />
|
||||||
<div className="task-hide ml5" style={{ maxWidth: "300px" }}>
|
<div className="task-hide ml5" style={{ maxWidth: "300px" }}>
|
||||||
{meg.message}
|
{meg.message}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -286,45 +278,42 @@ function Structure(props,ref){
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
return (
|
return (
|
||||||
<div className="disposePanel">
|
<div className="listPart">
|
||||||
<Banner>
|
<FlexAJ>
|
||||||
<FlexAJ>
|
{renderStatus()}
|
||||||
<span>构建列表</span>
|
{/* <Blueback>手动创建</Blueback> */}
|
||||||
<Link to={`/projects/${owner}/${projectsId}/devops/dispose`} className="font-15 color-grey-9">返回</Link>
|
{/* <span className="mr30">
|
||||||
</FlexAJ>
|
<i className="iconfont icon-fenzhi1 font-16 mr5 color-blue"></i>分支
|
||||||
</Banner>
|
</span>
|
||||||
<Div>
|
<span>
|
||||||
<div className="listPart">
|
<i className="iconfont icon-biaoqian3 font-16 mr5 color-blue"></i>
|
||||||
<FlexAJ>
|
标签
|
||||||
{renderStatus()}
|
</span> */}
|
||||||
<a onClick={()=>Init(status)} className="color-red font-16">刷新</a>
|
</FlexAJ>
|
||||||
</FlexAJ>
|
<Table
|
||||||
<Table
|
onRow={(record,index)=>{
|
||||||
onRow={(record,index)=>{
|
return{
|
||||||
return{
|
onClick:(event)=>clickRows(event,record)
|
||||||
onClick:(event)=>clickRows(event,record)
|
}
|
||||||
}
|
}}
|
||||||
}}
|
columns={column}
|
||||||
columns={column}
|
className="normalTable"
|
||||||
className="normalTable"
|
dataSource={data}
|
||||||
dataSource={data}
|
pagination={false}
|
||||||
pagination={false}
|
loading={tableLoading}
|
||||||
loading={tableLoading}
|
></Table>
|
||||||
></Table>
|
{total > LIMIT ?
|
||||||
{total > LIMIT ?
|
<div style={{ textAlign: "center", margin: "30px 50px" }}>
|
||||||
<div style={{ textAlign: "center", margin: "30px 50px" }}>
|
<Pagination
|
||||||
<Pagination
|
showQuickJumper
|
||||||
showQuickJumper
|
defaultCurrent={page}
|
||||||
defaultCurrent={page}
|
total={total}
|
||||||
total={total}
|
pageSize={LIMIT}
|
||||||
pageSize={LIMIT}
|
onChange={ChangePage}
|
||||||
onChange={ChangePage}
|
></Pagination>
|
||||||
></Pagination>
|
</div>
|
||||||
</div>
|
:
|
||||||
:
|
"" }
|
||||||
"" }
|
|
||||||
</div>
|
|
||||||
</Div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,317 +0,0 @@
|
||||||
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,7 +10,6 @@
|
||||||
padding:60px 0px;
|
padding:60px 0px;
|
||||||
}
|
}
|
||||||
.disposePanel{
|
.disposePanel{
|
||||||
border:1px solid #eee;
|
|
||||||
.language{
|
.language{
|
||||||
display: flex;
|
display: flex;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
|
|
@ -82,7 +81,48 @@
|
||||||
.ant-modal-close{
|
.ant-modal-close{
|
||||||
top:7px;
|
top:7px;
|
||||||
}
|
}
|
||||||
|
// 列表
|
||||||
|
.listPart{
|
||||||
|
.statusTag{
|
||||||
|
display: flex;
|
||||||
|
padding:0px 16px;
|
||||||
|
height: 32px;
|
||||||
|
line-height: 32px;
|
||||||
|
border-radius:20px;
|
||||||
|
float: left;
|
||||||
|
i{
|
||||||
|
font-size: 20px!important;
|
||||||
|
margin-right: 7px;
|
||||||
|
}
|
||||||
|
&.running{
|
||||||
|
background:#F1F8FF;
|
||||||
|
border:1px solid #5091FF;
|
||||||
|
color: #5091FF;
|
||||||
|
}
|
||||||
|
&.Preparing{
|
||||||
|
background:rgba(255,248,244,1);
|
||||||
|
border:1px solid rgba(255,110,33,1);
|
||||||
|
color:rgba(255,110,33,1) ;
|
||||||
|
}
|
||||||
|
&.pass{
|
||||||
|
background:#EEFDF5;
|
||||||
|
border:1px solid #28BD6C;
|
||||||
|
color:#28BD6C ;
|
||||||
|
}
|
||||||
|
&.failed{
|
||||||
|
background:#FCEEEE;
|
||||||
|
border:1px solid #F73030;
|
||||||
|
color:#F73030 ;
|
||||||
|
}
|
||||||
|
&.killed{
|
||||||
|
background:#eee;
|
||||||
|
border:1px solid #999;
|
||||||
|
color:#999 ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
// ops详情
|
// ops详情
|
||||||
.opsDetailPanel{
|
.opsDetailPanel{
|
||||||
|
|
@ -194,18 +234,6 @@
|
||||||
&.rightSection{
|
&.rightSection{
|
||||||
width:100%;
|
width:100%;
|
||||||
background-color: #081930;
|
background-color: #081930;
|
||||||
.devopsNav{
|
|
||||||
background-color: #111c24;
|
|
||||||
border-bottom: none;
|
|
||||||
.ant-menu-item{
|
|
||||||
color: #ccc;
|
|
||||||
padding:0px;
|
|
||||||
margin:0px 20px!important;
|
|
||||||
}
|
|
||||||
.ant-menu-item.ant-menu-item-selected{
|
|
||||||
color: #1890ff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.rightMainContent{
|
.rightMainContent{
|
||||||
padding:24px 30px;
|
padding:24px 30px;
|
||||||
height:100vh;
|
height:100vh;
|
||||||
|
|
@ -279,243 +307,3 @@
|
||||||
margin-bottom: 0px;
|
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 ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -87,7 +87,7 @@ export default (props) => {
|
||||||
</AlignCenter>
|
</AlignCenter>
|
||||||
<Link
|
<Link
|
||||||
style={{ color: "#ddd" }}
|
style={{ color: "#ddd" }}
|
||||||
to={`/projects/${owner}/${projectId}/devops/dispose`}
|
to={`/projects/${owner}/${projectId}/devops/list`}
|
||||||
>
|
>
|
||||||
<i className="iconfont icon-yiguanbi font-15 mr5"></i>退出
|
<i className="iconfont icon-yiguanbi font-15 mr5"></i>退出
|
||||||
</Link>
|
</Link>
|
||||||
|
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
import React, { useState, useEffect } from "react";
|
|
||||||
import XmlPanel from "./XmlPanel";
|
|
||||||
import mediator from "./mediator";
|
|
||||||
import axios from "axios";
|
|
||||||
|
|
||||||
// const defaulturl = `http://47.111.130.18:48088`;
|
|
||||||
const defaultValue = {
|
|
||||||
host: "106.75.231.63",
|
|
||||||
port: "2021",
|
|
||||||
ws_url: "wss://pre-webssh.educoder.net/ws",
|
|
||||||
username: "root",
|
|
||||||
secret: "Dron_123123",
|
|
||||||
};
|
|
||||||
function Index() {
|
|
||||||
const [sshConfigData, setSshConfigData] = useState(undefined);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!sshConfigData) {
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
setTimeout(() => {
|
|
||||||
mediator.publish("create-socket", 1);
|
|
||||||
}, 300);
|
|
||||||
}, [sshConfigData]);
|
|
||||||
|
|
||||||
// 获取服务器连接信息
|
|
||||||
function init() {
|
|
||||||
const url = `/api/ci/pipelines/ssh_server.json`;
|
|
||||||
axios.get(url).then(result=>{
|
|
||||||
if(result && result.data){
|
|
||||||
setSshConfigData({...result.data})
|
|
||||||
}
|
|
||||||
}).catch(error=>{})
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<XmlPanel
|
|
||||||
sshConfigData={sshConfigData||{}}
|
|
||||||
sid={1}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
export default Index;
|
|
||||||
|
|
@ -1,219 +0,0 @@
|
||||||
import React, { useRef, useEffect, useState } from 'react';
|
|
||||||
import { Base64 } from 'js-base64';
|
|
||||||
|
|
||||||
import { Terminal } from 'xterm';
|
|
||||||
import 'xterm/css/xterm.css';
|
|
||||||
import mediator from './mediator';
|
|
||||||
import ResizeObserver from 'resize-observer-polyfill';
|
|
||||||
|
|
||||||
function getColsAndRows(width, height, term) {
|
|
||||||
let w = term._core._renderService.dimensions.actualCellWidth || 9.5;
|
|
||||||
let h = term._core._renderService.dimensions.actualCellHeight || 18;
|
|
||||||
const rows = Math.floor(height / h);
|
|
||||||
const cols = Math.floor(width / w);
|
|
||||||
return [cols, rows];
|
|
||||||
}
|
|
||||||
|
|
||||||
function onLayout(term, el) {
|
|
||||||
const ro = new ResizeObserver(entries => {
|
|
||||||
console.log(entries);
|
|
||||||
for (let entry of entries) {
|
|
||||||
if (entry.target.offsetHeight > 0 || entry.target.offsetWidth > 0) {
|
|
||||||
const [cols, rows] = getColsAndRows(
|
|
||||||
entry.target.offsetWidth,
|
|
||||||
entry.target.offsetHeight,
|
|
||||||
term,
|
|
||||||
);
|
|
||||||
console.log('cols, rows', cols, rows);
|
|
||||||
term.resize(cols, rows);
|
|
||||||
mediator.publish('ssh-xterm-resize', {
|
|
||||||
columns: cols,
|
|
||||||
rows: rows,
|
|
||||||
width: entry.target.offsetWidth,
|
|
||||||
height: entry.target.offsetHeight,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
ro.observe(el);
|
|
||||||
return ro;
|
|
||||||
}
|
|
||||||
|
|
||||||
const TimeTicket = 30000;
|
|
||||||
|
|
||||||
//建立 websockt 来交互
|
|
||||||
//根据容器大小计算行数和列数并做到自适应
|
|
||||||
//socket 与 term 需要分开初始化 因为socket 可能重置连接
|
|
||||||
//mediator 监听消息,如果和id匹配,则建立连接,重置,或关闭连接
|
|
||||||
|
|
||||||
export default ({ sshConfigData, sid }) => {
|
|
||||||
const [term, setTerm] = useState(null);
|
|
||||||
|
|
||||||
const { ws_url, password, port, secret } = sshConfigData;
|
|
||||||
const el = useRef();
|
|
||||||
const socket = useRef();
|
|
||||||
const isFirstConnected = useRef(false);
|
|
||||||
|
|
||||||
//term init
|
|
||||||
useEffect(() => {
|
|
||||||
if (el.current && ws_url) {
|
|
||||||
const term = new Terminal({ fontSize: 16, rendererType: 'dom' });
|
|
||||||
term.open(el.current);
|
|
||||||
|
|
||||||
term.onData(data => {
|
|
||||||
if (socket.current) {
|
|
||||||
if (socket.current.readyState === 1) {
|
|
||||||
socket.current.send(JSON.stringify({ tp: 'client', data: data }));
|
|
||||||
mediator.publish('on-operating-ssh'); //有操作则自动延时
|
|
||||||
} else {
|
|
||||||
//断开连接后重连
|
|
||||||
// socket.current = null
|
|
||||||
// mediator.publish('create-socket', sid)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
term.write('Connecting...');
|
|
||||||
setTerm(term);
|
|
||||||
const ro = onLayout(term, el.current);
|
|
||||||
return () => {
|
|
||||||
term.dispose();
|
|
||||||
ro.unobserve(el.current);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}, [ws_url, el.current]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (term && ws_url) {
|
|
||||||
function createSocket() {
|
|
||||||
const socketInstance = new WebSocket(ws_url);
|
|
||||||
socket.current = socketInstance;
|
|
||||||
|
|
||||||
socketInstance.onopen = () => {
|
|
||||||
let container = term.element.parentElement;
|
|
||||||
if (container) {
|
|
||||||
let width = container.offsetWidth;
|
|
||||||
let height = container.offsetHeight;
|
|
||||||
console.log('init', {
|
|
||||||
tp: 'init',
|
|
||||||
data: {
|
|
||||||
...sshConfigData,
|
|
||||||
secret: secret,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
rows: term.rows,
|
|
||||||
columns: term.cols,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
socketInstance.send(
|
|
||||||
JSON.stringify({
|
|
||||||
tp: 'init',
|
|
||||||
data: {
|
|
||||||
...sshConfigData,
|
|
||||||
secret: secret,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
rows: term.rows,
|
|
||||||
columns: term.cols,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
term.focus();
|
|
||||||
};
|
|
||||||
socketInstance.onerror = error => {
|
|
||||||
console.log(
|
|
||||||
'------in socket error----',
|
|
||||||
error,
|
|
||||||
socketInstance,
|
|
||||||
ws_url,
|
|
||||||
);
|
|
||||||
//连接报错后,重新请求资源
|
|
||||||
// mediator.publish('on-recreate-socket')
|
|
||||||
};
|
|
||||||
socketInstance.onmessage = event => {
|
|
||||||
if (!isFirstConnected.current) {
|
|
||||||
term.write('\r');
|
|
||||||
// term.focus()
|
|
||||||
setTimeout(() => {
|
|
||||||
// term.clear();
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
isFirstConnected.current = true;
|
|
||||||
console.log('event:', event);
|
|
||||||
|
|
||||||
const data = Base64.decode(event.data.toString());
|
|
||||||
let w = term._core._renderService.dimensions.actualCellWidth || 9.5;
|
|
||||||
|
|
||||||
console.log('data:', data, w, term);
|
|
||||||
term.write(data);
|
|
||||||
};
|
|
||||||
|
|
||||||
socketInstance.onclose = evt => {
|
|
||||||
if (tid) {
|
|
||||||
clearInterval(tid);
|
|
||||||
}
|
|
||||||
term.write('\r\nconnection closed');
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const tid = setInterval(() => {
|
|
||||||
if (socket.current) {
|
|
||||||
socket.current.send(JSON.stringify({ tp: 'h' }));
|
|
||||||
}
|
|
||||||
}, TimeTicket);
|
|
||||||
|
|
||||||
const unSubCreate = mediator.subscribe('create-socket', id => {
|
|
||||||
if (sid === id) {
|
|
||||||
if (socket.current && socket.current.readyState === 1) {
|
|
||||||
term.focus();
|
|
||||||
} else {
|
|
||||||
createSocket();
|
|
||||||
}
|
|
||||||
term.focus();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const unSubClose = mediator.subscribe('close-socket', id => {
|
|
||||||
if (sid === id) {
|
|
||||||
if (socket.current) {
|
|
||||||
socket.current.close();
|
|
||||||
isFirstConnected.current = false;
|
|
||||||
term.clear();
|
|
||||||
}
|
|
||||||
socket.current = null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const unSubResize = mediator.subscribe('ssh-xterm-resize', option => {
|
|
||||||
if (socket.current && socket.current.readyState === 1) {
|
|
||||||
socket.current.send(
|
|
||||||
JSON.stringify({ tp: 'resize', data: { ...option } }),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const unSubAddTime = mediator.subscribe('ssh-add-connect-time', () => {
|
|
||||||
if (socket.current && socket.current.readyState === 1) {
|
|
||||||
socket.current.send(JSON.stringify({ tp: 'overtime' }));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
unSubClose();
|
|
||||||
unSubCreate();
|
|
||||||
unSubResize();
|
|
||||||
unSubAddTime();
|
|
||||||
if (socket.current) {
|
|
||||||
socket.current.close();
|
|
||||||
isFirstConnected.current = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}, [term, ws_url, port]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div ref={el} className="xterm-panel" style={{height:"100%"}}>
|
|
||||||
{!ws_url ? <p style={{ color: '#fff' }}>正在连接命令行服务...</p> : null}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
function Mediator(obj) {
|
|
||||||
const channels = {};
|
|
||||||
|
|
||||||
const mediator = {
|
|
||||||
subscribe: function(channel, cb) {
|
|
||||||
if (!channels[channel]) {
|
|
||||||
channels[channel] = [];
|
|
||||||
}
|
|
||||||
channels[channel].push(cb);
|
|
||||||
return this.unsubscribe.bind(null, channel, cb);
|
|
||||||
},
|
|
||||||
|
|
||||||
unsubscribe: function(channel, cb) {
|
|
||||||
let rs = channels[channel];
|
|
||||||
let index = -1;
|
|
||||||
if (rs) {
|
|
||||||
for (let i = 0; i < rs.length; i++) {
|
|
||||||
if (rs[i].name === cb.name) {
|
|
||||||
index = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (index >= 0) {
|
|
||||||
channels[channel].splice(index, 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
publish: function(channel) {
|
|
||||||
if (!channels[channel]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const args = Array.prototype.slice.call(arguments, 1);
|
|
||||||
channels[channel].forEach(subscription => {
|
|
||||||
subscription.apply(null, args);
|
|
||||||
});
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
return obj ? Object.assign(obj, mediator) : mediator;
|
|
||||||
}
|
|
||||||
const mediator = new Mediator();
|
|
||||||
export default mediator;
|
|
||||||
|
|
@ -1,174 +0,0 @@
|
||||||
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));
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
.diverModal{
|
|
||||||
.descUl{
|
|
||||||
background-color: #fffae6;
|
|
||||||
border-radius: 4px;
|
|
||||||
padding:10px 15px;
|
|
||||||
color: #efc16b;
|
|
||||||
border:1px solid #efc16b;
|
|
||||||
}
|
|
||||||
.ant-form-item-required::before{
|
|
||||||
content: "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -10,12 +10,4 @@ export const getTag = async (id,owner)=>{
|
||||||
// 获取hooks(仓库设置-管理web钩子)列表
|
// 获取hooks(仓库设置-管理web钩子)列表
|
||||||
export const getHooks = async (id,params)=>{
|
export const getHooks = async (id,params)=>{
|
||||||
return (await axios.get(`/projects/${id}/hooks.json`,{params})).data;
|
return (await axios.get(`/projects/${id}/hooks.json`,{params})).data;
|
||||||
}
|
|
||||||
// 获取子目录列表
|
|
||||||
export const getSubEntries = async (owner,projectsId,params)=>{
|
|
||||||
return (await axios.get(`/${owner}/${projectsId}/sub_entries.json`,{params})).data;
|
|
||||||
}
|
|
||||||
// 获取用户信息
|
|
||||||
export const getUser = async (login)=>{
|
|
||||||
return (await axios.get(`/users/${login}/hovercard.json`)).data;
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,66 +0,0 @@
|
||||||
import React, { useEffect , useState } from 'react';
|
|
||||||
import './header.scss';
|
|
||||||
|
|
||||||
function Footer(){
|
|
||||||
const [ value , setValue ] = useState(undefined);
|
|
||||||
|
|
||||||
useEffect(()=>{
|
|
||||||
try {
|
|
||||||
var chromesettingArray = JSON.parse(localStorage.getItem('chromesetting'));
|
|
||||||
setValue(chromesettingArray.footer);
|
|
||||||
} catch (e) {
|
|
||||||
}
|
|
||||||
},[])
|
|
||||||
|
|
||||||
function showhtml(htmlString){
|
|
||||||
var html = {__html:htmlString};
|
|
||||||
return <div dangerouslySetInnerHTML={html}></div> ;
|
|
||||||
}
|
|
||||||
|
|
||||||
return(
|
|
||||||
<div>
|
|
||||||
<div style={{height:"483px"}}></div>
|
|
||||||
<div className="newFooter edu-txt-center">
|
|
||||||
{value && showhtml(value)}
|
|
||||||
{/* <div className="footerInfos">
|
|
||||||
<ul>
|
|
||||||
<li>社区</li>
|
|
||||||
<li><a href={`/`} target="_blank">网站首页</a></li>
|
|
||||||
<li><a href={`https://www.trustie.net/agreement`} target="_blank">服务协议</a></li>
|
|
||||||
<li><a href={`https://forum.trustie.net/forums/1168/detail`} target="_blank">帮助中心</a></li>
|
|
||||||
<li><a href={`https://forum.trustie.net/`} target="_blank">问吧交流</a></li>
|
|
||||||
<li><a href={`https://www.trustie.net/cooperation`} target="_blank">合作伙伴</a></li>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li>支持与服务</li>
|
|
||||||
<li><a href={`https://forgeplus.trustie.net/docs/api`} target="_blank">API文档</a></li>
|
|
||||||
<li><a href={`https://forum.trustie.net/forums/1168/detail`} target="_blank">帮助中心</a></li>
|
|
||||||
<li><a href={`https://git-scm.com`} target="_blank">Git常用命令</a></li>
|
|
||||||
<li><a href={`https://forum.trustie.net/forums/3080/detail`} target="_blank">DevOps使用文档</a></li>
|
|
||||||
<li><a href={`https://forgeplus.trustie.net/projects/jasder/forgeplus/tree/master/CHANGELOG.md`} target="_blank">日志更新</a></li>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li>合作伙伴</li>
|
|
||||||
<li><a href={`http://www.sei.pku.edu.cn`} target="_blank">北京大学</a></li>
|
|
||||||
<li><a href={`http://scse.buaa.edu.cn`} target="_blank">北京航空航天大学</a></li>
|
|
||||||
<li><a href={`https://www.nju.edu.cn`} target="_blank">南京大学</a></li>
|
|
||||||
<li><a href={`https://www.xtu.edu.cn`} target="_blank">湘潭大学</a></li>
|
|
||||||
<li><a href={`http://www.iscas.ac.cn`} target="_blank">ISCAS</a></li>
|
|
||||||
<li><a href={`https://www.ucloud.cn`} target="_blank">UCloud优刻得</a></li>
|
|
||||||
<li><a href={`http://www.inforbus.com`} target="_blank">中创软件</a></li>
|
|
||||||
<li><a href={`https://www.inspur.com`} target="_blank">浪潮集团</a></li>
|
|
||||||
<li><a href={`http://www.copu.org.cn`} target="_blank">中国开源软件推进联盟</a></li>
|
|
||||||
<li><a href={`https://www.sjtu.edu.cn`} target="_blank">上海交通大学</a></li>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li>合作伙伴</li>
|
|
||||||
<li><span>热线:</span></li>
|
|
||||||
<li><span>QQ群:1071514693</span></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<p className="footerCopy">© Copyright 2007~2021 国防科技大学Trustie团队 & IntelliDE <a href="https://beian.miit.gov.cn">湘ICP备 17009477号</a></p> */}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export default Footer;
|
|
||||||
|
|
@ -1,728 +0,0 @@
|
||||||
import React, { Component } from 'react';
|
|
||||||
import AccountProfile from "../../modules/user/AccountProfile";
|
|
||||||
import { getImageUrl } from 'educoder'
|
|
||||||
import axios from 'axios';
|
|
||||||
import { Modal, Input, message, notification , Dropdown , Menu } 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;
|
|
||||||
|
|
@ -1,68 +0,0 @@
|
||||||
|
|
||||||
.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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -6,6 +6,7 @@ import { withRouter } from "react-router";
|
||||||
import { SnackbarHOC } from "educoder";
|
import { SnackbarHOC } from "educoder";
|
||||||
import { CNotificationHOC } from "../modules/courses/common/CNotificationHOC";
|
import { CNotificationHOC } from "../modules/courses/common/CNotificationHOC";
|
||||||
import { TPMIndexHOC } from "../modules/tpm/TPMIndexHOC";
|
import { TPMIndexHOC } from "../modules/tpm/TPMIndexHOC";
|
||||||
|
import Handbook from './Component/Handbook';
|
||||||
import "./css/index.scss";
|
import "./css/index.scss";
|
||||||
|
|
||||||
import Loadable from "react-loadable";
|
import Loadable from "react-loadable";
|
||||||
|
|
@ -30,29 +31,20 @@ 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) => (
|
||||||
|
|
|
||||||
|
|
@ -1,449 +0,0 @@
|
||||||
import React , { useEffect , useState } from 'react';
|
|
||||||
import { WhiteBack , Box , LongWidth , ShortWidth , Gap , AlignCenter , FlexAJ } from '../Component/layout';
|
|
||||||
import { Dropdown , Menu , Divider , Spin, Button } from 'antd';
|
|
||||||
import { getImageUrl } from "educoder";
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import CloneAddress from '../Branch/CloneAddress';
|
|
||||||
|
|
||||||
import SelectBranch from '../Branch/Select';
|
|
||||||
import User from '../Component/User';
|
|
||||||
import axios from 'axios';
|
|
||||||
import Path from './CoderDepotPath';
|
|
||||||
import Catalogue from './CoderDepotCatalogue';
|
|
||||||
import ReadMe from './CoderDepotReadme';
|
|
||||||
import CoderRootFileDetail from './CoderRootFileDetail';
|
|
||||||
import './Index.scss';
|
|
||||||
import Releases from '../Component/Releases';
|
|
||||||
import Contributors from '../Component/Contributors';
|
|
||||||
import LanguagePower from '../Component/LanguagePower';
|
|
||||||
import DrawerPanel from '../Component/DrawerPanel';
|
|
||||||
import UpdateDescModal from './sub/UpdateDescModal';
|
|
||||||
import Nodata from '../Nodata';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* projectDetail.type:0是托管项目,1是镜像项目,2是同步镜像项目(为2时不支持在线创建、在线上传、在线修改、在线删除、创建合并请求等功能)
|
|
||||||
*/
|
|
||||||
function CoderDepot(props){
|
|
||||||
const [ projectDetail , setProjectDetail ]= useState(undefined);
|
|
||||||
const [ treeValue , setTreeValue ] = useState(undefined);
|
|
||||||
const [ treeValuePath , setTreeValuePath ] = useState(undefined);
|
|
||||||
const [ lastCommit,setLastCommit ] = useState(undefined);
|
|
||||||
const [ lastCommitAuthor,setLastCommitAuthor ] = useState(undefined);
|
|
||||||
const [ type ,setType ] = useState('dir');
|
|
||||||
const [ hide , setHide ] = useState(true);
|
|
||||||
const [ hideBtn , setHideBtn ] = useState(false);
|
|
||||||
const [ commitCount ,setCommitCount ] = useState(0);
|
|
||||||
const [ dirInfo ,setDirInfo ] = useState(undefined);//文件夹目录列表
|
|
||||||
const [ fileInfo ,setFileInfo ] = useState(undefined);//文件内容信息
|
|
||||||
const [ zip_url , setZip_url ] = useState(undefined);
|
|
||||||
const [ tar_url , setTar_url ] = useState(undefined);
|
|
||||||
const [ readOnly , setReadOnly] = useState(true);
|
|
||||||
const [ isSpin , setIsSpin] = useState(true);
|
|
||||||
const [ visible ,setVisible ] = useState(false);
|
|
||||||
const [ mainFlag ,setMainFlag ] = useState(false);
|
|
||||||
const [ openModal , setOpenModal ] = useState(false);
|
|
||||||
const [ desc , setDesc ] = useState(undefined);
|
|
||||||
const [ website , setWebsite ] = useState(undefined);
|
|
||||||
const [ lesson_url , setLessonUrl ] = useState(undefined);
|
|
||||||
|
|
||||||
const owner = props.match.params.owner;
|
|
||||||
const projectsId = props.match.params.projectsId;
|
|
||||||
const branchName = props.match.params.branchName;
|
|
||||||
let pathname = props.history.location.pathname;
|
|
||||||
useEffect(()=>{
|
|
||||||
if(props.projectDetail){
|
|
||||||
setProjectDetail(props.projectDetail);
|
|
||||||
setDesc(props.projectDetail.description);
|
|
||||||
setWebsite(props.projectDetail.website);
|
|
||||||
setLessonUrl(props.projectDetail.lesson_url);
|
|
||||||
}
|
|
||||||
},[props])
|
|
||||||
|
|
||||||
useEffect(()=>{
|
|
||||||
if(treeValue){
|
|
||||||
setTreeValuePath(treeValue.split('/'));
|
|
||||||
}else{
|
|
||||||
setTreeValuePath(undefined);
|
|
||||||
}
|
|
||||||
},[treeValue])
|
|
||||||
|
|
||||||
useEffect(()=>{
|
|
||||||
if (pathname && projectDetail){
|
|
||||||
if(pathname.indexOf(`/projects/${owner}/${projectsId}`) > -1 && pathname.indexOf(`/tree/${branchName}/`) > -1) {
|
|
||||||
let url = pathname.split(`/tree/${branchName}/`)[1];
|
|
||||||
setTreeValue(url);
|
|
||||||
getFileInfo(url,branchName);
|
|
||||||
}else{
|
|
||||||
setTreeValue(undefined);
|
|
||||||
getDirInfo(branchName ||projectDetail.default_branch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},[pathname,projectDetail])
|
|
||||||
|
|
||||||
// 获取主目录列表
|
|
||||||
function getDirInfo(branch){
|
|
||||||
setIsSpin(true);
|
|
||||||
const url = `/${owner}/${projectsId}/entries.json`;
|
|
||||||
axios.get(url, {
|
|
||||||
params: { ref: branch }
|
|
||||||
}).then((result) => {
|
|
||||||
if (result) {
|
|
||||||
setCommitCount(result.data.commits_count);
|
|
||||||
setDirInfo(result.data.entries);
|
|
||||||
setFileInfo(undefined);
|
|
||||||
setTar_url(result.data.tar_url);
|
|
||||||
setZip_url(result.data.zip_url);
|
|
||||||
let c = result.data.last_commit
|
|
||||||
setLastCommit(c && c.commit);
|
|
||||||
setLastCommitAuthor(c && c.committer);
|
|
||||||
setMainFlag(true);
|
|
||||||
setReadOnly(true);
|
|
||||||
}
|
|
||||||
setTimeout(function(){setIsSpin(false);},500);
|
|
||||||
}).catch(error=>{setIsSpin(false);})
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(()=>{
|
|
||||||
if(projectDetail && lastCommit)
|
|
||||||
{
|
|
||||||
let ele = document.getElementById("ptxt");
|
|
||||||
if(ele){
|
|
||||||
let h = ele.offsetHeight;
|
|
||||||
if( h > 18 ) setHideBtn(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},[projectDetail,lastCommit])
|
|
||||||
// 获取子目录列表
|
|
||||||
function getFileInfo(path, ref){
|
|
||||||
setIsSpin(true);
|
|
||||||
const url = `/${owner}/${projectsId}/sub_entries.json`;
|
|
||||||
axios.get(url, {
|
|
||||||
params:{
|
|
||||||
filepath:path,
|
|
||||||
ref:ref || branchName,
|
|
||||||
type
|
|
||||||
}
|
|
||||||
}).then((result) => {
|
|
||||||
if (result) {
|
|
||||||
let en = result.data.entries;
|
|
||||||
if(en.type){
|
|
||||||
setDirInfo(undefined);
|
|
||||||
setFileInfo(en);
|
|
||||||
setType(en.type);
|
|
||||||
}else{
|
|
||||||
setFileInfo(undefined);
|
|
||||||
setDirInfo(en);
|
|
||||||
setType("dir");
|
|
||||||
}
|
|
||||||
let c = result.data.last_commit
|
|
||||||
setLastCommit(c && c.commit);
|
|
||||||
setLastCommitAuthor(c && c.committer);
|
|
||||||
setMainFlag(false);
|
|
||||||
setReadOnly(true);
|
|
||||||
}
|
|
||||||
setTimeout(function(){setIsSpin(false);},500)
|
|
||||||
}).catch(error=>{setIsSpin(false);})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 切换分支或者标签
|
|
||||||
function changeBranch(value){
|
|
||||||
let url = `/projects/${owner}/${projectsId}${value && `/tree/${value}`}${treeValue ? `/${treeValue}`:""}`;
|
|
||||||
props.history.push(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 文件相关的下拉项
|
|
||||||
const fileMenu =(
|
|
||||||
<Menu>
|
|
||||||
<Menu.Item><a onClick={()=>urlLink(`/projects/${owner}/${projectsId}/${branchName || (projectDetail && projectDetail.default_branch)}/uploadfile${treeValue === undefined ? "" : `/${treeValue}`}`)}>上传文件</a></Menu.Item>
|
|
||||||
<Menu.Item><a onClick={()=>urlLink(`/projects/${owner}/${projectsId}/${branchName || (projectDetail && projectDetail.default_branch)}/newfile${treeValue === undefined ? "" : `/${treeValue}`}`)}>新建文件</a></Menu.Item>
|
|
||||||
</Menu>
|
|
||||||
)
|
|
||||||
|
|
||||||
function getPathUrl(array,index){
|
|
||||||
if(array && array.length>0 && index){
|
|
||||||
let str = "";
|
|
||||||
for(let i=0;i<index;i++){
|
|
||||||
str += `/${array[i]}`;
|
|
||||||
}
|
|
||||||
return str.substr(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 页面地址返回到主目录
|
|
||||||
function returnMain(){
|
|
||||||
setTreeValue(undefined);
|
|
||||||
let branch = branchName || (projectDetail && projectDetail.default_branch);
|
|
||||||
props.history.push(`/projects/${owner}/${projectsId}/tree/${branch}`);
|
|
||||||
};
|
|
||||||
// 子目录路径返回链接
|
|
||||||
function returnUlr(url){
|
|
||||||
props.history.push(`/projects/${owner}/${projectsId}/tree${branchName?`/${branchName}`:""}/${url}`);
|
|
||||||
}
|
|
||||||
// 点击跳转到子目录
|
|
||||||
function goToSubRoot(path,type,filename){
|
|
||||||
setType(type);
|
|
||||||
props.history.push(`/projects/${owner}/${projectsId}${`/tree/${branchName || (projectDetail && projectDetail.default_branch)}`}${path?`/${path}`:""}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onEdit(readOnly){
|
|
||||||
setReadOnly(readOnly);
|
|
||||||
}
|
|
||||||
function ChangeFile(path, readOnly){
|
|
||||||
//点击直接跳转页面 加载一次路由
|
|
||||||
props.history.push(`/projects/${owner}/${projectsId}/tree/${branchName || (projectDetail && projectDetail.default_branch)}/${path}`);
|
|
||||||
setType("file");
|
|
||||||
setReadOnly(readOnly);
|
|
||||||
};
|
|
||||||
|
|
||||||
function changeHide(hide){
|
|
||||||
setHide(!hide);
|
|
||||||
}
|
|
||||||
|
|
||||||
function urlLink(link){
|
|
||||||
if(props.checkIfLogin()===false){
|
|
||||||
props.showLoginDialog()
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
props.history.push(link);
|
|
||||||
}
|
|
||||||
|
|
||||||
const downloadMenu = (
|
|
||||||
<div className="downMenu">
|
|
||||||
<div style={{padding:"20px",borderBottom:"1px solid #eee"}}>
|
|
||||||
<CloneAddress
|
|
||||||
http_url={projectDetail && projectDetail.clone_url}
|
|
||||||
showNotification={props.showNotification}/>
|
|
||||||
</div>
|
|
||||||
<Menu className="edu-txt-center">
|
|
||||||
<Menu.Item><a href={zip_url}>下载 ZIP</a></Menu.Item>
|
|
||||||
<Menu.Item><a href={tar_url}>下载 TAR.GZ</a></Menu.Item>
|
|
||||||
</Menu>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
// 确认修改简介、website、实践课程链接
|
|
||||||
function okUpdate(d,w,l){
|
|
||||||
const url = `/${owner}/${projectsId}.json`;
|
|
||||||
axios.put(url,{
|
|
||||||
description:d,website:w,lesson_url:l
|
|
||||||
}).then(result=>{
|
|
||||||
if(result && result.data && result.data.id){
|
|
||||||
setDesc(result.data.description);
|
|
||||||
setWebsite(result.data.website);
|
|
||||||
setLessonUrl(result.data.lesson_url);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
let n = fileInfo && fileInfo.name;
|
|
||||||
const mdFlag = n && n.substring(n.length-3,n.length) === ".md";
|
|
||||||
|
|
||||||
return(
|
|
||||||
<WhiteBack>
|
|
||||||
<UpdateDescModal desc={desc} website={website} lesson_url={lesson_url} visible={openModal} onCancel={()=>setOpenModal(false)} onOk={okUpdate}/>
|
|
||||||
<Spin spinning={isSpin}>
|
|
||||||
{
|
|
||||||
(dirInfo || fileInfo) &&
|
|
||||||
<React.Fragment>
|
|
||||||
<DrawerPanel
|
|
||||||
history={props.history}
|
|
||||||
owner={owner}
|
|
||||||
projectsId={projectsId}
|
|
||||||
name={projectDetail && projectDetail.name}
|
|
||||||
branch={branchName || (projectDetail && projectDetail.default_branch)}
|
|
||||||
visible={visible}
|
|
||||||
onClose={()=>setVisible(false)}
|
|
||||||
list = {mainFlag ? dirInfo : undefined}
|
|
||||||
/>
|
|
||||||
<div className="drawerBtn" onClick={()=>setVisible(true)}>
|
|
||||||
<i className="iconfont icon-youjiantou font-16"></i>
|
|
||||||
<span>目录</span>
|
|
||||||
</div>
|
|
||||||
</React.Fragment>
|
|
||||||
}
|
|
||||||
<div style={{minHeight:"500px"}}>
|
|
||||||
{
|
|
||||||
projectDetail &&
|
|
||||||
<Box className="Panels">
|
|
||||||
<LongWidth>
|
|
||||||
<div className="panelmenu">
|
|
||||||
<FlexAJ>
|
|
||||||
<AlignCenter>
|
|
||||||
<div className="mr20">
|
|
||||||
{
|
|
||||||
props && props.platform ?
|
|
||||||
<SelectBranch
|
|
||||||
repo_id={projectDetail && projectDetail.repo_id}
|
|
||||||
projectsId={projectsId}
|
|
||||||
branch={branchName || (projectDetail && projectDetail.default_branch)}
|
|
||||||
changeBranch={changeBranch}
|
|
||||||
owner={owner}
|
|
||||||
history={props.history}
|
|
||||||
branchList={projectDetail && projectDetail.branches && projectDetail.branches.list}
|
|
||||||
></SelectBranch>
|
|
||||||
:
|
|
||||||
<span>分支:<span className="color-grey-6">{branchName || (projectDetail && projectDetail.default_branch)}</span></span>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
<AlignCenter className="mr20">
|
|
||||||
<Link to={`/projects/${owner}/${projectsId}/branchs`} className="color-grey-9">
|
|
||||||
<i className="iconfont icon-fenzhi2 font-18 color-grey-9 mr3"></i>
|
|
||||||
<span className="color-grey-6 mr3">{projectDetail && projectDetail.branches && projectDetail.branches.total_count}个</span>分支
|
|
||||||
</Link>
|
|
||||||
</AlignCenter>
|
|
||||||
<AlignCenter className="mr20">
|
|
||||||
<Link to={`/projects/${owner}/${projectsId}/tag`} className="color-grey-9">
|
|
||||||
<i className="iconfont icon-biaoqian3 font-16 color-grey-9 mr3"></i>
|
|
||||||
<span className="color-grey-6 mr3">{projectDetail && projectDetail.tags && projectDetail.tags.total_count}个</span>标签
|
|
||||||
</Link>
|
|
||||||
</AlignCenter>
|
|
||||||
</AlignCenter>
|
|
||||||
<AlignCenter>
|
|
||||||
<div className="mr20 addOptionBtn">
|
|
||||||
{
|
|
||||||
projectDetail.type !== 2 &&
|
|
||||||
<a onClick={()=>urlLink(`/projects/${owner}/${projectsId}/pulls/new`)} >+ 合并请求</a>
|
|
||||||
}
|
|
||||||
<a onClick={()=>urlLink(`/projects/${owner}/${projectsId}/issues/new`)} >+ 任务</a>
|
|
||||||
</div>
|
|
||||||
{ type === "dir" && projectDetail.type !== 2 &&
|
|
||||||
<Dropdown overlay={fileMenu} className="mr20" 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;
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import { truncateCommitId } from '../common/util';
|
|
||||||
|
|
||||||
function CoderDepotCatalogue({item , goToSubRoot , owner , projectsId }){
|
|
||||||
return(
|
|
||||||
<li>
|
|
||||||
<span>
|
|
||||||
<a onClick={()=>goToSubRoot(item.path,item.type,item.name)}>
|
|
||||||
<i className={item.type === 'dir' ? "iconfont icon-wenjianjia1 color-green-file font-15 mr5":"iconfont icon-wenjia color-green-file font-15 mr5"}></i>{item.name}
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
<span title="init project">
|
|
||||||
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${item.commit && item.commit.sha}`)}`} title={item.commit && item.commit.message}>
|
|
||||||
{item.commit && item.commit.message}
|
|
||||||
</Link>
|
|
||||||
</span>
|
|
||||||
<span>{item.commit && item.commit.time_from_now}</span>
|
|
||||||
</li>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export default CoderDepotCatalogue;
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
|
|
||||||
function CoderDepotPath({treeValuePath , returnUlr , returnMain , getPathUrl , identifier}){
|
|
||||||
return(
|
|
||||||
<li className="listtablepath">
|
|
||||||
<p>
|
|
||||||
<a
|
|
||||||
onClick={returnMain}
|
|
||||||
className="color-blue"
|
|
||||||
>
|
|
||||||
{identifier}
|
|
||||||
</a>
|
|
||||||
{treeValuePath.map((item, key) => {
|
|
||||||
return (
|
|
||||||
<React.Fragment>
|
|
||||||
{
|
|
||||||
key === treeValuePath.length-1 ?
|
|
||||||
<span className="color-grey-6 subFileName" key={key}>{item}</span>
|
|
||||||
:
|
|
||||||
<a onClick={()=>returnUlr(`${getPathUrl(treeValuePath,key+1)}`)} className="color-blue subFileName">{item}</a>
|
|
||||||
}
|
|
||||||
</React.Fragment>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</p>
|
|
||||||
</li>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export default CoderDepotPath;
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
|
||||||
import RenderHtml from '../../components/render-html';
|
|
||||||
import { Dropdown , Menu , Spin } from 'antd';
|
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
const $ = window.$;
|
|
||||||
|
|
||||||
function CoderDepotReadme({ operate , history , readme , ChangeFile }){
|
|
||||||
const [ menuList ,setMenuList ] = useState(undefined);
|
|
||||||
|
|
||||||
useEffect(()=>{
|
|
||||||
if(readme && readme.content){
|
|
||||||
let path = history.location.pathname;
|
|
||||||
const items = $.map($("#readme").find("h1,h2,h3,h4,h5,h6"), function (el, _) {
|
|
||||||
const anchor = el.id;
|
|
||||||
const level = el.tagName.replace("H", "");
|
|
||||||
const href = `#${anchor}`;
|
|
||||||
return { href:`${path}${href}`,text:el.textContent , level:level }
|
|
||||||
});
|
|
||||||
setMenuList(items);
|
|
||||||
}
|
|
||||||
},[readme])
|
|
||||||
|
|
||||||
function menu(){
|
|
||||||
if(menuList && menuList.length > 0){
|
|
||||||
let hash = history.location.hash;
|
|
||||||
return(
|
|
||||||
<Menu className="menuslist">
|
|
||||||
{
|
|
||||||
menuList.map((item,key)=>{
|
|
||||||
return(
|
|
||||||
<Menu.Item key={item.id} className={decodeURI(hash).indexOf(item.text)>-1 ?"active":""}><Link to={`${item.href}`} style={{paddingLeft:`${item.level *10}px`}} title={item.text}>{item.text}</Link></Menu.Item>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</Menu>
|
|
||||||
)
|
|
||||||
}else{
|
|
||||||
return <Spin />
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return(
|
|
||||||
<div className="commonBox" id="readme">
|
|
||||||
<div className="commonBox-title">
|
|
||||||
<Dropdown overlay={menu()}>
|
|
||||||
<i className="iconfont icon-zhangjie1 font-16 color-grey-3 mr10"></i>
|
|
||||||
</Dropdown>
|
|
||||||
<span className="commonBox-title-read">README.md</span>
|
|
||||||
{
|
|
||||||
operate ?
|
|
||||||
<a className="ml20 pull-right" onClick={() =>ChangeFile(readme && readme.path, false)}>
|
|
||||||
<i className="iconfont icon-bianji6 font-16 color-blue"></i>
|
|
||||||
</a>
|
|
||||||
:""
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
<div className="commonBox-info">
|
|
||||||
<RenderHtml className="break_word_comments imageLayerParent" value={readme && readme.content} url={history.location}/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
export default CoderDepotReadme;
|
|
||||||
|
|
@ -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,7 +32,7 @@ export default ((props)=>{
|
||||||
return(
|
return(
|
||||||
<li key={key}>
|
<li key={key}>
|
||||||
<div>
|
<div>
|
||||||
<Link to={`/projects/${owner}/${projectsId}/tree/${item.name}`} className="color-blue font-15" style={{"maxWidth":"100px"}}>{item.name}</Link>
|
<Link to={`/projects/${owner}/${projectsId}?branch=${item.name}`} className="color-blue font-15" style={{"maxWidth":"100px"}}>{item.name}</Link>
|
||||||
<p className="f-wrap-alignCenter mt15">
|
<p className="f-wrap-alignCenter mt15">
|
||||||
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${item.last_commit.sha}`)}`} className="mr5 commitKey" style={{marginLeft:0}}>{item.last_commit && truncateCommitId(item.last_commit.sha)}</Link>
|
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${item.last_commit.sha}`)}`} className="mr5 commitKey" style={{marginLeft:0}}>{item.last_commit && truncateCommitId(item.last_commit.sha)}</Link>
|
||||||
<span className="color-grey-3 hide-1 messages leftPoint">{item.last_commit && item.last_commit.message}</span>
|
<span className="color-grey-3 hide-1 messages leftPoint">{item.last_commit && item.last_commit.message}</span>
|
||||||
|
|
@ -54,8 +54,6 @@ 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)=> (
|
||||||
|
|
@ -70,7 +68,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>
|
||||||
<div style={{minHeight:"400px"}}>{list()}</div>
|
{list()}
|
||||||
</div>
|
</div>
|
||||||
</Spin>
|
</Spin>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -12,44 +12,21 @@ class CoderRootCommit extends Component{
|
||||||
constructor(props){
|
constructor(props){
|
||||||
super(props)
|
super(props)
|
||||||
this.state={
|
this.state={
|
||||||
|
branch:"master",
|
||||||
commitDatas:undefined,
|
commitDatas:undefined,
|
||||||
dataCount:undefined,
|
dataCount:undefined,
|
||||||
limit:20,
|
limit:20,
|
||||||
page:1,
|
page:1,
|
||||||
isSpining:false,
|
isSpining:false
|
||||||
branchList:undefined
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount=()=>{
|
componentDidMount=()=>{
|
||||||
this.Init();
|
const { branch , page , limit } = this.state;
|
||||||
this.getBranchs();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取分支列表
|
|
||||||
getBranchs=()=>{
|
|
||||||
const { projectsId , owner } = this.props.match.params;
|
|
||||||
axios.get(`/${owner}/${projectsId}/branches.json`).then(result=>{
|
|
||||||
this.setState({
|
|
||||||
branchList:result.data
|
|
||||||
})
|
|
||||||
}).catch((error)=>{})
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate=(prevProps)=>{
|
|
||||||
const { location } = this.props;
|
|
||||||
const prevlocation = prevProps && prevProps.location;
|
|
||||||
if (location !== prevlocation) {
|
|
||||||
this.Init();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Init =()=>{
|
|
||||||
const { branchName } = this.props.match.params;
|
|
||||||
const { page , limit } = this.state;
|
|
||||||
this.setState({
|
this.setState({
|
||||||
isSpining:true
|
isSpining:true
|
||||||
})
|
})
|
||||||
this.getCommitList( branchName , page , limit );
|
this.getCommitList( branch , page , limit );
|
||||||
}
|
}
|
||||||
|
|
||||||
getCommitList=(branch , page , limit)=>{
|
getCommitList=(branch , page , limit)=>{
|
||||||
|
|
@ -74,7 +51,6 @@ class CoderRootCommit extends Component{
|
||||||
array.push({
|
array.push({
|
||||||
name:item.author && item.author.name,
|
name:item.author && item.author.name,
|
||||||
login: item.author && item.author.login,
|
login: item.author && item.author.login,
|
||||||
id: item.author && item.author.id,
|
|
||||||
image_url:item.author && item.author.image_url,
|
image_url:item.author && item.author.image_url,
|
||||||
sha:item.sha,
|
sha:item.sha,
|
||||||
time_from_now:item.time_from_now,
|
time_from_now:item.time_from_now,
|
||||||
|
|
@ -92,23 +68,29 @@ class CoderRootCommit extends Component{
|
||||||
|
|
||||||
// 切换分支 search:tag为根据标签搜索
|
// 切换分支 search:tag为根据标签搜索
|
||||||
changeBranch=(value)=>{
|
changeBranch=(value)=>{
|
||||||
const { projectsId , owner } = this.props.match.params;
|
const { page , limit } = this.state;
|
||||||
this.props.history.push(`/projects/${owner}/${projectsId}/commits/branch/${value}`);
|
const { getTopCount } = this.props;
|
||||||
|
this.setState({
|
||||||
|
isSpining:true,
|
||||||
|
branch:value,
|
||||||
|
})
|
||||||
|
this.getCommitList(value , page , limit);
|
||||||
|
getTopCount && getTopCount(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
ChangePage=(page)=>{
|
ChangePage=(page)=>{
|
||||||
const { branchName } = this.props.match.params;
|
|
||||||
const { limit } = this.state;
|
const { branch , limit } = this.state;
|
||||||
this.getCommitList(branchName , page , limit);
|
this.getCommitList(branch , page , limit);
|
||||||
}
|
}
|
||||||
render(){
|
render(){
|
||||||
const { commitDatas , dataCount , limit , page , isSpining , branchList } = this.state;
|
const { branch , commitDatas , dataCount , limit , page , isSpining } = this.state;
|
||||||
const { projectDetail, commit_class , defaultBranch } = this.props;
|
const { branchs , projectDetail, commit_class } = this.props;
|
||||||
const { projectsId , owner , branchName } = this.props.match.params;
|
const { projectsId , owner } = this.props.match.params;
|
||||||
let branch = branchName || defaultBranch;
|
|
||||||
return(
|
return(
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<div className={"main"}style={{padding:"0px",border:"none"}}>
|
<div className={commit_class}>
|
||||||
<div className="f-wrap-between">
|
<div className="f-wrap-between">
|
||||||
<SelectBranch
|
<SelectBranch
|
||||||
repo_id={projectDetail && projectDetail.repo_id}
|
repo_id={projectDetail && projectDetail.repo_id}
|
||||||
|
|
@ -116,8 +98,6 @@ class CoderRootCommit extends Component{
|
||||||
branch={branch}
|
branch={branch}
|
||||||
changeBranch={this.changeBranch}
|
changeBranch={this.changeBranch}
|
||||||
owner={owner}
|
owner={owner}
|
||||||
history={this.props.history}
|
|
||||||
branchList={branchList}
|
|
||||||
></SelectBranch>
|
></SelectBranch>
|
||||||
</div>
|
</div>
|
||||||
<Spin spinning={isSpining}>
|
<Spin spinning={isSpining}>
|
||||||
|
|
@ -129,7 +109,7 @@ class CoderRootCommit extends Component{
|
||||||
</div>
|
</div>
|
||||||
<div className="commitList">
|
<div className="commitList">
|
||||||
{
|
{
|
||||||
commitDatas && commitDatas.length > 0 && commitDatas.map((item,k)=>{
|
commitDatas && commitDatas.length > 0 ? commitDatas.map((item,k)=>{
|
||||||
return(
|
return(
|
||||||
<div key={k}>
|
<div key={k}>
|
||||||
<p className="f-wrap-alignCenter">
|
<p className="f-wrap-alignCenter">
|
||||||
|
|
@ -137,24 +117,15 @@ class CoderRootCommit extends Component{
|
||||||
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${item.sha}`)}`} className="flex1 ml20 font-16 color-grey-3">{item.message}</Link>
|
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${item.sha}`)}`} className="flex1 ml20 font-16 color-grey-3">{item.message}</Link>
|
||||||
</p>
|
</p>
|
||||||
<p className="f-wrap-alignCenter mt15">
|
<p className="f-wrap-alignCenter mt15">
|
||||||
{
|
<Link to={`/users/${item.login}`} className="show-user-link">
|
||||||
item.id ?
|
{item.image_url?<img src={getImageUrl(`images/${item.image_url}`)} alt="" width="28px" height="28px" className="mr15 radius"/>:""}
|
||||||
<Link to={`/users/${item.login}`} className="show-user-link">
|
<label className="font-14 color-grey-6" style={{'verticalAlign':'middle'}}>{item.name ?`${item.name}:`:""}提交于 {item.time_from_now}</label>
|
||||||
{item.image_url?<img src={getImageUrl(`/${item.image_url}`)} alt="" width="28px" height="28px" className="mr15 radius"/>:""}
|
</Link>
|
||||||
<label className="font-14 color-grey-6" style={{verticalAlign:'middle'}}>{item.name ?`${item.name}:`:""}提交于 {item.time_from_now}</label>
|
|
||||||
</Link>:
|
|
||||||
<span className="show-user-link">
|
|
||||||
{item.image_url?<img src={getImageUrl(`/${item.image_url}`)} alt="" width="28px" height="28px" className="mr15 radius"/>:""}
|
|
||||||
<label className="font-14 color-grey-6" style={{verticalAlign:'middle'}}>{item.name ?`${item.name}:`:""}提交于 {item.time_from_now}</label>
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})
|
}):<Nodata _html="暂无数据"/>
|
||||||
}
|
}
|
||||||
{commitDatas && commitDatas.length === 0 && <Nodata _html="暂无数据"/>}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,561 @@
|
||||||
|
import React, { Component } from "react";
|
||||||
|
import { Menu, Spin } from "antd";
|
||||||
|
import { getImageUrl } from "educoder";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
|
||||||
|
import './list.css';
|
||||||
|
import SelectBranch from '../Branch/Select';
|
||||||
|
import CloneAddress from '../Branch/CloneAddress';
|
||||||
|
import RootTable from './RootTable';
|
||||||
|
import CoderRootFileDetail from './CoderRootFileDetail';
|
||||||
|
import { truncateCommitId } from '../common/util';
|
||||||
|
import RenderHtml from '../../components/render-html';
|
||||||
|
import Nodata from '../Nodata';
|
||||||
|
|
||||||
|
import axios from "axios";
|
||||||
|
/**
|
||||||
|
* address:http和SSH,http_url(对应git地址)
|
||||||
|
* branch:当前分支
|
||||||
|
* filePath:点击目录时当前目录的路径
|
||||||
|
* subfileType:保存当前点击目录的文件类型(显示目录列表时才显示新建文件,如果点击的是文件就不显示新建文件按钮)
|
||||||
|
* readMeContent:根目录下面的readme文件内容
|
||||||
|
*/
|
||||||
|
function getPathUrl(array,index){
|
||||||
|
if(array && array.length>0 && index){
|
||||||
|
let str = "";
|
||||||
|
for(let i=0;i<index;i++){
|
||||||
|
str += `/${array[i]}`;
|
||||||
|
}
|
||||||
|
return str.substr(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class CoderRootDirectory extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
address: "http",
|
||||||
|
branch: "master",
|
||||||
|
filePath: undefined,
|
||||||
|
subFileType: undefined,
|
||||||
|
readMeContent: undefined,
|
||||||
|
readMeFile: undefined,
|
||||||
|
|
||||||
|
isSpin: true,
|
||||||
|
|
||||||
|
branchList: undefined,
|
||||||
|
fileDetail: undefined,
|
||||||
|
branchLastCommit: undefined,
|
||||||
|
lastCommitAuthor: undefined,
|
||||||
|
|
||||||
|
rootList: undefined,
|
||||||
|
readOnly: true,
|
||||||
|
zip_url:undefined,
|
||||||
|
tar_url:undefined,
|
||||||
|
chooseType:undefined,
|
||||||
|
|
||||||
|
md:false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
changeAddress = (address) => {
|
||||||
|
this.setState({
|
||||||
|
address,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidMount = () => {
|
||||||
|
this.Init();
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidUpdate = (prevState) => {
|
||||||
|
const { location } = this.props;
|
||||||
|
const prevlocation = prevState && prevState.location;
|
||||||
|
if (location !== prevlocation) {
|
||||||
|
this.setState({
|
||||||
|
isSpin: true,
|
||||||
|
});
|
||||||
|
this.Init();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Init = () => {
|
||||||
|
let { search } = this.props.history.location;
|
||||||
|
let branchName = undefined;
|
||||||
|
if (search && (search.indexOf("?branch=") > -1 || search.indexOf("&branch=") > -1)) {
|
||||||
|
branchName = search.split("branch=")[1];
|
||||||
|
|
||||||
|
if(branchName && branchName.indexOf("&")){
|
||||||
|
branchName=branchName.split("&")[0];
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
branch: branchName,
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
branchName = undefined;
|
||||||
|
this.setState({
|
||||||
|
branch: "master",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (search && (search.indexOf("?url=") > -1 || search.indexOf("&url=") > -1)) {
|
||||||
|
let url = search.split("url=")[1];
|
||||||
|
if(url && decodeURI(url).indexOf("&")){
|
||||||
|
url=decodeURI(url).split("&")[0];
|
||||||
|
}
|
||||||
|
this.getFileDetail(decodeURI(url),branchName);
|
||||||
|
} else {
|
||||||
|
const { branch } = this.state;
|
||||||
|
this.getProjectRoot(branchName || branch);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 页面地址返回到主目录
|
||||||
|
returnMain = (branch) => {
|
||||||
|
const { projectsId , owner } = this.props.match.params;
|
||||||
|
this.setState({
|
||||||
|
readOnly:true
|
||||||
|
})
|
||||||
|
this.props.history.push(`/projects/${owner}/${projectsId}`);
|
||||||
|
this.getProjectRoot(branch);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取根目录
|
||||||
|
getProjectRoot = (branch) => {
|
||||||
|
const { projectsId , owner } = this.props.match.params;
|
||||||
|
const url = `/${owner}/${projectsId}/entries.json`;
|
||||||
|
axios.get(url, { params: { ref: branch } })
|
||||||
|
.then((result) => {
|
||||||
|
if (result) {
|
||||||
|
let last_commit = result.data && result.data.last_commit;
|
||||||
|
let entries = result.data && result.data.entries;
|
||||||
|
this.setState({
|
||||||
|
filePath: undefined,
|
||||||
|
fileDetail: undefined,
|
||||||
|
isSpin: false,
|
||||||
|
branchLastCommit: last_commit && last_commit.commit,
|
||||||
|
lastCommitAuthor:
|
||||||
|
last_commit && (last_commit.author || (last_commit.commit && last_commit.commit.author)),
|
||||||
|
zip_url: result.data.zip_url,
|
||||||
|
tar_url: result.data.tar_url
|
||||||
|
});
|
||||||
|
if (entries && entries.length > 0) {
|
||||||
|
this.renderData(entries);
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
rootList: entries,
|
||||||
|
subFileType: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).catch((error) => {});
|
||||||
|
};
|
||||||
|
|
||||||
|
ChangeFile = (arr, readOnly) => {
|
||||||
|
const { projectsId , owner } = this.props.match.params;
|
||||||
|
//点击直接跳转页面 加载一次路由
|
||||||
|
this.props.history.push(`/projects/${owner}/${projectsId}?url=${arr.path}`);
|
||||||
|
this.setState({
|
||||||
|
readOnly: readOnly,
|
||||||
|
chooseType:"file"
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
renderUrl = (name, path, type) => {
|
||||||
|
let list = [];
|
||||||
|
const { filePath } = this.state;
|
||||||
|
if (path.indexOf("/")) {
|
||||||
|
const array = path.split("/");
|
||||||
|
let str = "";
|
||||||
|
array.map((i, k) => {
|
||||||
|
str += "/" + i;
|
||||||
|
return list.push({
|
||||||
|
key: k,
|
||||||
|
index: k,
|
||||||
|
name: i,
|
||||||
|
path: str.substr(1),
|
||||||
|
type: filePath && filePath.length > 0 ? filePath[k] ? filePath[k].type : type : type,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
const { projectsId , owner } = this.props.match.params;
|
||||||
|
//点击直接跳转页面 加载一次路由
|
||||||
|
this.props.history.push(`/projects/${owner}/${projectsId}?url=${str.substr(1)}`);
|
||||||
|
} else {
|
||||||
|
list.push({
|
||||||
|
index: 0,
|
||||||
|
name,
|
||||||
|
path,
|
||||||
|
type,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
filePath: list,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取子目录
|
||||||
|
getFileDetail = (path, ref) => {
|
||||||
|
this.setState({
|
||||||
|
filePath: decodeURI(path),
|
||||||
|
});
|
||||||
|
const { projectsId ,owner } = this.props.match.params;
|
||||||
|
const { branch , chooseType } = this.state;
|
||||||
|
const url = `/${owner}/${projectsId}/sub_entries.json`;
|
||||||
|
axios.get(url,{
|
||||||
|
params:{
|
||||||
|
filepath:path,
|
||||||
|
ref:ref || branch,
|
||||||
|
type:chooseType
|
||||||
|
}
|
||||||
|
}).then((result)=>{
|
||||||
|
let entries = result.data && result.data.entries;
|
||||||
|
this.setState({
|
||||||
|
isSpin:false
|
||||||
|
})
|
||||||
|
if(result){
|
||||||
|
if(entries){
|
||||||
|
// 返回对象entries.type则是文件类型,否则是文件夹
|
||||||
|
if(entries.type){
|
||||||
|
this.setState({
|
||||||
|
fileDetail:[entries],
|
||||||
|
rootList:undefined,
|
||||||
|
subFileType:false
|
||||||
|
})
|
||||||
|
}else{
|
||||||
|
this.setState({
|
||||||
|
fileDetail:undefined,
|
||||||
|
rootList:entries,
|
||||||
|
branchLastCommit:result.data.last_commit && result.data.last_commit.commit,
|
||||||
|
lastCommitAuthor:result.data.last_commit && (result.data.last_commit.author || (result.data.last_commit.commit && result.data.last_commit.commit.author))
|
||||||
|
})
|
||||||
|
this.renderData(entries);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
this.setState({
|
||||||
|
fileDetail:undefined,
|
||||||
|
rootList:undefined,
|
||||||
|
isSpin:false,
|
||||||
|
subFileType:false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
this.setState({
|
||||||
|
isSpin:false
|
||||||
|
})
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
renderData = (data) => {
|
||||||
|
const rootList = [];
|
||||||
|
const readMeContent = [];
|
||||||
|
const readMeFile = [];
|
||||||
|
data && data.map((item, key) => {
|
||||||
|
rootList.push({
|
||||||
|
key,
|
||||||
|
message: item.commit && item.commit.message,
|
||||||
|
...item,
|
||||||
|
});
|
||||||
|
if (item.is_readme_file) {
|
||||||
|
readMeContent.push({ ...item });
|
||||||
|
readMeFile.push({ ...item });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.setState({
|
||||||
|
rootList: rootList,
|
||||||
|
readMeContent,
|
||||||
|
readMeFile,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 点击跳转到子目录
|
||||||
|
goToSubRoot=(path,type,filename)=>{
|
||||||
|
this.setState({
|
||||||
|
chooseType:type
|
||||||
|
})
|
||||||
|
const { projectsId, owner } = this.props.match.params;
|
||||||
|
this.props.history.push(`/projects/${owner}/${projectsId}?url=${path}`);
|
||||||
|
if(filename.substring(filename.length - 3) === ".md"){
|
||||||
|
this.setState({
|
||||||
|
md:true
|
||||||
|
})
|
||||||
|
}else{
|
||||||
|
this.setState({
|
||||||
|
md:false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// readme文件内容
|
||||||
|
renderReadMeContent = (readMeContent, permission) => {
|
||||||
|
const { fileDetail, readMeFile } = this.state;
|
||||||
|
if (fileDetail) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (readMeContent && readMeContent.length > 0) {
|
||||||
|
return (
|
||||||
|
<div className="commonBox">
|
||||||
|
<div className="commonBox-title">
|
||||||
|
<span className="mr10">
|
||||||
|
<i className="iconfont icon-wenjian1 font-16 color-grey-9 fl mt3"></i>
|
||||||
|
</span>
|
||||||
|
<span className="commonBox-title-read">
|
||||||
|
{readMeContent[0].name}
|
||||||
|
</span>
|
||||||
|
{permission ?
|
||||||
|
<a
|
||||||
|
onClick={() => this.ChangeFile(readMeFile[0], false)}
|
||||||
|
className="ml20 pull-right"
|
||||||
|
>
|
||||||
|
<i className="iconfont icon-bianji6 font-16 color-blue"></i>
|
||||||
|
</a>
|
||||||
|
:
|
||||||
|
""
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div className="commonBox-info">
|
||||||
|
{readMeContent[0].content ?
|
||||||
|
<RenderHtml className="break_word_comments imageLayerParent" value={readMeContent[0].content} />
|
||||||
|
:
|
||||||
|
<span>暂无~</span>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 选择分支
|
||||||
|
changeBranch = (value) => {
|
||||||
|
this.setState({
|
||||||
|
branch: value,
|
||||||
|
isSpin: true,
|
||||||
|
readOnly:true
|
||||||
|
});
|
||||||
|
const { getTopCount } = this.props;
|
||||||
|
getTopCount && getTopCount(value);
|
||||||
|
|
||||||
|
let { search } = this.props.history.location;
|
||||||
|
if (search && search.indexOf("?url=") > -1) {
|
||||||
|
let url = search.split("?url=")[1];
|
||||||
|
this.setState({
|
||||||
|
filePath: decodeURI(url),
|
||||||
|
});
|
||||||
|
this.getFileDetail(decodeURI(url), value);
|
||||||
|
} else {
|
||||||
|
this.getProjectRoot(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 子目录路径返回链接
|
||||||
|
returnUlr=(url)=>{
|
||||||
|
this.setState({
|
||||||
|
chooseType:"dir",
|
||||||
|
readOnly:true
|
||||||
|
})
|
||||||
|
const { projectsId , owner } = this.props.match.params;
|
||||||
|
this.props.history.push(`/projects/${owner}/${projectsId}?url=${url}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
onEdit=(readOnly)=>{
|
||||||
|
this.setState({
|
||||||
|
readOnly
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
downloadUrl = (zip_url,tar_url) => {
|
||||||
|
return(
|
||||||
|
<Menu>
|
||||||
|
{zip_url && (
|
||||||
|
<Menu.Item>
|
||||||
|
<a href={zip_url}>ZIP</a>
|
||||||
|
</Menu.Item>
|
||||||
|
)}
|
||||||
|
{tar_url && (
|
||||||
|
<Menu.Item>
|
||||||
|
<a href={tar_url}>TAR.GZ</a>
|
||||||
|
</Menu.Item>
|
||||||
|
)}
|
||||||
|
</Menu>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
title = (branchLastCommit,lastCommitAuthor) => {
|
||||||
|
if (branchLastCommit) {
|
||||||
|
const { projectsId , owner } = this.props.match.params;
|
||||||
|
return (
|
||||||
|
<div className="f-wrap-alignCenter">
|
||||||
|
{lastCommitAuthor ? (
|
||||||
|
<React.Fragment>
|
||||||
|
{lastCommitAuthor.login ? (
|
||||||
|
<Link
|
||||||
|
to={`/users/${lastCommitAuthor.login}/projects`}
|
||||||
|
className="show-user-link"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src={getImageUrl(`images/${lastCommitAuthor.image_url}`)}
|
||||||
|
className="radius mr10"
|
||||||
|
width="32"
|
||||||
|
height="32"
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
<span className="mr15">{lastCommitAuthor.name}</span>
|
||||||
|
</Link>
|
||||||
|
) : (
|
||||||
|
<span className="mr15">{lastCommitAuthor.name}</span>
|
||||||
|
)}
|
||||||
|
</React.Fragment>
|
||||||
|
) : (
|
||||||
|
""
|
||||||
|
)}
|
||||||
|
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${branchLastCommit.sha}`)}`} className="color-blue flex-1 hide-1">
|
||||||
|
{branchLastCommit.message}
|
||||||
|
</Link>
|
||||||
|
<span>{branchLastCommit.time_from_now}</span>
|
||||||
|
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${branchLastCommit.sha}`)}`} className="commitKey">
|
||||||
|
{truncateCommitId(branchLastCommit.sha)}
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render(){
|
||||||
|
const { branchLastCommit , lastCommitAuthor , rootList , branch ,filePath , fileDetail , subFileType , readMeContent, isSpin , zip_url , tar_url} = this.state;
|
||||||
|
const { isManager , isDeveloper , projectDetail , platform } = this.props;
|
||||||
|
|
||||||
|
const { projectsId , owner } = this.props.match.params;
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
dataIndex: 'name',
|
||||||
|
width:"30%",
|
||||||
|
render: (text,item) => (
|
||||||
|
<a onClick={()=>this.goToSubRoot(item.path,item.type,text)} className="ml12 task-hide" style={{ display: "block", maxWidth: "345px" }}>
|
||||||
|
<i className={ item.type === "file" ? "iconfont icon-wenjia font-15 color-green-file mr5" : "iconfont icon-wenjianjia1 color-green-file font-15 mr5"}></i>{text}
|
||||||
|
</a>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataIndex: "commit",
|
||||||
|
width: "60%",
|
||||||
|
render: (text, item) =>
|
||||||
|
item.commit && item.commit.message ?
|
||||||
|
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${item.commit.sha}`)}`} title={item.commit.message} className="task-hide" style={{ display: "block", maxWidth: "670px" }} >
|
||||||
|
{item.commit.message}
|
||||||
|
</Link>
|
||||||
|
: ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataIndex: "commit",
|
||||||
|
width: "10%",
|
||||||
|
className: "edu-txt-right",
|
||||||
|
render: (text, item) =>
|
||||||
|
item.commit && item.commit.time_from_now ?
|
||||||
|
<a title={item.commit.created_at} className="mr12" style={{ cursor: "default", color: "#888" }} >
|
||||||
|
{item.commit.time_from_now}
|
||||||
|
</a>
|
||||||
|
:""
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const urlRoot = filePath === undefined ? "" : `/${filePath}`;
|
||||||
|
let array = filePath && filePath.split("/");
|
||||||
|
return (
|
||||||
|
<Spin spinning={isSpin}>
|
||||||
|
<div className="main">
|
||||||
|
<div className="f-wrap-between mb20">
|
||||||
|
<div className="f-wrap-alignCenter">
|
||||||
|
{
|
||||||
|
platform ?
|
||||||
|
<SelectBranch
|
||||||
|
repo_id={projectDetail && projectDetail.repo_id}
|
||||||
|
projectsId={projectsId}
|
||||||
|
branch={branch}
|
||||||
|
changeBranch={this.changeBranch}
|
||||||
|
owner={owner}
|
||||||
|
></SelectBranch>
|
||||||
|
:
|
||||||
|
<span>分支:<span className="color-grey-6">master</span></span>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{filePath && (
|
||||||
|
<span className="ml20 font-16">
|
||||||
|
<a
|
||||||
|
onClick={() => this.returnMain(branch)}
|
||||||
|
className="color-blue"
|
||||||
|
>
|
||||||
|
{projectDetail && projectDetail.identifier}
|
||||||
|
</a>
|
||||||
|
{array &&
|
||||||
|
array.map((item, key) => {
|
||||||
|
return (
|
||||||
|
<React.Fragment>
|
||||||
|
{
|
||||||
|
key === array.length-1 ?
|
||||||
|
<span className="color-grey-6 subFileName" key={key}>{item}</span>
|
||||||
|
:
|
||||||
|
<a onClick={()=>this.returnUlr(`${getPathUrl(array,key+1)}`)} className="color-blue subFileName">{item}</a>
|
||||||
|
}
|
||||||
|
</React.Fragment>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="f-wrap-alignCenter">
|
||||||
|
{subFileType && (projectDetail && parseInt(projectDetail.type)) !== 2 && (isManager || isDeveloper) && platform && (
|
||||||
|
<div>
|
||||||
|
<span>
|
||||||
|
<Link to={`/projects/${owner}/${projectsId}/${branch}/uploadfile${urlRoot}`} >
|
||||||
|
<span className="color-green mr30">上传文件</span>
|
||||||
|
</Link>
|
||||||
|
</span>
|
||||||
|
<span className="mr30">
|
||||||
|
<Link
|
||||||
|
to={`/projects/${owner}/${projectsId}/${branch}/newfile${urlRoot}`}
|
||||||
|
>
|
||||||
|
<span className="color-blue">新建文件</span>
|
||||||
|
</Link>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{projectDetail && projectDetail.clone_url && (
|
||||||
|
<CloneAddress
|
||||||
|
http_url={projectDetail.clone_url}
|
||||||
|
downloadUrl={this.downloadUrl(zip_url,tar_url)}
|
||||||
|
showNotification={this.props.showNotification}
|
||||||
|
></CloneAddress>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/* 主目录列表 */}
|
||||||
|
{rootList && (
|
||||||
|
<RootTable
|
||||||
|
columns={columns}
|
||||||
|
data={rootList}
|
||||||
|
title={() => this.title(branchLastCommit,lastCommitAuthor)}
|
||||||
|
></RootTable>
|
||||||
|
)}
|
||||||
|
{/* 子目录列表、文件 */}
|
||||||
|
{fileDetail && fileDetail.length > 0 && (
|
||||||
|
<CoderRootFileDetail
|
||||||
|
detail={fileDetail[0]}
|
||||||
|
{...this.props}
|
||||||
|
{...this.state}
|
||||||
|
readOnly={this.state.readOnly}
|
||||||
|
onEdit={this.onEdit}
|
||||||
|
currentBranch={branch}
|
||||||
|
></CoderRootFileDetail>
|
||||||
|
)}
|
||||||
|
{
|
||||||
|
!rootList && !fileDetail && <Nodata _html="暂未发现当前文件!"/>
|
||||||
|
}
|
||||||
|
{/* readme.txt (isManager || isDeveloper)*/}
|
||||||
|
{ rootList && this.renderReadMeContent(readMeContent, isManager || isDeveloper)}
|
||||||
|
</div>
|
||||||
|
</Spin>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default CoderRootDirectory;
|
||||||
|
|
@ -24,25 +24,13 @@ class CoderRootFileDetail extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount = () => {
|
componentDidMount = () => {
|
||||||
const { detail , mdFlag } = this.props;
|
const { detail } = this.props;
|
||||||
this.setState({
|
this.setState({
|
||||||
value: detail.content,
|
value: detail.content,
|
||||||
});
|
});
|
||||||
this.languages_total();
|
this.languages_total();
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidUpdate=(prevProps)=>{
|
|
||||||
const { content } = this.props && this.props.detail;
|
|
||||||
const prevcontent = prevProps.detail && prevProps.detail.content;
|
|
||||||
if (content && prevcontent) {
|
|
||||||
if (prevcontent !== content){
|
|
||||||
this.setState({
|
|
||||||
description: content
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
languages_total = () => {
|
languages_total = () => {
|
||||||
const { detail } = this.props;
|
const { detail } = this.props;
|
||||||
const file_name = detail.path.split("/").pop().split(".").pop();
|
const file_name = detail.path.split("/").pop().split(".").pop();
|
||||||
|
|
@ -176,16 +164,15 @@ class CoderRootFileDetail extends Component {
|
||||||
current_user,
|
current_user,
|
||||||
isManager,
|
isManager,
|
||||||
isDeveloper,
|
isDeveloper,
|
||||||
currentBranch,
|
|
||||||
platform,
|
|
||||||
md,
|
md,
|
||||||
type
|
currentBranch,
|
||||||
|
platform
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const { language, languages, description } = this.state;
|
const { language, languages, description } = this.state;
|
||||||
let flag = current_user && current_user.login && (isManager || isDeveloper);
|
let flag = current_user && current_user.login && (isManager || isDeveloper);
|
||||||
const Option = Select.Option;
|
const Option = Select.Option;
|
||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<div className="mb20">
|
||||||
<div className="grid-item branchTitle">
|
<div className="grid-item branchTitle">
|
||||||
<div className="grid-item">
|
<div className="grid-item">
|
||||||
<span className="ml20 color-grey-6 font-16">
|
<span className="ml20 color-grey-6 font-16">
|
||||||
|
|
@ -198,18 +185,17 @@ class CoderRootFileDetail extends Component {
|
||||||
{readOnly ? (
|
{readOnly ? (
|
||||||
<span>
|
<span>
|
||||||
{
|
{
|
||||||
!detail.direct_download?
|
detail.direct_download ?
|
||||||
|
""
|
||||||
|
:
|
||||||
<span>
|
<span>
|
||||||
<a onClick={() => this.DownLoadFile(detail.download_url)} className="ml20">
|
<a onClick={() => this.DownLoadFile(detail.download_url)} className="ml20">
|
||||||
<i className="iconfont icon-xiazai1 font-15 color-grey-6"></i>
|
<i className="iconfont icon-xiazai1 font-15 color-grey-6"></i>
|
||||||
</a>
|
</a>
|
||||||
{
|
<a onClick={() => this.EditFile(false)} className="ml20">
|
||||||
type !==2 &&
|
<i className="iconfont icon-bianji1 font-15 color-grey-6"></i>
|
||||||
<a onClick={() => this.EditFile(false)} className="ml20">
|
</a>
|
||||||
<i className="iconfont icon-bianji1 font-15 color-grey-6"></i>
|
</span>
|
||||||
</a>
|
|
||||||
}
|
|
||||||
</span>:""
|
|
||||||
}
|
}
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
|
|
@ -240,21 +226,18 @@ class CoderRootFileDetail extends Component {
|
||||||
</button>
|
</button>
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
)}
|
)}
|
||||||
{
|
|
||||||
type !==2 &&
|
<Popconfirm
|
||||||
<Popconfirm
|
title="确认删除这个文件?"
|
||||||
title="确认删除这个文件?"
|
className="ml20"
|
||||||
className="ml20"
|
okText="确定"
|
||||||
okText="确定"
|
cancelText="取消"
|
||||||
cancelText="取消"
|
onConfirm={this.deleteFile}
|
||||||
onConfirm={this.deleteFile}
|
>
|
||||||
>
|
<a>
|
||||||
<a>
|
<i className="iconfont icon-shanchu font-15 color-grey-6"></i>
|
||||||
<i className="iconfont icon-shanchu font-15 color-grey-6"></i>
|
</a>
|
||||||
</a>
|
</Popconfirm>
|
||||||
</Popconfirm>
|
|
||||||
}
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -262,7 +245,11 @@ class CoderRootFileDetail extends Component {
|
||||||
<div>
|
<div>
|
||||||
{detail.image_type ? (
|
{detail.image_type ? (
|
||||||
<div className="edu-txt-center pt20 pb20">
|
<div className="edu-txt-center pt20 pb20">
|
||||||
<img alt="" src={detail.download_url} style={{ maxWidth: "80%" }} />
|
<img
|
||||||
|
alt=""
|
||||||
|
src={detail.download_url}
|
||||||
|
style={{ maxWidth: "80%" }}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
) : detail.direct_download ? (
|
) : detail.direct_download ? (
|
||||||
<div className="mt20 text-center">
|
<div className="mt20 text-center">
|
||||||
|
|
@ -273,7 +260,7 @@ class CoderRootFileDetail extends Component {
|
||||||
) : (
|
) : (
|
||||||
md && readOnly ?
|
md && readOnly ?
|
||||||
<div className="files-md">
|
<div className="files-md">
|
||||||
<RenderHtml className="file-md imageLayerParent" value={description} url={this.props.history.location}/>
|
<RenderHtml className="file-md imageLayerParent" value={description} />
|
||||||
</div>
|
</div>
|
||||||
:
|
:
|
||||||
<Meditor
|
<Meditor
|
||||||
|
|
@ -281,14 +268,14 @@ class CoderRootFileDetail extends Component {
|
||||||
{...this.state}
|
{...this.state}
|
||||||
language={language ? language : "javascript"}
|
language={language ? language : "javascript"}
|
||||||
filepath={`/${detail.path}`}
|
filepath={`/${detail.path}`}
|
||||||
content={description}
|
content={detail.content}
|
||||||
readOnly={readOnly}
|
readOnly={readOnly}
|
||||||
editorType="update"
|
editorType="update"
|
||||||
currentBranch={currentBranch}
|
currentBranch={currentBranch}
|
||||||
></Meditor>
|
></Meditor>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</React.Fragment>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,10 @@ const UploadFile = Loadable({
|
||||||
loader: () => import('../Newfile/upload_file'),
|
loader: () => import('../Newfile/upload_file'),
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
})
|
})
|
||||||
|
const CoderRootDirectory = Loadable({
|
||||||
|
loader: () => import('./CoderRootDirectory'),
|
||||||
|
loading: Loading,
|
||||||
|
})
|
||||||
const CoderRootCommit = Loadable({
|
const CoderRootCommit = Loadable({
|
||||||
loader: () => import('./CoderRootCommit'),
|
loader: () => import('./CoderRootCommit'),
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
|
|
@ -51,23 +55,14 @@ class CoderRootIndex extends Component{
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount=()=>{
|
componentDidMount=()=>{
|
||||||
this.Init();
|
let { search } = this.props.history.location;
|
||||||
}
|
let branchName = undefined;
|
||||||
componentDidUpdate=(prevProps)=>{
|
if (search && search.indexOf("?branch=") > -1) {
|
||||||
const { location } = this.props;
|
branchName = search.split("?branch=")[1];
|
||||||
const prevlocation = prevProps && prevProps.location;
|
|
||||||
if (location !== prevlocation) {
|
|
||||||
this.Init();
|
|
||||||
}
|
}
|
||||||
|
this.getTopCount(branchName);
|
||||||
}
|
}
|
||||||
|
|
||||||
Init=()=>{
|
|
||||||
const { branchName } = this.props.match.params;
|
|
||||||
const { defaultBranch } = this.props;
|
|
||||||
this.getTopCount(branchName || defaultBranch);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取<Top />组件里要显示的数据
|
|
||||||
getTopCount=(branch)=>{
|
getTopCount=(branch)=>{
|
||||||
const { projectsId , owner } = this.props.match.params;
|
const { projectsId , owner } = this.props.match.params;
|
||||||
const url = `/${owner}/${projectsId}/top_counts.json`;
|
const url = `/${owner}/${projectsId}/top_counts.json`;
|
||||||
|
|
@ -102,6 +97,8 @@ class CoderRootIndex extends Component{
|
||||||
(props) => (<FileNew {...this.props} {...props} {...this.state} getTopCount={this.getTopCount} />)
|
(props) => (<FileNew {...this.props} {...props} {...this.state} getTopCount={this.getTopCount} />)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
|
|
||||||
|
{/* diff */}
|
||||||
<Route path="/projects/:owner/:projectsId/commits/:sha"
|
<Route path="/projects/:owner/:projectsId/commits/:sha"
|
||||||
render={
|
render={
|
||||||
(props) => (<Diff {...this.props} {...props} {...this.state}/>)
|
(props) => (<Diff {...this.props} {...props} {...this.state}/>)
|
||||||
|
|
@ -112,6 +109,7 @@ class CoderRootIndex extends Component{
|
||||||
() => (<CoderRootCommit {...this.props} {...this.state} commit_class="main" getTopCount={this.getTopCount} />)
|
() => (<CoderRootCommit {...this.props} {...this.state} commit_class="main" getTopCount={this.getTopCount} />)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
|
|
||||||
<Route path="/projects/:owner/:projectsId/releases/:versionId/update"
|
<Route path="/projects/:owner/:projectsId/releases/:versionId/update"
|
||||||
render={
|
render={
|
||||||
(props) => (<CoderRootVersionUpdate {...this.props} {...this.state} {...props} />)
|
(props) => (<CoderRootVersionUpdate {...this.props} {...this.state} {...props} />)
|
||||||
|
|
@ -122,21 +120,28 @@ class CoderRootIndex extends Component{
|
||||||
() => (<CoderRootVersionNew {...this.props} {...this.state} />)
|
() => (<CoderRootVersionNew {...this.props} {...this.state} />)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
|
|
||||||
<Route path="/projects/:owner/:projectsId/releases"
|
<Route path="/projects/:owner/:projectsId/releases"
|
||||||
render={
|
render={
|
||||||
() => (<CoderRootVersion {...this.props} {...this.state} />)
|
() => (<CoderRootVersion {...this.props} {...this.state} />)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
|
|
||||||
<Route path="/projects/:owner/:projectsId/tag"
|
<Route path="/projects/:owner/:projectsId/tag"
|
||||||
render={
|
render={
|
||||||
() => (<CoderRootTag {...this.props} {...this.state} />)
|
() => (<CoderRootTag {...this.props} {...this.state} />)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
<Route path="/projects/:owner/:projectsId/branchs"
|
<Route path="/projects/:owner/:projectsId/branch"
|
||||||
render={
|
render={
|
||||||
() => (<CoderRootBranch {...this.props} {...this.state} />)
|
() => (<CoderRootBranch {...this.props} {...this.state} />)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
|
<Route path="/projects/:owner/:projectsId"
|
||||||
|
render={
|
||||||
|
() => (<CoderRootDirectory {...this.props} {...this.state} getTopCount={this.getTopCount} />)
|
||||||
|
}
|
||||||
|
></Route>
|
||||||
</Switch>
|
</Switch>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -28,9 +28,8 @@ export default (( props, { projectDetail }) => {
|
||||||
return (
|
return (
|
||||||
<div className="main">
|
<div className="main">
|
||||||
<Spin spinning={isSpin}>
|
<Spin spinning={isSpin}>
|
||||||
<div style={{minHeight:"400px"}}>
|
{
|
||||||
{
|
data && data.length > 0 ?
|
||||||
data && data.length > 0 &&
|
|
||||||
<div className="div_table">
|
<div className="div_table">
|
||||||
<ul className="ul_thead">
|
<ul className="ul_thead">
|
||||||
<li>
|
<li>
|
||||||
|
|
@ -41,7 +40,7 @@ export default (( props, { projectDetail }) => {
|
||||||
</ul>
|
</ul>
|
||||||
<ul className="ul_tbody">
|
<ul className="ul_tbody">
|
||||||
{
|
{
|
||||||
data.map((item, key) => {
|
data && data.length > 0 && data.map((item, key) => {
|
||||||
return (
|
return (
|
||||||
<li>
|
<li>
|
||||||
<span className="flex1">
|
<span className="flex1">
|
||||||
|
|
@ -61,9 +60,9 @@ export default (( props, { projectDetail }) => {
|
||||||
}
|
}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
}
|
:
|
||||||
{ data && data.length === 0 && <Nodata _html={`暂无标签!`}/> }
|
<Nodata _html={`暂无标签!`}/>
|
||||||
</div>
|
}
|
||||||
</Spin>
|
</Spin>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ import React, { Component } from 'react';
|
||||||
import { Spin, Tooltip } from 'antd';
|
import { Spin, Tooltip } from 'antd';
|
||||||
import { Link, Route, Switch } from 'react-router-dom';
|
import { Link, Route, Switch } from 'react-router-dom';
|
||||||
import { Content } from '../Component/layout';
|
import { Content } from '../Component/layout';
|
||||||
import DetailBanner from './sub/DetailBanner';
|
|
||||||
import '../css/index.scss'
|
import '../css/index.scss'
|
||||||
import './list.css';
|
import './list.css';
|
||||||
|
|
||||||
|
|
@ -11,6 +10,17 @@ import Loading from '../../Loading';
|
||||||
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
|
import img_1 from '../Images/1.png';
|
||||||
|
import img_2 from '../Images/2.png';
|
||||||
|
import img_3 from '../Images/3.png';
|
||||||
|
import img_6 from '../Images/6.png';
|
||||||
|
import img_7 from '../Images/7.png';
|
||||||
|
import img_parise from '../Images/parise.png';
|
||||||
|
import img_focus from '../Images/focus.png';
|
||||||
|
import img_parised from '../Images/parised.png';
|
||||||
|
import img_focused from '../Images/focused.png';
|
||||||
|
import img_fork from '../Images/fork.png';
|
||||||
|
import img_milepost from '../Images/milepost.png';
|
||||||
const Setting = Loadable({
|
const Setting = Loadable({
|
||||||
loader: () => import('../Settings/Index'),
|
loader: () => import('../Settings/Index'),
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
|
|
@ -97,19 +107,7 @@ const ForkUsers = Loadable({
|
||||||
loader: () => import('../UsersList/fork_users'),
|
loader: () => import('../UsersList/fork_users'),
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
})
|
})
|
||||||
const Contribute = Loadable({
|
|
||||||
loader: () => import('./sub/Contribute'),
|
|
||||||
loading: Loading,
|
|
||||||
})
|
|
||||||
|
|
||||||
const CoderRootCommit = Loadable({
|
|
||||||
loader: () => import('./CoderRootCommit'),
|
|
||||||
loading: Loading,
|
|
||||||
})
|
|
||||||
const CoderDepot = Loadable({
|
|
||||||
loader: () => import('./CoderDepot'),
|
|
||||||
loading: Loading,
|
|
||||||
})
|
|
||||||
|
|
||||||
const TrendsIndex = Loadable({
|
const TrendsIndex = Loadable({
|
||||||
loader: () => import('../Activity/Activity'),
|
loader: () => import('../Activity/Activity'),
|
||||||
|
|
@ -120,10 +118,6 @@ const DevAbout = Loadable({
|
||||||
loader: () => import('../About/Index'),
|
loader: () => import('../About/Index'),
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
})
|
})
|
||||||
const Source = Loadable({
|
|
||||||
loader: () => import('../Source/Index'),
|
|
||||||
loading: Loading,
|
|
||||||
})
|
|
||||||
const DevIndex = Loadable({
|
const DevIndex = Loadable({
|
||||||
loader: () => import('../DevOps/Index'),
|
loader: () => import('../DevOps/Index'),
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
|
|
@ -131,26 +125,23 @@ const DevIndex = Loadable({
|
||||||
/**
|
/**
|
||||||
* permission:Manager:管理员,Reporter:报告人员(只有读取权限),Developer:开发人员(除不能设置仓库信息外)
|
* permission:Manager:管理员,Reporter:报告人员(只有读取权限),Developer:开发人员(除不能设置仓库信息外)
|
||||||
*/
|
*/
|
||||||
function checkPathname(projectsId,owner,pathname){
|
function checkPathname(pathname){
|
||||||
let name = "";
|
let name = "";
|
||||||
if(pathname && pathname !== `/projects/${owner}/${projectsId}`){
|
if(pathname){
|
||||||
let url = pathname.split(`/projects/${owner}/${projectsId}`)[1];
|
if(pathname.indexOf("/about")>-1){
|
||||||
if(url.indexOf("/about")>-1){
|
|
||||||
name="about"
|
name="about"
|
||||||
}else if(url.indexOf("/issues")>-1 ||url.indexOf("Milepost") > 0){
|
}else if(pathname.indexOf("/issues")>-1 ||pathname.indexOf("Milepost") > 0){
|
||||||
name = "issues";
|
name = "issues";
|
||||||
}else if(url.indexOf("/pulls")>-1){
|
}else if(pathname.indexOf("/pulls")>-1){
|
||||||
name="pulls"
|
name="pulls"
|
||||||
}else if(url.indexOf("/milestones")>-1){
|
}else if(pathname.indexOf("/milestones")>-1){
|
||||||
name="milestones"
|
name="milestones"
|
||||||
}else if(url.indexOf("/activity")>-1){
|
}else if(pathname.indexOf("/activity")>-1){
|
||||||
name="activity"
|
name="activity"
|
||||||
}else if(url.indexOf("/setting")>-1){
|
}else if(pathname.indexOf("/setting")>-1){
|
||||||
name="setting"
|
name="setting"
|
||||||
}else if(url.indexOf(`/devops`)>-1){
|
}else if(pathname.indexOf("/devops")>-1){
|
||||||
name="devops"
|
name="devops"
|
||||||
}else if(url.indexOf(`/source`)>-1){
|
|
||||||
name="source"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return name;
|
return name;
|
||||||
|
|
@ -170,14 +161,13 @@ class Detail extends Component {
|
||||||
watched: false,
|
watched: false,
|
||||||
praised: false,
|
praised: false,
|
||||||
http_url: undefined,
|
http_url: undefined,
|
||||||
|
author: undefined,
|
||||||
branchs: undefined,
|
branchs: undefined,
|
||||||
branchList: undefined,
|
branchList: undefined,
|
||||||
project: null,
|
project: null,
|
||||||
firstSync:false,
|
firstSync:false,
|
||||||
secondSync:false,
|
secondSync:false,
|
||||||
open_devops:false,
|
open_devops:false,
|
||||||
// 默认分支
|
|
||||||
defaultBranch:undefined,
|
|
||||||
|
|
||||||
// 非本平台项目
|
// 非本平台项目
|
||||||
platform:false
|
platform:false
|
||||||
|
|
@ -207,6 +197,17 @@ class Detail extends Component {
|
||||||
platform:result.data.platform && result.data.platform !== 'educoder'
|
platform:result.data.platform && result.data.platform !== 'educoder'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 工作流:两种状态进入的链接不同
|
||||||
|
const pathname = this.props.history.location.pathname;
|
||||||
|
let p = checkPathname(pathname);
|
||||||
|
if(p==="devops"){
|
||||||
|
if(result.data.open_devops && pathname === `/projects/${owner}/${projectsId}/devops`){
|
||||||
|
this.props.history.push(`/projects/${owner}/${projectsId}/devops/list`);
|
||||||
|
}else if(result.data.open_devops===false && pathname !== `/projects/${owner}/${projectsId}/devops`){
|
||||||
|
this.props.history.push(`/projects/${owner}/${projectsId}/devops`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (result.data.type !== 0 && result.data.mirror_status === 1) {
|
if (result.data.type !== 0 && result.data.mirror_status === 1) {
|
||||||
console.log("--------start channel --------");
|
console.log("--------start channel --------");
|
||||||
// 是镜像项目,且未完成迁移
|
// 是镜像项目,且未完成迁移
|
||||||
|
|
@ -264,8 +265,7 @@ class Detail extends Component {
|
||||||
|
|
||||||
getDetail = () => {
|
getDetail = () => {
|
||||||
const { projectsId , owner } = this.props.match.params;
|
const { projectsId , owner } = this.props.match.params;
|
||||||
this.getBanner();
|
const url = `/${owner}/${projectsId}.json`;
|
||||||
const url = `/${owner}/${projectsId}/detail.json`;
|
|
||||||
axios.get(url).then((result) => {
|
axios.get(url).then((result) => {
|
||||||
if (result && result.data) {
|
if (result && result.data) {
|
||||||
this.setState({
|
this.setState({
|
||||||
|
|
@ -275,30 +275,17 @@ class Detail extends Component {
|
||||||
isReporter: result.data.permission && result.data.permission === "Reporter",
|
isReporter: result.data.permission && result.data.permission === "Reporter",
|
||||||
isDeveloper: result.data.permission && result.data.permission === "Developer",
|
isDeveloper: result.data.permission && result.data.permission === "Developer",
|
||||||
http_url: result.data.clone_url,
|
http_url: result.data.clone_url,
|
||||||
|
author: result.data.author,
|
||||||
praised: result.data.praised,
|
praised: result.data.praised,
|
||||||
watched: result.data.watched,
|
watched: result.data.watched,
|
||||||
watchers_count: result.data.watchers_count,
|
watchers_count: result.data.watchers_count,
|
||||||
praises_count: result.data.praises_count,
|
praises_count: result.data.praises_count,
|
||||||
forked_count: result.data.forked_count,
|
forked_count: result.data.forked_count,
|
||||||
defaultBranch:result.data.default_branch
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}).catch((error) => { })
|
}).catch((error) => { })
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取动态导航栏菜单
|
|
||||||
getBanner(){
|
|
||||||
const { projectsId , owner } = this.props.match.params;
|
|
||||||
const url = `/${owner}/${projectsId}/menu_list.json`;
|
|
||||||
axios.get(url).then(result=>{
|
|
||||||
if(result){
|
|
||||||
this.setState({
|
|
||||||
bannerList:result.data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}).catch(error=>{})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 关注和取消关注
|
// 关注和取消关注
|
||||||
focusFunc = (flag) => {
|
focusFunc = (flag) => {
|
||||||
const { platform } = this.state;
|
const { platform } = this.state;
|
||||||
|
|
@ -379,7 +366,6 @@ class Detail extends Component {
|
||||||
const url = `/${owner}/${projectsId}/sync_mirror.json`;
|
const url = `/${owner}/${projectsId}/sync_mirror.json`;
|
||||||
axios.post(url).then(result => {
|
axios.post(url).then(result => {
|
||||||
if (result && result.data && result.data.status === 0) {
|
if (result && result.data && result.data.status === 0) {
|
||||||
this.props.showNotification("镜像同步成功!");
|
|
||||||
this.getProject(2);
|
this.getProject(2);
|
||||||
} else {
|
} else {
|
||||||
this.props.showNotification("镜像同步失败!");
|
this.props.showNotification("镜像同步失败!");
|
||||||
|
|
@ -395,13 +381,13 @@ class Detail extends Component {
|
||||||
const { projectDetail, watchers_count, praises_count,
|
const { projectDetail, watchers_count, praises_count,
|
||||||
forked_count, firstSync , secondSync ,
|
forked_count, firstSync , secondSync ,
|
||||||
isManager, watched, praised,
|
isManager, watched, praised,
|
||||||
project , open_devops , platform , defaultBranch , bannerList } = this.state;
|
project , open_devops , platform } = this.state;
|
||||||
const url = this.props.history.location.pathname;
|
const url = this.props.history.location.pathname;
|
||||||
const urlArr = url.split("/");
|
const urlArr = url.split("/");
|
||||||
const urlFlag = (urlArr.length === 3);
|
const urlFlag = (urlArr.length === 3);
|
||||||
|
let pathname = checkPathname(url);
|
||||||
|
|
||||||
const { projectsId , owner } = this.props.match.params;
|
const { projectsId , owner } = this.props.match.params;
|
||||||
let pathname = checkPathname(projectsId,owner,url);
|
|
||||||
|
|
||||||
const { state } = this.props.history.location;
|
const { state } = this.props.history.location;
|
||||||
|
|
||||||
|
|
@ -417,8 +403,7 @@ class Detail extends Component {
|
||||||
|
|
||||||
const common = {
|
const common = {
|
||||||
getDetail: this.getDetail,
|
getDetail: this.getDetail,
|
||||||
changeOpenDevops:this.changeOpenDevops,
|
changeOpenDevops:this.changeOpenDevops
|
||||||
defaultBranch
|
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -427,7 +412,7 @@ class Detail extends Component {
|
||||||
<div className="f-wrap-between pb15" style={{ position: "relative" }}>
|
<div className="f-wrap-between pb15" style={{ position: "relative" }}>
|
||||||
<p className="font-22 df flex-1 lineH2 mt15" style={{ alignItems: "center" }}>
|
<p className="font-22 df flex-1 lineH2 mt15" style={{ alignItems: "center" }}>
|
||||||
{project && project.author &&
|
{project && project.author &&
|
||||||
<Link to={`${project.author.type ==="Organization" ? "/organize":'/users'}/${project.author.login}`} className="show-user-link">
|
<Link to={`/users/${project.author.login}`} className="show-user-link">
|
||||||
{project.author.name}
|
{project.author.name}
|
||||||
</Link>
|
</Link>
|
||||||
}
|
}
|
||||||
|
|
@ -470,15 +455,14 @@ class Detail extends Component {
|
||||||
<span>{watched ? '取消关注' : '关注'}</span>
|
<span>{watched ? '取消关注' : '关注'}</span>
|
||||||
</a>
|
</a>
|
||||||
{
|
{
|
||||||
watchers_count > 0 ?
|
|
||||||
platform ?
|
platform ?
|
||||||
<Link className="detail_tag_btn_count" style={{color:`${watched?"#2878FF":"#666"}`}} to={platform?{ pathname: `/projects/${owner}/${projectsId}/watchers`, state }:""}>
|
<Link className="detail_tag_btn_count" style={{color:`${watched?"#2878FF":"#666"}`}} to={platform?{ pathname: `/projects/${owner}/${projectsId}/watchers`, state }:""}>
|
||||||
{watchers_count}
|
{watchers_count}
|
||||||
</Link>
|
</Link>
|
||||||
:
|
:
|
||||||
<span className="detail_tag_btn_count">{watchers_count}</span>
|
<span className="detail_tag_btn_count">{watchers_count}</span>
|
||||||
:""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
</span>
|
</span>
|
||||||
<span className="detail_tag_btn">
|
<span className="detail_tag_btn">
|
||||||
<a className="detail_tag_btn_name" style={{cursor:platform?"pointer":"default"}} onClick={() => this.pariseFunc(praised)}>
|
<a className="detail_tag_btn_name" style={{cursor:platform?"pointer":"default"}} onClick={() => this.pariseFunc(praised)}>
|
||||||
|
|
@ -486,30 +470,24 @@ class Detail extends Component {
|
||||||
<span>{praised ? '取消点赞' : '点赞'}</span>
|
<span>{praised ? '取消点赞' : '点赞'}</span>
|
||||||
</a>
|
</a>
|
||||||
{
|
{
|
||||||
praises_count > 0 ?
|
|
||||||
platform ?
|
platform ?
|
||||||
<Link className="detail_tag_btn_count" style={{color:`${praised?"#2878FF":"#666"}`}} to={{ pathname: `/projects/${owner}/${projectsId}/stargazers`, state }}>
|
<Link className="detail_tag_btn_count" style={{color:`${praised?"#2878FF":"#666"}`}} to={{ pathname: `/projects/${owner}/${projectsId}/stargazers`, state }}>
|
||||||
{praises_count}
|
{praises_count}
|
||||||
</Link>:
|
</Link>:
|
||||||
<span className="detail_tag_btn_count">{praises_count}</span>
|
<span className="detail_tag_btn_count">{praises_count}</span>
|
||||||
:""
|
|
||||||
}
|
}
|
||||||
</span>
|
</span>
|
||||||
<span className="detail_tag_btn">
|
<span className="detail_tag_btn">
|
||||||
<Tooltip title="复刻是fork的中文名,即复制代码仓库" placement="bottom">
|
<a className="detail_tag_btn_name" style={{cursor:platform?"pointer":"default"}} onClick={this.forkFunc}>
|
||||||
<a className="detail_tag_btn_name" style={{cursor:platform?"pointer":"default"}} onClick={this.forkFunc}>
|
<i className="iconfont icon-fork color-grey-9 mr3"></i>Fork
|
||||||
<i className="iconfont icon-fork color-grey-9 mr3"></i>复刻
|
</a>
|
||||||
</a>
|
|
||||||
</Tooltip>
|
|
||||||
{
|
{
|
||||||
forked_count > 0 ?
|
|
||||||
platform ?
|
platform ?
|
||||||
<Link className="detail_tag_btn_count" to={{ pathname: `/projects/${owner}/${projectsId}/fork_users`, state }}>
|
<Link className="detail_tag_btn_count" to={{ pathname: `/projects/${owner}/${projectsId}/fork_users`, state }}>
|
||||||
{forked_count}
|
{forked_count}
|
||||||
</Link>
|
</Link>
|
||||||
:
|
:
|
||||||
<span className="detail_tag_btn_count">{forked_count}</span>
|
<span className="detail_tag_btn_count">{praises_count}</span>
|
||||||
:""
|
|
||||||
}
|
}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -517,36 +495,83 @@ class Detail extends Component {
|
||||||
</div>
|
</div>
|
||||||
{
|
{
|
||||||
firstSync ? "" :
|
firstSync ? "" :
|
||||||
<DetailBanner
|
<div className="f-wrap-between mt15">
|
||||||
history={this.props.history}
|
<ul className="headerMenu-wrapper">
|
||||||
list={bannerList}
|
<li className={pathname==="about" ? "active" : ""}>
|
||||||
owner={owner}
|
<Link to={{ pathname: `/projects/${owner}/${projectsId}/about`, state }}>
|
||||||
projectsId={projectsId}
|
<i className={(pathname==="" || urlFlag) ? "iconfont icon-zhuye1 color-grey-3 mr5 font-14":"iconfont icon-zhuye1 color-grey-6 font-14 mr5"}></i>
|
||||||
pathname={pathname}
|
<span>主页</span>
|
||||||
state={state}
|
</Link>
|
||||||
projectDetail={projectDetail}
|
</li>
|
||||||
open_devops={open_devops}
|
<li className={(pathname==="" || urlFlag) ? "active" : ""}>
|
||||||
platform={platform}
|
<Link to={{ pathname: `/projects/${owner}/${projectsId}`, state }}>
|
||||||
urlFlag={urlFlag}
|
<i className={(pathname==="" || urlFlag) ? "iconfont icon-daimaku color-grey-3 mr5 font-14":"iconfont icon-daimaku color-grey-6 font-14 mr5"}></i>
|
||||||
isManager={isManager}
|
<span>代码库</span>
|
||||||
/>
|
</Link>
|
||||||
|
</li>
|
||||||
|
<li className={pathname==="issues" ? "active" : ""}>
|
||||||
|
<Link to={{ pathname: `/projects/${owner}/${projectsId}/issues`, state }}>
|
||||||
|
<i className={pathname==="issues" ? "iconfont icon-renwu color-grey-3 mr5 font-14":"iconfont icon-renwu color-grey-6 font-14 mr5"}></i>
|
||||||
|
<span>任务</span>
|
||||||
|
{projectDetail && projectDetail.issues_count ? <span className="num">{projectDetail.issues_count}</span> : ""}
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
{
|
||||||
|
projectDetail && parseInt(projectDetail.type) !== 2 && platform &&
|
||||||
|
<li className={pathname==="pulls" ? "active" : ""}>
|
||||||
|
<Link to={{ pathname: `/projects/${owner}/${projectsId}/pulls`, state }}>
|
||||||
|
<i className={pathname==="pulls" ? "iconfont icon-hebingqingqiu1 color-grey-3 mr5 font-14":"iconfont icon-hebingqingqiu1 color-grey-6 font-14 mr5"}></i>
|
||||||
|
<span>合并请求</span>
|
||||||
|
{projectDetail && projectDetail.pull_requests_count ? <span className="num">{projectDetail.pull_requests_count}</span> : ""}
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
{
|
||||||
|
platform &&
|
||||||
|
<li className={pathname==="devops" ? "active" : ""}>
|
||||||
|
<Link to={{ pathname: `/projects/${owner}/${projectsId}/devops${open_devops ? `/list`:""}`, state }}>
|
||||||
|
<i className="iconfont icon-gongzuoliu font-13 mr8"></i>工作流(beta版)
|
||||||
|
{projectDetail && projectDetail.ops_count ? <span>{projectDetail.ops_count}</span> : ""}
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
|
||||||
|
<li className={pathname==="milestones" ? "active" : ""}>
|
||||||
|
<Link to={{ pathname: `/projects/${owner}/${projectsId}/milestones`, state }}>
|
||||||
|
<i className={pathname==="milestones" ? "iconfont icon-lichengbei color-grey-3 mr5 font-14":"iconfont icon-lichengbei color-grey-6 font-14 mr5"}></i>
|
||||||
|
<span>里程碑</span>
|
||||||
|
{projectDetail && projectDetail.versions_count ? <span className="num">{projectDetail.versions_count}</span> :""}
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
<li className={pathname==="activity" ? "active" : ""}>
|
||||||
|
<Link to={{ pathname: `/projects/${owner}/${projectsId}/activity`, state }}>
|
||||||
|
<i className={pathname==="activity" ? "iconfont icon-tongzhi color-grey-3 mr5 font-14":"iconfont icon-tongzhi color-grey-6 font-14 mr5"}></i>
|
||||||
|
<span>动态</span>
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
{
|
||||||
|
isManager && platform &&
|
||||||
|
<li className={url.indexOf("/setting") > 0 ? "active" : ""}>
|
||||||
|
<Link to={`/projects/${owner}/${projectsId}/setting`}>
|
||||||
|
<i className={url.indexOf("/setting") > 0 ? "iconfont icon-cangku color-grey-3 mr5 font-14":"iconfont icon-cangku color-grey-6 font-14 mr5"}></i>
|
||||||
|
<span>仓库设置</span>
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{
|
{
|
||||||
firstSync ?
|
firstSync ?
|
||||||
<Content className="spincontent">
|
<Content className="spincontent">
|
||||||
<Spin className="spinstyle" tip={project && `正在从 ${project.mirror_url} 迁移`} size="large" />
|
<Spin className="spinstyle" tip={project && `正在从 ${project.mirror_url} 迁移`} size="large">
|
||||||
|
</Spin>
|
||||||
</Content>
|
</Content>
|
||||||
:
|
:
|
||||||
<Spin spinning={secondSync} className="spinstyle" tip="正在同步镜像" size="large">
|
<Spin spinning={secondSync} className="spinstyle" tip="正在同步镜像" size="large">
|
||||||
<Switch {...this.props}>
|
<Switch {...this.props}>
|
||||||
{/* 资源 */}
|
|
||||||
<Route path="/projects/:owner/:projectsId/source"
|
|
||||||
render={
|
|
||||||
() => (<Source {...this.props} {...this.state} {...common} />)
|
|
||||||
}
|
|
||||||
></Route>
|
|
||||||
{/* 主页 */}
|
{/* 主页 */}
|
||||||
<Route path="/projects/:owner/:projectsId/about"
|
<Route path="/projects/:owner/:projectsId/about"
|
||||||
render={
|
render={
|
||||||
|
|
@ -637,7 +662,6 @@ class Detail extends Component {
|
||||||
(props) => (<OrderIndex {...this.props} {...props} {...this.state} {...common} />)
|
(props) => (<OrderIndex {...this.props} {...props} {...this.state} {...common} />)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
{/* 新建合并请求 */}
|
|
||||||
<Route path="/projects/:owner/:projectsId/pulls/new"
|
<Route path="/projects/:owner/:projectsId/pulls/new"
|
||||||
render={
|
render={
|
||||||
(props) => (<CreateMerge {...this.props} {...props} {...this.state} {...common} is_fork={true} />)
|
(props) => (<CreateMerge {...this.props} {...props} {...this.state} {...common} is_fork={true} />)
|
||||||
|
|
@ -664,6 +688,11 @@ class Detail extends Component {
|
||||||
(props) => (<MergeIndexDetail {...this.props} {...props} {...this.state} {...common} />)
|
(props) => (<MergeIndexDetail {...this.props} {...props} {...this.state} {...common} />)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
|
<Route path="/projects/:owner/:projectsId/coders/filesurl"
|
||||||
|
render={
|
||||||
|
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state} {...common} />)
|
||||||
|
}
|
||||||
|
></Route>
|
||||||
<Route path="/projects/:owner/:projectsId/watchers"
|
<Route path="/projects/:owner/:projectsId/watchers"
|
||||||
render={
|
render={
|
||||||
(props) => (<WatchUsers {...this.props} {...props} {...this.state} {...common} />)
|
(props) => (<WatchUsers {...this.props} {...props} {...this.state} {...common} />)
|
||||||
|
|
@ -679,32 +708,9 @@ class Detail extends Component {
|
||||||
(props) => (<ForkUsers {...this.props} {...props} {...this.state} {...common} />)
|
(props) => (<ForkUsers {...this.props} {...props} {...this.state} {...common} />)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
{/* 贡献者列表 */}
|
|
||||||
<Route path="/projects/:owner/:projectsId/contribute"
|
|
||||||
render={
|
|
||||||
() => (<Contribute {...this.props} {...this.state} {...common} />)
|
|
||||||
}
|
|
||||||
></Route>
|
|
||||||
|
|
||||||
{/* 代码库----详情页面 */}
|
|
||||||
<Route path="/projects/:owner/:projectsId/commits/branch/:branchName"
|
|
||||||
render={
|
|
||||||
(props) => (<CoderRootCommit {...this.props} {...props} {...this.state} {...common}/>)
|
|
||||||
}
|
|
||||||
></Route>
|
|
||||||
<Route path="/projects/:owner/:projectsId/tree/:branchName"
|
|
||||||
render={
|
|
||||||
(props) => (<CoderDepot {...this.props} {...props} {...this.state} {...common}/>)
|
|
||||||
}
|
|
||||||
></Route>
|
|
||||||
<Route path="/projects/:owner/:projectsId/:subIndex"
|
|
||||||
render={
|
|
||||||
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state} {...common}/>)
|
|
||||||
}
|
|
||||||
></Route>
|
|
||||||
<Route path="/projects/:owner/:projectsId"
|
<Route path="/projects/:owner/:projectsId"
|
||||||
render={
|
render={
|
||||||
(props) => (<CoderDepot {...this.props} {...props} {...this.state} {...common}/>)
|
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state} {...common} />)
|
||||||
}
|
}
|
||||||
></Route>
|
></Route>
|
||||||
</Switch>
|
</Switch>
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ class DetailTop extends Component {
|
||||||
<i className="iconfont icon-tijiaojilu font-20 mr3 font-bd"></i>
|
<i className="iconfont icon-tijiaojilu font-20 mr3 font-bd"></i>
|
||||||
<span>{(coderCount && coderCount.commits_count) || 0}</span>个提交
|
<span>{(coderCount && coderCount.commits_count) || 0}</span>个提交
|
||||||
</Link>
|
</Link>
|
||||||
<Link to={`/projects/${owner}/${projectsId}/branchs`} className={pathname.indexOf("/branchs") > 0 ? "active" : ""}>
|
<Link to={`/projects/${owner}/${projectsId}/branch`} className={pathname.indexOf("/branch") > 0 ? "active" : ""}>
|
||||||
<i className="iconfont icon-fenzhi1 font-18 mr3"></i>
|
<i className="iconfont icon-fenzhi1 font-18 mr3"></i>
|
||||||
<span>{(coderCount && coderCount.branches_count) || 0}</span>个分支
|
<span>{(coderCount && coderCount.branches_count) || 0}</span>个分支
|
||||||
</Link>
|
</Link>
|
||||||
|
|
|
||||||
|
|
@ -59,13 +59,13 @@ export default ({ match , history }) => {
|
||||||
{commit && commit.message &&
|
{commit && commit.message &&
|
||||||
<pre className="task-hide" style={{marginBottom:"0px",height:"28px",whiteSpace:"pre-wrap"}}>{commit.message}</pre>
|
<pre className="task-hide" style={{marginBottom:"0px",height:"28px",whiteSpace:"pre-wrap"}}>{commit.message}</pre>
|
||||||
}
|
}
|
||||||
<Button type="primary" onClick={()=>{history.push(`/projects/${owner}/${projectsId}/tree/${truncateCommitId(sha)}`)}} className="ml30">浏览代码</Button>
|
<Button type="primary" onClick={()=>{history.push(`/projects/${owner}/${projectsId}?branch=${truncateCommitId(sha)}`)}} className="ml30">浏览代码</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="f-wrap-between" style={{ alignItems: "center" }}>
|
<div className="f-wrap-between" style={{ alignItems: "center" }}>
|
||||||
<ul className="df">
|
<ul className="df">
|
||||||
<User
|
<User
|
||||||
url={(committer && getImageUrl(`/${committer.image_url}`))|| "https://dss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3025493530,1989042357&fm=26&gp=0.jpg"}
|
url={(committer && getImageUrl(`images/${committer.image_url}`))|| "https://dss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3025493530,1989042357&fm=26&gp=0.jpg"}
|
||||||
name={committer && committer.name}
|
name={committer && committer.name}
|
||||||
/>
|
/>
|
||||||
{committer && committer.time_from_now && <li className="ml20 mt2">{committer.time_from_now}</li>}
|
{committer && committer.time_from_now && <li className="ml20 mt2">{committer.time_from_now}</li>}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { Menu, Input , Spin, Pagination , Popover , Select } from 'antd';
|
import { Menu, Input , Spin, Pagination , Popover , Select } from 'antd';
|
||||||
import { getImageUrl } from 'educoder';
|
import { getUrl } from 'educoder';
|
||||||
import '../css/index.scss'
|
import '../css/index.scss'
|
||||||
import './list.css';
|
import './list.css';
|
||||||
import './Index.scss';
|
import './Index.scss';
|
||||||
|
|
@ -245,10 +245,10 @@ class Index extends Component {
|
||||||
|
|
||||||
pagination=(total,limit,page)=>{
|
pagination=(total,limit,page)=>{
|
||||||
return(
|
return(
|
||||||
total && total > limit ?
|
total && total > limit &&
|
||||||
<div className="edu-txt-center pt30 mb30 border-top-grey">
|
<div className="edu-txt-center pt30 mb30 border-top-grey">
|
||||||
<Pagination simple defaultCurrent={page} total={total} pageSize={limit} onChange={this.ChangePage}></Pagination>
|
<Pagination simple defaultCurrent={page} total={total} pageSize={limit} onChange={this.ChangePage}></Pagination>
|
||||||
</div>:""
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -271,13 +271,13 @@ class Index extends Component {
|
||||||
return(
|
return(
|
||||||
<div onClick={()=>this.getoDetail(item.author && item.author.login,item.identifier)}>
|
<div onClick={()=>this.getoDetail(item.author && item.author.login,item.identifier)}>
|
||||||
<div className="mainInfo">
|
<div className="mainInfo">
|
||||||
<img src={getImageUrl(`/${item.author && item.author.image_url}`)} alt=""/>
|
<img src={getUrl(`/images/${item.author && item.author.image_url}`)} alt=""/>
|
||||||
<p className="school">{item.name}</p>
|
<p className="school">{item.name}</p>
|
||||||
<p className="name">{item.author && item.author.name}</p>
|
<p className="name">{item.author && item.author.name}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="baseInfo">
|
<div className="baseInfo">
|
||||||
<span className="look"><i className="iconfont icon-dianjiliang font-12"></i>{item.visits}</span>
|
<span className="look"><i className="iconfont icon-dianjiliang font-12"></i>{item.visits}</span>
|
||||||
<span className="type">{item.category && item.category.name}</span>
|
<span className="type">项目类型:{item.category && item.category.name}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@
|
||||||
width: 220px;
|
width: 220px;
|
||||||
margin-right: 25px;
|
margin-right: 25px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border: 1px solid #eee;
|
|
||||||
&:last-child{
|
&:last-child{
|
||||||
margin-right: 0px;
|
margin-right: 0px;
|
||||||
}
|
}
|
||||||
|
|
@ -69,247 +68,7 @@
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
text-align: right;
|
text-align: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// coderDepot
|
|
||||||
.Panels{
|
|
||||||
max-width: 1200px;
|
|
||||||
margin: 0 auto;
|
|
||||||
.panelmenu{
|
|
||||||
padding-top:30px;
|
|
||||||
}
|
|
||||||
.addOptionBtn{
|
|
||||||
height: 32px;
|
|
||||||
line-height: 30px;
|
|
||||||
display: flex;
|
|
||||||
border:1px solid #d9d9d9;
|
|
||||||
border-radius: 2px;
|
|
||||||
a{
|
|
||||||
padding:0px 13px;
|
|
||||||
color: rgba(0, 0, 0, 0.65);
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
& > a:first-child{
|
|
||||||
border-right: 1px solid #d9d9d9;
|
|
||||||
}
|
|
||||||
& > a:last-child{
|
|
||||||
border-right: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.infoCount{
|
|
||||||
display: inline-block;
|
|
||||||
padding:0px 5px;
|
|
||||||
height: 16px;
|
|
||||||
line-height: 16px;
|
|
||||||
background-color: #eee;
|
|
||||||
color:#999;
|
|
||||||
border-radius: 12px;
|
|
||||||
margin-left: 10px;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
.attrPerson{
|
|
||||||
padding-top: 15px;
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
a{
|
|
||||||
margin: 10px 10px 0px 0px;
|
|
||||||
img{
|
|
||||||
border-radius: 50%;
|
|
||||||
width: 35px;
|
|
||||||
height: 35px;
|
|
||||||
}
|
|
||||||
&:nth-child(6){
|
|
||||||
margin-right: 0px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.progress{
|
|
||||||
display: flex;
|
|
||||||
border-radius: 10px;
|
|
||||||
height: 7px;
|
|
||||||
margin-top: 12px;
|
|
||||||
span{
|
|
||||||
border-left: 1px solid #fff;
|
|
||||||
&:first-child{
|
|
||||||
border-left: none;
|
|
||||||
border-radius: 10px 0px 0px 10px;
|
|
||||||
}
|
|
||||||
&:last-child{
|
|
||||||
border-radius: 0px 10px 10px 0px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.progresstip{
|
|
||||||
margin-top: 15px;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
i.zero{
|
|
||||||
position: absolute;
|
|
||||||
display: block;
|
|
||||||
border-radius: 50%;
|
|
||||||
height: 8px;
|
|
||||||
width: 8px;
|
|
||||||
left: 0px;
|
|
||||||
top:10px
|
|
||||||
}
|
|
||||||
&>span{
|
|
||||||
padding-left: 15px;
|
|
||||||
position: relative;
|
|
||||||
min-width: 33.5%;
|
|
||||||
span{
|
|
||||||
color: #666;
|
|
||||||
&:last-child{
|
|
||||||
color: #999;
|
|
||||||
margin-left: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.listtable{
|
|
||||||
margin-top: 20px;
|
|
||||||
border:1px solid #d9d9d9;
|
|
||||||
border-radius: 4px;
|
|
||||||
.listtablehead{
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: flex-start;
|
|
||||||
border-bottom: 1px solid #d9d9d9;
|
|
||||||
padding:7px 20px;
|
|
||||||
border-radius: 4px 4px 0px 0px;
|
|
||||||
background-color: #FAFBFC;
|
|
||||||
.ellipsistxt{
|
|
||||||
margin-left: 13px;
|
|
||||||
line-height:18px;
|
|
||||||
margin-top:6px;
|
|
||||||
flex:1;
|
|
||||||
width: 0;
|
|
||||||
color: #666;
|
|
||||||
&>p{
|
|
||||||
word-break:break-all;
|
|
||||||
}
|
|
||||||
&.hide{
|
|
||||||
height: 18px;
|
|
||||||
overflow: hidden;
|
|
||||||
position: relative;
|
|
||||||
padding-right:8px;
|
|
||||||
}
|
|
||||||
&.hide::after{
|
|
||||||
position: absolute;
|
|
||||||
right: 0px;
|
|
||||||
bottom: 0px;
|
|
||||||
content:"...";
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.ellipsis{
|
|
||||||
margin-left: 8px;
|
|
||||||
cursor: pointer;
|
|
||||||
border-radius: 2px;
|
|
||||||
background-color: #c1c1c1;
|
|
||||||
padding:0px 4px;
|
|
||||||
height: 14px;
|
|
||||||
line-height: 14px;
|
|
||||||
margin-top: 9px;
|
|
||||||
i{
|
|
||||||
font-size: 15px!important;
|
|
||||||
color: #fff;
|
|
||||||
height: 14px;
|
|
||||||
line-height: 14px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.listtablebody{
|
|
||||||
li.listtablepath{
|
|
||||||
a{color: #40a9ff;}
|
|
||||||
p{
|
|
||||||
margin-bottom: 0px!important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
& > li{
|
|
||||||
height: 42px;
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
border-bottom: 1px solid #d9d9d9;
|
|
||||||
padding:0px 20px 0px 24px;
|
|
||||||
& > span:first-child{
|
|
||||||
width: 30%;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
& > span:nth-child(2){
|
|
||||||
width: 60%;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
& > span:nth-child(3){
|
|
||||||
width: 10%;
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&> li:last-child{
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.drawerBtn{
|
|
||||||
position: fixed;
|
|
||||||
left: -13px;
|
|
||||||
border:1px solid rgb(207,205,223);
|
|
||||||
width: 34px;
|
|
||||||
border-radius: 0px 12px 12px 0px;
|
|
||||||
height: 70px;
|
|
||||||
top:50%;
|
|
||||||
margin-top: -35px;
|
|
||||||
cursor: pointer;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: flex-end;
|
|
||||||
justify-content: center;
|
|
||||||
&:hover{
|
|
||||||
box-shadow: 1px 0px 7px rgba(0,0,0,0.1);
|
|
||||||
}
|
|
||||||
span{
|
|
||||||
writing-mode: vertical-lr;
|
|
||||||
color: #202429;
|
|
||||||
width: 25px;
|
|
||||||
}
|
|
||||||
i{
|
|
||||||
color: #24292e;
|
|
||||||
height: 18px;
|
|
||||||
line-height: 18px;
|
|
||||||
width: 18px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.downMenu{
|
|
||||||
box-shadow: 0px 0px 9px rgba(134, 134, 134,0.4);
|
|
||||||
background-color: #fff;
|
|
||||||
.ant-menu-vertical .ant-menu-item:hover{
|
|
||||||
background-color: #e6f7ff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.menuslist{
|
|
||||||
max-height: 200px;
|
|
||||||
overflow-y: auto;
|
|
||||||
padding:10px 15px;
|
|
||||||
border-radius: 4px;
|
|
||||||
.ant-dropdown-menu-item{
|
|
||||||
border-radius: 8px;
|
|
||||||
text-align: left!important;
|
|
||||||
a{
|
|
||||||
width: 350px;
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.ant-dropdown-menu-item.active{
|
|
||||||
background-color: #e6f7ff;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { Tooltip } from 'antd';
|
import { Tooltip } from 'antd';
|
||||||
import { getImageUrl } from 'educoder';
|
import { getImageUrl , getImage } from 'educoder';
|
||||||
import { AlignCenter } from '../Component/layout';
|
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import '../css/index.scss';
|
import '../css/index.scss';
|
||||||
import Nodata from '../Nodata';
|
import Nodata from '../Nodata';
|
||||||
|
|
@ -17,64 +16,65 @@ class IndexItem extends Component {
|
||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
const { projects } = this.props;
|
const { projects } = this.props;
|
||||||
return (
|
const renderList = (
|
||||||
<div className="project-list minH-670">
|
projects && projects.length > 0 ? projects.map((item, key) => {
|
||||||
{ projects && projects.length > 0 ? projects.map((item, key) => {
|
return (
|
||||||
return (
|
<div className="p-r-Item" key={key}>
|
||||||
<div className="p-r-Item" key={key}>
|
{
|
||||||
{
|
item.platform === "educoder" ?
|
||||||
item.platform === "educoder" ?
|
<a href="javascript:void(0)" style={{cursor:"default"}} className="show-user-link">
|
||||||
<a href="javascript:void(0)" style={{cursor:"default"}} className="show-user-link">
|
<img className="p-r-photo" alt="" src={item.author && item.author.image_url} ></img>
|
||||||
<img className="p-r-photo" alt="" src={item.author && item.author.image_url} ></img>
|
</a>
|
||||||
</a>
|
:
|
||||||
:
|
<Link to={`/users/${item.author.login}`} className="show-user-link">
|
||||||
<Link to={item.author && (item.author.type === "Organization" ? `/organize/${item.author.login}`:`/users/${item.author.login}`)} className="show-user-link">
|
<img className="p-r-photo" alt="" src={getImageUrl(`${item.author && item.author.image_url}`)} ></img>
|
||||||
<img className="p-r-photo" alt="" src={getImageUrl(`/${item.author && item.author.image_url}`)} ></img>
|
</Link>
|
||||||
</Link>
|
}
|
||||||
}
|
<div className="p-r-Infos">
|
||||||
<div className="p-r-Infos">
|
<div className="p-r-name">
|
||||||
<div className="p-r-name">
|
<Link to={`/projects/${item.author.login}/${item.identifier}`} className="hide-1 color-grey-3 font-18 task-hide " style={{ whiteSpace: "wrap", display: 'flex', width: 400 }}>
|
||||||
<AlignCenter>
|
{item.author.name}/{item.name}
|
||||||
<Link to={`/projects/${item.author.login}/${item.identifier}`} className="color-grey-3 font-18 task-hide " style={{maxWidth: 490 }}>
|
{
|
||||||
{item.author.name}/{item.name}
|
item.forked_from_project_id ?
|
||||||
</Link>
|
|
||||||
{
|
|
||||||
item.forked_from_project_id ?
|
|
||||||
<span className="ml5">
|
|
||||||
<i className="iconfont icon-fork font-18 color-orange" />
|
|
||||||
</span>
|
|
||||||
: ""
|
|
||||||
}
|
|
||||||
{
|
|
||||||
item.type && item.type !== 0 ?
|
|
||||||
item.type === 2 ?
|
|
||||||
<Tooltip title="该项目是一个镜像" className="ml5">
|
|
||||||
<i className="iconfont icon-banbenku font-18 color-green" />
|
|
||||||
</Tooltip>:
|
|
||||||
<span className="ml5">
|
<span className="ml5">
|
||||||
<i className="iconfont icon-jingxiang font-18 color-green" />
|
<i className="iconfont icon-fork font-18 color-orange" />
|
||||||
</span>:""
|
</span>
|
||||||
}
|
: ""
|
||||||
</AlignCenter>
|
}
|
||||||
<span className="p-r-tags">
|
{
|
||||||
<span className="pariseTag"><img src={img_parise} alt="" className="pariseImg" />赞 {item.praises_count}</span>
|
item.type && item.type !== 0 ?
|
||||||
<span><i className="iconfont icon-fork mr3 font-16" style={{ color: "#1B8FFF" }} />fork {item.forked_count}</span>
|
item.type === 2 ?
|
||||||
</span>
|
<Tooltip title="该项目是一个镜像" className="ml5">
|
||||||
</div>
|
<i className="iconfont icon-banbenku font-18 color-green" />
|
||||||
<p className="break_word task-hide-2 mt10" style={{ maxHeight: "44px",lineHeight:"22px" }}>{item.description}</p>
|
</Tooltip>:
|
||||||
|
<span className="ml5">
|
||||||
|
<i className="iconfont icon-jingxiang font-18 color-green" />
|
||||||
|
</span>:""
|
||||||
|
}
|
||||||
|
</Link>
|
||||||
|
<span className="p-r-tags">
|
||||||
|
<span className="pariseTag"><img src={img_parise} alt="" className="pariseImg" />赞 ({item.praises_count})</span>
|
||||||
|
<span><i className="iconfont icon-fork mr3 font-16" style={{ color: "#1B8FFF" }} />fork ({item.forked_count})</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<p className="break_word task-hide-2 mt10" style={{ maxHeight: "44px",lineHeight:"22px" }}>{item.description}</p>
|
||||||
|
|
||||||
<div className="p-r-about">
|
<div className="p-r-about">
|
||||||
<span className="p-r-detail">
|
<span className="p-r-detail">
|
||||||
{/* <span><label>浏览量:</label>{item.visits}</span> */}
|
<span><label>浏览量:</label>{item.visits}</span>
|
||||||
{/* {item.category && item.category.id && <span>{item.category.name}</span>} */}
|
{item.category && item.category.id && <span><label>项目类别:</label>{item.category.name}</span>}
|
||||||
{item.last_update_time ? <span><label>更新于</label>{item.time_ago}</span> : ""}
|
{item.last_update_time ? <span ><label>更新于</label>{item.time_ago}</span> : ""}
|
||||||
{item.language && item.language.id ? <span className="color-grey-3">{item.language.name}</span> : ""}
|
{item.language && item.language.id ? <span className="color-grey-3">{item.language.name}</span> : ""}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
</div>
|
||||||
}) : <Nodata _html="暂无数据~"></Nodata>}
|
)
|
||||||
|
}) : <Nodata _html="暂无数据~"></Nodata>
|
||||||
|
)
|
||||||
|
return (
|
||||||
|
<div className="project-list minH-670">
|
||||||
|
{renderList}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue