Compare commits

..

84 Commits

Author SHA1 Message Date
caishi c32b333bc2 Merge branch 'dev_m_copy' into dev_military
# Conflicts:
#	src/forge/DevOps/Index.jsx
#	src/forge/Index.js
#	src/forge/Main/Detail.js
#	src/forge/Merge/MessageCount.js
#	src/forge/Settings/Collaborator.js
#	src/forge/Settings/CollaboratorMember.jsx
#	src/forge/users/watch_users.js
#	src/modules/tpm/NewHeader.js
2021-04-12 15:57:30 +08:00
caishi c965da7dd5 默认 2021-03-22 09:47:34 +08:00
caishi b44399968f 协作者分页 2021-03-22 09:46:30 +08:00
caishi 2591f28ccc bug 2021-03-22 09:37:37 +08:00
caishi 5530e8c723 diff-查看文件 2021-03-10 10:48:08 +08:00
caishi fa26dc9fa5 diff-查看文件 2021-03-10 10:47:23 +08:00
caishi 4cf40f9dfc update 2021-03-09 15:33:18 +08:00
caishi 2c034f5dff 修改资料-url 2021-03-09 14:09:06 +08:00
caishi d68d8318c1 account 2021-03-09 13:59:02 +08:00
caishi 41ae6b1f8d 修改资料练级 2021-03-09 13:55:02 +08:00
caishi a6e2171fca filedetail 2021-03-09 11:49:48 +08:00
caishi 916cc293ac url 2021-03-08 11:15:05 +08:00
caishi 5565eac601 nodata 2021-03-08 09:55:12 +08:00
caishi 860b71c7c6 外围贡献者 2021-03-04 17:02:20 +08:00
caishi f1c2841fe0 logo 2021-03-03 16:46:45 +08:00
caishi c6d5078d42 Merge branch 'develop' into dev_m_copy 2021-03-02 11:43:58 +08:00
caishi ebe2d625fa Merge branch 'dev_military' of https://git.trustie.net/jasder/forgeplus-react into dev_military 2021-03-02 11:43:26 +08:00
caishi b5e1a91af5 style 2021-03-02 11:43:19 +08:00
caishi 4b8d72a6eb Merge branch 'develop' into dev_m_copy 2021-03-02 10:52:09 +08:00
caishi f0e1858cd4 update 2021-03-01 16:01:26 +08:00
caishi a92468953a style 2021-03-01 11:11:30 +08:00
caishi fdab967b6a Merge branch 'develop' into dev_m_copy
# Conflicts:
#	src/AppConfig.js
#	src/forge/DevOps/Index.jsx
#	src/forge/Index.js
#	src/forge/Main/Detail.js
#	src/forge/Main/IndexItem.js
#	src/forge/Merge/MessageCount.js
#	src/forge/Settings/Collaborator.js
#	src/forge/users/watch_users.js
#	src/modules/tpm/NewHeader.js
2021-03-01 10:21:14 +08:00
caishi 7e8929f166 appconfig 2021-03-01 10:17:38 +08:00
caishi 0a39ed80da Merge branch 'dev_m_copy' into dev_military
# Conflicts:
#	src/forge/Merge/MessageCount.js
2021-03-01 10:11:48 +08:00
caishi 5ed44f1d63 特殊项目审核 2021-02-26 16:58:31 +08:00
caishi 64e639ebea update 2021-02-26 11:53:08 +08:00
caishi 3fb9eb40f3 watch_users 2021-02-25 17:07:35 +08:00
caishi efc2443bb8 列表查询 2021-02-25 16:58:59 +08:00
caishi 2c3d917bd4 mygetHelmetapi2 2021-02-09 10:44:41 +08:00
caishi 617f139f52 fault 2021-02-04 15:13:08 +08:00
caishi de550d5f42 remove 2021-02-04 15:05:37 +08:00
caishi f12230dc91 url 2021-02-04 15:02:26 +08:00
caishi 1df2639cd5 pulls权限 2021-01-13 15:47:10 +08:00
caishi c746e9e634 pulls 2021-01-13 14:21:12 +08:00
caishi d8d464a332 pullrequest 2021-01-12 17:45:54 +08:00
caishi 83e337b2e9 pullrequest 2021-01-12 17:44:46 +08:00
caishi 5a6b7bd717 update 2021-01-12 09:30:30 +08:00
caishi c68a3dbd6f 项目成员访问特殊开源许可证项目不用上传文件 2021-01-11 18:14:59 +08:00
caishi 350f9426ea 工作流 2021-01-05 10:33:58 +08:00
caishi 5bda100e32 update 2021-01-05 09:23:58 +08:00
caishi dde7fa730a 同上-update 2021-01-04 16:43:15 +08:00
caishi 3f8f1b8083 特殊项目申请列表 2021-01-04 16:28:19 +08:00
caishi 6eef4bd09e 信息 2020-12-31 15:16:26 +08:00
caishi 0dcaea3db4 检测是否上传了文件 2020-12-31 14:13:31 +08:00
caishi 033134fa83 json 2020-12-29 16:28:08 +08:00
caishi 1bab0b01f7 debug 2020-12-29 16:18:20 +08:00
caishi 7b2f233cae 隐藏devops 2020-12-29 11:38:08 +08:00
caishi 2ecdd73c7f 外围贡献者 2020-12-28 20:42:12 +08:00
caishi 4e7a2fa3d7 Merge branch 'develop' into dev_m_copy
# Conflicts:
#	public/css/edu-purge.css
#	public/css/iconfont.css
#	src/AppConfig.js
#	src/forge/Main/CoderRootDirectory.js
#	src/forge/Main/Index.js
#	src/forge/Main/list.css
#	src/forge/Newfile/m_editor.js
#	src/forge/css/index.scss
#	src/modules/tpm/NewHeader.js
#	src/modules/tpm/TPMIndex.css
2020-12-24 17:50:26 +08:00
caishi 91662e2e3e back 2020-12-24 15:37:40 +08:00
sylor_huang@126.com c2129c994a change Header5 2020-09-16 15:14:46 +08:00
sylor_huang@126.com e968ece34c Change Header4 2020-09-16 15:08:54 +08:00
sylor_huang@126.com 70d407963e Change Header2 2020-09-16 14:58:37 +08:00
sylor_huang@126.com 00ccba74a1 Change Header1 2020-09-16 14:48:58 +08:00
sylor_huang@126.com 0790abb6f9 Change Header 2020-09-16 14:39:13 +08:00
caishi 6c4c161a1b Merge branch 'dev_military' of https://git.trustie.net/jasder/forgeplus-react into dev_military
# Conflicts:
#	src/AppConfig.js
2020-09-15 17:21:42 +08:00
caishi 65a2bd43cf route 2020-09-15 17:21:10 +08:00
sylor_huang@126.com 10f813a443 Change banner 2020-09-15 09:38:57 +08:00
sylor_huang@126.com e79ec30c81 Change Index Category8 2020-09-14 14:53:09 +08:00
sylor_huang@126.com 2a7fea3612 Change Index Category6 2020-09-14 14:44:41 +08:00
sylor_huang@126.com cc46a3ac30 Change Index Category5 2020-09-14 14:08:03 +08:00
sylor_huang@126.com cca5f98c9b Change Index Category4 2020-09-14 11:50:45 +08:00
sylor_huang@126.com d4535005c8 Change Index Category3 2020-09-14 11:28:20 +08:00
sylor_huang@126.com 73d128e0c9 Change Resume 2020-09-14 09:26:46 +08:00
sylor_huang@126.com f09457a0ac Change Index Category 2020-09-11 18:49:41 +08:00
sylor_huang@126.com 78c218b12b Change Index Category 2020-09-11 18:45:34 +08:00
sylor_huang@126.com d9f87fdd18 Change Index Page 2020-09-11 18:31:31 +08:00
caishi 33c3395221 getpath 2020-08-27 10:14:07 +08:00
sylor_huang@126.com 74d26a40d3 Change Edit Url 2020-08-24 11:37:51 +08:00
sylor_huang@126.com 3f78ed249c Fix:Issues 2020-08-21 11:29:05 +08:00
caishi 07e1525f09 router 2020-08-20 18:10:40 +08:00
sylor_huang@126.com a9161b86a2 Change 2020-08-20 15:01:01 +08:00
sylor_huang@126.com e0e6cdcc79 Fix: Issues 2020-08-20 11:57:36 +08:00
sylor_huang@126.com 3b0c708d82 Fix: Issues 2020-08-20 11:44:27 +08:00
sylor_huang@126.com 0922df3875 Hide LoginDialog 2020-08-19 18:18:03 +08:00
sylor_huang@126.com ad3fe09cfb Merge branch 'newVersion_forge' into dev_military 2020-08-18 17:43:24 +08:00
sylor_huang@126.com 91f4327eb4 Change 2020-08-18 17:43:04 +08:00
sylor_huang@126.com f2f910b5e4 Add Dun Check For Project 2020-08-18 10:36:33 +08:00
sylor_huang@126.com 85d924db70 Fix: Add New File Language Api Wrong6 2020-08-13 11:56:39 +08:00
Jasder f1614a4b62 Delete url 2020-08-10 11:27:41 +08:00
Jasder 2fa71241db FIX 更改header的背景色 2020-08-09 23:24:12 +08:00
Jasder 13c6556574 FIX 更改logo导航链接 2020-08-09 23:20:08 +08:00
caishi 5601b71937 junke 2020-08-09 23:08:11 +08:00
Jasder 1a024f8011 FIX 去掉使用手册 2020-08-09 22:20:51 +08:00
189 changed files with 4044 additions and 6028 deletions

258
package-lock.json generated
View File

@ -1,40 +1,35 @@
{
"name": "forge",
"name": "educoder",
"version": "0.1.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@ant-design/colors": {
"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",
"integrity": "sha1-WtQ9YZ6RHzSI66wwPWBuZqhCOQM=",
"resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-3.2.2.tgz",
"integrity": "sha512-YKgNbG2dlzqMhA9NtI3/pbY16m3Yl/EeWBRa+lB1X1YaYxHrxNexiQYCLTWO/uDvAjLFMEDU+zR901waBtMtjQ==",
"requires": {
"tinycolor2": "^1.4.1"
}
},
"@ant-design/create-react-context": {
"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",
"integrity": "sha1-9fWpFjtHcgl3EoNzl60w4i55+Fg=",
"resolved": "https://registry.npmjs.org/@ant-design/create-react-context/-/create-react-context-0.2.5.tgz",
"integrity": "sha512-1rMAa4qgP2lfl/QBH9i78+Gjxtj9FTMpMyDGZsEBW5Kih72EuUo9958mV8PgpRkh4uwPSQ7vVZWXeyNZXVAFDg==",
"requires": {
"gud": "^1.0.0",
"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": {
"version": "2.1.1",
"resolved": "https://registry.npm.taobao.org/@ant-design/icons/download/@ant-design/icons-2.1.1.tgz",
"integrity": "sha1-e5wI3/1PXUHbZn2dvl4BB9C9mko="
"resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-2.1.1.tgz",
"integrity": "sha512-jCH+k2Vjlno4YWl6g535nHR09PwCEmTBKAG6VqF+rhkrSPRLfgpU2maagwbZPLjaHuU5Jd1DFQ2KJpQuI6uG8w=="
},
"@ant-design/icons-react": {
"version": "2.0.1",
"resolved": "https://registry.npm.taobao.org/@ant-design/icons-react/download/@ant-design/icons-react-2.0.1.tgz",
"integrity": "sha1-F6JRNXGrMXrKKSfljOol3THlNvs=",
"resolved": "https://registry.npmjs.org/@ant-design/icons-react/-/icons-react-2.0.1.tgz",
"integrity": "sha512-r1QfoltMuruJZqdiKcbPim3d8LNsVPB733U0gZEUSxBLuqilwsW28K2rCTWSMTjmFX7Mfpf+v/wdiFe/XCqThw==",
"requires": {
"@ant-design/colors": "^3.1.0",
"babel-runtime": "^6.26.0"
@ -451,8 +446,8 @@
},
"@types/react-slick": {
"version": "0.23.4",
"resolved": "https://registry.npm.taobao.org/@types/react-slick/download/@types/react-slick-0.23.4.tgz",
"integrity": "sha1-yX4qnn49GTPGhZO46CdS+rHozlM=",
"resolved": "https://registry.npmjs.org/@types/react-slick/-/react-slick-0.23.4.tgz",
"integrity": "sha512-vXoIy4GUfB7/YgqubR4H7RALo+pRdMYCeLgWwV3MPwl5pggTlEkFBTF19R7u+LJc85uMqC7RfsbkqPLMQ4ab+A==",
"requires": {
"@types/react": "*"
}
@ -868,9 +863,9 @@
}
},
"antd": {
"version": "3.26.20",
"resolved": "https://registry.nlark.com/antd/download/antd-3.26.20.tgz",
"integrity": "sha1-8/Vw76qllQoUSULyHrKqqgiOlAc=",
"version": "3.26.16",
"resolved": "https://registry.npmjs.org/antd/-/antd-3.26.16.tgz",
"integrity": "sha512-EYRwlEf8FCPCVRk5yDcgjSZOC0exu+m75SwlSQU+Mh17f9wGhLeL2/DV7/Sra1r+BZlfiahFdkgrLY7UgMMBEQ==",
"requires": {
"@ant-design/create-react-context": "^0.2.4",
"@ant-design/icons": "~2.1.1",
@ -930,16 +925,16 @@
"dependencies": {
"raf": {
"version": "3.4.1",
"resolved": "https://registry.npm.taobao.org/raf/download/raf-3.4.1.tgz",
"integrity": "sha1-B0LpmkplUvRF1z4+4DKK8P8e3jk=",
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
"integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
"requires": {
"performance-now": "^2.1.0"
}
},
"rc-pagination": {
"version": "1.20.15",
"resolved": "https://registry.npm.taobao.org/rc-pagination/download/rc-pagination-1.20.15.tgz",
"integrity": "sha1-zLTNDpvU5H9y8p6kMsA1C/ez2Ac=",
"version": "1.20.14",
"resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-1.20.14.tgz",
"integrity": "sha512-sNKwbFrxiqATqcIIShfrFs8BT03n4UUwTAMYae+JhHTmILQmXdvimEnZbVuWcno6G02DAJcLrFpmkn1h2tmEJw==",
"requires": {
"babel-runtime": "6.x",
"classnames": "^2.2.6",
@ -949,8 +944,8 @@
},
"rc-rate": {
"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",
"integrity": "sha1-Vfxf0j6p3MciULmoiYA0efSEKWE=",
"resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.5.1.tgz",
"integrity": "sha512-3iJkNJT8xlHklPCdeZtUZmJmRVUbr6AHRlfSsztfYTXVlHrv2TcPn3XkHsH+12j812WVB7gvilS2j3+ffjUHXg==",
"requires": {
"classnames": "^2.2.5",
"prop-types": "^15.5.8",
@ -960,8 +955,8 @@
},
"rc-select": {
"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",
"integrity": "sha1-ZDQOLW72TovDz8b0aP/ShiVYmsI=",
"resolved": "https://registry.npmjs.org/rc-select/-/rc-select-9.2.3.tgz",
"integrity": "sha512-WhswxOMWiNnkXRbxyrj0kiIvyCfo/BaRPaYbsDetSIAU2yEDwKHF798blCP5u86KLOBKBvtxWLFCkSsQw1so5w==",
"requires": {
"babel-runtime": "^6.23.0",
"classnames": "2.x",
@ -979,8 +974,8 @@
},
"rc-tree": {
"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",
"integrity": "sha1-73WfPnmaIbQ8Hs+ceU6hwU5wtZs=",
"resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-2.1.4.tgz",
"integrity": "sha512-Xey794Iavgs8YldFlXcZLOhfcIhlX5Oz/yfKufknBXf2AlZCOkc7aHqSM9uTF7fBPtTGPhPxNEfOqHfY7b7xng==",
"requires": {
"@ant-design/create-react-context": "^0.2.4",
"classnames": "2.x",
@ -1088,8 +1083,8 @@
},
"array-tree-filter": {
"version": "2.1.0",
"resolved": "https://registry.npm.taobao.org/array-tree-filter/download/array-tree-filter-2.1.0.tgz",
"integrity": "sha1-hzrAD+yDdJ8lWsjdCDgUtPYykZA="
"resolved": "https://registry.npmjs.org/array-tree-filter/-/array-tree-filter-2.1.0.tgz",
"integrity": "sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw=="
},
"array-union": {
"version": "1.0.2",
@ -3765,8 +3760,8 @@
},
"copy-to-clipboard": {
"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",
"integrity": "sha1-EVqhqZmP+rYZb5MHatbaO5E2Yq4=",
"resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz",
"integrity": "sha512-i13qo6kIHTTpCm8/Wup+0b1mVWETvu2kIMzKoK8FpkLkFxlt0znUAHcMzox+T8sPlqtZXq3CulEjQHsYiGFJUw==",
"requires": {
"toggle-selection": "^1.0.6"
}
@ -3893,6 +3888,11 @@
"randomfill": "^1.0.3"
}
},
"crypto-js": {
"version": "4.0.0",
"resolved": "https://registry.npm.taobao.org/crypto-js/download/crypto-js-4.0.0.tgz",
"integrity": "sha1-KQSrJnep0EKFai6i74DekuSjbcw="
},
"crypto-random-string": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz",
@ -4852,7 +4852,7 @@
},
"dom-closest": {
"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=",
"requires": {
"dom-matches": ">=1.0.1"
@ -4896,7 +4896,7 @@
},
"dom-matches": {
"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="
},
"dom-scroll-into-view": {
@ -5018,8 +5018,8 @@
},
"draft-js": {
"version": "0.10.5",
"resolved": "https://registry.npm.taobao.org/draft-js/download/draft-js-0.10.5.tgz",
"integrity": "sha1-v6m+sBj+BTPbsI1mdcNxprCPp0I=",
"resolved": "https://registry.npmjs.org/draft-js/-/draft-js-0.10.5.tgz",
"integrity": "sha512-LE6jSCV9nkPhfVX2ggcRLA4FKs6zWq9ceuO/88BpXdNCS7mjRTgs0NsV6piUCJX9YxMsB9An33wnkMmU2sD2Zg==",
"requires": {
"fbjs": "^0.8.15",
"immutable": "~3.7.4",
@ -5149,7 +5149,7 @@
},
"enquire.js": {
"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="
},
"entities": {
@ -5668,7 +5668,7 @@
},
"eventlistener": {
"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="
},
"events": {
@ -7925,7 +7925,7 @@
},
"hammerjs": {
"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="
},
"handle-thing": {
@ -8766,7 +8766,7 @@
},
"immutable": {
"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="
},
"import-fresh": {
@ -9180,9 +9180,9 @@
}
},
"is-mobile": {
"version": "2.2.2",
"resolved": "https://registry.nlark.com/is-mobile/download/is-mobile-2.2.2.tgz",
"integrity": "sha1-9snF1Q7gElTOBec5vdg18e1OmVQ="
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/is-mobile/-/is-mobile-2.2.1.tgz",
"integrity": "sha512-6zELsfVFr326eq2CI53yvqq6YBanOxKBybwDT+MbMS2laBnK6Ez8m5XHSuTQQbnKRfpDzCod1CMWW5q3wZYMvA=="
},
"is-npm": {
"version": "1.0.0",
@ -10354,7 +10354,7 @@
},
"lodash.throttle": {
"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="
},
"lodash.uniq": {
@ -11409,8 +11409,8 @@
},
"omit.js": {
"version": "1.0.2",
"resolved": "https://registry.npm.taobao.org/omit.js/download/omit.js-1.0.2.tgz",
"integrity": "sha1-kaFPDrqEBm36AVvzDkdMR/MLyFg=",
"resolved": "https://registry.npmjs.org/omit.js/-/omit.js-1.0.2.tgz",
"integrity": "sha512-/QPc6G2NS+8d4L/cQhbk6Yit1WTB6Us2g84A7A/1+w9d/eRGHyEqC5kkQtHVoHZ5NFWGG7tUGgrhVZwgZanKrQ==",
"requires": {
"babel-runtime": "^6.23.0"
}
@ -14213,9 +14213,9 @@
}
},
"rc-calendar": {
"version": "9.15.11",
"resolved": "https://registry.npm.taobao.org/rc-calendar/download/rc-calendar-9.15.11.tgz",
"integrity": "sha1-zh5eqOTXdDW+ZqjHfbEvHw+aNF8=",
"version": "9.15.10",
"resolved": "https://registry.npmjs.org/rc-calendar/-/rc-calendar-9.15.10.tgz",
"integrity": "sha512-xh1A3rYejKskAvkjnd9BcHXFbBnAYsHMGHBdtoAkbwp43B6yEieNL0g0Tzz8s1gApDZV2j5vF1jJ9IIpPYFNLw==",
"requires": {
"babel-runtime": "6.x",
"classnames": "2.x",
@ -14228,8 +14228,8 @@
},
"rc-cascader": {
"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",
"integrity": "sha1-T96R0jt2CMQgJjw47unAaH+A99w=",
"resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-0.17.5.tgz",
"integrity": "sha512-WYMVcxU0+Lj+xLr4YYH0+yXODumvNXDcVEs5i7L1mtpWwYkubPV/zbQpn+jGKFCIW/hOhjkU4J1db8/P/UKE7A==",
"requires": {
"array-tree-filter": "^2.1.0",
"prop-types": "^15.5.8",
@ -14242,8 +14242,8 @@
},
"rc-checkbox": {
"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",
"integrity": "sha1-7t2e+cLzr1s7jlzeUlSqia0aiAo=",
"resolved": "https://registry.npmjs.org/rc-checkbox/-/rc-checkbox-2.1.8.tgz",
"integrity": "sha512-6qOgh0/by0nVNASx6LZnhRTy17Etcgav+IrI7kL9V9kcDZ/g7K14JFlqrtJ3NjDq/Kyn+BPI1st1XvbkhfaJeg==",
"requires": {
"babel-runtime": "^6.23.0",
"classnames": "2.x",
@ -14253,8 +14253,8 @@
},
"rc-collapse": {
"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",
"integrity": "sha1-ZqQAidRpUZ6UJACasckn4hQEHYA=",
"resolved": "https://registry.npmjs.org/rc-collapse/-/rc-collapse-1.11.8.tgz",
"integrity": "sha512-8EhfPyScTYljkbRuIoHniSwZagD5UPpZ3CToYgoNYWC85L2qCbPYF7+OaC713FOrIkp6NbfNqXsITNxmDAmxog==",
"requires": {
"classnames": "2.x",
"css-animation": "1.x",
@ -14267,8 +14267,8 @@
},
"rc-dialog": {
"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",
"integrity": "sha1-EVRczAuUWTT6dgeXJuDYU+UtcF8=",
"resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-7.6.1.tgz",
"integrity": "sha512-KUKf+2eZ4YL+lnXMG3hR4ZtIhC9glfH27NtTVz3gcoDIPAf3uUvaXVRNoDCiSi+OGKLyIb/b6EoidFh6nQC5Wg==",
"requires": {
"babel-runtime": "6.x",
"rc-animate": "2.x",
@ -14277,8 +14277,8 @@
},
"rc-drawer": {
"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",
"integrity": "sha1-y8sE1MB/C2by7OEdhH9KG9gOoLc=",
"resolved": "https://registry.npmjs.org/rc-drawer/-/rc-drawer-3.1.3.tgz",
"integrity": "sha512-2z+RdxmzXyZde/1OhVMfDR1e/GBswFeWSZ7FS3Fdd0qhgVdpV1wSzILzzxRaT481ItB5hOV+e8pZT07vdJE8kg==",
"requires": {
"classnames": "^2.2.6",
"rc-util": "^4.16.1",
@ -14287,8 +14287,8 @@
},
"rc-dropdown": {
"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",
"integrity": "sha1-qu9us6UVLN2ZgolcKnjZtfBGzew=",
"resolved": "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-2.4.1.tgz",
"integrity": "sha512-p0XYn0wrOpAZ2fUGE6YJ6U8JBNc5ASijznZ6dkojdaEfQJAeZtV9KMEewhxkVlxGSbbdXe10ptjBlTEW9vEwEg==",
"requires": {
"babel-runtime": "^6.26.0",
"classnames": "^2.2.6",
@ -14299,8 +14299,8 @@
},
"rc-editor-core": {
"version": "0.8.10",
"resolved": "https://registry.npm.taobao.org/rc-editor-core/download/rc-editor-core-0.8.10.tgz",
"integrity": "sha1-byFbxd+cM/+p9sWzDKc6favoq3w=",
"resolved": "https://registry.npmjs.org/rc-editor-core/-/rc-editor-core-0.8.10.tgz",
"integrity": "sha512-T3aHpeMCIYA1sdAI7ynHHjXy5fqp83uPlD68ovZ0oClTSc3tbHmyCxXlA+Ti4YgmcpCYv7avF6a+TIbAka53kw==",
"requires": {
"babel-runtime": "^6.26.0",
"classnames": "^2.2.5",
@ -14313,8 +14313,8 @@
},
"rc-editor-mention": {
"version": "1.1.13",
"resolved": "https://registry.npm.taobao.org/rc-editor-mention/download/rc-editor-mention-1.1.13.tgz",
"integrity": "sha1-nxyrEGX4awFSOEAyF5DCqxKsXos=",
"resolved": "https://registry.npmjs.org/rc-editor-mention/-/rc-editor-mention-1.1.13.tgz",
"integrity": "sha512-3AOmGir91Fi2ogfRRaXLtqlNuIwQpvla7oUnGHS1+3eo7b+fUp5IlKcagqtwUBB5oDNofoySXkLBxzWvSYNp/Q==",
"requires": {
"babel-runtime": "^6.23.0",
"classnames": "^2.2.5",
@ -14342,9 +14342,9 @@
}
},
"rc-hammerjs": {
"version": "0.6.10",
"resolved": "https://registry.npm.taobao.org/rc-hammerjs/download/rc-hammerjs-0.6.10.tgz",
"integrity": "sha1-GDGjvY8hmXAL/MWtayCjVjCuteA=",
"version": "0.6.9",
"resolved": "https://registry.npmjs.org/rc-hammerjs/-/rc-hammerjs-0.6.9.tgz",
"integrity": "sha512-4llgWO3RgLyVbEqUdGsDfzUDqklRlQW5VEhE3x35IvhV+w//VPRG34SBavK3D2mD/UaLKaohgU41V4agiftC8g==",
"requires": {
"babel-runtime": "6.x",
"hammerjs": "^2.0.8",
@ -14352,9 +14352,9 @@
}
},
"rc-input-number": {
"version": "4.5.9",
"resolved": "https://registry.nlark.com/rc-input-number/download/rc-input-number-4.5.9.tgz?cache=0&sync_timestamp=1619578110950&other_urls=https%3A%2F%2Fregistry.nlark.com%2Frc-input-number%2Fdownload%2Frc-input-number-4.5.9.tgz",
"integrity": "sha1-HL9zXiT+I8TrmkMBAxcguV8qPj0=",
"version": "4.5.6",
"resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-4.5.6.tgz",
"integrity": "sha512-AXbL4gtQ1mSQnu6v/JtMv3UbGRCzLvQznmf0a7U/SAtZ8+dCEAqD4JpJhkjv73Wog53eRYhw4l7ApdXflc9ymg==",
"requires": {
"babel-runtime": "6.x",
"classnames": "^2.2.0",
@ -14365,8 +14365,8 @@
},
"rc-mentions": {
"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",
"integrity": "sha1-wYq3Ae+55LdbOFGgwNLdaYZA4kY=",
"resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-0.4.2.tgz",
"integrity": "sha512-DTZurQzacLXOfVuiHydGzqkq7cFMHXF18l2jZ9PhWUn2cqvOSY3W4osN0Pq29AOMOBpcxdZCzgc7Lb0r/bgkDw==",
"requires": {
"@ant-design/create-react-context": "^0.2.4",
"classnames": "^2.2.6",
@ -14394,8 +14394,8 @@
},
"rc-notification": {
"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",
"integrity": "sha1-C6o+cPjUCrAVzo+njCYMSQ/HvrQ=",
"resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-3.3.1.tgz",
"integrity": "sha512-U5+f4BmBVfMSf3OHSLyRagsJ74yKwlrQAtbbL5ijoA0F2C60BufwnOcHG18tVprd7iaIjzZt1TKMmQSYSvgrig==",
"requires": {
"babel-runtime": "6.x",
"classnames": "2.x",
@ -14416,9 +14416,9 @@
}
},
"rc-progress": {
"version": "2.5.3",
"resolved": "https://registry.npm.taobao.org/rc-progress/download/rc-progress-2.5.3.tgz",
"integrity": "sha1-APAblb2+GFbTpfgiQgUZAui3qOc=",
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/rc-progress/-/rc-progress-2.5.2.tgz",
"integrity": "sha512-ajI+MJkbBz9zYDuE9GQsY5gsyqPF7HFioZEDZ9Fmc+ebNZoiSeSJsTJImPFCg0dW/5WiRGUy2F69SX1aPtSJgA==",
"requires": {
"babel-runtime": "6.x",
"prop-types": "^15.5.8"
@ -14435,8 +14435,8 @@
},
"rc-resize-observer": {
"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",
"integrity": "sha1-CXGR+cOrGG7ZB7VTum71Zd8Rwkk=",
"resolved": "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-0.1.3.tgz",
"integrity": "sha512-uzOQEwx83xdQSFOkOAM7x7GHIQKYnrDV4dWxtCxyG1BS1pkfJ4EvDeMfsvAJHSYkQXVBu+sgRHGbRtLG3qiuUg==",
"requires": {
"classnames": "^2.2.1",
"rc-util": "^4.13.0",
@ -14464,8 +14464,8 @@
},
"rc-slider": {
"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",
"integrity": "sha1-ntBzYtyTSJo45lSyG4EirXD9PEI=",
"resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-8.7.1.tgz",
"integrity": "sha512-WMT5mRFUEcrLWwTxsyS8jYmlaMsTVCZIGENLikHsNv+tE8ThU2lCoPfi/xFNUfJFNFSBFP3MwPez9ZsJmNp13g==",
"requires": {
"babel-runtime": "6.x",
"classnames": "^2.2.5",
@ -14479,8 +14479,8 @@
},
"rc-steps": {
"version": "3.5.0",
"resolved": "https://registry.npm.taobao.org/rc-steps/download/rc-steps-3.5.0.tgz",
"integrity": "sha1-NrKn8fSZB7DZA2OISxhiPK+ftgA=",
"resolved": "https://registry.npmjs.org/rc-steps/-/rc-steps-3.5.0.tgz",
"integrity": "sha512-2Vkkrpa7PZbg7qPsqTNzVDov4u78cmxofjjnIHiGB9+9rqKS8oTLPzbW2uiWDr3Lk+yGwh8rbpGO1E6VAgBCOg==",
"requires": {
"babel-runtime": "^6.23.0",
"classnames": "^2.2.3",
@ -14489,9 +14489,9 @@
}
},
"rc-switch": {
"version": "1.9.2",
"resolved": "https://registry.npm.taobao.org/rc-switch/download/rc-switch-1.9.2.tgz?cache=0&sync_timestamp=1603791200779&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-switch%2Fdownload%2Frc-switch-1.9.2.tgz",
"integrity": "sha1-eSHHZkEf6aZCZRDDQpAi1rpN/eI=",
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/rc-switch/-/rc-switch-1.9.0.tgz",
"integrity": "sha512-Isas+egaK6qSk64jaEw4GgPStY4umYDbT7ZY93bZF1Af+b/JEsKsJdNOU2qG3WI0Z6tXo2DDq0kJCv8Yhu0zww==",
"requires": {
"classnames": "^2.2.1",
"prop-types": "^15.5.6",
@ -14500,8 +14500,8 @@
},
"rc-table": {
"version": "6.10.15",
"resolved": "https://registry.nlark.com/rc-table/download/rc-table-6.10.15.tgz",
"integrity": "sha1-GB9McMT9dPZX7o8jGW5+sIoDZco=",
"resolved": "https://registry.npmjs.org/rc-table/-/rc-table-6.10.15.tgz",
"integrity": "sha512-LAr0M/gqt+irOjvPNBLApmQ0CUHNOfKsEBhu1uIuB3OlN1ynA9z+sdoTQyNd9+8NSl0MYnQOOfhtLChAY7nU0A==",
"requires": {
"classnames": "^2.2.5",
"component-classes": "^1.2.6",
@ -14515,8 +14515,8 @@
},
"rc-tabs": {
"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",
"integrity": "sha1-rglpW+9ZY9bmTnvBBSHHbf3YRIs=",
"resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-9.7.0.tgz",
"integrity": "sha512-kvmgp8/MfLzFZ06hWHignqomFQ5nF7BqKr5O1FfhE4VKsGrep52YSF/1MvS5oe0NPcI9XGNS2p751C5v6cYDpQ==",
"requires": {
"@ant-design/create-react-context": "^0.2.4",
"babel-runtime": "6.x",
@ -14533,8 +14533,8 @@
"dependencies": {
"raf": {
"version": "3.4.1",
"resolved": "https://registry.npm.taobao.org/raf/download/raf-3.4.1.tgz",
"integrity": "sha1-B0LpmkplUvRF1z4+4DKK8P8e3jk=",
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
"integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
"requires": {
"performance-now": "^2.1.0"
}
@ -14543,8 +14543,8 @@
},
"rc-time-picker": {
"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",
"integrity": "sha1-ZajekECTJQrpyCsCpJBeD5leI+I=",
"resolved": "https://registry.npmjs.org/rc-time-picker/-/rc-time-picker-3.7.3.tgz",
"integrity": "sha512-Lv1Mvzp9fRXhXEnRLO4nW6GLNxUkfAZ3RsiIBsWjGjXXvMNjdr4BX/ayElHAFK0DoJqOhm7c5tjmIYpEOwcUXg==",
"requires": {
"classnames": "2.x",
"moment": "2.x",
@ -14556,8 +14556,8 @@
"dependencies": {
"raf": {
"version": "3.4.1",
"resolved": "https://registry.npm.taobao.org/raf/download/raf-3.4.1.tgz",
"integrity": "sha1-B0LpmkplUvRF1z4+4DKK8P8e3jk=",
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
"integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
"requires": {
"performance-now": "^2.1.0"
}
@ -14566,8 +14566,8 @@
},
"rc-tooltip": {
"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",
"integrity": "sha1-KArsavyqROjf8EgPuv+eh/wArsw=",
"resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-3.7.3.tgz",
"integrity": "sha512-dE2ibukxxkrde7wH9W8ozHKUO4aQnPZ6qBHtrTH9LoO836PjDdiaWO73fgPB05VfJs9FbZdmGPVEbXCeOP99Ww==",
"requires": {
"babel-runtime": "6.x",
"prop-types": "^15.5.8",
@ -14615,8 +14615,8 @@
},
"rc-tree-select": {
"version": "2.9.4",
"resolved": "https://registry.nlark.com/rc-tree-select/download/rc-tree-select-2.9.4.tgz",
"integrity": "sha1-aqeU4fDmXGbEBqoKKg50/QpVewk=",
"resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-2.9.4.tgz",
"integrity": "sha512-0HQkXAN4XbfBW20CZYh3G+V+VMrjX42XRtDCpyv6PDUm5vikC0Ob682ZBCVS97Ww2a5Hf6Ajmu0ahWEdIEpwhg==",
"requires": {
"classnames": "^2.2.1",
"dom-scroll-into-view": "^1.2.1",
@ -14633,8 +14633,8 @@
"dependencies": {
"rc-tree": {
"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",
"integrity": "sha1-73WfPnmaIbQ8Hs+ceU6hwU5wtZs=",
"resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-2.1.4.tgz",
"integrity": "sha512-Xey794Iavgs8YldFlXcZLOhfcIhlX5Oz/yfKufknBXf2AlZCOkc7aHqSM9uTF7fBPtTGPhPxNEfOqHfY7b7xng==",
"requires": {
"@ant-design/create-react-context": "^0.2.4",
"classnames": "2.x",
@ -14647,8 +14647,8 @@
},
"rc-trigger": {
"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",
"integrity": "sha1-9tmx2oomsrLR2RKgaHbBpIb1mA8=",
"resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-3.0.0.tgz",
"integrity": "sha512-hQxbbJpo23E2QnYczfq3Ec5J5tVl2mUDhkqxrEsQAqk16HfADQg+iKNWzEYXyERSncdxfnzYuaBgy764mNRzTA==",
"requires": {
"babel-runtime": "6.x",
"classnames": "^2.2.6",
@ -14660,14 +14660,18 @@
},
"dependencies": {
"rc-animate": {
"version": "3.1.1",
"resolved": "https://registry.npm.taobao.org/rc-animate/download/rc-animate-3.1.1.tgz?cache=0&sync_timestamp=1601018005635&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-animate%2Fdownload%2Frc-animate-3.1.1.tgz",
"integrity": "sha1-3v3YY/VoFsIiU05Nxo/t3s0IE4Y=",
"version": "3.0.0-rc.6",
"resolved": "https://registry.npmjs.org/rc-animate/-/rc-animate-3.0.0-rc.6.tgz",
"integrity": "sha512-oBLPpiT6Q4t6YvD/pkLcmofBP1p01TX0Otse8Q4+Mxt8J+VSDflLZGIgf62EwkvRwsQUkLPjZVFBsldnPKLzjg==",
"requires": {
"@ant-design/css-animation": "^1.7.2",
"classnames": "^2.2.6",
"babel-runtime": "6.x",
"classnames": "^2.2.5",
"component-classes": "^1.2.6",
"fbjs": "^0.8.16",
"prop-types": "15.x",
"raf": "^3.4.0",
"rc-util": "^4.15.3"
"rc-util": "^4.5.0",
"react-lifecycles-compat": "^3.0.4"
}
}
}
@ -15106,9 +15110,9 @@
}
},
"react-lazy-load": {
"version": "3.1.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",
"integrity": "sha1-I2lD92twhMyEWHFtljKhyYU+pc0=",
"version": "3.0.13",
"resolved": "https://registry.npmjs.org/react-lazy-load/-/react-lazy-load-3.0.13.tgz",
"integrity": "sha1-OwqS0zbUPT8Nc8vm81sXBQsIuCQ=",
"requires": {
"eventlistener": "0.0.1",
"lodash.debounce": "^4.0.0",
@ -15246,8 +15250,8 @@
},
"react-slick": {
"version": "0.25.2",
"resolved": "https://registry.nlark.com/react-slick/download/react-slick-0.25.2.tgz",
"integrity": "sha1-VjMbZ9R9i8/i3OtqyrHI/VvR9rw=",
"resolved": "https://registry.npmjs.org/react-slick/-/react-slick-0.25.2.tgz",
"integrity": "sha512-8MNH/NFX/R7zF6W/w+FS5VXNyDusF+XDW1OU0SzODEU7wqYB+ZTGAiNJ++zVNAVqCAHdyCybScaUB+FCZOmBBw==",
"requires": {
"classnames": "^2.2.5",
"enquire.js": "^2.1.6",
@ -16091,8 +16095,8 @@
},
"rmc-feedback": {
"version": "2.0.0",
"resolved": "https://registry.npm.taobao.org/rmc-feedback/download/rmc-feedback-2.0.0.tgz",
"integrity": "sha1-y8bLOuY8emNe7w4l5PuvWsNm7qo=",
"resolved": "https://registry.npmjs.org/rmc-feedback/-/rmc-feedback-2.0.0.tgz",
"integrity": "sha512-5PWOGOW7VXks/l3JzlOU9NIxRpuaSS8d9zA3UULUCuTKnpwBHNvv1jSJzxgbbCQeYzROWUpgKI4za3X4C/mKmQ==",
"requires": {
"babel-runtime": "6.x",
"classnames": "^2.2.5"
@ -16675,8 +16679,8 @@
},
"shallow-equal": {
"version": "1.2.1",
"resolved": "https://registry.npm.taobao.org/shallow-equal/download/shallow-equal-1.2.1.tgz",
"integrity": "sha1-TBar+lYEOqINBQMk76aJQLDaedo="
"resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.1.tgz",
"integrity": "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA=="
},
"shallowequal": {
"version": "1.1.0",
@ -20476,16 +20480,6 @@
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
"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": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",

View File

@ -111,9 +111,7 @@
"webpack-dev-server": "^3.10.3",
"webpack-manifest-plugin": "^2.2.0",
"whatwg-fetch": "2.0.3",
"wrap-md-editor": "^0.2.20",
"xterm": "4.8.1",
"xterm-addon-fit": "0.4.0"
"wrap-md-editor": "^0.2.20"
},
"scripts": {
"start": "node --max_old_space_size=15360 scripts/start.js",

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,5 @@
/*头部导航条样式---2018-03-19--by-cs*/
.newHeader {
background: #24292D !important;
width: 100%;
height: 60px !important;
min-width: 1200px;

View File

@ -2346,6 +2346,7 @@ input::-ms-clear {
/*中间部分宽度固定为1200*/
.newMain {
margin: 0 auto;
padding-bottom: 110px;
min-width: 1200px;
}
@ -4107,6 +4108,21 @@ em.vertical-line {
/* 右侧内容宽度变化的话需要调整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 {
border-bottom: 1px solid #47494d;
@ -6703,12 +6719,3 @@ ul.count_ul li:not(:last-child):after {
input.ant-input-lg::placeholder{
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

View File

@ -5,55 +5,6 @@
"css_prefix_text": "icon-",
"description": "",
"glyphs": [
{
"icon_id": "991344",
"name": "提交",
"font_class": "tijiao",
"unicode": "e860",
"unicode_decimal": 59488
},
{
"icon_id": "1852052",
"name": "数据库",
"font_class": "dataBase",
"unicode": "e85a",
"unicode_decimal": 59482
},
{
"icon_id": "4165948",
"name": "文件",
"font_class": "wenjian4",
"unicode": "e85b",
"unicode_decimal": 59483
},
{
"icon_id": "17165148",
"name": "链接",
"font_class": "lianjie2",
"unicode": "e85c",
"unicode_decimal": 59484
},
{
"icon_id": "17463741",
"name": "分支",
"font_class": "fenzhi2",
"unicode": "e85d",
"unicode_decimal": 59485
},
{
"icon_id": "17972521",
"name": "分支-3",
"font_class": "fenzhi-3",
"unicode": "e85e",
"unicode_decimal": 59486
},
{
"icon_id": "18682391",
"name": "天平",
"font_class": "tianping",
"unicode": "e85f",
"unicode_decimal": 59487
},
{
"icon_id": "1770896",
"name": "撤销",

View File

@ -20,27 +20,6 @@ Created by iconfont
/>
<missing-glyph />
<glyph glyph-name="tijiao" unicode="&#59488;" d="M776.340596 759.889666l-369.442335 0c-7.573056 0-14.839097-2.967819-20.263042-8.187088L201.197681 571.177294c-5.526284-5.423946-8.801119-12.997002-8.801119-20.774735l-1.023386-513.637418c0-7.777733 2.967819-15.043774 8.494104-20.570058 5.526284-5.526284 12.792325-8.494104 20.570058-8.494104L382.746352 7.700979c12.485309 0 22.514491 10.029182 22.514491 22.514491s-10.029182 22.514491-22.514491 22.514491L236.402159 52.729962l0.921047 467.687388 194.03398 0c16.681191 0 30.189886 13.508695 30.189886 30.189886L461.547072 714.860684l298.828703 0 0-665.200879L621.195283 49.659804c-12.485309 0-22.514491-10.029182-22.514491-22.514491s10.029182-22.514491 22.514491-22.514491l155.145313 0c16.06716 0 29.064162 12.997002 29.064162 29.064162L805.404757 730.825505C805.404757 746.892664 792.407755 759.889666 776.340596 759.889666zM416.518089 565.446332 259.837697 565.446332l153.610234 149.414351 3.172497 0L416.620428 565.446332zM713.30002 434.452928c0 12.485309-10.029182 22.514491-22.514491 22.514491L326.460124 456.96742c-12.485309 0-22.514491-10.029182-22.514491-22.514491l0 0c0-12.485309 10.029182-22.514491 22.514491-22.514491l364.325405 0C703.270837 411.938437 713.30002 421.967619 713.30002 434.452928L713.30002 434.452928zM713.30002 357.698981c0 12.485309-10.029182 22.514491-22.514491 22.514491L326.460124 380.213472c-12.485309 0-22.514491-10.029182-22.514491-22.514491l0 0c0-12.485309 10.029182-22.514491 22.514491-22.514491l364.325405 0C703.270837 335.184489 713.30002 345.213672 713.30002 357.698981L713.30002 357.698981zM713.30002 279.921647c0 12.485309-10.029182 22.514491-22.514491 22.514491L326.460124 302.436138c-12.485309 0-22.514491-10.029182-22.514491-22.514491l0 0c0-12.485309 10.029182-22.514491 22.514491-22.514491l364.325405 0C703.270837 257.407156 713.30002 267.436338 713.30002 279.921647L713.30002 279.921647zM501.970818 220.155906c-1.535079 1.535079-4.093544 1.43274-5.526284-0.102339l-54.853488-59.458725c-2.251449-2.456126-0.511693-6.447332 2.865481-6.447332L479.968019 154.147511l0-88.829902c0-2.251449 1.842095-4.298221 4.093544-4.298221l36.841895 0c2.251449 0 4.093544 2.046772 4.093544 4.298221L524.997002 154.045173l35.511493 0c3.479512 0 5.219268 4.195882 2.660804 6.652009L501.970818 220.155906z" horiz-adv-x="1024" />
<glyph glyph-name="dataBase" unicode="&#59482;" d="M512 793.4c110.7 0 215-12.3 293.9-34.7 35.8-10.2 65-22.1 84.5-34.7 18.6-12 21.3-19.7 21.6-20.6-0.2-0.9-3-8.6-21.6-20.6-19.5-12.5-48.7-24.5-84.5-34.7-78.9-22.3-183.2-34.7-293.9-34.7s-215 12.3-293.9 34.7c-35.8 10.2-65 22.1-84.5 34.7-18.6 12-21.3 19.7-21.6 20.6 0.2 0.9 3 8.6 21.6 20.6 19.5 12.5 48.7 24.5 84.5 34.7 78.9 22.4 183.2 34.7 293.9 34.7M512 833.4c-243 0-440-58.2-440-130s197-130 440-130 440 58.2 440 130-197 130-440 130zM112 705.6h-40v-641h40v641zM952 705.9h-40v-641h40v641zM912 65v-0.5c-0.2-0.9-3-8.6-21.6-20.6-19.5-12.5-48.7-24.5-84.5-34.7-78.9-22.3-183.2-34.6-293.9-34.6s-215 12.3-293.9 34.7c-35.8 10.2-65 22.1-84.5 34.7-18.6 12-21.3 19.7-21.6 20.6v0.3l-40-0.3v-0.1c0-71.8 197-130 440-130s440 58.2 440 130v0.4l-40 0.1zM912 275.5v-0.5c-0.2-0.9-3-8.6-21.6-20.6-19.5-12.5-48.7-24.5-84.5-34.7-78.9-22.3-183.2-34.7-293.9-34.7s-215 12.3-293.9 34.7c-35.8 10.2-65 22.1-84.5 34.7-18.6 12-21.3 19.7-21.6 20.6v0.3l-40-0.3v-0.1c0-71.8 197-130 440-130s440 58.2 440 130v0.4l-40 0.2zM912 497v-0.5c-0.2-0.9-3-8.6-21.6-20.6-19.5-12.5-48.7-24.5-84.5-34.7-78.9-22.3-183.2-34.7-293.9-34.7s-215 12.3-293.9 34.7c-35.8 10.2-65 22.1-84.5 34.7-18.6 12-21.3 19.7-21.6 20.6v0.3l-40-0.3v-0.1c0-71.8 197-130 440-130s440 58.2 440 130v0.4l-40 0.2z" horiz-adv-x="1024" />
<glyph glyph-name="wenjian4" unicode="&#59483;" d="M751.3-61.4H274.7c-82.7 0-150 67.3-150 150V679.8c0 82.7 67.3 150 150 150h138.9c13.8 0 25-11.2 25-25s-11.2-25-25-25H274.7c-55.1 0-100-44.9-100-100v-591.2c0-55.1 44.9-100 100-100h476.6c55.1 0 100 44.9 100 100v390H653.6c-32.4 0-62.8 12.6-85.7 35.6-22.9 23-35.4 53.5-35.2 85.9l0.9 204.9c0 10 6 19 15.2 22.9 9.2 3.9 19.8 2 27-4.8l317.7-301.2 0.3-0.3 0.5-0.5c4.3-4.5 6.9-10.6 6.9-17.2v-415c0.1-83-67.2-150.3-149.9-150.3z m-168 808.3l-0.6-147.1c-0.1-19 7.3-36.9 20.7-50.4 13.4-13.5 31.3-20.9 50.3-20.9h160L583.3 746.9zM701.4 298H324.6c-13.8 0-25 11.2-25 25s11.2 25 25 25h376.8c13.8 0 25-11.2 25-25s-11.2-25-25-25zM701.4 148.7H324.6c-13.8 0-25 11.2-25 25s11.2 25 25 25h376.8c13.8 0 25-11.2 25-25s-11.2-25-25-25z" horiz-adv-x="1024" />
<glyph glyph-name="lianjie2" unicode="&#59484;" d="M427.392 259.328a40.448 40.448 0 0 0-31.168 13.376c-93.44 93.44-93.44 244.864 0 342.784l209.28 209.28c93.44 93.44 249.344 93.44 342.784 0a243.264 243.264 0 0 0 71.232-169.216c0-62.272-26.688-124.608-71.232-169.152L832.64 361.728c-17.856-17.792-44.544-17.792-57.92 0-17.792 17.792-17.792 44.544 0 57.856l120.256 120.256a155.904 155.904 0 0 1 0 222.592 155.904 155.904 0 0 1-222.656 0l-209.28-209.28a155.904 155.904 0 0 1 0-222.592c17.856-17.792 17.856-44.48 0-57.856-8.832-4.48-22.208-13.376-35.584-13.376zM240.448-128c-66.816 0-124.672 26.688-169.216 71.232A243.264 243.264 0 0 0 0 112.448c0 62.272 26.688 124.608 71.232 169.152l120.192 120.192c17.856 17.856 44.544 17.856 57.92 0 17.792-17.792 17.792-44.48 0-57.856l-120.256-120.192a155.904 155.904 0 0 1 0-222.656 158.08 158.08 0 0 1 111.36-44.48 158.08 158.08 0 0 1 111.296 44.48l209.28 209.28a158.08 158.08 0 0 1 44.48 111.36c0 44.48-17.792 80.064-44.544 111.232-17.792 17.792-17.792 44.544 0 57.92 17.792 17.792 44.544 17.792 57.92 0a243.264 243.264 0 0 0 71.232-169.216c0-66.752-26.752-124.672-71.232-169.152l-209.28-209.28C365.056-101.312 307.2-128 240.448-128z" horiz-adv-x="1024" />
<glyph glyph-name="fenzhi2" unicode="&#59485;" d="M737.792 811.2a128 128 0 0 0 36.352-250.752C761.6 440.96 690.176 374.08 567.936 369.28l-14.208-0.256c-104.704 0-179.456-21.12-225.472-61.312l0.064-121.6a128 128 0 1 0-76.8 0V561.024a128 128 0 1 0 76.8 0l-0.128-160.96c53.44 28.352 121.6 43.264 203.84 45.44l21.76 0.32c88.064 0 133.248 35.456 143.36 115.968a128 128 0 0 0 40.64 249.344zM289.92 128a64 64 0 1 1 0-128 64 64 0 0 1 0 128z m0 619.2a64 64 0 1 1 0-128 64 64 0 0 1 0 128z m447.872 0a64 64 0 1 1 0-128 64 64 0 0 1 0 128z" horiz-adv-x="1024" />
<glyph glyph-name="fenzhi-3" unicode="&#59486;" d="M199.095774 895.999795a170.536926 170.536926 0 0 0 59.166708-330.526654c30.719994-284.446663 286.719943-339.046332 406.753199-349.85977a170.577886 170.577886 0 1 0 159.866848-229.826514 171.622366 171.622366 0 0 0-161.566688 113.786857c-241.766352 11.386878-325.406655 102.973419-407.326639 205.373399v-101.273579a170.659806 170.659806 0 1 0-113.786857 0V564.346742A170.721246 170.721246 0 0 0 199.095774 895.999795m0-113.786857a56.893429 56.893429 0 1 1 56.893428-56.893429 57.057269 57.057269 0 0 1-56.893428 56.893429m0-682.659704a56.893429 56.893429 0 1 1 56.893428-56.893428 57.057269 57.057269 0 0 1-56.893428 56.893428m625.766275 113.786858a56.893429 56.893429 0 1 1 56.893428-56.893429 57.057269 57.057269 0 0 1-56.893428 56.893429z" horiz-adv-x="1024" />
<glyph glyph-name="tianping" unicode="&#59487;" d="M669.5 495.5c0-74.4 60.5-134.9 134.9-134.9s134.9 60.5 134.9 134.9c0 30.3-21.4 84.9-63.7 162.3-31 56.8-62.5 105.9-62.8 106.4v0.1c-0.2 0.3-0.4 0.6-0.7 0.9 0 0.1-0.1 0.1-0.1 0.2-0.2 0.2-0.4 0.5-0.6 0.7-0.1 0.1-0.2 0.2-0.3 0.2-0.2 0.2-0.4 0.3-0.6 0.5-0.1 0.1-0.2 0.1-0.3 0.2-0.6 0.4-1.3 0.8-2 1.1-0.1 0-0.2 0.1-0.2 0.1l-0.9 0.3c-0.1 0-0.2 0.1-0.3 0.1-0.3 0.1-0.6 0.1-0.9 0.2h-0.3c-0.4 0-0.8 0.1-1.2 0.1H556.6c-4.6 20.4-22.8 35.7-44.6 35.7s-40-15.3-44.6-35.7H221.6c-0.4 0-0.8 0-1.2-0.1h-0.3c-0.3 0-0.6-0.1-0.9-0.2-0.1 0-0.2-0.1-0.3-0.1l-0.9-0.3c-0.1 0-0.2-0.1-0.2-0.1-0.7-0.3-1.4-0.7-2-1.1-0.1-0.1-0.2-0.1-0.3-0.2-0.2-0.2-0.4-0.3-0.6-0.5-0.1-0.1-0.2-0.2-0.3-0.2l-0.7-0.7-0.1-0.1c-0.2-0.3-0.5-0.6-0.7-0.9v-0.1c-0.3-0.5-31.8-49.5-62.8-106.4-42.3-77.4-63.7-132-63.7-162.3 0-74.4 60.5-134.9 134.9-134.9s134.9 60.5 134.9 134.9c0 30.3-21.4 84.9-63.7 162.3-20.6 37.7-41.4 72-53.1 91h227.7c3.9-17.2 17.4-30.7 34.6-34.6v-587.9H315.7c-5.5 0-10-4.5-10-10V55H172.9c-5.5 0-10-4.5-10-10v-71.4c0-5.5 4.5-10 10-10h678.2c5.5 0 10 4.5 10 10V45c0 5.5-4.5 10-10 10H718.3v61.4c0 5.5-4.5 10-10 10H522V714.2c17.2 3.9 30.7 17.4 34.6 34.6h229.7c-11.7-18.9-32.5-53.2-53.2-91-42.2-77.3-63.6-131.9-63.6-162.3z m171.6-512H182.9v51.4h658.3v-51.4z m-142.8 71.4H325.7v51.4h372.7v-51.4zM221.6 380.6c-63.4 0-114.9 51.6-114.9 114.9 0 1.1 0 2.2 0.1 3.4h229.7c0.1-1.2 0.1-2.3 0.1-3.4-0.1-63.3-51.6-114.9-115-114.9z m111.3 138.3H110.2c6.3 24.4 22.1 64.2 57.6 129.2 21.1 38.6 42.4 73.6 53.7 91.9 11.4-18.3 32.7-53.3 53.7-91.9 35.6-65 51.5-104.8 57.7-129.2zM512 733.1c-14.2 0-25.7 11.5-25.7 25.7s11.5 25.7 25.7 25.7 25.7-11.5 25.7-25.7-11.5-25.7-25.7-25.7z m292.4-352.5c-63.4 0-114.9 51.6-114.9 114.9 0 1.1 0 2.3 0.1 3.5 0.6-0.1 1.1-0.2 1.7-0.2h227.9c0.1-1.2 0.1-2.3 0.1-3.4 0.1-63.2-51.5-114.8-114.9-114.8z m0 359.4c11.4-18.3 32.7-53.3 53.7-91.9 35.5-65 51.3-104.9 57.6-129.2H693.1c6.3 24.4 22.1 64.2 57.6 129.2 21.1 38.7 42.3 73.7 53.7 91.9z" horiz-adv-x="1024" />
<glyph glyph-name="chexiao" unicode="&#58967;" d="M530.496 524.928h-6.144V661.632c0 51.136-29.312 72.448-65.472 43.328L122.816 434.624c-36.096-28.992-36.096-76.48 0.128-105.472l333.504-267.648c36.16-28.992 67.968 0.448 67.968 43.584v144.256h50.496c145.856 0 257.152-62.976 325.248-184.576 13.376-22.08 27.456-17.28 27.456 0-2.944 216.576-186.368 460.16-397.12 460.16z" horiz-adv-x="1024" />

Before

Width:  |  Height:  |  Size: 733 KiB

After

Width:  |  Height:  |  Size: 724 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -2,12 +2,12 @@ import axios from 'axios';
import { requestProxy } from "./indexEduplus2RequestProxy";
import { broadcastChannelOnmessage, isDev, queryString } from 'educoder';
import { notification } from 'antd';
import cookie from 'react-cookies';
import './index.css';
let message501 = false;
broadcastChannelOnmessage('refreshPage', () => {
window.location.reload();
window.location.reload()
})
function locationurl(list) {
@ -25,21 +25,54 @@ if (isDev) {
}
debugType = window.location.search.indexOf('debug=t') !== -1 ? 'teacher' :
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 || 's'
}
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;
export function initAxiosInterceptors(props) {
// 判断网络是否连接
initOnlineOfflineListener();
initOnlineOfflineListener()
// TODO 避免重复的请求 https://github.com/axios/axios#cancellation
var
proxy = "http://localhost:3000";
proxy = "https://forge.osredm.com";
var proxy = "https://testforgeplus.trustie.net";
const requestMap = {};
window.setfalseInRequestMap = function (keyName) {
requestMap[keyName] = false;
}
//响应前的设置
axios.interceptors.request.use(
config => {
if(config.url.indexOf("http") !== -1) {
setpostcookie()
clearAllCookie()
if (config.url.indexOf(proxy) !== -1) {
return config
}
requestProxy(config);
requestProxy(config)
let url = `/api${config.url}`;
if (`${config[0]}` !== `true`) {
@ -53,6 +86,11 @@ export function initAxiosInterceptors(props) {
} else {
config.url = url;
}
setpostcookie();
}
if (config.url.indexOf('update_file') === -1) {
requestMap[config.url] = true;
window.setTimeout("setfalseInRequestMap('" + config.url + "')", 900)
}
return config;
},
@ -107,6 +145,8 @@ export function initAxiosInterceptors(props) {
message501 = false
}, 2000);
}
requestMap[response.config.url] = false;
setpostcookie();
return response;
}, function (error) {
return Promise.reject(error);

View File

@ -68,7 +68,7 @@ export function appendFileSizeToUploadFile(item) {
return `${item.title}${uploadNameSizeSeperator}${item.filesize}`
}
export function appendFileSizeToUploadFileAll(fileList) {
return fileList.map(item => {
return fileList && fileList.map(item => {
if (item.name.indexOf(uploadNameSizeSeperator) == -1) {
return Object.assign({}, item, { name: `${item.name}${uploadNameSizeSeperator}${bytesToSize(item.size)}` })
}

View File

@ -6,23 +6,23 @@ const { Search } = Input;
const $ = window.$;
const isDev = window.location.port == 3007;
const isdev2= window.location.hostname ==='www.educoder.net'
export const TEST_HOST = "https://testforgeplus.trustie.net/"
export const TEST_HOST = "http://39.105.176.215:49999"
export function getImageUrl(path) {
// https://www.educoder.net
// https://testbdweb.trustie.net
// const local = 'http://localhost:3000'
const local = 'https://testforgeplus.trustie.net';
const local = 'http://39.105.176.215:49999';
if (isDev) {
return `${local}/${path}`
}
return `${path}`;
return `/${path}`;
}
export function getImage(path) {
// https://www.educoder.net
// https://testbdweb.trustie.net
// const local = 'http://localhost:3000'
const local = 'https://testforgeplus.trustie.net/';
const local = 'http://39.105.176.215:49999';
if(path.indexOf("http://")===-1){
if (isDev) {
return `${local}/images/${path}`
@ -93,7 +93,7 @@ export function setImagesUrl(path){
}
export function getUrl(path, goTest) {
const local = 'https://testforgeplus.trustie.net'
const local = 'http://39.105.176.215:49999'
if (isDev) {
return `${local}${path?path:''}`
}
@ -162,28 +162,28 @@ export function getmyUrl(geturl) {
}
export function getUploadActionUrl(path, goTest) {
return `${getUrl()}/api/attachments.json${isDev ?`${isDev ?`?debug=${window._debugType || 'admin'}` : ""}` : ""}`;
return `${getUrl()}/api/attachments.json`;
}
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) {
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() {
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) {
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) {
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) {

View File

@ -64,7 +64,7 @@ function CommentItem({
const commentAvatar = (author) => (
<img
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=""
/>
);

View File

@ -67,14 +67,15 @@ function Index(props){
}
return(
<div className="aboutPanels">
<div className="aboutContent">
<AlignCenterBetween style={{padding:"14px 20px"}}>
<span className="font-16"><i className="iconfont icon-xiangmujianjie mr5 font-16 color-blue"></i>项目概览</span>
<AlignCenterBetween style={{padding:"14px 0px"}}>
<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> }
</AlignCenterBetween>
{
edit ?
<div className="padding20">
<div>
<MDEditor
placeholder={"请输入描述信息"}
height={500}
@ -113,11 +114,11 @@ function Index(props){
</div>
</div>
:
<div className="padding20">
<div style={{padding:"20px 0px"}}>
{content ?
<RenderHtml className="break_word_comments imageLayerParent" value={content} url={props.history.location}/>
:
<div>暂无概览~</div>
<div>暂无简介~</div>
}
{attachments && attachments.length > 0 &&
<Attachments

View File

@ -4,6 +4,7 @@
.aboutContent{
border-radius: 2px;
border: 1px solid #EEEEEE;
padding:0px 30px;
width:100%;
background-color: #fff;
margin-top:20px;

View File

@ -33,7 +33,7 @@ class ActivityItem extends Component {
}
<p className="itemLine mt10">
<Link to={`/users/${item && item.user_login}`} className="show-user-link">
<img alt="" src={getImageUrl(`/${item.user_avatar}`)} className="createImage" />
<img alt="" src={getImageUrl(`images/${item.user_avatar}`)} className="createImage" />
<span className="mr20">{item.user_name}</span>
</Link>
{item.created_at && <span className="color-grey-9">创建于<span className="ml2 color-grey-6">{item.created_at}</span></span>}

View File

@ -14,7 +14,7 @@ class CloneAddress extends Component {
const { http_url, downloadUrl } = this.props;
return (
<div className="gitAddressClone">
{/* <p className="addressTips"><span>版本库地址已变更,请基于新地址提交代码</span></p> */}
<p className="addressTips"><span>版本库地址已变更请基于新地址提交代码</span></p>
{
http_url && <span>HTTP</span>
}

View File

@ -102,10 +102,9 @@ export default (({ projectsId , branch , owner , changeBranch , branchList , tag
</div>
);
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">
{/* {nav === 0 ?"分支":"标签"} */}
<span className="color-grey-9 mr3 ml8"><i className="iconfont icon-fenzhi2 font-18"></i></span>
<span className="color-grey-9 mr3 ml8">{nav === 0 ?"分支":"标签"}:</span>
<a className="ant-dropdown-link">
{showValue}
</a>

View File

@ -51,7 +51,7 @@
display: flex;
align-items: center;
cursor: pointer;
min-width: 140px;
min-width: 240px;
}
.branch-tagBox-list .ant-popover-arrow{
display: none;

View File

@ -42,7 +42,7 @@ function AddMember({getID,login}){
className="user_img radius"
width="28"
height="28"
src={getImageUrl(`/${item && item.image_url}`)}
src={getImageUrl(`images/${item && item.image_url}`)}
alt=""
/>
<span className="ml10" style={{ "vertical-align": "middle" }}>

View File

@ -3,10 +3,10 @@ import { getImageUrl } from 'educoder';
import { Link } from 'react-router-dom';
import './Component.scss';
function Cards({img , title, desc , rightBtn , src , bottomInfos}){
function Cards({img , title, desc , rightBtn , src}){
return(
<div className="cards">
{img &&<div className="img"><img src={getImageUrl(`/${img}`)} alt=""/></div>}
{img &&<div className="img"><img src={getImageUrl(`images/${img}`)} alt=""/></div>}
<div className="content">
<p className="titles">
<Link to={src}>{title}</Link>
@ -15,7 +15,6 @@ function Cards({img , title, desc , rightBtn , src , bottomInfos}){
<div className="desc">
{desc}
</div>
{bottomInfos}
</div>
</div>
)

View File

@ -20,7 +20,6 @@ li.ant-menu-item{
background-color: #fff;
margin-bottom:18px;
min-height: 130px;
border:1px solid #eee;
.img{
margin-right: 20px;
width: 190px;
@ -62,7 +61,6 @@ li.ant-menu-item{
}
// Tabs
.tabsStyle{
border:1px solid #eee;
.ant-tabs-bar.ant-tabs-top-bar{
padding-left: 35px;
margin-bottom: 0px;
@ -112,9 +110,6 @@ li.ant-menu-item{
right:240px;
z-index: 10000;
}
.laterest{
color: #05690d;
}
@media screen and (max-width: 1800px){
.handleBox{
@ -141,55 +136,3 @@ li.ant-menu-item{
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;
}
}
}

View File

@ -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;

View File

@ -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;

View File

@ -1,9 +0,0 @@
.ant-modal-mask{
z-index: 1001;
}
.ant-modal-wrap{
z-index: 1002;
.ant-form-explain{
position: absolute;
}
}

View File

@ -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));

View File

@ -1,3 +1,5 @@
import React , { useState , useEffect } from 'react';
import { Select } from 'antd';
import axios from 'axios';
@ -57,7 +59,6 @@ const LANGUAGE = [
export default (({ language , select_language })=>{
const [ languages , setLanguage ] = useState(undefined);
// useEffect(()=>{
// const url = '/dev_ops/languages.json';
// axios.get(url).then(result=>{

View File

@ -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;

View File

@ -45,7 +45,7 @@ const Div = styled.div`{
export default (({ user , img, name, time, focusStatus, is_current_user, login , successFunc }) => {
return (
<Div>
<Link to={`/users/${user && user.login}`}><Img src={getImageUrl(`/${img}`)} /></Link>
<Link to={`/users/${user && user.login}`}><Img src={getImageUrl(`images/${img}`)} /></Link>
<div className="m-infos">
<Link to={`/users/${user && user.login}`}><Name>{name}</Name></Link>
<Time><I className="iconfont icon-shijian"></I>加入时间:{time}</Time>

View File

@ -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;

View File

@ -1,33 +1,24 @@
import React , { useState , useEffect } from 'react';
import React , { useState } from 'react';
import { AutoComplete } from 'antd';
import { getImageUrl } from "educoder";
import axios from 'axios';
const Option = AutoComplete.Option;
export default ({ getUser , placeholder, width ,value })=>{
const [ source , setSource ] = useState(undefined);
export default ({ getUser })=>{
const [ searchKey , setSearchKey ] = useState(undefined);
useEffect(()=>{
if(!value){
setSearchKey(undefined);
}
},[value])
useEffect(()=>{
getUserList();
},[searchKey])
const [ userDataSource , setUserDataSource ] = useState(undefined);
function getUserList(e){
const url = `/users/list.json`;
axios.get(url, {
params: {
search: searchKey,
search: e,
},
}).then((result) => {
})
.then((result) => {
if (result) {
sourceOptions(result.data.users);
setUserDataSource(result.data.users);
}
})
.catch((error) => {
@ -35,20 +26,25 @@ export default ({ getUser , placeholder, width ,value })=>{
});
};
function sourceOptions(userDataSource){
const s = userDataSource && userDataSource.map((item, key) => {
function changeInputUser(value){
setSearchKey(value);
getUserList(value);
}
function selectInputUser(id, option){
setSearchKey(option.props.value);
getUserList(option.props.value);
getUser && getUser(id);
}
const source =
userDataSource && userDataSource.map((item, key) => {
return (
<Option
key={key}
value={`${item.user_id}`}
login={`${item.login}`}
name={item.username}
>
<Option key={key} value={`${item.login}`}>
<img
className="user_img radius"
width="28"
height="28"
src={getImageUrl(`/${item && item.image_url}`)}
src={getImageUrl(`images/${item && item.image_url}`)}
alt=""
/>
<span className="ml10" style={{ "vertical-align": "middle" }}>
@ -58,31 +54,14 @@ export default ({ getUser , placeholder, width ,value })=>{
</Option>
);
});
setSource(s);
}
function changeInputUser(e){
setSearchKey(e);
};
//
function selectInputUser(e, option){
setSearchKey(option.props.name);
getUser(option.props.login);
};
return(
<div className="addPanel">
<AutoComplete
getPopupContainer={trigger => trigger.parentNode}
dataSource={source}
value={searchKey}
style={{ width: width || 300 }}
style={{ width: 300 }}
onChange={changeInputUser}
onSelect={selectInputUser}
placeholder={placeholder || "搜索需要添加的用户..."}
allowClear
placeholder="搜索需要添加的用户..."
/>
</div>
)
}

View File

@ -1,8 +1,8 @@
import React from 'react';
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`
display:flex;
${column && "flex-direction: column;text-align:center;"}
@ -19,16 +19,8 @@ export default ({ url , name , column , id , login })=>{
}
`;
return(
id?
<Link to={`/users/${login}`}>
<Img>
{ url && <img src={url} alt=""/> }
<span>{name}</span>
</Img>
</Link>
:
<Img>
{ url && <img src={url} alt=""/> }
<img src={url} alt=""/>
<span>{name}</span>
</Img>
)

View File

@ -24,33 +24,18 @@ export const AlignCenter = styled.div`{
display:flex;
align-items: center;
}`
export const AlignTop = styled.div`{
display:flex;
align-items: flex-start;
}`
//
export const Box = styled.div`{
display:flex;
align-items:flex-start;
}`
export const LongWidth = styled.div`{
flex:1;
width:0;
border-radius:5px;
margin-bottom:30px;
align-item:flex-start;
}`
export const Long = styled.div`{
width:78%;
border-radius:5px;
margin-bottom:30px;
}`
export const ShortWidth = styled.div`{
width:300px;
width:72%;
border-radius:5px;
margin-bottom:30px;
}`
export const Short = styled.div`{
flex:1;
width:28%;
border-radius:5px;
margin-bottom:30px;
}`

View File

@ -36,7 +36,8 @@ function About(props, ref) {
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;
useEffect(()=>{
if(CurrentLogin === AuthorLogin){
@ -55,6 +56,11 @@ function About(props, ref) {
setIsSpining(false);
if(result && result.data ){
setStep(result.data.step);
// setStep(0);
// setFieldsValue({...result.data.cloud_account});
// if(result.data.cloud_account){
// setDisabled(true);
// }
}
}).catch(error=>{
setIsSpining(false);

View File

@ -45,9 +45,9 @@ function Dispose(props){
}).then(result=>{
if(result && result.data){
setList(result.data.pipelines);
}
setSpining(false);
}).catch(error=>{setSpining(false);})
}
}).catch(error=>{})
}
useEffect(()=>{
@ -137,17 +137,13 @@ function Dispose(props){
props.history.push(`/projects/${owner}/${projectsId}/devops/mould`);
}
//
function toparameter(){
props.history.push(`/projects/${owner}/${projectsId}/devops/params`);
}
const operate = current_user && (permission && permission !== "Reporter");
return(
<Spin spinning={spining}>
<PipelineName branchList={branchList} visible={visible} value={updateInfo} onCancel={()=>setVisible(false)} onOk={onOk}/>
<div className="disposePanel">
<Head manager={ operate ? toModalManage : undefined} parameter={operate ? toparameter :undefined}/>
<Head manager={ operate ? toModalManage : undefined} />
<Div>
{ operate && <Blueback onClick={()=>addNew(undefined,undefined)}>新增流水线</Blueback> }
<div className="mt20 disposeList">

View File

@ -2,47 +2,13 @@ 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>
);
}
const STATUS = {
running:"运行中",
failure:"未通过",
error:"未通过",
success:"已通过",
killed:"已撤销",
pending:"准备中"
}
function List({ list, operate , projectsId , owner , showModal , deleteFunc }){
@ -66,7 +32,7 @@ function List({ list, operate , projectsId , owner , showModal , deleteFunc }){
ellipsis:true,
render:(value,item)=>{
return(
<Link to={`/projects/${owner}/${projectsId}/tree/${item.branch}/${value}`} className="color-blue">{value}</Link>
<Link to={`/projects/${owner}/${projectsId}/branch/${item.branch}/tree/${value}`} className="color-blue">{value}</Link>
)
}
},
@ -95,10 +61,10 @@ function List({ list, operate , projectsId , owner , showModal , deleteFunc }){
title:"最近构建状态",
dataIndex:"pipeline_status",
key:1,
width:"12%",
width:"10%",
ellipsis:true,
render:(txt)=>{
return renderTableStatus(txt)
return(STATUS[txt])
}
},
{

View File

@ -2,18 +2,15 @@ import React from 'react';
import { AlignCenterBetween , Blueline , FlexAJ } from '../../Component/layout';
function head({manager , parameter}){
function head({manager}){
return(
<AlignCenterBetween>
<span className="font-20">工作流配置</span>
<FlexAJ>
{
parameter && <Blueline onClick={parameter}>参数管理</Blueline>
}
<a href={`https://forum.trustie.net/forums/3111/detail`} target="_blank" className="color-grey-6"><i className="iconfont icon-tishi1 font-14 mr3"></i>模板使用说明</a>
{
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>
)

View File

@ -26,11 +26,6 @@ const Mould = Loadable({
loader: () => import('./Mould'),
loading: Loading,
})
const Params = Loadable({
loader: () => import('./Manage/Params'),
loading: Loading,
})
export default ((props)=>{
return(
@ -41,11 +36,6 @@ export default ((props)=>{
(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}/>)

View File

@ -1,8 +1,9 @@
import React , { useEffect , useState } from 'react';
import React , { useEffect , useState , useRef } from 'react';
import { Banner } from '../Component/layout';
import { Link } from 'react-router-dom';
import Dispost from './Dispose';
import Structure from './Structure';
import styled from 'styled-components';
@ -10,11 +11,22 @@ const Div = styled.div`{
padding:24px 30px;
}`;
export default ((props)=>{
const [ menu , setMenu ] = useState(false);
const [ permission , setPermission ] = useState("");
const childRef = useRef();
const path = props.location.pathname;
const owner = props.match.params.owner;
const projectsId = props.match.params.projectsId;
const projectDetail = props.projectDetail;
useEffect(()=>{
if(path === `/projects/${owner}/${projectsId}/devops/list`){
setMenu(true);
}else{
setMenu(false);
}
},[path])
useEffect(()=>{
if(projectDetail){
@ -22,13 +34,22 @@ export default ((props)=>{
}
},[projectDetail])
const updateChildState = () => {
// changeVal
if (childRef.current) {
childRef.current.changeVal();
}
}
return(
<div className="disposePanel">
<Banner>
{ permission !=="Reporter" && <Link to={`/projects/${owner}/${props.match.params.projectsId}/devops/dispose`}>工作流配置</Link>}
{/* <Link to={`/projects/${owner}/${props.match.params.projectsId}/devops/list`}className={menu===true && "color-blue"}>构建列表</Link> */}
{/* { menu===true && <a onClick={updateChildState} style={{float:"right",fontSize:"14px",color:"#FF6E21",marginTop:"5px"}}>刷新</a>} */}
</Banner>
<Div>
{/* { menu === true && <Structure {...props} wrappedComponentRef={(form) => childRef.current = form} ref={childRef}/> } */}
<Dispost {...props}/>
</Div>
</div>

View File

@ -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;

View File

@ -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));

View File

@ -1,4 +0,0 @@
.ant-form-explain{
position: absolute;
bottom: -15px;
}

View File

@ -1,8 +1,7 @@
import React, { useState, useEffect } from "react";
import { Spin , Menu } from "antd";
import { Spin } from "antd";
import { FlexAJ, AlignCenter } from "../Component/layout";
import axios from "axios";
import CodeSSH from './ssh/Index';
export default ({
data,
@ -18,8 +17,6 @@ export default ({
const [spining, setSpining] = useState(true);
const [stage, setStage] = useState(undefined);
const [step, setStep] = useState(undefined);
const [nav, setNav] = useState("0");
useEffect(() => {
setSpining(rightSpin);
}, [rightSpin]);
@ -38,7 +35,6 @@ export default ({
: p[0];
setStep(sub);
setNav("0");
if (sub && sub.status !== "skipped") {
getStep(pre.number, sub.number);
}
@ -69,13 +65,6 @@ export default ({
}
}
return (
<React.Fragment>
{/* <Menu className="devopsNav" onClick={(e)=>{setNav(e.key)}} selectedKeys={[nav]} mode="horizontal">
<Menu.Item key={'0'} value="0">开发流水线</Menu.Item>
<Menu.Item key={'1'} value="1">命令行</Menu.Item>
</Menu> */}
{
nav === "0" &&
<Spin spinning={spining}>
<div className="rightMainContent">
{data && data.status !== "error" ? (
@ -114,10 +103,5 @@ export default ({
)}
</div>
</Spin>
}
{
nav === "1" && <CodeSSH />
}
</React.Fragment>
);
};

View File

@ -58,7 +58,6 @@ function Structure(props,ref){
return {
...item,
author:item.author && item.author.name,
image_url:item.author && item.author.image_url,
message: {
branch: item.branch_target,
message: item.message,
@ -188,7 +187,7 @@ function Structure(props,ref){
<i className="iconfont icon-weitongguo"></i>已撤销
</span>
);
default:
case 'pending':
return (
<span className="statusTag Preparing">
<i className="iconfont icon-zhunbeizhong"></i>准备中
@ -245,7 +244,7 @@ function Structure(props,ref){
{meg.sha && <span className="color-orange">{meg.sha}</span>}
</div>
<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" }}>
{meg.message}
</div>

View File

@ -10,7 +10,6 @@
padding:60px 0px;
}
.disposePanel{
border:1px solid #eee;
.language{
display: flex;
margin-bottom: 20px;
@ -82,6 +81,47 @@
.ant-modal-close{
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详情
@ -194,18 +234,6 @@
&.rightSection{
width:100%;
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{
padding:24px 30px;
height:100vh;
@ -482,40 +510,3 @@
.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 ;
}
}

View File

@ -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;

View File

@ -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>
);
};

View File

@ -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;

View File

@ -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));

View File

@ -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: "";
}
}

View File

@ -11,11 +11,3 @@ export const getTag = async (id,owner)=>{
export const getHooks = async (id,params)=>{
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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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;
}
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 222 KiB

View File

@ -6,6 +6,7 @@ import { withRouter } from "react-router";
import { SnackbarHOC } from "educoder";
import { CNotificationHOC } from "../modules/courses/common/CNotificationHOC";
import { TPMIndexHOC } from "../modules/tpm/TPMIndexHOC";
import Handbook from './Component/Handbook';
import "./css/index.scss";
import Loadable from "react-loadable";
@ -34,6 +35,7 @@ class Index extends Component {
render() {
return (
<div className="newMain clearfix">
<Handbook />
<Switch {...this.props}>
<Route
path="/projects/:projectsType/new/:OIdentifier"
@ -47,12 +49,6 @@ class Index extends Component {
<ProjectNew {...this.props} {...props} />
)}
></Route>
<Route
path="/projects/new"
render={(props) => (
<ProjectNew {...this.props} {...props} />
)}
></Route>
<Route
path="/projects/:owner/:projectsId"
render={(props) => (

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -32,7 +32,7 @@ export default ((props)=>{
return(
<li key={key}>
<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">
<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>

View File

@ -74,7 +74,6 @@ class CoderRootCommit extends Component{
array.push({
name:item.author && item.author.name,
login: item.author && item.author.login,
id: item.author && item.author.id,
image_url:item.author && item.author.image_url,
sha:item.sha,
time_from_now:item.time_from_now,
@ -108,7 +107,7 @@ class CoderRootCommit extends Component{
let branch = branchName || defaultBranch;
return(
<React.Fragment>
<div className={"main"}style={{padding:"0px",border:"none"}}>
<div className={commit_class}>
<div className="f-wrap-between">
<SelectBranch
repo_id={projectDetail && projectDetail.repo_id}
@ -137,18 +136,10 @@ class CoderRootCommit extends Component{
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${item.sha}`)}`} className="flex1 ml20 font-16 color-grey-3">{item.message}</Link>
</p>
<p className="f-wrap-alignCenter mt15">
{
item.id ?
<Link to={`/users/${item.login}`} className="show-user-link">
{item.image_url?<img src={getImageUrl(`/${item.image_url}`)} alt="" width="28px" height="28px" className="mr15 radius"/>:""}
{item.image_url?<img src={getImageUrl(`images/${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>
</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>
}
</Link>
</p>
</div>
)

View File

@ -0,0 +1,517 @@
import React, { Component } from "react";
import { Menu, Spin } from "antd";
import { getImageUrl } from "educoder";
import { Link } from "react-router-dom";
import './list.css';
import SelectBranch from '../Branch/Select';
import CloneAddress from '../Branch/CloneAddress';
import RootTable from './RootTable';
import CoderRootFileDetail from './CoderRootFileDetail';
import { truncateCommitId } from '../common/util';
import RenderHtml from '../../components/render-html';
import Nodata from '../Nodata';
import { getBranch } from '../GetData/getData';
import axios from "axios";
/**
* address:http和SSHhttp_url(对应git地址)
* filePath:点击目录时当前目录的路径
* subfileType:保存当前点击目录的文件类型显示目录列表时才显示新建文件如果点击的是文件就不显示新建文件按钮
* readMeContent:根目录下面的readme文件内容
*/
function getPathUrl(array,index){
if(array && array.length>0 && index){
let str = "";
for(let i=0;i<index;i++){
str += `/${array[i]}`;
}
return str.substr(1);
}
}
class CoderRootDirectory extends Component {
constructor(props) {
super(props);
this.state = {
address: "http",
filePath: undefined,
subFileType: undefined,
readMeContent: undefined,
readMeFile: undefined,
isSpin: true,
branchList: undefined,
fileDetail: undefined,
branchLastCommit: undefined,
lastCommitAuthor: undefined,
rootList: undefined,
readOnly: true,
zip_url:undefined,
tar_url:undefined,
chooseType:undefined,
md:false,
treeValue:undefined
}
}
changeAddress = (address) => {
this.setState({
address,
});
};
componentDidMount = () => {
this.Init();
this.getBranchs();
};
// 获取分支列表
getBranchs=()=>{
const { projectsId , owner } = this.props.match.params;
axios.get(`/${owner}/${projectsId}/branches.json`).then(result=>{
this.setState({
branchList:result.data
})
}).catch((error)=>{})
}
componentDidUpdate = (prevState) => {
const { location } = this.props;
const prevlocation = prevState && prevState.location;
if (location !== prevlocation) {
this.setState({
isSpin: true,
});
this.Init();
}
};
Init = () => {
let { pathname } = this.props.history.location;
const { branchName , owner , projectsId } = this.props.match.params;
const { defaultBranch } = this.props;
let branch = branchName || defaultBranch;
if (pathname && (pathname.indexOf(`/projects/${owner}/${projectsId}`) > -1 && pathname.indexOf(`/tree/${branchName}/`) > -1)) {
let url = pathname.split(`/tree/${branchName}/`)[1];
this.setState({treeValue:url})
this.getFileDetail(decodeURI(url),branch);
} else {
this.getProjectRoot(branch);
}
};
// 页面地址返回到主目录
returnMain = (branch) => {
const { projectsId , owner , branchName } = this.props.match.params;
this.setState({
readOnly:true,
treeValue:undefined
})
this.props.history.push(`/projects/${owner}/${projectsId}${branchName?`/tree/${branchName}`:""}`);
this.getProjectRoot(branch);
};
// 获取根目录
getProjectRoot = (branch) => {
const { projectsId , owner } = this.props.match.params;
const url = `/${owner}/${projectsId}/entries.json`;
axios.get(url, { params: { ref: branch } })
.then((result) => {
if (result) {
let last_commit = result.data && result.data.last_commit;
let entries = result.data && result.data.entries;
this.setState({
filePath: undefined,
fileDetail: [],
isSpin: false,
branchLastCommit: last_commit && last_commit.commit,
lastCommitAuthor:
last_commit && (last_commit.author || (last_commit.commit && last_commit.commit.author)),
zip_url: result.data.zip_url,
tar_url: result.data.tar_url
});
if (entries && entries.length > 0) {
this.renderData(entries);
}
this.setState({
rootList: entries,
subFileType: true,
});
}
}).catch((error) => {});
};
ChangeFile = (arr, readOnly) => {
const { projectsId , owner } = this.props.match.params;
//点击直接跳转页面 加载一次路由
this.props.history.push(`/projects/${owner}/${projectsId}/tree/${arr.path}`);
this.setState({
readOnly: readOnly,
chooseType:"file"
});
};
// 获取子目录
getFileDetail = (path, ref) => {
this.setState({
filePath: decodeURI(path),
});
const { projectsId , owner , branchName } = this.props.match.params;
const { chooseType } = this.state;
const url = `/${owner}/${projectsId}/sub_entries.json`;
axios.get(url,{
params:{
filepath:path,
ref:ref || branchName,
type:chooseType
}
}).then((result)=>{
let entries = result.data && result.data.entries;
this.setState({
isSpin:false
})
if(result){
if(entries){
// 返回对象entries.type则是文件类型否则是文件夹
if(entries.type){
this.setState({
fileDetail:[entries],
rootList:[],
subFileType:false
})
}else{
this.setState({
fileDetail:[],
rootList:entries,
branchLastCommit:result.data.last_commit && result.data.last_commit.commit,
lastCommitAuthor:result.data.last_commit && (result.data.last_commit.author || (result.data.last_commit.commit && result.data.last_commit.commit.author))
})
this.renderData(entries);
}
}else{
this.setState({
fileDetail:[],
rootList:[],
isSpin:false,
subFileType:false
})
}
}
})
.catch((error) => {
this.setState({
isSpin:false
})
console.log(error);
});
};
renderData = (data) => {
const rootList = [];
const readMeContent = [];
const readMeFile = [];
data && data.map((item, key) => {
rootList.push({
key,
message: item.commit && item.commit.message,
...item,
});
if (item.is_readme_file) {
readMeContent.push({ ...item });
readMeFile.push({ ...item });
}
});
this.setState({
rootList: rootList,
readMeContent,
readMeFile,
});
};
// 点击跳转到子目录
goToSubRoot=(path,type,filename)=>{
this.setState({
chooseType:type
})
const { projectsId, owner , branchName } = this.props.match.params;
const { defaultBranch } = this.props;
this.props.history.push(`/projects/${owner}/${projectsId}${`/tree/${branchName || defaultBranch}`}${path?`/${path}`:""}`);
if(filename.substring(filename.length - 3) === ".md"){
this.setState({
md:true
})
}else{
this.setState({
md:false
})
}
};
// readme文件内容
renderReadMeContent = (readMeContent, permission) => {
const { fileDetail, readMeFile } = this.state;
if (fileDetail && fileDetail.length !== 0) {
return;
}
if (readMeContent && readMeContent.length > 0) {
return (
<div className="commonBox">
<div className="commonBox-title">
<span className="mr10">
<i className="iconfont icon-wenjian1 font-16 color-grey-9 fl mt3"></i>
</span>
<span className="commonBox-title-read">
{readMeContent[0].name}
</span>
{permission ?
<a
onClick={() => this.ChangeFile(readMeFile[0], false)}
className="ml20 pull-right"
>
<i className="iconfont icon-bianji6 font-16 color-blue"></i>
</a>
:
""
}
</div>
<div className="commonBox-info">
{readMeContent[0].content ?
<RenderHtml className="break_word_comments imageLayerParent" value={readMeContent[0].content} url={this.props.history.location}/>
:
<span>暂无~</span>
}
</div>
</div>
);
}
};
// 选择分支
changeBranch = (value) => {
const { projectsId , owner } = this.props.match.params;
const { treeValue } = this.state;
let url = `/projects/${owner}/${projectsId}${value && `/tree/${value}`}${treeValue ? `/${treeValue}`:""}`;
this.props.history.push(url);
}
// 子目录路径返回链接
returnUlr=(url)=>{
this.setState({
chooseType:"dir",
readOnly:true,
treeValue:url
})
const { projectsId , owner , branchName } = this.props.match.params;
this.props.history.push(`/projects/${owner}/${projectsId}${branchName?`/branch/${branchName}`:""}/tree/${url}`);
}
onEdit=(readOnly)=>{
this.setState({
readOnly
})
}
downloadUrl = (zip_url,tar_url) => {
return(
<Menu>
{zip_url && (
<Menu.Item>
<a href={zip_url}>ZIP</a>
</Menu.Item>
)}
{tar_url && (
<Menu.Item>
<a href={tar_url}>TAR.GZ</a>
</Menu.Item>
)}
</Menu>
)
}
title = (branchLastCommit,lastCommitAuthor) => {
if (branchLastCommit) {
const { projectsId , owner } = this.props.match.params;
return (
<div className="f-wrap-alignCenter">
{lastCommitAuthor ? (
<React.Fragment>
{lastCommitAuthor.login ? (
<Link
to={`/users/${lastCommitAuthor.login}/projects`}
className="show-user-link"
>
<img
src={getImageUrl(`images/${lastCommitAuthor.image_url}`)}
className="radius mr10"
width="32"
height="32"
alt=""
/>
<span className="mr15">{lastCommitAuthor.name}</span>
</Link>
) : (
<span className="mr15">{lastCommitAuthor.name}</span>
)}
</React.Fragment>
) : (
""
)}
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${branchLastCommit.sha}`)}`} className="color-blue flex-1 hide-1">
{branchLastCommit.message}
</Link>
<span>{branchLastCommit.time_from_now}</span>
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${branchLastCommit.sha}`)}`} className="commitKey">
{truncateCommitId(branchLastCommit.sha)}
</Link>
</div>
);
}else{
return false;
}
}
render(){
const { branchLastCommit , lastCommitAuthor , rootList ,filePath , fileDetail , subFileType , readMeContent, isSpin , zip_url , tar_url , branchList} = this.state;
const { isManager , isDeveloper , projectDetail , platform , defaultBranch } = this.props;
const { projectsId , owner , branchName } = this.props.match.params;
let branch = branchName || defaultBranch;
const columns = [
{
key:"name",
dataIndex: 'name',
width:"30%",
render: (text,item) => (
<a onClick={()=>this.goToSubRoot(item.path,item.type,text)} className="ml12 task-hide" style={{ display: "block", maxWidth: "345px" }}>
<i className={ item.type === "file" ? "iconfont icon-wenjia font-15 color-green-file mr5" : "iconfont icon-wenjianjia1 color-green-file font-15 mr5"}></i>{text}
</a>
),
},
{
key:"message",
dataIndex: "message",
width: "60%",
render: (text, item) =>
item.commit && item.commit.message ?
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${item.commit.sha}`)}`} title={item.commit.message} className="task-hide" style={{ display: "block", maxWidth: "670px" }} >
{item.commit.message}
</Link>
: ""
},
{
key:"time_from_now",
dataIndex: "time_from_now",
width: "10%",
className: "edu-txt-right",
render: (text, item) =>
item.commit && item.commit.time_from_now ?
<a title={item.commit.created_at} className="mr12" style={{ cursor: "default", color: "#888" }} >
{item.commit.time_from_now}
</a>
:""
},
];
const urlRoot = filePath === undefined ? "" : `/${filePath}`;
let array = filePath && filePath.split("/");
return (
<Spin spinning={isSpin}>
<div className="main" style={{minHeight:'400px'}}>
<div className="f-wrap-between mb20">
<div className="f-wrap-alignCenter">
{
platform ?
<SelectBranch
repo_id={projectDetail && projectDetail.repo_id}
projectsId={projectsId}
branch={branch}
changeBranch={this.changeBranch}
owner={owner}
history={this.props.history}
branchList={branchList}
></SelectBranch>
:
<span>分支<span className="color-grey-6">master</span></span>
}
{filePath && (
<span className="ml20 font-16">
<a
onClick={() => this.returnMain(branch)}
className="color-blue"
>
{projectDetail && projectDetail.identifier}
</a>
{array &&
array.map((item, key) => {
return (
<React.Fragment>
{
key === array.length-1 ?
<span className="color-grey-6 subFileName" key={key}>{item}</span>
:
<a onClick={()=>this.returnUlr(`${getPathUrl(array,key+1)}`)} className="color-blue subFileName">{item}</a>
}
</React.Fragment>
);
})}
</span>
)}
</div>
<div className="f-wrap-alignCenter">
{subFileType && (projectDetail && parseInt(projectDetail.type)) !== 2 && (isManager || isDeveloper) && platform && (
<div>
<span>
<Link to={`/projects/${owner}/${projectsId}/${branch}/uploadfile${urlRoot}`} >
<span className="color-green mr30">上传文件</span>
</Link>
</span>
<span className="mr30">
<Link
to={`/projects/${owner}/${projectsId}/${branch}/newfile${urlRoot}`}
>
<span className="color-blue">新建文件</span>
</Link>
</span>
</div>
)}
{projectDetail && projectDetail.clone_url && (
<CloneAddress
http_url={projectDetail.clone_url}
downloadUrl={this.downloadUrl(zip_url,tar_url)}
showNotification={this.props.showNotification}
></CloneAddress>
)}
</div>
</div>
{/* 主目录列表 */}
{rootList && rootList.length > 0 && (
<RootTable
columns={columns}
data={rootList}
title={() => this.title(branchLastCommit,lastCommitAuthor)}
></RootTable>
)}
{/* 子目录列表、文件 */}
{fileDetail && fileDetail.length > 0 && (
<CoderRootFileDetail
detail={fileDetail[0]}
{...this.props}
{...this.state}
readOnly={this.state.readOnly}
onEdit={this.onEdit}
currentBranch={branch}
></CoderRootFileDetail>
)}
{
(rootList && rootList.length === 0) && (fileDetail && fileDetail.length === 0) && <Nodata _html="暂未发现文件!"/>
}
{ rootList && this.renderReadMeContent(readMeContent, isManager || isDeveloper)}
</div>
</Spin>
);
}
}
export default CoderRootDirectory;

View File

@ -24,25 +24,13 @@ class CoderRootFileDetail extends Component {
}
componentDidMount = () => {
const { detail , mdFlag } = this.props;
const { detail } = this.props;
this.setState({
value: detail.content,
});
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 = () => {
const { detail } = this.props;
const file_name = detail.path.split("/").pop().split(".").pop();
@ -176,16 +164,15 @@ class CoderRootFileDetail extends Component {
current_user,
isManager,
isDeveloper,
currentBranch,
platform,
md,
type
currentBranch,
platform
} = this.props;
const { language, languages, description } = this.state;
let flag = current_user && current_user.login && (isManager || isDeveloper);
const Option = Select.Option;
return (
<React.Fragment>
<div className="mb20">
<div className="grid-item branchTitle">
<div className="grid-item">
<span className="ml20 color-grey-6 font-16">
@ -198,18 +185,17 @@ class CoderRootFileDetail extends Component {
{readOnly ? (
<span>
{
!detail.direct_download?
detail.direct_download ?
""
:
<span>
<a onClick={() => this.DownLoadFile(detail.download_url)} className="ml20">
<i className="iconfont icon-xiazai1 font-15 color-grey-6"></i>
</a>
{
type !==2 &&
<a onClick={() => this.EditFile(false)} className="ml20">
<i className="iconfont icon-bianji1 font-15 color-grey-6"></i>
</a>
}
</span>:""
</span>
}
</span>
) : (
@ -240,8 +226,7 @@ class CoderRootFileDetail extends Component {
</button>
</React.Fragment>
)}
{
type !==2 &&
<Popconfirm
title="确认删除这个文件?"
className="ml20"
@ -253,8 +238,6 @@ class CoderRootFileDetail extends Component {
<i className="iconfont icon-shanchu font-15 color-grey-6"></i>
</a>
</Popconfirm>
}
</div>
)}
</p>
@ -262,7 +245,11 @@ class CoderRootFileDetail extends Component {
<div>
{detail.image_type ? (
<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>
) : detail.direct_download ? (
<div className="mt20 text-center">
@ -281,14 +268,14 @@ class CoderRootFileDetail extends Component {
{...this.state}
language={language ? language : "javascript"}
filepath={`/${detail.path}`}
content={description}
content={detail.content}
readOnly={readOnly}
editorType="update"
currentBranch={currentBranch}
></Meditor>
)}
</div>
</React.Fragment>
</div>
);
}
}

View File

@ -13,6 +13,10 @@ const UploadFile = Loadable({
loader: () => import('../Newfile/upload_file'),
loading: Loading,
})
const CoderRootDirectory = Loadable({
loader: () => import('./CoderRootDirectory'),
loading: Loading,
})
const CoderRootCommit = Loadable({
loader: () => import('./CoderRootCommit'),
loading: Loading,
@ -67,7 +71,6 @@ class CoderRootIndex extends Component{
this.getTopCount(branchName || defaultBranch);
}
// 获取<Top />组件里要显示的数据
getTopCount=(branch)=>{
const { projectsId , owner } = this.props.match.params;
const url = `/${owner}/${projectsId}/top_counts.json`;
@ -102,6 +105,13 @@ class CoderRootIndex extends Component{
(props) => (<FileNew {...this.props} {...props} {...this.state} getTopCount={this.getTopCount} />)
}
></Route>
{/* diff */}
<Route path="/projects/:owner/:projectsId/commits/branch/:branchName"
render={
(props) => (<CoderRootCommit {...this.props} {...props} {...this.state} commit_class="main" getTopCount={this.getTopCount} />)
}
></Route>
<Route path="/projects/:owner/:projectsId/commits/:sha"
render={
(props) => (<Diff {...this.props} {...props} {...this.state}/>)
@ -112,6 +122,7 @@ class CoderRootIndex extends Component{
() => (<CoderRootCommit {...this.props} {...this.state} commit_class="main" getTopCount={this.getTopCount} />)
}
></Route>
<Route path="/projects/:owner/:projectsId/releases/:versionId/update"
render={
(props) => (<CoderRootVersionUpdate {...this.props} {...this.state} {...props} />)
@ -122,21 +133,33 @@ class CoderRootIndex extends Component{
() => (<CoderRootVersionNew {...this.props} {...this.state} />)
}
></Route>
<Route path="/projects/:owner/:projectsId/releases"
render={
() => (<CoderRootVersion {...this.props} {...this.state} />)
}
></Route>
<Route path="/projects/:owner/:projectsId/tag"
render={
() => (<CoderRootTag {...this.props} {...this.state} />)
}
></Route>
<Route path="/projects/:owner/:projectsId/tree/:branchName"
render={
(props) => (<CoderRootDirectory {...this.props} {...this.state} getTopCount={this.getTopCount} />)
}
></Route>
<Route path="/projects/:owner/:projectsId/branchs"
render={
() => (<CoderRootBranch {...this.props} {...this.state} />)
}
></Route>
<Route path="/projects/:owner/:projectsId"
render={
() => (<CoderRootDirectory {...this.props} {...this.state} getTopCount={this.getTopCount} />)
}
></Route>
</Switch>
</div>
)

View File

@ -2,9 +2,9 @@ import React, { Component } from 'react';
import { Spin, Tooltip } from 'antd';
import { Link, Route, Switch } from 'react-router-dom';
import { Content } from '../Component/layout';
import DetailBanner from './sub/DetailBanner';
import '../css/index.scss'
import './list.css';
import SpecialModal from './SpecialModal';
import Loadable from 'react-loadable';
import Loading from '../../Loading';
@ -97,19 +97,7 @@ const ForkUsers = Loadable({
loader: () => import('../UsersList/fork_users'),
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({
loader: () => import('../Activity/Activity'),
@ -120,10 +108,6 @@ const DevAbout = Loadable({
loader: () => import('../About/Index'),
loading: Loading,
})
const Source = Loadable({
loader: () => import('../Source/Index'),
loading: Loading,
})
const DevIndex = Loadable({
loader: () => import('../DevOps/Index'),
loading: Loading,
@ -149,8 +133,6 @@ function checkPathname(projectsId,owner,pathname){
name="setting"
}else if(url.indexOf(`/devops`)>-1){
name="devops"
}else if(url.indexOf(`/source`)>-1){
name="source"
}
}
return name;
@ -170,6 +152,7 @@ class Detail extends Component {
watched: false,
praised: false,
http_url: undefined,
author: undefined,
branchs: undefined,
branchList: undefined,
project: null,
@ -180,7 +163,9 @@ class Detail extends Component {
defaultBranch:undefined,
// 非本平台项目
platform:false
platform:false,
visible:false,
user_apply_signatures:[]
}
}
@ -197,6 +182,7 @@ class Detail extends Component {
}
getProject = (num) => {
const {user} = this.props;
const { projectsId , owner } = this.props.match.params;
const url = `/${owner}/${projectsId}/simple.json`;
axios.get(url).then((result) => {
@ -206,6 +192,24 @@ class Detail extends Component {
open_devops:result.data.open_devops,
platform:result.data.platform && result.data.platform !== 'educoder'
})
let signa = result.data.user_apply_signatures && result.data.user_apply_signatures[0];
if(result.data.is_secret && !result.data.is_member && (!signa || (signa && signa.status !== "passed")) && user.login !== owner){
this.setState({
visible:true,
is_secret:result.data.is_secret,
user_apply_signatures:signa
})
}
// 工作流:两种状态进入的链接不同
const pathname = this.props.history.location.pathname;
if(pathname===`/projects/${owner}/${projectsId}/devops`){
if(result.data.open_devops && pathname === `/projects/${owner}/${projectsId}/devops`){
this.props.history.push(`/projects/${owner}/${projectsId}/devops/list`);
}else if(result.data.open_devops===false && pathname !== `/projects/${owner}/${projectsId}/devops`){
this.props.history.push(`/projects/${owner}/${projectsId}/devops`);
}
}
if (result.data.type !== 0 && result.data.mirror_status === 1) {
console.log("--------start channel --------");
@ -264,8 +268,7 @@ class Detail extends Component {
getDetail = () => {
const { projectsId , owner } = this.props.match.params;
this.getBanner();
const url = `/${owner}/${projectsId}/detail.json`;
const url = `/${owner}/${projectsId}.json`;
axios.get(url).then((result) => {
if (result && result.data) {
this.setState({
@ -275,6 +278,7 @@ class Detail extends Component {
isReporter: result.data.permission && result.data.permission === "Reporter",
isDeveloper: result.data.permission && result.data.permission === "Developer",
http_url: result.data.clone_url,
author: result.data.author,
praised: result.data.praised,
watched: result.data.watched,
watchers_count: result.data.watchers_count,
@ -286,19 +290,6 @@ class Detail extends Component {
}).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) => {
const { platform } = this.state;
@ -389,13 +380,24 @@ class Detail extends Component {
})
}
hideModal=()=>{
this.setState({
visible:false
})
}
sureModal=()=>{
this.hideModal();
this.props.history.push('/projects');
}
render() {
const { projectDetail, watchers_count, praises_count,
forked_count, firstSync , secondSync ,
isManager, watched, praised,
project , open_devops , platform , defaultBranch , bannerList } = this.state;
project , open_devops , platform , defaultBranch , project_id , user_apply_signatures , visible } = this.state;
const url = this.props.history.location.pathname;
const urlArr = url.split("/");
const urlFlag = (urlArr.length === 3);
@ -422,18 +424,19 @@ class Detail extends Component {
}
return (
<div>
<SpecialModal {...this.props} visible={visible} hideModal={this.sureModal} user_apply_signatures={user_apply_signatures} project_id={project_id} sureModal={this.sureModal}></SpecialModal>
<div className="detailHeader-wrapper">
<div className="normal">
<div className="f-wrap-between pb15" style={{ position: "relative" }}>
<p className="font-22 df flex-1 lineH2 mt15" style={{ alignItems: "center" }}>
<p className="color-white font-22 df flex-1 lineH2 mt15" style={{ alignItems: "center" }}>
{project && project.author &&
<Link to={`${project.author.type ==="Organization" ? "/organize":'/users'}/${project.author.login}`} className="show-user-link">
<Link to={`/users/${project.author.login}`} className="show-user-link color-white">
{project.author.name}
</Link>
}
<span className="ml5 mr5">/</span>
<span className="hide-1 flex-1 df">
<Link to={`/projects/${owner}/${projectsId}`} className="font-22">{project && project.name}</Link>
<Link to={`/projects/${owner}/${projectsId}`} className="color-white font-22">{project && project.name}</Link>
{
projectDetail && projectDetail.forked_from_project_id && projectDetail.fork_info ?
<Tooltip placement={'right'} title={text}>
@ -470,15 +473,14 @@ class Detail extends Component {
<span>{watched ? '取消关注' : '关注'}</span>
</a>
{
watchers_count > 0 ?
platform ?
<Link className="detail_tag_btn_count" style={{color:`${watched?"#2878FF":"#666"}`}} to={platform?{ pathname: `/projects/${owner}/${projectsId}/watchers`, state }:""}>
{watchers_count}
</Link>
:
<span className="detail_tag_btn_count">{watchers_count}</span>
:""
}
</span>
<span className="detail_tag_btn">
<a className="detail_tag_btn_name" style={{cursor:platform?"pointer":"default"}} onClick={() => this.pariseFunc(praised)}>
@ -486,30 +488,24 @@ class Detail extends Component {
<span>{praised ? '取消点赞' : '点赞'}</span>
</a>
{
praises_count > 0 ?
platform ?
<Link className="detail_tag_btn_count" style={{color:`${praised?"#2878FF":"#666"}`}} to={{ pathname: `/projects/${owner}/${projectsId}/stargazers`, state }}>
{praises_count}
</Link>:
<span className="detail_tag_btn_count">{praises_count}</span>
:""
}
</span>
<span className="detail_tag_btn">
<Tooltip title="复刻是fork的中文名即复制代码仓库" placement="bottom">
<a className="detail_tag_btn_name" style={{cursor:platform?"pointer":"default"}} onClick={this.forkFunc}>
<i className="iconfont icon-fork color-grey-9 mr3"></i>
<i className="iconfont icon-fork color-grey-9 mr3"></i> (Fork)
</a>
</Tooltip>
{
forked_count > 0 ?
platform ?
<Link className="detail_tag_btn_count" to={{ pathname: `/projects/${owner}/${projectsId}/fork_users`, state }}>
{forked_count}
</Link>
:
<span className="detail_tag_btn_count">{forked_count}</span>
:""
<span className="detail_tag_btn_count">{praises_count}</span>
}
</span>
</span>
@ -517,36 +513,83 @@ class Detail extends Component {
</div>
{
firstSync ? "" :
<DetailBanner
history={this.props.history}
list={bannerList}
owner={owner}
projectsId={projectsId}
pathname={pathname}
state={state}
projectDetail={projectDetail}
open_devops={open_devops}
platform={platform}
urlFlag={urlFlag}
isManager={isManager}
/>
<div className="f-wrap-between pb20">
<ul className="headerMenu-wrapper">
<li className={pathname==="about" ? "active" : ""}>
<Link to={{ pathname: `/projects/${owner}/${projectsId}/about`, state }}>
<i className={ pathname === "about" ? "iconfont icon-zhuye1 color-blue mr5 font-14":"iconfont icon-zhuye1 color-white font-14 mr5"}></i>
<span>主页</span>
</Link>
</li>
<li className={(pathname==="" || urlFlag) ? "active" : ""}>
<Link to={{ pathname: `/projects/${owner}/${projectsId}`, state }}>
<i className={(pathname==="" || urlFlag) ? "iconfont icon-daimaku color-blue mr5 font-14":"iconfont icon-daimaku color-white font-14 mr5"}></i>
<span>代码库</span>
</Link>
</li>
<li className={pathname==="issues" ? "active" : ""}>
<Link to={{ pathname: `/projects/${owner}/${projectsId}/issues`, state }}>
<i className={pathname==="issues" ? "iconfont icon-renwu color-blue mr5 font-14":"iconfont icon-renwu color-white font-14 mr5"}></i>
<span>易修 (Issue)</span>
{projectDetail && projectDetail.issues_count ? <span className="num">{projectDetail.issues_count}</span> : ""}
</Link>
</li>
{
projectDetail && parseInt(projectDetail.type) !== 2 && platform &&
<li className={pathname==="pulls" ? "active" : ""}>
<Link to={{ pathname: `/projects/${owner}/${projectsId}/pulls`, state }}>
<i className={pathname==="pulls" ? "iconfont icon-hebingqingqiu1 color-blue mr5 font-14":"iconfont icon-hebingqingqiu1 color-white font-14 mr5"}></i>
<span>合并请求</span>
{projectDetail && projectDetail.pull_requests_count ? <span className="num">{projectDetail.pull_requests_count}</span> : ""}
</Link>
</li>
}
{/* {
platform &&
<li className={pathname==="devops" ? "active" : ""}>
<Link to={{ pathname: `/projects/${owner}/${projectsId}/devops${open_devops ? `/list`:""}`, state }}>
<i className="iconfont icon-gongzuoliu font-13 mr8"></i>(beta)
{projectDetail && projectDetail.ops_count ? <span>{projectDetail.ops_count}</span> : ""}
</Link>
</li>
} */}
<li className={pathname==="milestones" ? "active" : ""}>
<Link to={{ pathname: `/projects/${owner}/${projectsId}/milestones`, state }}>
<i className={pathname==="milestones" ? "iconfont icon-lichengbei color-blue mr5 font-14":"iconfont icon-lichengbei color-white font-14 mr5"}></i>
<span>里程碑</span>
{projectDetail && projectDetail.versions_count ? <span className="num">{projectDetail.versions_count}</span> :""}
</Link>
</li>
<li className={pathname==="activity" ? "active" : ""}>
<Link to={{ pathname: `/projects/${owner}/${projectsId}/activity`, state }}>
<i className={pathname==="activity" ? "iconfont icon-tongzhi color-blue mr5 font-14":"iconfont icon-tongzhi color-white font-14 mr5"}></i>
<span>动态</span>
</Link>
</li>
{
isManager && platform &&
<li className={url.indexOf("/setting") > 0 ? "active" : ""}>
<Link to={`/projects/${owner}/${projectsId}/setting`}>
<i className={url.indexOf("/setting") > 0 ? "iconfont icon-cangku color-blue mr5 font-14":"iconfont icon-cangku color-white font-14 mr5"}></i>
<span>仓库设置</span>
</Link>
</li>
}
</ul>
</div>
}
</div>
</div>
{
firstSync ?
<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>
:
<Spin spinning={secondSync} className="spinstyle" tip="正在同步镜像" size="large">
<Switch {...this.props}>
{/* 资源 */}
<Route path="/projects/:owner/:projectsId/source"
render={
() => (<Source {...this.props} {...this.state} {...common} />)
}
></Route>
{/* 主页 */}
<Route path="/projects/:owner/:projectsId/about"
render={
@ -637,7 +680,6 @@ class Detail extends Component {
(props) => (<OrderIndex {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 新建合并请求 */}
<Route path="/projects/:owner/:projectsId/pulls/new"
render={
(props) => (<CreateMerge {...this.props} {...props} {...this.state} {...common} is_fork={true} />)
@ -664,6 +706,11 @@ class Detail extends Component {
(props) => (<MergeIndexDetail {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/projects/:owner/:projectsId/coders/filesurl"
render={
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/projects/:owner/:projectsId/watchers"
render={
(props) => (<WatchUsers {...this.props} {...props} {...this.state} {...common} />)
@ -679,32 +726,19 @@ class Detail extends Component {
(props) => (<ForkUsers {...this.props} {...props} {...this.state} {...common} />)
}
></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}/>)
(props) => (<CoderRootIndex {...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"
render={
(props) => (<CoderDepot {...this.props} {...props} {...this.state} {...common}/>)
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
</Switch>

View File

@ -59,13 +59,13 @@ export default ({ match , history }) => {
{commit && commit.message &&
<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 className="f-wrap-between" style={{ alignItems: "center" }}>
<ul className="df">
<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}
/>
{committer && committer.time_from_now && <li className="ml20 mt2">{committer.time_from_now}</li>}

View File

@ -1,7 +1,6 @@
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { Menu, Input , Spin, Pagination , Popover , Select } from 'antd';
import { getImageUrl } from 'educoder';
import { Menu, Input , Spin, Pagination , Popover } from 'antd';
import '../css/index.scss'
import './list.css';
import './Index.scss';
@ -9,7 +8,7 @@ import ListItem from './IndexItem'
import axios from 'axios';
import img_new from '../Images/new.png';
import img_array from '../Images/array.png';
import banner from '../Images/banner_list.jpg';
import banner from '../Images/banner_list.png';
const Search = Input.Search;
class Index extends Component {
@ -23,7 +22,6 @@ class Index extends Component {
sort: undefined,
total: 0,
isSpin: true,
project_type: undefined,
category_id: undefined,
typeList: undefined,
@ -37,8 +35,8 @@ class Index extends Component {
}
componentDidMount = () => {
const { page, limit, search, sort, project_type, category_id , languageId } = this.state;
this.getListData(page, limit, search, sort, project_type, category_id , languageId);
const { page,search, sort,category_id , languageId } = this.state;
this.getListData(page,search, sort,category_id , languageId);
this.getType();
@ -73,19 +71,18 @@ class Index extends Component {
}
// 获取列表
getListData = (page, limit, search, sort, project_type, category_id,languageId) => {
getListData = (page,search, sort,category_id,language_id) => {
const { current_user } = this.props;
const url = `/projects.json`;
axios.get(url, {
params: {
user_id: current_user && current_user.user_id,
page,
limit,
limit:15,
search,
sort_by: sort,
project_type,
category_id,
language_id:languageId
language_id
}
}).then((result) => {
if (result) {
@ -112,7 +109,7 @@ class Index extends Component {
this.setState({
typeList: list.map((item, key) => {
return (
<li key={key} className={active_type && active_type === item.project_type ? 'active' : ''} onClick={() => this.changeType(`${item.project_type}`, list)}>
<li key={key} className={active_type && parseInt(active_type) === item.id ? 'active' : ''} onClick={() => this.changeType(`${item.id}`, list)}>
<p>
<span className="font-16">{item.name}</span>
<span className="color-blue">{item.projects_count}</span>
@ -124,15 +121,15 @@ class Index extends Component {
}
// 切换类型
changeType = (type, list) => {
changeType = (id, list) => {
this.setState({
isSpin: true,
project_type: type,
languageId: id,
search: undefined
})
this.setTypeList(list, type)
const { page, limit, sort, category_id , languageId } = this.state;
this.getListData(page, limit, undefined, sort, type, category_id , languageId);
this.setTypeList(list, id)
const { page,sort, category_id} = this.state;
this.getListData(page,undefined, sort,category_id , id);
}
// 获取类型
@ -167,8 +164,8 @@ class Index extends Component {
page: 1
});
this.setCategoryList(list, id)
const { limit, sort, project_type , languageId } = this.state;
this.getListData(1, limit, undefined, sort, project_type, id , languageId);
const { sort,languageId } = this.state;
this.getListData(1,undefined, sort,id , languageId);
}
// 排序
@ -179,8 +176,8 @@ class Index extends Component {
search: undefined,
isSpin: true
})
const { limit, project_type, category_id , languageId } = this.state;
this.getListData(1, limit, undefined, e.key, project_type, category_id , languageId);
const {category_id , languageId } = this.state;
this.getListData(1,undefined, e.key,category_id , languageId);
}
// 搜索
@ -192,8 +189,8 @@ class Index extends Component {
project_type: undefined,
sort: "updated_on"
})
const { limit, sort, category_id , languageId } = this.state;
this.getListData(1, limit, value, sort, undefined, category_id , languageId);
const {sort, category_id , languageId } = this.state;
this.getListData(1,value, sort,category_id , languageId);
}
changeSearchValue = (e) => {
this.setState({
@ -205,23 +202,14 @@ class Index extends Component {
this.setState({
page
})
const { limit, search, sort, project_type, category_id , languageId } = this.state;
this.getListData(page, limit, search, sort, project_type, category_id , languageId);
const {search, sort,category_id , languageId } = this.state;
this.getListData(page,search, sort, category_id , languageId);
}
getoDetail=(login,identifier)=>{
this.props.history.push(`/projects/${login}/${identifier}`);
}
// 选择语言类别
changeLanguage=(e)=>{
this.setState({
isSpin:true,
languageId:e === 0 ?undefined:e
})
const { page, limit, sort , project_type , category_id } = this.state;
this.getListData(page, limit, undefined, sort, project_type, category_id ,e === 0 ?undefined:e);
}
menu =()=> {
return(
@ -255,15 +243,14 @@ class Index extends Component {
render() {
const { current_user } = this.props;
const { projectsList , recommendList , languageList , languageId ,
isSpin, total, search, limit, page, typeList, categoryList } = this.state;
const { projectsList , isSpin , total , search , limit , page , typeList , categoryList } = this.state;
return (
<div>
<p className="t_project_banner">
<img src={banner} width="100%" alt=""/>
</p>
{
{/* {
recommendList && recommendList.length>0 &&
<div className="recommandProjects">
{
@ -271,7 +258,7 @@ class Index extends Component {
return(
<div onClick={()=>this.getoDetail(item.author && item.author.login,item.identifier)}>
<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="name">{item.author && item.author.name}</p>
</div>
@ -285,44 +272,23 @@ class Index extends Component {
}
</div>
}
*/}
<div className="ProjectListIndex">
<div className="list-left">
<ul className="list-l-Menu">
<li className="MenuTitle"><i className="iconfont icon-xiangmuleixing color-grey-9 font-15 mr5"></i></li>
{typeList}
<li className="MenuTitle"><i className="iconfont icon-bianchengyuyan color-grey-9 font-15 mr5"></i>
语言</li>
<div className="list-affix">{typeList}</div>
</ul>
<ul className="list-l-Menu">
<li className="MenuTitle"><i className="iconfont icon-xiangmuleibie color-grey-9 font-15 mr5"></i></li>
{categoryList}
<div className="list-affix">{categoryList}</div>
</ul>
</div>
<div className="list-right boxShandow radius-2" style={{padding:0}}>
<Spin spinning={isSpin}>
<div className="list-r-operation">
<div>
<Select
showSearch
placeholder="请选择语言"
style={{width:"150px",marginRight:"20px"}}
size={"large"}
onChange={this.changeLanguage}
value={languageId}
allowClear={true}
optionFilterProp="children"
filterOption={(input,option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
>
<Select.Option key={0} value={0}>请选择语言</Select.Option>
{
languageList && languageList.length>0 && languageList.map((item,key)=>{
return(
<Select.Option key={item.id} value={item.id}>
{item.name}
</Select.Option>
)
})
}
</Select>
<Search
placeholder="输入项目名称关键字进行搜索"
enterButton="搜索"
@ -350,7 +316,7 @@ class Index extends Component {
</Popover>
</div>
</div>
<ListItem {...this.props} {...this.state} projects={projectsList}></ListItem>
<ListItem {...this.props} {...this.state} projects={projectsList} getListData={this.getListData}></ListItem>
{this.pagination(total,limit,page)}
</Spin>
</div>

View File

@ -10,7 +10,6 @@
width: 220px;
margin-right: 25px;
cursor: pointer;
border: 1px solid #eee;
&:last-child{
margin-right: 0px;
}
@ -73,243 +72,15 @@
}
}
}
// 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{
.singleBtn{
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{
.ant-upload-list-item{
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;
width: 100%;
left: 0px;
.ant-upload-list-item-name{
text-align: left;
}
}
}
.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;
}
}

View File

@ -1,43 +1,86 @@
import React, { Component } from 'react';
import { Tooltip } from 'antd';
import { getImageUrl } from 'educoder';
import { AlignCenter } from '../Component/layout';
import { Link } from 'react-router-dom';
import '../css/index.scss';
import Nodata from '../Nodata';
import './list.css';
import img_parise from '../Images/parise.png';
import SpecialModal from './SpecialModal';
class IndexItem extends Component {
constructor(props){
super(props);
this.state={
visible:false,
user_apply_signatures:[],
project_id:undefined
}
}
TurnToDetail = (login, url) => {
this.props.history.push({
pathname: url,
state: login
})
}
/**
* link:跳转到详情的地址
* user_apply_signatures:是否已经发送访问特殊开源项目的文件
* project_id项目id
* is_secret:是否是特殊开源许可证项目
* id创建者login
* is_member:是否是项目成员(如果是项目成员可以直接进入项目)
* */
projectHref=(link , user_apply_signatures,project_id,is_secret , id,is_member)=>{
const { user , showLoginDialog } = this.props;
if(is_secret && (!user || (user && !user.login))){
showLoginDialog();
return;
}
let signa = user_apply_signatures && user_apply_signatures[0];
if((is_secret && !is_member && (!signa || (signa && signa.status !== "passed"))) && user.login !== id ){
this.setState({
visible:true,
user_apply_signatures:user_apply_signatures.length>0 ? user_apply_signatures[0] : undefined,
project_id
})
}else{
this.props.history.push(link);
}
}
hideModal=()=>{
this.setState({
visible:false
})
}
sureModal=()=>{
this.hideModal();
const { getListData } = this.props;
getListData && getListData(1);
}
render() {
const { projects } = this.props;
return (
<div className="project-list minH-670">
{ projects && projects.length > 0 ? projects.map((item, key) => {
const { visible , user_apply_signatures , project_id } = this.state;
const renderList = (
projects && projects.length > 0 ? projects.map((item, key) => {
return (
<div className="p-r-Item" key={key}>
{
item.platform === "educoder" ?
<a href="javascript:void(0)" style={{cursor:"default"}} className="show-user-link">
<a style={{cursor:"default"}} className="show-user-link">
<img className="p-r-photo" alt="" src={item.author && item.author.image_url} ></img>
</a>
:
<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>
<Link to={`/users/${item.author.login}`} className="show-user-link">
<img className="p-r-photo" alt="" src={getImageUrl(`${item.author && item.author.image_url}`)} ></img>
</Link>
}
<div className="p-r-Infos">
<div className="p-r-name">
<AlignCenter>
<Link to={`/projects/${item.author.login}/${item.identifier}`} className="color-grey-3 font-18 task-hide " style={{maxWidth: 490 }}>
<a onClick={()=>this.projectHref(`/projects/${item.author.login}/${item.identifier}`,item.user_apply_signatures, item.id,item.is_secret,item.author.login,item.is_member)} className="hide-1 color-grey-3 font-18 task-hide fwt-500 " style={{ whiteSpace: "wrap", display: 'flex', width: 400 }}>
{item.author.name}/{item.name}
</Link>
{
item.forked_from_project_id ?
<span className="ml5">
@ -55,13 +98,13 @@ class IndexItem extends Component {
<i className="iconfont icon-jingxiang font-18 color-green" />
</span>:""
}
</AlignCenter>
</a>
<span className="p-r-tags">
<span className="pariseTag"><img src={img_parise} alt="" className="pariseImg" /> {item.praises_count}</span>
<span><i className="iconfont icon-fork mr3 font-16" style={{ color: "#1B8FFF" }} />fork {item.forked_count}</span>
</span>
</div>
<p className="break_word task-hide-2 mt10" style={{ maxHeight: "44px",lineHeight:"22px" }}>{item.description}</p>
<p className="break_word task-hide-2 mt8 color-grey-3 " style={{ maxHeight: "44px",lineHeight:"22px" }}>{item.description}</p>
<div className="p-r-about">
<span className="p-r-detail">
@ -74,7 +117,12 @@ class IndexItem extends Component {
</div>
</div>
)
}) : <Nodata _html="暂无数据~"></Nodata>}
}) : <Nodata _html="暂无数据~"></Nodata>
)
return (
<div className="project-list minH-670">
<SpecialModal {...this.props} visible={visible} hideModal={this.hideModal} user_apply_signatures={user_apply_signatures} project_id={project_id} sureModal={this.sureModal}></SpecialModal>
{renderList}
</div>
)
}

View File

@ -0,0 +1,49 @@
import React , { useEffect , useState } from 'react';
import { Modal } from 'antd';
import UploadSingle from '../Upload/single';
import './Index.scss';
import axios from 'axios';
import { getUrl } from 'educoder';
function SpecialModal({ visible , hideModal , sureModal , showNotification , user_apply_signatures , project_id }){
const [ id ,setId ] = useState(undefined);
function loadFunc(id){
setId(id);
}
function sure(){
if(!user_apply_signatures || (user_apply_signatures && user_apply_signatures.status !== "waiting")){
if(!id || (id && id.length === 0)){
showNotification("请先提交文件进行审核!");
return;
}
const url = `/apply_signatures.json`;
axios.post(url,{
attachment_id:id,
project_id:project_id
}).then(result=>{
if(result && result.data.id){
showNotification("已提交文件,正在等待审核!");
sureModal();
}
})
}else{
sureModal();
}
}
return(
<Modal title="提示" visible={visible} closable={false} onCancel={hideModal} onOk={sure}>
{
!user_apply_signatures || (user_apply_signatures && user_apply_signatures.status !== "waiting") ?
<div style={{width:"420px",textAlign:'center',margin:"0 auto",paddingBottom:"30px",position:"relative"}}>
<div>该项目为私有项目请先<a href={getUrl(`/api/apply_signatures/template_file`)} className="color-blue">下载</a>开源协议,阅读并填写<br/>相关信息后将协议<UploadSingle size={"5"} load={loadFunc} showNotification={showNotification} className={'singleBtn'}><span className="color-blue" style={{cursor:"pointer"}}>上传</span></UploadSingle>,平台审核通过后即可进入当前项目</div>
</div>
:
<p style={{textAlign:'center'}}>您上传的文件正在审核中,通过后才能访问当前项目</p>
}
</Modal>
)
}
export default SpecialModal;

View File

@ -18,17 +18,10 @@
box-sizing: border-box;
margin-bottom: 20px;
}
.list-left > div{
border:1px solid #eee;
}
.list-left > div.bgcF{
border:none;
}
.list-right{
width:74%;
background: #fff;
padding:10px;
border:1px solid #eee;
}
@ -215,9 +208,7 @@
}
/* -----------详情------------ */
.detailHeader-wrapper{
background-color:#FAFBFC;
/* background: url(../Images/forgeBanner.jpg) no-repeat center; */
/* background-size:cover; */
background:linear-gradient(82deg,rgba(82,91,215,1) 0%,rgba(34,24,171,1) 100%);
}
.headerMenu-wrapper{
font-size: 16px;
@ -229,36 +220,42 @@
text-align: center;
height: 40px;
line-height: 28px;
margin-right: 40px;
border:1px solid transparent;
}
.headerMenu-wrapper{
font-size: 16px;
display: flex;
flex-direction: row;
}
.headerMenu-wrapper li{
padding:0px 18px;
position: relative;
text-align: center;
height: 30px;
line-height: 30px;
}
.headerMenu-wrapper li a{
color: #666;
color: #fff;
display: flex;
align-items: center;
}
.headerMenu-wrapper li a > img{
margin-right: 8px;
}
.headerMenu-wrapper li a > span.num{
height: 28px;
line-height: 29px;
margin-left: 8px;
font-size: 12px;
color: #2878FF;
float: right;
.headerMenu-wrapper li a > span{
display: block;
margin-left: 5px;
font-size: 16px;
}
.headerMenu-wrapper li.active::after{
position: absolute;
bottom:0px;
height:2px;
background-color: #5091FF;
content:'';
left: 0px;
width:100%;
.headerMenu-wrapper li.active{
border-radius: 15px;
border:1px solid #71A6FF;
}
.detail_tag_btn{
height:26px;
line-height: 26px;
border-radius:5px;
border:1px solid #f1f1f1;
border:1px solid #71A6FF;
display: flex;
align-items: center;
margin-left: 30px
@ -266,21 +263,29 @@
.ant-tooltip {
max-width: fit-content!important;
}
.detail_tag_btn_name{
padding:0px 10px;
color: #666!important;
display: flex;
align-items: center;
color: #fff;
}
.detail_tag_btn_name img{
margin-right: 10px;
}
.detail_tag_btn_count{
padding:0px 10px;
background: #fff;
color: #fff !important;
background: rgba(255,255,255,0.2);
border-radius: 0px 4px 4px 0px;
font-size: 12px;
height:100%;
}
.detail_tag_btn_count:hover{
/* color: #1C91FF !important; */
background: rgba(255,255,255,0.5);
}
.files-md{
border:1px solid #eee;
padding:20px;
}
/* 详情-代码 */
@ -430,11 +435,18 @@
max-width: 100%;
}
/* 分支 */
.branchTable{
border:1px solid #f7f7f7;
border-radius: 4px;
}
.branchTitle{
padding:8px 10px;
padding:12px 10px;
color: #333;
font-size: 16px;
border-bottom: 1px solid #d9d9d9;
background:rgba(241,248,255,1);
}
.branchUl{
padding:0px 30px;
}
.branchUl li{
display: flex;
@ -547,19 +559,17 @@
}
.commonBox{
border:1px solid #ddd;
margin-top: 30px;
border-radius: 4px;
margin-top: 25px;
}
.commonBox .commonBox-title{
padding:0px 20px;
padding:0px 15px;
box-sizing: border-box;
font-size: 16px;
background: #FAFBFC;/* F1F8FF */
background: #F1F8FF;
font-weight: bold;
height: 45px;
line-height: 45px;
border-bottom: 1px solid #d9d9d9;
border-radius: 4px 4px 0px 0px;
height: 50px;
line-height: 50px;
border-bottom: 1px solid #ddd;
}
.synchronism{
display: block;
@ -576,7 +586,7 @@
.commonBox .commonBox-info{
padding:20px 15px;
}
.commonBox-title-read{vertical-align: middle;color: #666;}
.commonBox-title-read{vertical-align: middle;}
@media screen and (max-width: 370px){
.p-r-tags,.p-r-btn{
@ -666,7 +676,7 @@ a.color-grey-ccc:hover{
.commitList{
padding:0px 30px;
min-height: 400px;
min-height: 450px;
}
.commitList > div{
border-bottom: 1px solid #EEEEEE;

View File

@ -1,80 +0,0 @@
import React, { useEffect, useState } from 'react';
import { WhiteBack , AlignCenter } from '../../Component/layout';
import "./sub.scss";
import axios from 'axios';
import { Pagination , Spin } from 'antd';
import NoData from '../../Nodata';
import { getImageUrl } from 'educoder';
import { Link } from 'react-router-dom';
function Contribute(props){
const [ list , setList ] = useState(undefined);
const [ page , setPage ] = useState(1);
const [ total , setTotal ] = useState(0);
const [ isSpin , setIsSpin ] = useState(true);
const owner = props.match.params.owner;
const projectsId = props.match.params.projectsId;
const LIMIT = 20;
useEffect(()=>{
if(owner && projectsId){
getData();
}
},[owner,projectsId,page]);
function getData(){
setIsSpin(true);
const url = `/${owner}/${projectsId}/contributors.json`;
axios.get(url,{
params:{
limit:LIMIT,page,
}
}).then(result=>{
if(result){
setList(result.data.contributors);
setTotal(result.data.total_count);
setIsSpin(false);
}
}).catch(error=>{})
}
return(
<WhiteBack>
<Spin spinning={isSpin}>
<div className="boxPanel">
<p className="font-18 mb20">贡献者列表</p>
{
list && list.length > 0 ?
<div className="contrbuteList">
{
list.map((item,key)=>{
return(
<AlignCenter>
<img alt="" style={{borderRadius:"50%",marginRight:"10px"}} src={getImageUrl(`/${item.image_url}`)} width="50px" height="50px"/>
<div>
<Link to={`/users/${item.login}`} className="font-16">{item.name}</Link>
<p className="font-12 color-grey-9">提交{item.contributions}</p>
</div>
</AlignCenter>
)
})
}
</div>
:""
}
{
list && list.length === 0 ? <NoData _html="暂无贡献者" />:""
}
{
total > LIMIT ?
<div className="mt20 edu-txt-center">
<Pagination simple pageSize={LIMIT} onChange={(p)=>{setPage(p)}} current={page} total={total}/>
</div>
:""
}
</div>
</Spin>
</WhiteBack>
)
}
export default Contribute;

View File

@ -1,127 +0,0 @@
import React, { useEffect, useState } from 'react';
import { Skeleton , Tooltip} from 'antd';
import { Link } from 'react-router-dom';
function DetailBanner({ history,list , owner , projectsId , isManager , url , pathname , state , urlFlag , projectDetail , platform ,open_devops }){
const [ menuName , setMenuName ] = useState(undefined);
useEffect(()=>{
if(list){
// banner
if(pathname && pathname==="source"){
let a = list.filter(item=>item.menu_name === "resources");
if(a && a.length === 0){
history.push(`/projects/${owner}/${projectsId}`);
}
}
setMenuName(list);
}
},[list]);
return(
<div className="f-wrap-between mt15">
{
menuName && projectDetail ?
<ul className="headerMenu-wrapper">
{
menuName.map((item,key)=>{
return(
<React.Fragment>
{
item.menu_name === "home" &&
<li className={pathname==="about" ? "active" : ""}>
<Link to={{ pathname: `/projects/${owner}/${projectsId}/about`, state }}>
<i className={(pathname==="" || urlFlag) ? "iconfont icon-zhuye1 color-grey-3 mr5 font-14":"iconfont icon-zhuye1 color-grey-6 font-14 mr5"}></i>
<span>主页</span>
</Link>
</li>
}
{
item.menu_name === "code" &&
<li className={(pathname==="" || urlFlag) ? "active" : ""}>
<Link to={{ pathname: `/projects/${owner}/${projectsId}`, state }}>
<i className={(pathname==="" || urlFlag) ? "iconfont icon-daimaku color-grey-3 mr5 font-14":"iconfont icon-daimaku color-grey-6 font-14 mr5"}></i>
<span>代码库</span>
</Link>
</li>
}
{
item.menu_name === "issues" &&
<li className={pathname==="issues" ? "active" : ""}>
<Tooltip title="易修是Issue的中文名即问题列表" placement="bottom">
<Link to={{ pathname: `/projects/${owner}/${projectsId}/issues`, state }}>
<i className={pathname==="issues" ? "iconfont icon-renwu color-grey-3 mr5 font-14":"iconfont icon-renwu color-grey-6 font-14 mr5"}></i>
<span>易修</span>
{projectDetail && projectDetail.issues_count ? <span className="num">{projectDetail.issues_count}</span> : ""}
</Link>
</Tooltip>
</li>
}
{
item.menu_name === "pulls" && projectDetail && parseInt(projectDetail.type) !== 2 && platform ?
<li className={pathname==="pulls" ? "active" : ""}>
<Link to={{ pathname: `/projects/${owner}/${projectsId}/pulls`, state }}>
<i className={pathname==="pulls" ? "iconfont icon-hebingqingqiu1 color-grey-3 mr5 font-14":"iconfont icon-hebingqingqiu1 color-grey-6 font-14 mr5"}></i>
<span>合并请求</span>
{projectDetail && projectDetail.pull_requests_count ? <span className="num">{projectDetail.pull_requests_count}</span> : ""}
</Link>
</li>:""
}
{
item.menu_name === "devops" && platform ?
<li className={pathname==="devops" ? "active" : ""}>
<Link to={{ pathname: `/projects/${owner}/${projectsId}/devops${open_devops ? `/dispose`:""}`, state }}>
<i className="iconfont icon-gongzuoliu font-13 mr8"></i>工作流(beta版)
{projectDetail && projectDetail.ops_count ? <span>{projectDetail.ops_count}</span> : ""}
</Link>
</li>
:""
}
{/* {
item.menu_name === "resources" &&
<li className={pathname==="source" ? "active" : ""}>
<Link to={{ pathname: `/projects/${owner}/${projectsId}/source`, state }}>
<i className={pathname==="source" ? "iconfont icon-ziyuanpaihanghetuijian color-grey-3 mr5 font-14":"iconfont icon-ziyuanpaihanghetuijian color-grey-6 font-14 mr5"}></i>
<span>资源库</span>
{projectDetail && projectDetail.source_count ? <span className="num">{projectDetail.source_count}</span> :""}
</Link>
</li>
} */}
{
item.menu_name === "versions" &&
<li className={pathname==="milestones" ? "active" : ""}>
<Link to={{ pathname: `/projects/${owner}/${projectsId}/milestones`, state }}>
<i className={pathname==="milestones" ? "iconfont icon-lichengbei color-grey-3 mr5 font-14":"iconfont icon-lichengbei color-grey-6 font-14 mr5"}></i>
<span>里程碑</span>
{projectDetail && projectDetail.versions_count ? <span className="num">{projectDetail.versions_count}</span> :""}
</Link>
</li>
}
{
item.menu_name === "activity" &&
<li className={pathname==="activity" ? "active" : ""}>
<Link to={{ pathname: `/projects/${owner}/${projectsId}/activity`, state }}>
<i className={pathname==="activity" ? "iconfont icon-tongzhi color-grey-3 mr5 font-14":"iconfont icon-tongzhi color-grey-6 font-14 mr5"}></i>
<span>动态</span>
</Link>
</li>
}
{
item.menu_name === "setting" &&
<li className={pathname === "setting" ? "active" : ""}>
<Link to={`/projects/${owner}/${projectsId}/setting`}>
<i className={url && url.indexOf("/setting") > 0 ? "iconfont icon-cangku color-grey-3 mr5 font-14":"iconfont icon-cangku color-grey-6 font-14 mr5"}></i>
<span>仓库设置</span>
</Link>
</li>
}
</React.Fragment>
)
})
}
</ul>
:
<Skeleton paragraph={false} active={true}/>
}
</div>
)
}
export default DetailBanner;

View File

@ -1,63 +0,0 @@
import React , { forwardRef, useEffect } from 'react';
import {Form , Modal , Input } from 'antd';
import "./sub.scss";
const { TextArea } = Input;
function UpdateDescModal({form , visible , onCancel , onOk,desc,website,lesson_url}){
const { getFieldDecorator, validateFields , setFieldsValue } = form;
useEffect(()=>{
if(desc || website){
setFieldsValue({
website,desc,lesson_url
})
}
},[desc,website])
function onSure(){
validateFields((err,values)=>{
if(!err){
onCancel();
onOk(values.desc,values.website,values.lesson_url)
}
})
}
return(
<Modal
title={"修改信息"}
closable={false}
visible={visible}
centered
onCancel={onCancel}
onOk={onSure}
okText="确定"
cancelText="取消"
width="400px"
className={"descmodal"}
>
<Form>
<Form.Item label="项目简介">
{getFieldDecorator("desc",{
rules:[]
})(
<TextArea placeholder="请输入项目简介" rows={4} maxLength={200}/>
)}
</Form.Item>
<Form.Item label="website">
{getFieldDecorator("website",{
rules:[]
})(
<Input placeholder="website链接"/>
)}
</Form.Item>
<Form.Item label="实践课程">
{getFieldDecorator("lesson_url",{
rules:[]
})(
<Input placeholder="实践课程链接"/>
)}
</Form.Item>
</Form>
</Modal>
)
}
export default Form.create()(forwardRef(UpdateDescModal));

View File

@ -1,23 +0,0 @@
.boxPanel{
width: 1200px;
margin:0px auto;
padding:20px 0px;
min-height: 500px;
.contrbuteList{
display: flex;
flex-wrap: wrap;
& > div{
width: 20%;
}
align-items: flex-start;
}
}
.descmodal{
.ant-row.ant-form-item{
margin-bottom: 10px;
}
.ant-col.ant-form-item-label{
height: 20px;
line-height: 20px;
}
}

View File

@ -22,7 +22,7 @@ function Commits({ commits , projectsId , owner }){
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(item.sha)}`} className="color-blue">浏览代码</Link>
</FlexAJ>
<AlignCenter className="mt15">
<User url={getImageUrl(`/${item.committer && item.committer.image_url}`)} name={`${item.committer && item.committer.name}`}></User><span>提交于{item.time_from_now}</span>
<User url={getImageUrl(`images/${item.committer && item.committer.image_url}`)} name={`${item.committer && item.committer.name}`}></User><span>提交于{item.time_from_now}</span>
</AlignCenter>
</div>
</div>

View File

@ -1,7 +1,6 @@
import React, { Component } from "react";
import { Link } from "react-router-dom";
import { Tag } from "antd";
import { AlignCenter } from '../Component/layout';
import { Popconfirm, Tag } from "antd";
import { getImageUrl } from "educoder";
import "./merge.css";
@ -75,13 +74,13 @@ class MergeItem extends Component {
>
<img
className="radius"
src={getImageUrl(`/${item && item.avatar_url}`)}
src={getImageUrl(`images/${item && item.avatar_url}`)}
alt=""
width="24"
height="24"
/>
</Link>
<AlignCenter>
<span>
<Link
to={`/users/${item && item.author_login}`}
className="show-user-link color-grey-8 ml5"
@ -99,7 +98,7 @@ class MergeItem extends Component {
<span className="ml15">
<Tag className="pr-branch-tag">
<Link
to={`/projects/${item.is_original ? item.fork_project_user : owner}/${ item.is_original ? item.fork_project_identifier : projectsId }/tree/${item.pull_request_head}`}
to={`/projects/${item.is_original ? item.fork_project_user : owner}/${ item.is_original ? item.fork_project_identifier : projectsId }/branch/${item.pull_request_head}`}
className="maxW200px hide-1 ver-middle"
>
{item.is_original
@ -117,7 +116,7 @@ class MergeItem extends Component {
</span>
<Tag className="pr-branch-tag">
<Link
to={`/projects/${owner}/${projectsId}/tree/${item.pull_request_base}`}
to={`/projects/${owner}/${projectsId}/branch/${item.pull_request_base}`}
className="maxW200px hide-1 ver-middle"
>
{/* {item.is_fork ? item.pull_request_base : `${item.author_name}:${item.pull_request_base}`} */}
@ -125,7 +124,7 @@ class MergeItem extends Component {
</Link>
</Tag>
</span>
</AlignCenter>
</span>
</p>
</div>
<ul
@ -178,7 +177,7 @@ class MergeItem extends Component {
>
<div className="grid-item mr15 color-grey-9">
<Link
to={`/projects/${owner}/${projectsId}/pulls/${item.pull_request_id}/updatemerge`}
to={`/projects/${owner}/${projectsId}/merge/${item.pull_request_id}/updatemerge`}
className="color-grey-9"
>
<i className="iconfont icon-bianji3 font-14 mr5"></i>

View File

@ -101,7 +101,7 @@ class MergeSubmit extends Component{
render: (text,item) => (
<span className="f-wrap-alignCenter">
<Link to={`/users/${item.login}`} className="show-user-link">
<img src={getImageUrl(`/${item.image_url}`)} alt="" width="28px" height="28px" className="mr3 radius"/>
<img src={getImageUrl(`images/${item.image_url}`)} alt="" width="28px" height="28px" className="mr3 radius"/>
<label className="hide-1" style={{maxWidth:"75px",'vertical-align':'middle'}}>{text}</label>
</Link>
</span>

View File

@ -305,7 +305,7 @@ class MessageCount extends Component {
<div className="mt15">
<Tag className="pr-branch-tag">
<Link
to={`/projects/${owner}/${data.pull_request.is_original?data.project_identifier:projectsId}/tree/${data.pull_request.head}`}
to={`/projects/${owner}/${data.pull_request.is_original?data.project_identifier:projectsId}/branch/${data.pull_request.head}`}
className="ver-middle"
>
{data.pull_request.is_original ? data.pull_request.fork_project_user : data.issue.project_author_name}:{data.pull_request.head}
@ -320,7 +320,7 @@ class MessageCount extends Component {
</span>
<Tag className="pr-branch-tag">
<Link
to={`/projects/${owner}/${projectsId}/tree/${data.pull_request.base}`}
to={`/projects/${owner}/${projectsId}/branch/${data.pull_request.base}`}
className="ver-middle"
>
{/* {data.pull_request.is_fork ? data.pull_request.base : `${data.pull_request.pull_request_user}:${data.pull_request.base}`} */}
@ -331,14 +331,26 @@ class MessageCount extends Component {
}
<div className="mt15">
<Link to={`/users/${data.issue.author_login}`} className="show-user-link">
<img className="mr5" src={getImageUrl(`/${data.issue.author_picture}`)}
alt="" width="24" height="24" style={{borderRadius:"50%"}}
<Link
to={`/users/${data.issue.author_login}`}
className="show-user-link"
>
<img
className="mr5"
src={getImageUrl(
`images/${data.issue.author_picture}`
)}
alt=""
width="24"
height="24"
/>
</Link>
<span className="ver-middle">
<span className="color-grey-8 mr5"></span>
<Link to={`/users/${data.issue.author_login}`} className="show-user-link color-blue">
<Link
to={`/users/${data.issue.author_login}`}
className="show-user-link color-blue"
>
{data.issue.author_name}
</Link>
<span className="ml5 color-grey-8">

View File

@ -178,7 +178,7 @@ class NewMerge extends Component {
let arr = projects_names && projects_names.filter(item=>item.id===value);
let identifier = arr && arr[0].project_id;
let login = arr && arr[0].project_user_login;
let is_fork_id = parseInt(value) !== parseInt(id);
let is_fork_id = parseInt(value) !== parseInt(id)
this.setState({
isSpin: true,
merge_head: is_fork_id,

View File

@ -168,7 +168,6 @@ form .ant-cascader-picker, form .ant-select {
}
.linesContent > p{
flex:1;
word-break: break-all;
}
.linesContent .lines{
display: flex;

View File

@ -253,9 +253,27 @@ class merge extends Component {
</Menu.Item>
</Menu>
);
const Paginations = (
<React.Fragment>
{search_count > limit ? (
<div className="mt30 mb50 edu-txt-center">
<Pagination
simple
defaultCurrent={page}
total={search_count}
pageSize={limit}
onChange={this.ChangePage}
></Pagination>
</div>
) : (
""
)}
</React.Fragment>
);
return (
<div className="main" style={{padding:"0px"}}>
<div className="topWrapper" style={{borderBottom:"none",padding:"20px"}}>
<div className="main">
<div className="topWrapper" style={{borderBottom:"none"}}>
<div className="target-detail-search">
<Search
placeholder="输入关键字搜索合并请求"
@ -401,21 +419,9 @@ class merge extends Component {
{...this.props}
{...this.state}
></OrderItem>
{Paginations}
</div>
):""}
{search_count > select_params.limit ? (
<div className="mt30 mb50 edu-txt-center">
<Pagination
simple
current={select_params.page}
total={search_count}
pageSize={select_params.limit}
onChange={this.ChangePage}
></Pagination>
</div>
) : (
""
)}
{ data && data.issues && data.issues.length === 0 ? <NoneData _html="暂时还没有相关数据!" projectsId={projectsId} owner={owner} /> :""}
</Spin>
</div>

View File

@ -34,19 +34,17 @@ class MergeForm extends Component {
this.set_defatul();
};
componentDidUpdate=(prevPros)=>{
const { projectsId ,owner } = this.props.match.params;
const pId = prevPros.match.params.projectsId;
const oId = prevPros.match.params.owner;
if(pId !== projectsId || oId !== owner ){
// console.log("切换了项目分支···········");
this.get_default_selects();
}
if(prevPros && this.props && !this.props.checkIfLogin()){
this.props.history.push("/403")
return
}
}
// check_is_login =() =>{
// if(!this.props.checkIfLogin()){
// this.props.history.push("/403")
// return
// }
// };
get_default_selects = () => {
const { projectsId ,owner } = this.props.match.params;
this.setState({ isSpin: true });

View File

@ -44,7 +44,8 @@ class Index extends Component {
project_category_name: undefined,
license_name: undefined,
ignore_name: undefined,
descNum:0
licenseForDisabled:undefined
}
}
componentDidMount = () => {
@ -146,7 +147,7 @@ class Index extends Component {
_data = data.filter(item => item.name.toLowerCase().indexOf(name.toLowerCase()) > -1);
}
let list = _data && _data.map((item) => (
<Option key={item.id} value={item.name}>
<Option key={item.id} value={item.name} onClick={()=>this.selectSerect(item.is_secret)}>
{item.name}
</Option>
));
@ -156,6 +157,17 @@ class Index extends Component {
}
}
selectSerect=(flag)=>{
if(flag){
this.props.form.setFieldsValue({
private:true
})
}
this.setState({
licenseForDisabled:flag
})
}
subMitFrom = () => {
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
@ -165,7 +177,7 @@ class Index extends Component {
const { projectsType } = this.props.match.params;
const { project_language_id, project_category_id, license_id, ignore_id , owners_id , owners_name } = this.state;
const decoderPass = Base64.encode(values.password);
const url = (projectsType && projectsType === "mirror") ? "/projects/migrate.json" : "/projects.json";
const url = projectsType === "deposit" ? "/projects.json" : "/projects/migrate.json";
axios.post(url, {
...values,
auth_password:decoderPass,
@ -180,7 +192,7 @@ class Index extends Component {
this.setState({
isSpin: false
})
this.props.showNotification(`${projectsType && projectsType === "mirror" ? "镜像" : "托管"}项目创建成功!`);
this.props.showNotification(`${projectsType === "deposit" ? "托管" : "镜像"}项目创建成功!`);
this.props.history.push(`/projects/${owners_name}/${result.data.identifier}`);
}
}
@ -199,7 +211,8 @@ class Index extends Component {
}
ChangePlatform = (value, e, name, list) => {
this.setOptionsList(list, name, value)
this.setOptionsList(list, name, value);
this.setState({
[name + "_id"]: e.key,
[name + "_name"]: value,
@ -255,13 +268,6 @@ class Index extends Component {
}
}
changeDesc=(e)=>{
let value = e.target.value;
this.setState({
descNum:value ? value.length :0
})
}
render() {
const { getFieldDecorator } = this.props.form;
// 项目类型deposit-托管项目mirror-镜像项目
@ -280,15 +286,14 @@ class Index extends Component {
project_category_list,
license_list,
ignore_list,
licenseForDisabled,
mirrorCheck,
descNum
mirrorCheck
} = this.state;
return (
<div className="main back-white" style={{padding:"0px",border:"none"}}>
<div className="main back-white">
<div className="newPanel">
<div className="newPanel_title">创建{projectsType && projectsType === "mirror" ? "镜像" : "托管"}项目</div>
<div className="newPanel_title">创建{projectsType === "deposit" ? "托管" : "镜像"}项目</div>
<Spin spinning={isSpin}>
<Form>
<div className="newPanel_content">
@ -313,7 +318,7 @@ class Index extends Component {
)}
</Form.Item>
{
projectsType && projectsType === "mirror" &&
projectsType !== "deposit" &&
<React.Fragment>
<Form.Item
label="镜像版本库地址"
@ -331,7 +336,7 @@ class Index extends Component {
</React.Fragment>
}
{
projectsType && projectsType === "mirror" &&
projectsType !== "deposit" &&
<React.Fragment>
<p className="mt10 mb10 color-grey-3 pointer" onClick={this.changeMirrorCheck}>需要授权验证<i className={mirrorCheck?"iconfont icon-xiajiantou font-13 ml10 color-grey-8":"iconfont icon-youjiantou font-13 ml10 color-grey-8"}></i></p>
{
@ -371,11 +376,10 @@ class Index extends Component {
required: true, message: '请填写项目名称'
}],
})(
<Input placeholder="例如:团队协作方法与研究" maxLength={50}/>
<Input placeholder="例如:团队协作方法与研究" />
)}
</Form.Item>
<div className="pr">
<span className="toprightNum">{descNum}/200</span>
<Form.Item
label="项目简介"
>
@ -384,10 +388,9 @@ class Index extends Component {
required: true, message: '请填写项目简介'
}],
})(
<Input.TextArea maxLength={200} placeholder="项目的介绍" autoSize={{ minRows: 2, maxRows: 6 }} onChange={this.changeDesc}/>
<Input.TextArea placeholder="项目的介绍" autoSize={{ minRows: 2, maxRows: 6 }} />
)}
</Form.Item>
</div>
<Form.Item
label="仓库名称"
>
@ -396,7 +399,7 @@ class Index extends Component {
required: true, message: '请填写仓库名称'
}],
})(
<Input placeholder="仓库名称请使用与项目相关的英文关键字" maxLength={100} />
<Input placeholder="仓库名称请使用与项目相关的英文关键字" />
)}
</Form.Item>
<Form.Item
@ -440,7 +443,7 @@ class Index extends Component {
)}
</Form.Item>
{
(projectsType === "deposit" || !projectsType) &&
projectsType === "deposit" &&
<React.Fragment>
<Form.Item
label=".gitignore"
@ -489,12 +492,12 @@ class Index extends Component {
style={{ margin: "0px" }}
className="privatePart"
>
{getFieldDecorator('private')(
<Checkbox value="limit">将项目设为私有<span className="ml15 font-13 color-grey-9">(只有项目所有人或拥有权限的项目成员才能看到)</span></Checkbox>
{getFieldDecorator('private',{valuePropName:"checked"})(
<Checkbox value="limit" disabled={licenseForDisabled}>将项目设为私有<span className="ml15 font-13 color-grey-9">(只有项目所有人或拥有权限的项目成员才能看到)</span></Checkbox>
)}
</Form.Item >
{
projectsType && projectsType === "mirror" &&
projectsType !== "deposit" &&
<Form.Item
label="迁移类型:"
style={{ margin: "0px" }}

View File

@ -54,7 +54,7 @@ class UserSubmitComponent extends Component {
const { getTopCount } = this.props;
getTopCount && getTopCount(values.branchname);
}
let url = `/projects/${owner}/${projectsId}${values.branchname ? `/tree/${values.branchname}`: (branch ? `/tree/${branch}` : "")}`;
let url = `/projects/${owner}/${projectsId}${values.branchname ? `/branch/${values.branchname}`: (branch ? `/branch/${branch}` : "")}`;
this.props.history.push(url);
}
})
@ -89,7 +89,7 @@ class UserSubmitComponent extends Component {
.then((result) => {
this.setState({ isSpin: false });
if (result.data && result.data.status === 1) {
let url = `/projects/${owner}/${projectsId}${(values.branchname ? `/tree/${values.branchname}` : ((currentBranch || branch) ? `/tree/${currentBranch || branch}`:""))}`;
let url = `/projects/${owner}/${projectsId}${(values.branchname ? `/branch/${values.branchname}` : ((currentBranch || branch) ? `/branch/${currentBranch || branch}`:""))}`;
this.props.history.push(url);
this.props.showNotification("文件修改成功!");
}
@ -114,10 +114,10 @@ class UserSubmitComponent extends Component {
const { editor_type } = this.props;
return (
<div>
<span className="df" style={{ alignItems: "center" }}>
<span className="df mt30" style={{ alignItems: "center" }}>
<Link to={`/users/${current_user && current_user.login}`} className="show-user-link" >
<img
src={getImageUrl(`/${current_user && current_user.image_url}`)}
src={getImageUrl(`images/${current_user && current_user.image_url}`)}
alt=""
className="screwImg"
/>

View File

@ -61,6 +61,10 @@
.screwPanel .ant-radio-wrapper{
display: block;
}
.branchTable{
border:1px solid #eaeaea;
border-radius: 2px;
}
.branchTable .margin-view-overlays{
border-right: 1px solid #eaeaea;
background-color: #fbfbfb;

View File

@ -12,13 +12,6 @@ class m_editor extends Component {
editorValue: this.props.content,
};
}
componentDidUpdate=(prevProps)=>{
if(prevProps && this.props && this.props.content !== prevProps.content){
this.setState({
editorValue:this.props.content
})
}
}
changeEditor = (editorValue) => {
this.setState({
editorValue,
@ -51,7 +44,7 @@ class m_editor extends Component {
return (
<React.Fragment>
<div>
<div className="branchTable" style={{border:"1px solid #eee"}}>
<div className="branchTable">
<Editor
height="400px"
language={language ? language : "plaintext"}
@ -63,8 +56,8 @@ class m_editor extends Component {
editorWillMount={this.editorWillMount}
/>
</div>
{!readOnly && (
<div style={{marginTop:"20px"}}>
<UserSubmitComponent
{...this.props}
{...this.state}
@ -73,7 +66,6 @@ class m_editor extends Component {
editor_type={editorType}
currentBranch={currentBranch}
></UserSubmitComponent>
</div>
)}
</div>
</React.Fragment>

View File

@ -1,88 +0,0 @@
import React, { useEffect, useState } from "react";
import { Link } from 'react-router-dom';
import './Index.scss';
import Loadable from "react-loadable";
import Loading from "../../Loading";
import { Route, Switch } from "react-router-dom";
const Notify = Loadable({
loader: () => import("./Notify"),
loading: Loading,
});
const UndoEvent = Loadable({
loader: () => import("./UndoEvent"),
loading: Loading,
});
function Index(props){
const username = props.match.params.username;
const pathname = props.history.location.pathname;
const user = props.user;
const undo_messages = props.undo_messages;
const [ menu , setMenu ] = useState("notify");
const [ messages , setMessages ] = useState(0);
const [ transferProjects , setTransferProjects ] = useState(0);
useEffect(()=>{
if(user){
setTransferProjects(user.undo_transfer_projects);
}
if(undo_messages){
setMessages(undo_messages);
}
},[user,undo_messages])
useEffect(()=>{
if(pathname && username){
if(pathname === `/users/${username}/notice`){
setMenu("notify");
}
if(pathname === `/users/${username}/notice/undo`){
setMenu("undo");
}
}
},[pathname])
function fetchUser(){
props && props.fetchUser();
}
function changeNum(){
fetchUser();
}
return (
<div>
<ul className="noticeMenu">
<li className={menu === "notify" ? "active":""}>
<Link to={`/users/${username}/notice`} onClick={changeNum}>
<span>通知</span>
{messages ? <span className="unNum">{messages}</span>:""}
</Link>
</li>
<li className={menu === "undo" ? "active":""}>
<Link to={`/users/${username}/notice/undo`}>
<span>接收仓库</span>
{transferProjects ? <span className="unNum">{transferProjects}</span>:""}
</Link>
</li>
</ul>
<Switch>
<Route
path="/users/:username/notice/undo"
render={(p) => {
return <UndoEvent {...props} {...p} fetchUser={fetchUser}/>;
}}
></Route>
<Route
path="/users/:username/notice"
render={(p) => {
return <Notify {...props} {...p} fetchUser={fetchUser}/>;
}}
></Route>
</Switch>
</div>
);
}
export default Index;

View File

@ -1,72 +0,0 @@
.noticeMenu{
padding:0px 20px;
display: flex;
border-bottom: 1px solid #eee;
height: 54px;
line-height: 54px;
li{
font-size: 16px;
padding:0px;
margin:0px 30px 0px 20px!important;
height: 54px;
line-height: 54px;
position: relative;
transform: none;
a{
display: flex;
&>span{
position: relative;
}
}
&.active a span:first-child::after{
position: absolute;
bottom: 0px;
height: 2px;
left: 0px;
content: "";
background-color: #1890ff;
width: 100%;
}
.unNum{
color: #d38900;
font-size: 12px;
border-radius: 13px;
height: 16px;
line-height: 16px;
padding:0px 4px;
min-width: 23px;
text-align: center;
background-color: #ffe4b3;
margin-top: 19px;
margin-left: 10px;
display: block;
}
}
}
.notifyList{
padding:0px 20px;
min-height: 400px;
li{
display: flex;
border-bottom: 1px solid #eee;
padding:20px 0px;
.notifyImg{
width: 48px;
height: 48px;
border-radius: 50%;
margin-right: 15px;
}
.notifyFlex{
flex:1;
p{
margin:0px;
}
.notifyInfos{
margin-bottom: 8px;
}
}
&:last-child{
border-bottom: none;
}
}
}

View File

@ -1,91 +0,0 @@
import React, { useEffect, useState } from "react";
import Nodata from '../Nodata';
import {Pagination } from 'antd';
import { Link } from 'react-router-dom';
import { getImageUrl } from 'educoder';
import Axios from "axios";
const limit = 15;
function Notify(props){
const username = props.match.params.username;
const [ list , setList ] = useState(undefined);
const [ page , setPage ] = useState(1);
const [ total , setTotal ] = useState(0);
useEffect(()=>{
if(username){
getList();
}
},[username,page])
function getList(){
const url = `/users/${username}/applied_messages.json`;
Axios.get(url,{
params:{
page,per_page:limit
}
}).then(result=>{
if(result){
setList(result.data.applied_messages);
setTotal(result.data.total_count);
}
}).catch(error=>{})
}
function renderStatus(status,applied){
let { project , owner} = applied
if(status){
switch(status){
case 'canceled':
return <p>取消转移<Link to={`/projects/${project && project.owner && project.owner.login}/${project && project.identifier}`}>{project && project.name}</Link>仓库</p>
case 'common':
return <p>正在将<Link to={`/projects/${project && project.owner && project.owner.login}/${project && project.identifier}`}>{project && project.name}</Link>仓库转移给<Link to={`/users/${owner && owner.login}`}>{owner && owner.name}</Link></p>
case 'successed':
return <p><Link to={`/projects/${project && project.owner && project.owner.login}/${project && project.identifier}`}>{project && project.name}</Link>仓库成功转移给<Link to={`/users/${owner && owner.login}`}>{owner && owner.name}</Link></p>
default:
return <p>拒绝转移<Link to={`/projects/${project && project.owner && project.owner.login}/${project && project.identifier}`}>{project && project.name}</Link>仓库</p>
}
}else{
return ""
}
}
return(
<div>
{
list && list.length > 0 ?
<div>
<ul className="notifyList">
{
list.map((i,k)=>{
return(
<li>
<Link to={`/users/${i.login}`}><img src={getImageUrl(`/${i.applied_user && i.applied_user.image_url}`)} alt="" className="notifyImg"/></Link>
<div className="notifyFlex">
<p className="notifyInfos">
<Link to={`/users/${i.applied_user && i.applied_user.login}`} className="font-15 mr20">{i.applied_user && i.applied_user.name}</Link>
<span className="color-grey-9">{i.time_ago}</span>
</p>
{renderStatus(i.status,i.applied)}
</div>
</li>
)
})
}
</ul>
</div>
:
""
}
{list && list.length === 0 && <Nodata _html="暂无通知" />}
{
total > limit &&
<div className="edu-txt-center pt20 pb20">
<Pagination simple pageSize={limit} total={total} current={page} onChange={(p)=>{setPage(p)}}/>
</div>
}
</div>
)
}
export default Notify;

View File

@ -1,118 +0,0 @@
import React, { useEffect, useState } from "react";
import Nodata from '../Nodata';
import { FlexAJ } from '../Component/layout';
import { Pagination , Popconfirm } from 'antd';
import { Link } from 'react-router-dom';
import { getImageUrl } from 'educoder';
import Axios from 'axios';
const limit = 15;
function UndoEvent(props){
const username = props.match.params.username;
const [ list , setList ] = useState(undefined);
const [ page , setPage ] = useState(1);
const [ total , setTotal ] = useState(0);
useEffect(()=>{
if(username){
getList();
}
},[username,page])
function getList(){
const url = `/users/${username}/applied_transfer_projects.json`;
Axios.get(url,{
params:{
page,per_page:limit
}
}).then(result=>{
if(result){
setList(result.data.applied_transfer_projects);
setTotal(result.data.total_count);
}
}).catch(error=>{})
}
//
function acceptDivert(id){
const url = `/users/${username}/applied_transfer_projects/${id}/accept.json`;
Axios.post(url).then(result=>{
if(result && result.data){
getList();
props && props.fetchUser();
}
}).catch(error=>{})
}
//
function revertDivert(id){
const url = `/users/${username}/applied_transfer_projects/${id}/refuse.json`;
Axios.post(url).then(result=>{
if(result && result.data){
getList();
props && props.fetchUser();
}
}).catch(error=>{})
}
return(
<div>
{
list && list.length > 0 ?
<div>
<ul className="notifyList">
{
list.map((i,k)=>{
return(
<li>
<Link to={`/users/${i.user && i.user.login}`}><img src={getImageUrl(`/${i.user && i.user.image_url}`)} alt="" className="notifyImg"/></Link>
<div className="notifyFlex">
<p className="notifyInfos">
<Link to={`/users/${i.login}`} className="font-15 mr20">{i.user && i.user.name}</Link>
<span className="color-grey-9">{i.time_ago}</span>
</p>
<FlexAJ>
<p className="color-grey-6">请求将仓库<Link to={`/projects/${i.project && i.project.owner && i.project.owner.login}/${i.project && i.project.identifier}`}>{i.project && i.project.name}</Link>
转移给<Link to={`/users/${i.owner && i.owner.login}`}>{i.owner && i.owner.name}</Link>,是否接受</p>
{
i.status === "common" &&
<span>
<Popconfirm title={`确定接受仓库${i.project && i.project.name}`} okText="确定" cancelText="取消" onConfirm={()=>acceptDivert(i.id)}>
<a className="color-blue">接受</a>
</Popconfirm>
<Popconfirm title={`确定拒绝接受仓库${i.project && i.project.name}`} okText="确定" cancelText="取消" onConfirm={()=>revertDivert(i.id)}>
<a className="color-red ml20">拒绝</a>
</Popconfirm>
</span>
}
{
i.status === "canceled" && <span className="color-grey-9">对方已取消转移</span>
}
{
i.status === "accepted" && <span className="color-grey-9">已接受</span>
}
{
i.status === "refused" && <span className="color-grey-9">已拒绝</span>
}
</FlexAJ>
</div>
</li>
)
})
}
</ul>
</div>
:
""
}
{list && list.length === 0 && <Nodata _html="暂无接收信息" />}
{
total > limit &&
<div className="edu-txt-center pt20 pb20">
<Pagination simple pageSize={limit} total={total} current={page} onChange={(p)=>{setPage(p)}}/>
</div>
}
</div>
)
}
export default UndoEvent;

View File

@ -212,7 +212,7 @@ class Detail extends Component {
>
<img
className="user_img"
src={getImageUrl(`/${data && data.author_picture}`)}
src={getImageUrl(`images/${data && data.author_picture}`)}
alt=""
width="50"
height="50"

View File

@ -218,7 +218,7 @@ class MilepostDetail extends Component {
</span>
<div className="milepostdiv">
<Link to={`/projects/${owner}/${projectsId}/milestones/${meilid}/edit`} className="topWrapper_btn" style={{ marginRight: 15 }} >编辑里程碑</Link>
<Link to={`/projects/${owner}/${projectsId}/issues/${meilid}/new`} className="topWrapper_btn">创建易修</Link>
<Link to={`/projects/${owner}/${projectsId}/issues/${meilid}/new`} className="topWrapper_btn">创建任务</Link>
</div>
</FlexAJ>
</div>

Some files were not shown because too many files have changed in this diff Show More