Compare commits

...

384 Commits

Author SHA1 Message Date
durian 724c110437 Merge pull request '我的通知' (#33) from durian/forgeplus-react:feature_notification_xiesi into feature_notification 2021-09-27 14:57:28 +08:00
谢思 ca7ab2ebe0 更正 2021-09-27 14:54:33 +08:00
durian e0a5e4348e Merge pull request '我的通知' (#32) from durian/forgeplus-react:feature_notification_xiesi into feature_notification 2021-09-27 14:01:12 +08:00
谢思 e5bb8d10b2 我的通知优化-用户未登录 2021-09-27 13:56:32 +08:00
谢思 26de781181 我的通知tab栏跳转优化 2021-09-27 11:32:05 +08:00
谢思 3a816ce5e5 Merge branch 'feature_notification' of https://git.trustie.net/tongChong/forgeplus-react into feature_notification_xiesi 2021-09-23 08:59:32 +08:00
谢思 4079765edb 我的通知 2021-09-22 12:59:51 +08:00
durian 76ffd0e8b9 Merge pull request '我的通知-消息悬停框' (#27) from durian/forgeplus-react:feature_notification_xiesi into feature_notification 2021-09-22 10:22:54 +08:00
谢思 975dfad4aa 消息悬停框 2021-09-22 10:14:22 +08:00
谢思 e1372fdd02 个人设置页面左侧导航栏鼠标悬停样式 2021-09-18 09:00:11 +08:00
何童崇 628606480a 修改小铃铛bug 2021-09-17 14:59:26 +08:00
tongChong cd949d4f2a Merge pull request '我的通知' (#26) from durian/forgeplus-react:feature_notification_xiesi into feature_notification 2021-09-17 14:14:55 +08:00
谢思 78014b02bf 通知中心 2021-09-17 14:11:31 +08:00
何童崇 a299b9a841 Merge branch 'pre_develop_dev' of https://git.trustie.net/Gitlink/forgeplus-react into feature_notification 2021-09-17 11:33:53 +08:00
yystopf bcde15cec1 需求更改
同步镜像调用websockt,成功后刷新页面;
合并请求可选标签,仓库设置类别、语言可选
2021-09-17 09:43:31 +08:00
caishi 23b423a32d 同步镜像点击事件,设置和合并请求编辑的可选项 2021-09-17 09:34:24 +08:00
tongChong 993b1bde40 Merge pull request '我的通知' (#24) from durian/forgeplus-react:feature_notification_xiesi into feature_notification 2021-09-16 17:20:00 +08:00
谢思 d45e87d46f Merge branch 'feature_notification' of https://git.trustie.net/tongChong/forgeplus-react into feature_notification_xiesi 2021-09-16 17:17:40 +08:00
谢思 cdc2ca755e 通知中心优化 2021-09-16 17:16:23 +08:00
何童崇 d7242f0fa1 上传合并蔡世修改 2021-09-16 17:09:15 +08:00
yystopf a1c8440fe2 将平台标签改为标记 2021-09-16 16:37:48 +08:00
caishi 6cfb56e6ca update 标签 to 标记 2021-09-16 16:26:51 +08:00
caishi a5c3cd168e 同上-影响后端接口,暂不上线 2021-09-16 15:48:43 +08:00
何童崇 44dc10ff8c Merge branch 'feature_notification' of https://git.trustie.net/tongChong/forgeplus-react into feature_notification 2021-09-16 13:11:24 +08:00
tongChong 0d9d9887f4 Merge pull request '我的通知' (#23) from durian/forgeplus-react:feature_notification_xiesi into feature_notification 2021-09-16 13:09:00 +08:00
谢思 def926bff0 通知中心优化 2021-09-16 11:49:31 +08:00
谢思 94a7cf1e6c 通知中心优化 2021-09-16 11:46:29 +08:00
caishi 09a75bc77c Merge branch 'pre_develop_dev' of https://git.trustie.net/Gitlink/forgeplus-react into pre_develop_dev 2021-09-16 11:10:21 +08:00
caishi 25186132f2 markdown @+字母,会有跳转链接,去掉 2021-09-16 11:10:11 +08:00
何童崇 7e683ac6bb Merge branch 'feature_notification' of https://git.trustie.net/tongChong/forgeplus-react into feature_notification 2021-09-16 10:38:52 +08:00
tongChong 7cf0ae4e67 Merge pull request '我的通知' (#22) from durian/forgeplus-react:feature_notification_xiesi into feature_notification 2021-09-16 10:38:10 +08:00
谢思 0462b28abf 通知中心优化 2021-09-16 10:35:14 +08:00
何童崇 ff1ffc120f Merge branch 'pre_develop_dev' of https://git.trustie.net/Gitlink/forgeplus-react into feature_notification 2021-09-16 10:28:54 +08:00
yystopf 7158eca4f6 issue任务:文案、跳转、样式细节修改 2021-09-16 10:12:41 +08:00
caishi 917374ba11 update 标签 to 标记 2021-09-16 10:03:39 +08:00
caishi f6ec470070 issue-文案、细节修改 2021-09-16 09:47:26 +08:00
tongChong 23ccaadba2 Merge pull request '我的通知' (#21) from durian/forgeplus-react:feature_notification_xiesi into feature_notification 2021-09-15 16:54:15 +08:00
谢思 4bb1b8d538 我的通知 2021-09-15 16:52:34 +08:00
何童崇 06314a51a6 修改小铃铛 2021-09-15 16:32:32 +08:00
何童崇 49fad4b8bc Merge branch 'feature_notification' of https://git.trustie.net/tongChong/forgeplus-react into feature_notification 2021-09-15 16:10:12 +08:00
tongChong 4e8657357f Merge pull request '我的通知' (#20) from durian/forgeplus-react:feature_notification_xiesi into feature_notification 2021-09-15 16:10:04 +08:00
谢思 dcbba90c18 我的通知 2021-09-15 16:07:53 +08:00
谢思 ec65ac3cef 我的通知 2021-09-15 16:05:24 +08:00
谢思 49c66c73a7 我的通知 2021-09-15 15:36:38 +08:00
谢思 6ca0e48697 我的通知 2021-09-15 15:36:16 +08:00
何童崇 52c5187d0e Merge branch 'feature_notification' of https://git.trustie.net/tongChong/forgeplus-react into feature_notification 2021-09-15 14:51:32 +08:00
tongChong 6430ed76a6 Merge pull request '消息铃铛' (#19) from durian/forgeplus-react:feature_notification_xiesi into feature_notification 2021-09-15 14:49:48 +08:00
谢思 c1ea865f1e 我的通知 2021-09-15 14:47:36 +08:00
tongChong 480fcc1f8e Merge pull request '我的通知' (#18) from durian/forgeplus-react:feature_notification_xiesi into feature_notification 2021-09-15 14:44:59 +08:00
谢思 ee6a40a5d9 我的通知 2021-09-15 14:41:59 +08:00
谢思 aaa58e532b 我的通知 2021-09-15 14:23:42 +08:00
何童崇 ebf927dc46 Merge branch 'feature_notification' of https://git.trustie.net/tongChong/forgeplus-react into feature_notification 2021-09-15 13:17:54 +08:00
tongChong 9b6ad6340f Merge pull request '我的通知' (#17) from durian/forgeplus-react:feature_notification_xiesi into feature_notification 2021-09-15 13:16:35 +08:00
谢思 f6a98e4169 我的通知 2021-09-15 13:09:52 +08:00
谢思 9050c5ca2b Merge branch 'feature_notification' of https://git.trustie.net/tongChong/forgeplus-react into feature_notification_xiesi 2021-09-14 16:40:13 +08:00
何童崇 71438d1030 Merge branch 'pre_develop_dev' of https://git.trustie.net/Gitlink/forgeplus-react into feature_notification 2021-09-14 16:34:47 +08:00
何童崇 0e31deb88c 上传通知修改 2021-09-14 16:33:08 +08:00
谢思 d55242f7e8 Merge branch 'feature_notification' of https://git.trustie.net/tongChong/forgeplus-react into feature_notification_xiesi 2021-09-14 16:21:24 +08:00
tongChong 9852bb14c3 Merge pull request '我的通知' (#14) from durian/forgeplus-react:feature_notification_xiesi into feature_notification 2021-09-14 16:20:59 +08:00
谢思 c0a4432c18 Merge branch 'feature_notification' of https://git.trustie.net/tongChong/forgeplus-react into feature_notification_xiesi 2021-09-14 16:19:41 +08:00
谢思 9ea8ec422d 我的通知 2021-09-14 16:18:31 +08:00
谢思 7fbd76630c 我的通知 2021-09-14 16:02:22 +08:00
何童崇 bc11ac3d79 修改小铃铛及浮动框相关代码 2021-09-14 14:56:21 +08:00
谢思 c5bb61cb9a 通知中心 2021-09-14 09:45:53 +08:00
谢思 f30903072e 通知中心 2021-09-13 14:25:52 +08:00
谢思 dabe7d6551 通知中心 2021-09-13 13:21:34 +08:00
tongChong 3598225cac Merge pull request '通知中心静态页面0910' (#12) from durian/forgeplus-react:feature_notification_xiesi into feature_notification 2021-09-12 15:29:31 +08:00
谢思 1b21d9e3fb 通知中心 2021-09-12 14:47:49 +08:00
jasder 4eae7e68b8 Merge pull request 'FIX 代码库一级页面改版' (#63) from feature_repo_upgrade into pre_develop_dev 2021-09-10 18:25:36 +08:00
jasder 3f33e03549 Merge pull request '新建页面-用户密码不自动填充' (#62) from caishi/forgeplus-react:pre_develop_dev into pre_develop_dev 2021-09-10 18:24:46 +08:00
jasder c3546a66cd Merge pull request '和测试版同步,以及一些样式细节问题' (#61) from caishi/forgeplus-react:feature_repo_upgrade into feature_repo_upgrade 2021-09-10 18:24:25 +08:00
谢思 4795de938e 通知中心静态页面0910 2021-09-10 18:23:28 +08:00
caishi 8c0757c942 加粗 2021-09-10 18:20:33 +08:00
caishi 41af42ce6f Merge branch 'pre_develop_dev' of https://git.trustie.net/Gitlink/forgeplus-react into pre_develop_dev 2021-09-10 18:13:49 +08:00
caishi 0ffa5e0cae 新建页面-用户密码不自动填充 2021-09-10 18:13:45 +08:00
caishi 747ae8ccd5 Merge branch 'pre_develop_dev' of https://git.trustie.net/Gitlink/forgeplus-react into feature_repo_upgrade 2021-09-10 15:13:24 +08:00
jasder 6eb9108aa7 Merge pull request '修改相关页面的issue' (#60) from caishi/forgeplus-react:pre_develop_dev into pre_develop_dev 2021-09-10 15:13:08 +08:00
caishi 828de5d770 项目列表省略效果没有生效 2021-09-10 15:10:39 +08:00
caishi 007feded68 新建项目相关bug 2021-09-10 15:02:19 +08:00
jasder 5f90b85c1d Merge pull request '代码库一级页面样式修改' (#59) from caishi/forgeplus-react:feature_repo_upgrade into feature_repo_upgrade 2021-09-10 14:09:19 +08:00
caishi f1a4f7c68f Merge branch 'pre_develop_dev' of https://git.trustie.net/Gitlink/forgeplus-react into feature_repo_upgrade 2021-09-10 11:53:15 +08:00
jasder 98ca09e64b Merge pull request 'issue-组织列表显示的名称' (#58) from caishi/forgeplus-react:pre_develop_dev into pre_develop_dev 2021-09-10 11:51:51 +08:00
caishi 3e9c9ea6d1 个人中心-组织列表-显示组织的名称nickname 2021-09-10 11:50:30 +08:00
caishi 3a16c4be8a delete .map文件、update style 2021-09-10 11:47:48 +08:00
caishi 81623b38f7 style 2021-09-10 09:50:29 +08:00
caishi 06f3eacb9d style 2021-09-09 17:50:46 +08:00
caishi 93736781c5 Merge branch 'feature_repo_upgrade' of https://git.trustie.net/caishi/forgeplus-react into feature_repo_upgrade 2021-09-09 16:59:12 +08:00
hc1913847458 5bfb6ee4c1 Merge branch 'pre_develop_dev' of https://git.trustie.net/Gitlink/forgeplus-react into feature_repo_upgrade 2021-09-09 16:55:28 +08:00
jasder baf9a3f4a8 Merge pull request 'issue上线' (#57) from caishi/forgeplus-react:pre_develop_dev into pre_develop_dev 2021-09-09 16:55:02 +08:00
caishi eb89f6a6a7 新建按钮字的内容修改 2021-09-09 16:49:09 +08:00
caishi a24132412e 新建项目页面排版调整 2021-09-09 16:35:02 +08:00
caishi d558443c22 style 2021-09-09 16:09:16 +08:00
tongChong 495e11fb4c Merge pull request '通知中心' (#11) from durian/forgeplus-react:feature_notification_xiesi into feature_notification 2021-09-09 14:36:52 +08:00
谢思 c477fbe89a 通知中心新增的三个页面 2021-09-09 14:31:31 +08:00
谢思 e07e435557 通知中心静态页面 2021-09-09 14:25:04 +08:00
caishi a4475e995b 同上,文案已改,项目新建页面前端修改,wait后端 2021-09-09 14:11:02 +08:00
caishi e0aeab0e20 项目列表tip文案-待定 2021-09-09 10:10:19 +08:00
谢思 8e17efb9c6 通知中心静态页面 2021-09-09 09:34:51 +08:00
hc1913847458 ef7cc1ebd6 Merge branch 'feature_repo_upgrade' of https://git.trustie.net/hc1913847458/forgeplus-react into feature_repo_upgrade 2021-09-08 18:09:48 +08:00
hc1913847458 9e1ce515a8 issue 2021-09-08 18:09:26 +08:00
hc1913847458 1e1f2a0e2f Merge branch 'feature_repo_upgrade' of https://git.trustie.net/caishi/forgeplus-react into feature_repo_upgrade 2021-09-08 18:07:03 +08:00
hc1913847458 19afa410b1 issue 2021-09-08 18:04:53 +08:00
hc1913847458 fbb73968c9 Merge branch 'pre_develop_dev' of https://git.trustie.net/caishi/forgeplus-react into feature_repo_upgrade 2021-09-08 18:03:47 +08:00
caishi 0768ab2970 delete 2021-09-08 18:02:29 +08:00
caishi 46e8135585 overflow 2021-09-08 18:00:51 +08:00
hc1913847458 540553199a issue 2021-09-08 17:53:21 +08:00
jasder 1c8ad3dc60 Merge pull request '新建项目页面取消按钮,跳转地址错误' (#56) from caishi/forgeplus-react:pre_develop_dev into pre_develop_dev 2021-09-08 17:46:54 +08:00
hc1913847458 b3c9eb3c33 issue 2021-09-08 17:42:04 +08:00
caishi 64b1c51fad 新建页面取消按钮,跳转地址错误 2021-09-08 11:33:36 +08:00
何童崇 22b5859b62 上传请求公共处理函数 2021-09-07 17:06:35 +08:00
hc1913847458 e0d1de7a53 issue 2021-09-07 15:10:36 +08:00
jasder fc274f09e9 Merge pull request 'issue任务上线测试版' (#55) from caishi/forgeplus-react:pre_develop_dev into pre_develop_dev 2021-09-07 15:09:28 +08:00
hc1913847458 f8075ccb2f issue 2021-09-07 14:00:04 +08:00
caishi 46c604bf92 markdown图片点击放大 2021-09-07 13:57:28 +08:00
caishi daf81be4f6 Merge branch 'pre_develop_dev' of https://git.trustie.net/Gitlink/forgeplus-react into pre_develop_dev
# Conflicts:
#	src/forge/Main/Detail.js
2021-09-07 13:54:04 +08:00
caishi 030c779103 issue图片放大功能 2021-09-07 13:53:35 +08:00
jasder 3c5c4266cd Merge pull request 'FIX some bug' (#54) from feature_router into pre_develop_dev 2021-09-07 13:53:02 +08:00
hc1913847458 94fbc972be issue 2021-09-07 11:29:09 +08:00
tongChong ca51702799 Merge pull request '我的通知静态页面' (#9) from durian/forgeplus-react:feature_notification_xiesi into feature_notification 2021-09-07 11:27:11 +08:00
谢思 e721399e17 Merge branch 'feature_notification' of https://git.trustie.net/tongChong/forgeplus-react into feature_notification_xiesi 2021-09-07 11:22:59 +08:00
何童崇 244881f142 上传通知的修改 2021-09-07 11:16:05 +08:00
谢思 b6cf496efa 通知中心-我的通知 2021-09-07 11:14:53 +08:00
何童崇 6665a15aa3 新增函数调用模态框 2021-09-07 10:42:48 +08:00
何童崇 a667f41ec1 下拉主分支代码 2021-09-07 10:33:01 +08:00
hc1913847458 5424973c52 issue 2021-09-07 10:16:34 +08:00
tongChong 258de069e4 Merge pull request '通知中心' (#8) from durian/forgeplus-react:feature_notification_xiesi into feature_notification 2021-09-07 09:41:28 +08:00
谢思 cb58481daf 通知系统 2021-09-07 09:33:46 +08:00
jasder 548cdee35b Merge pull request '代码库一级页面样式修改+8.30至9.03日的更新提交' (#53) from caishi/forgeplus-react:feature_repo_upgrade into feature_repo_upgrade 2021-09-06 18:36:14 +08:00
caishi 488d04284c delete 多余文件 2021-09-06 18:32:51 +08:00
hc1913847458 01f1a5c68c issue 2021-09-06 18:09:09 +08:00
hc1913847458 6f80d439c3 issue 2021-09-06 18:08:50 +08:00
hc1913847458 6696222c02 issue 2021-09-06 18:07:36 +08:00
hc1913847458 4acfb88ee5 issue 2021-09-06 18:07:36 +08:00
hc1913847458 97e6a5d5f2 issue 2021-09-06 18:07:13 +08:00
hc1913847458 b26f300832 issue 2021-09-06 18:06:59 +08:00
hc1913847458 349851dc59 issue 2021-09-06 18:04:38 +08:00
hc1913847458 09e9f01f7e save files 2021-09-06 18:04:25 +08:00
hc1913847458 da657e559b save files 2021-09-06 18:04:07 +08:00
caishi 53fa18907d 代码style 2021-09-06 18:03:05 +08:00
hc1913847458 9d4893eb49 限制字符 2021-09-06 18:03:05 +08:00
caishi 6e849aa800 install babel-polyfill 2021-09-06 18:02:45 +08:00
caishi 194f6af412 merge develop 2021-09-06 18:02:09 +08:00
caishi d5652fba18 新建项目-maxlength 2021-09-06 18:00:24 +08:00
caishi fbe5da1014 设置所有标签的marginbottom为0 2021-09-06 17:59:45 +08:00
caishi 478b080d45 issue 49808 :tab页鼠标悬停规范调整 2021-09-06 17:55:15 +08:00
caishi dcef7e7872 reset 2021-09-06 17:54:35 +08:00
caishi 2882289267 里程碑-切换分页需要带上状态参数 2021-09-06 17:54:35 +08:00
caishi 37f608cdb8 代码库-样式 2021-09-06 17:54:35 +08:00
caishi 984856a29c md fullscreen 2021-09-06 17:48:13 +08:00
caishi cbfb73d1cb 同上-细节修改 2021-09-06 17:48:13 +08:00
caishi 411b4e9de6 代码库样式整改 2021-09-06 17:47:47 +08:00
hc1913847458 b611308f3c 'update' 2021-09-06 17:41:29 +08:00
jasder 154225d229 Merge pull request 'FIX 解决组织跨项目发送Pr的bug' (#51) from feature_router into pre_develop 2021-09-06 17:02:21 +08:00
baladiwei c859a16837 Merge pull request '修复登陆和未登陆时,访问没有的项目返回页面不同的问题' (#50) from tongChong/forgeplus-react:feature_router into feature_router 2021-09-06 16:36:43 +08:00
何童崇 33a669a940 修改路由跳转404的问题 2021-09-06 10:37:06 +08:00
jasder 7b2d842ac2 Merge pull request '修复PR的bug' (#48) from tongChong/forgeplus-react:feature_router into feature_router 2021-09-04 11:26:45 +08:00
何童崇 245086cf47 Merge branch 'pre_develop' of https://git.trustie.net/Gitlink/forgeplus-react into feature_router 2021-09-04 11:19:37 +08:00
何童崇 a90eeac318 上传PR修改 2021-09-04 11:16:08 +08:00
何童崇 1764fbdb88 速度速度 2021-09-03 21:51:53 +08:00
caishi 22ccc3c974 fork白屏+关注 2021-09-03 19:06:14 +08:00
jasder 46f83ed44d Merge pull request '发布 V3.1.0版本' (#47) from pre_develop_dev into pre_develop 2021-09-03 18:13:49 +08:00
jasder 657bfbc6df Merge pull request 'FIX 合并 featrue_router' (#46) from feature_router into pre_develop_dev 2021-09-03 18:01:09 +08:00
jasder 7e1dde4ecd Merge pull request '新建项目接口报错后前端需要去掉加载效果' (#45) from caishi/forgeplus-react:feature_router into feature_router 2021-09-03 17:57:01 +08:00
caishi 3d6136bbbb 新建项目不成功,需要去掉加载状态 2021-09-03 17:46:49 +08:00
jasder b6ed5d79e7 Merge pull request '修改相关issue的代码提交' (#44) from caishi/forgeplus-react:feature_router into feature_router 2021-09-03 17:18:20 +08:00
caishi 21ce83e537 issue 2021-09-03 17:14:45 +08:00
jasder 03a8e79382 Merge pull request 'issue修改' (#43) from caishi/forgeplus-react:feature_router into feature_router 2021-09-03 16:08:12 +08:00
caishi 3fce9a99ad 头部姓名过长,省略 2021-09-03 14:57:39 +08:00
caishi db18cd41b0 Merge branch 'feature_router' of https://git.trustie.net/Gitlink/forgeplus-react into feature_router 2021-09-03 14:46:16 +08:00
caishi 7fb7dbe687 issue 2021-09-03 14:46:06 +08:00
jasder 5e58f349cd Merge pull request '修改路由相关issue' (#42) from tongChong/forgeplus-react:feature_router into feature_router 2021-09-03 14:43:55 +08:00
何童崇 4e08bf6fe3 修改路由labels 2021-09-03 14:39:21 +08:00
caishi bc8e513b97 Merge branch 'feature_router' of https://git.trustie.net/Gitlink/forgeplus-react into feature_router 2021-09-03 14:10:57 +08:00
caishi 4621a75ec8 项目列表 2021-09-03 14:10:36 +08:00
何童崇 17671a7c87 Merge branch 'feature_router' of https://git.trustie.net/Gitlink/forgeplus-react into feature_router 2021-09-03 13:51:24 +08:00
jasder 47ecda06ca Merge pull request '个人信息资料提示+新的需求' (#41) from caishi/forgeplus-react:feature_router into feature_router 2021-09-03 13:50:38 +08:00
何童崇 ebd94ed3a1 修改路由相关issue及顺带测出的问题 2021-09-03 13:48:56 +08:00
caishi d1128a0dfc 个人资料完善box style 2021-09-03 13:48:07 +08:00
baladiwei 47f5d98d79 Merge pull request '修改例子中的路由以及新提出的路由,修改之前由于修改路由带来的issue' (#40) from tongChong/forgeplus-react:feature_router into feature_router 2021-09-03 11:48:21 +08:00
何童崇 a5bdf26f96 修改路由issue 2021-09-03 11:38:22 +08:00
何童崇 f6a0c3b33f Merge branch 'feature_router' of https://git.trustie.net/Gitlink/forgeplus-react into feature_router 2021-09-03 11:37:08 +08:00
jasder 9d2dc3426c Merge pull request '关注页面issue+个人资料弹框漏掉的按钮' (#39) from caishi/forgeplus-react:feature_router into feature_router 2021-09-03 11:32:40 +08:00
caishi 5abe75d637 个人资料issue+样式 2021-09-03 11:26:23 +08:00
何童崇 9e14821125 Merge branch 'feature_router' of https://git.trustie.net/Gitlink/forgeplus-react into feature_router 2021-09-03 10:17:32 +08:00
jasder 2f3f33d58e Merge pull request '个人资料完善弹框样式修改' (#38) from caishi/forgeplus-react:feature_router into feature_router 2021-09-03 10:13:35 +08:00
caishi 43b31427d8 弹框样式修改 2021-09-03 10:08:24 +08:00
何童崇 03d568f5f7 合并蔡世代码并解决冲突 2021-09-03 09:26:34 +08:00
何童崇 24c4c746cd 修改其他路由及修改issue 2021-09-03 09:23:12 +08:00
jasder 3fc0737e43 Merge pull request '个人信息资料完善提示弹框,基本资料页面路由修改' (#37) from caishi/forgeplus-react:feature_router into feature_router 2021-09-02 17:44:43 +08:00
何童崇 4f39f03b19 修改路由的issue 2021-09-02 17:20:26 +08:00
caishi b475edae74 hover-issue delete 2021-09-02 16:39:35 +08:00
caishi dbb5efdcd5 issue-part 2 2021-09-02 15:04:26 +08:00
caishi 322260c3fc Merge branch 'feature_router' of https://git.trustie.net/Gitlink/forgeplus-react into feature_router
# Conflicts:
#	src/forge/Team/List.jsx
2021-09-02 14:16:30 +08:00
caishi 375ad38364 issue 2021-09-02 14:13:16 +08:00
baladiwei ef6f334d94 Merge pull request '修改路由带来的bug' (#36) from tongChong/forgeplus-react:feature_router into feature_router 2021-09-02 13:40:15 +08:00
何童崇 559b797c2e 修改路由带来的bug 2021-09-02 13:37:24 +08:00
caishi adc134ec44 复制-组件 2021-09-02 10:10:21 +08:00
caishi bf3f404238 Merge branch 'feature_router' of https://git.trustie.net/Gitlink/forgeplus-react into feature_router 2021-09-01 18:15:32 +08:00
jasder 9b62b3b047 Merge pull request '上传路由修改,上传sourcesource-map配置' (#35) from tongChong/forgeplus-react:feature_router into feature_router 2021-09-01 17:54:05 +08:00
caishi c14f06301f appconfig 2021-09-01 17:49:42 +08:00
caishi 105e1c61b8 个人资料是否完善-弹框 2021-09-01 17:46:58 +08:00
何童崇 80dde2bc97 上传路由修改,上传sourcesource-map配置 2021-09-01 17:34:47 +08:00
caishi 3b03ead3af Merge branch 'feature_router' of https://git.trustie.net/Gitlink/forgeplus-react into feature_router 2021-09-01 11:24:43 +08:00
caishi 86f50d4278 基本资料 2021-09-01 11:24:37 +08:00
baladiwei bddc0f2f91 Merge pull request '改nopage的问题' (#34) from tongChong/forgeplus-react:feature_router into feature_router 2021-09-01 11:01:22 +08:00
何童崇 30a141c92e 修改nopage的问题 2021-09-01 10:58:38 +08:00
caishi 58115f8dae box 2021-09-01 10:28:11 +08:00
baladiwei 9655cd5105 Merge pull request 'router修改' (#33) from tongChong/forgeplus-react:feature_router into feature_router 2021-09-01 09:41:00 +08:00
何童崇 01b3ee8d49 修改projects路由 2021-09-01 09:33:22 +08:00
何童崇 662a758980 修改user/org路由时的bug 2021-08-30 17:42:13 +08:00
何童崇 0b64631222 合并镜像、权限、wiki修改 2021-08-30 10:39:09 +08:00
何童崇 eb02b814a9 修改user路由 2021-08-30 10:31:51 +08:00
baladiwei ca9a606e53 Merge pull request 'pre-release merge' (#29) from pre_develop_dev into pre_develop 2021-08-30 10:26:54 +08:00
baladiwei 8adf7f8de6 Merge pull request '优化日期显示' (#31) from tongChong/forgeplus-react:pre_develop_dev into pre_develop_dev 2021-08-27 16:33:43 +08:00
何童崇 349c2a6f35 修改返回日期的显示 2021-08-27 16:31:15 +08:00
baladiwei f096d6db6e Merge pull request '注释资源库,wiki修改显示' (#30) from tongChong/forgeplus-react:pre_develop_dev into pre_develop_dev 2021-08-27 16:10:00 +08:00
何童崇 492e8e067f 注释资源库,wiki修改显示 2021-08-27 16:07:21 +08:00
baladiwei 95ae2bbd46 Merge pull request '组织团队权限-测试通过版' (#28) from caishi/forgeplus-react:pre_develop into pre_develop_dev 2021-08-27 15:01:47 +08:00
caishi a1b5395b8c 合并请求-判断条件改成user_admin_or_member 2021-08-27 14:04:27 +08:00
caishi dee7b23f3e 转移到组织-提示文案 2021-08-27 11:44:41 +08:00
caishi f7dd67d41a merge 2021-08-27 10:54:55 +08:00
caishi e7fd980116 组织团队权限 2021-08-27 10:53:00 +08:00
caishi d8ab7c0759 权限问题测试版-第二版 2021-08-26 17:38:56 +08:00
caishi d64eb738f7 团队权限分支 2021-08-26 17:38:56 +08:00
jasder 55080f93c1 Merge pull request '镜像问题websocket失败兼容' (#27) from tongChong/forgeplus-react:hotfix_websocket into pre_develop_dev 2021-08-26 17:35:00 +08:00
何童崇 e606147d03 修改组织和首页的路由 2021-08-26 14:18:14 +08:00
caishi 7851785335 团队权限分支 2021-08-25 14:25:35 +08:00
何童崇 52e08e77e5 修改websocket问题 2021-08-25 11:52:52 +08:00
baladiwei fcac8c782a Merge pull request '组织团队(新增和设置)权限' (#21) from caishi/forgeplus-react:pre_develop into pre_develop_dev 2021-08-25 11:03:30 +08:00
caishi 061fa0ee71 组织团队设置:增加可选访问单元wiki 2021-08-24 16:25:55 +08:00
caishi 5d465ec782 组织团队设置:可以设置版本库权限,允许设置访问项目单元 2021-08-24 16:25:47 +08:00
baladiwei 39fef1ce3c Merge pull request '修改头像的bug,提取copyUrl组件,优化函数式模态框组件' (#20) from tongChong/forgeplus-react:feature_wikis into pre_develop_dev 2021-08-23 11:47:44 +08:00
何童崇 d1a3c7b9c3 优化删除函数组件 2021-08-23 09:41:57 +08:00
何童崇 ba263a28f1 修改头像,增加复制toolTip组件,优化组件代码 2021-08-20 14:45:16 +08:00
jasder fb872f3a3d change request url 2021-08-20 09:06:57 +08:00
何童崇 19ef012a0e 修改指向路径 2021-08-20 09:01:40 +08:00
jasder b3d62b9cf1 FIX bug 2021-08-19 21:54:56 +08:00
何童崇 d988c4ea5f 兼容页面刷新时的id新增 2021-08-19 21:23:48 +08:00
caishi 313f1edc71 镜像问题websocket传值
镜像问题websocket传值
2021-08-19 17:44:13 +08:00
caishi 8adc662e9b wiki功能分支合并
wiki功能分支合并
2021-08-19 17:31:36 +08:00
何童崇 ff75065a0a 新增wiki模块 2021-08-19 17:21:18 +08:00
何童崇 6e74f88d9e 紧急修复镜像bug 2021-08-19 10:40:44 +08:00
caishi 3294d99516 href 2021-08-09 11:03:49 +08:00
caishi 001cb8da53 issue 2021-08-06 15:06:23 +08:00
caishi d09e6e2bc6 issue 2021-08-06 14:07:59 +08:00
caishi e2ad3b1308 issue-同步镜像项目不能对仓库进行操作(新建合并请求、新建发行版等) 2021-08-05 17:13:57 +08:00
caishi 14f80d56ad Merge branch 'develop' of https://git.trustie.net/jasder/forgeplus-react into develop 2021-08-05 11:12:11 +08:00
caishi 65e7025035 Merge branch 'develop' of https://git.trustie.net/jasder/forgeplus-react into develop
# Conflicts:
#	src/forge/Main/sub/UpdateDescModal.jsx
2021-08-05 11:11:51 +08:00
hc1913847458 aa786f0cf0 限制字符 2021-08-05 10:57:43 +08:00
hc1913847458 2aad9c67f5 限制字符 2021-08-05 10:53:29 +08:00
hc1913847458 de636eed6d 限制字符 2021-08-05 10:42:08 +08:00
caishi 4bde5da97c markdown-issue 2021-08-05 10:30:04 +08:00
caishi f944ebad6f issue 2021-08-04 17:12:29 +08:00
caishi 5140bfbe77 issue修改 2021-08-03 17:37:14 +08:00
caishi affbe87dfd 新增流水线弹框z-index 2021-08-03 10:38:39 +08:00
caishi dd1beb3116 合并请求-已拒绝的不能编辑 2021-08-03 09:34:11 +08:00
caishi d67862156c update issue 2021-08-02 15:32:51 +08:00
caishi 47365c0bed webhook-修改一版 2021-08-02 10:35:36 +08:00
caishi b1ec068663 webhook自动填充 2021-07-30 20:13:34 +08:00
caishi 51d34a7667 同上-password-webhook 2021-07-30 17:35:53 +08:00
caishi 2b47c1ff9a 同上-修改bug 2021-07-30 17:02:44 +08:00
caishi f7698334ab webhook上线测试版-1 2021-07-30 15:06:32 +08:00
caishi f100875b0f ssh翻页 2021-07-26 09:38:21 +08:00
caishi 4f9f5649a9 设置模块-测试版第一版 2021-07-22 17:44:12 +08:00
caishi f90243243f 新建项目跳转后的地址 2021-07-21 10:09:48 +08:00
caishi 7a5db58a03 appconfig 2021-07-15 14:46:22 +08:00
caishi 0889ee69c5 未登录时:路由/不显示顶部和底部 2021-07-13 10:42:56 +08:00
caishi 876ee66a05 详情:复刻按钮不能连续点击 2021-07-13 09:58:08 +08:00
caishi cb514315a6 新建合并请求:切换目标分支或者源分支时不用调用check_can_merge接口 2021-07-12 18:22:36 +08:00
caishi c5b729038c 邀请码位置,页面整体的加载 2021-07-09 17:10:55 +08:00
caishi a6d713d1f6 代码库:增加文件类型submodule 不允许点击 2021-07-09 11:28:51 +08:00
caishi ee1217e171 本地版:replaceAll无替换时报错 2021-07-09 11:05:19 +08:00
caishi 967ff385aa 代码库根目录:点击readme文件的编辑按钮时要显示编辑状态 2021-07-07 11:16:07 +08:00
caishi e6e0546e27 permission有为空的情况 2021-07-06 14:40:23 +08:00
caishi 1bb339bfb1 新建:拥有者默认选中当前登录用户,默认路由 2021-07-06 11:54:57 +08:00
caishi 275b7d2015 数据为0时不显示 2021-07-05 20:35:29 +08:00
caishi 9e9e4c07bf 合并请求详情:发布合并请求者跳转链接错误 2021-07-05 15:04:17 +08:00
caishi f854d2164c 工作流-构建列表-头像地址错误 2021-07-02 18:18:49 +08:00
caishi e48628389e 镜像地址增加跳转链接 2021-07-02 15:35:43 +08:00
caishi 62b9abedbb index.html lang="zh-cN"禁止浏览器翻译 2021-07-01 16:45:47 +08:00
caishi f97ca92e41 update 2021-07-01 15:48:04 +08:00
caishi 84bbf5fd52 易修批量修改:非项目协作者不能操作 2021-07-01 13:56:09 +08:00
caishi ff60cf11e1 update issue 2021-06-30 10:43:22 +08:00
caishi 45f188e6f4 fork项目不能修改可见性(公有私有) 2021-06-29 17:29:35 +08:00
caishi 4b832f40c0 项目详情:顶部信息排版调整,修改显示bug 2021-06-29 14:03:53 +08:00
caishi 1cdf316852 合并请求:冲突文件的显示换行 2021-06-25 18:33:54 +08:00
caishi 79996bd185 权限:易修和合并请求的新建修改等操作权限 2021-06-25 18:21:31 +08:00
caishi 2d312b6176 路由:tree后面的参数branch内容含有/ 2021-06-25 14:10:13 +08:00
caishi bad4f79a0c 易修:批量删除和批量修改issue状态要更新数量 2021-06-22 10:22:00 +08:00
caishi fad42414dc 代码库:提交信息的显示和隐藏 2021-06-21 17:52:48 +08:00
caishi c10799b6d0 Merge branch 'develop_search' into develop 2021-06-21 10:00:35 +08:00
caishi cb95e50a82 代码库:从文件详情切换到文件列表时,上传文件和新建文件的按钮没有显示 2021-06-18 16:55:52 +08:00
caishi 5eaebd4e42 上传文件显示: ADD file via upload
创建新文件显示: Add 文件名
修改文件: Update 文件名
2021-06-18 14:23:46 +08:00
caishi e9badf0d7c 合并请求默认选中开启中的 2021-06-18 09:59:33 +08:00
caishi e72e817bb1 复刻自,如果是组织要跳转到组织界面 2021-06-17 16:28:27 +08:00
caishi b5835145f7 个人中心性别icon不显示 2021-06-17 11:38:53 +08:00
caishi d4e1b2f414 详情banner数量,显示开启中的数量,且执行关闭或者拒绝等修改状态的操作时要更新数量 2021-06-16 15:51:47 +08:00
caishi f4b3afde6a 项目详情和个人中心的项目列表,增加私有标识 2021-06-16 11:17:46 +08:00
caishi 5806f60491 右侧按钮-帮助弹框 2021-06-16 09:17:33 +08:00
caishi 8298aef72f forked from 文案 2021-06-15 11:36:42 +08:00
caishi 7ed8d1c8c3 合并全局搜索 2021-06-15 09:21:56 +08:00
何童崇 1d274985ca 解决冲突并提交 2021-06-11 19:03:17 +08:00
何童崇 71d1eb57cc 还原代理的配置 2021-06-11 17:51:54 +08:00
caishi 56434a9714 Merge branch 'draft' into develop 2021-06-11 17:21:27 +08:00
caishi 8b161630c3 添加成员--随便输入不存在的用户时的提示 2021-06-11 16:46:59 +08:00
何童崇 405053696c 修改头部搜索框高度和代理服务路径 2021-06-11 15:28:40 +08:00
caishi 3dffbce8d9 头部导航栏-搜索小改 2021-06-11 11:01:46 +08:00
caishi 63e9cfe394 项目邀请码-第一版测试版上线 2021-06-11 09:25:59 +08:00
何童崇 b38cdd4bb3 修改search校验,同页搜索问题 2021-06-10 17:05:49 +08:00
何童崇 681d0b17e3 修改搜索的功能及图标 2021-06-09 19:47:14 +08:00
caishi b5fa231adf 小修 2021-06-09 18:00:31 +08:00
caishi 39f0a165b6 issue 2021-06-09 18:00:09 +08:00
caishi 2157f2ffe5 merge 2021-06-09 18:00:06 +08:00
caishi 7c40f9be36 merge 冲突 2021-06-09 17:59:07 +08:00
caishi 93694594c4 冲突 2021-06-09 17:58:11 +08:00
caishi 32299252ad 详情+邀请码的显示 2021-06-09 17:37:04 +08:00
caishi a12ab04ec0 小修 2021-06-09 11:52:36 +08:00
何童崇 f93df6069c 修改搜索placeplaceholder 2021-06-08 16:08:58 +08:00
何童崇 ff2586f5b9 注释众包/帖子等tab 2021-06-08 16:05:32 +08:00
caishi b7613584f9 添加成员后要清除选中的成员 2021-06-08 15:09:52 +08:00
caishi 0b7d6ab5fd issue 2021-06-08 14:56:00 +08:00
caishi 3d764d3075 issue+新建组织-未登录没有弹出登录框 2021-06-08 10:44:44 +08:00
caishi 3cd51d1c72 修改-个人主页 2021-06-07 11:13:38 +08:00
caishi 40f8f5d872 数据统计三个时间筛选参数值必须是时间戳 2021-06-04 14:29:55 +08:00
caishi e185ae6484 同上+样式 2021-06-04 13:58:42 +08:00
caishi 0bfa7572a5 bug 2021-06-04 10:55:05 +08:00
caishi fd19a43168 修改资料+密码管理 2021-06-04 09:43:38 +08:00
何童崇 dd9c11dbd9 上传搜索的页面 2021-06-03 10:37:03 +08:00
何童崇 695d5e4f50 Merge remote-tracking branch 'upstream/develop' into dev-search 2021-06-03 10:01:51 +08:00
何童崇 b88c5b1faf 修改导航的搜索 2021-06-03 10:00:24 +08:00
caishi 975d49b80b 同上=issue修改 2021-06-02 18:22:29 +08:00
caishi 4b6592dfb3 同上-修改细节 2021-05-31 18:39:30 +08:00
caishi 1432afebfd 个人中心整体上线 2021-05-31 17:44:30 +08:00
caishi a9285f37e7 概览页数据绑定完成,只差数据统计页 2021-05-31 09:48:30 +08:00
caishi d41dce26b1 year 2021-05-28 17:02:54 +08:00
caishi 7bbda5f65d 概览+用户画像 2021-05-28 16:19:40 +08:00
caishi 0274cf84ee 上一版+update 2021-05-26 16:48:18 +08:00
caishi 8e419e63da 上一版-update 2021-05-26 16:00:55 +08:00
caishi 1378ba5c93 代码库-无默认分支时调用entries接口未传ref参数,+个人主页的三个echart 2021-05-26 15:25:21 +08:00
caishi ae9b48953e markdown定位问题 2021-05-25 10:05:14 +08:00
caishi 3453aa31eb readme下拉 2021-05-21 19:21:16 +08:00
caishi ebf75ed433 issue 2021-05-21 18:58:17 +08:00
caishi a1bd41795a 分享功能(仅微信)+ 合并请求增加状态的显示,合并请求详情增加(冲突情况下的提示) 2021-05-21 16:44:40 +08:00
caishi 09bf75c6c3 右侧按钮-帮助列表超出没有隐藏 2021-05-14 17:03:27 +08:00
caishi 70af7dae5f 右侧按钮-帮助和返回顶部 2021-05-14 14:37:59 +08:00
caishi d029840874 头部导航栏无logo是nav也要显示 2021-05-14 11:30:08 +08:00
caishi 303e06586e 新增icon+添加右侧的返回顶部等按钮(接口没有,先隐藏、需要合并到其它分支,上一个提交也一样) 2021-05-14 09:32:23 +08:00
caishi 7ccc1221ef style 2021-05-11 14:22:01 +08:00
caishi 6a6f0ca784 组件之间进行页面跳转时,滚动条未返回至顶部 2021-05-10 17:24:49 +08:00
caishi b70dd5928e details 2021-05-10 11:34:30 +08:00
caishi 202081bbeb 样式 2021-05-08 16:53:16 +08:00
caishi af8872176c 编辑合并请求-url地址错误 2021-05-08 14:24:02 +08:00
caishi 037a79de67 detail+同步镜像type=2的才不需要合并请求 2021-05-07 17:33:41 +08:00
caishi a408d435f3 统一项目简介、项目概览 2021-05-07 16:26:50 +08:00
caishi 016f7f1a7e 去掉Markdown代码块的间隔色、编号等+issue 2021-05-07 16:00:57 +08:00
caishi e7eceb5b23 issue-字符限制 2021-05-06 17:12:42 +08:00
caishi c28ae9adb3 Revert "设置所有标签的marginbottom为0"
This reverts commit 227b686046.
2021-05-06 15:15:02 +08:00
caishi 870fbaa2a9 新建项目-maxlength 2021-05-06 14:59:54 +08:00
caishi 227b686046 设置所有标签的marginbottom为0 2021-05-06 10:56:09 +08:00
caishi 582f7a39b3 代码库-提交描述未换行 2021-05-06 10:14:06 +08:00
caishi ac4b7542e2 撤销隐藏-资源库 2021-04-28 20:22:54 +08:00
caishi 3a3a0251aa Merge branch 'undo' into develop
# Conflicts:
#	src/forge/Component/SearchUser.jsx
2021-04-28 20:17:59 +08:00
caishi 2fcb645d42 04-28休假期修改issue --需合并至其它分支(合并请求相关) 2021-04-28 20:17:30 +08:00
caishi 93a53e2c7f 转移项目-bug 2021-04-27 18:44:40 +08:00
caishi 79d8f4e5ad 清空弹窗里的内容 2021-04-27 18:27:56 +08:00
caishi ae34240bfb 通知-跳转 2021-04-27 17:46:05 +08:00
caishi efaf0c29b5 不能修改组织账号 2021-04-27 17:24:48 +08:00
caishi 81ad2358f5 不能修改组织账号 2021-04-27 17:23:58 +08:00
caishi 605d5a047d merge undo 2021-04-27 17:15:07 +08:00
caishi 1474f5d3fe 转移项目-bug和修改需求 2021-04-27 17:12:00 +08:00
caishi 8d509f1473 组织地址、website的问题,可合并至develop 2021-04-27 17:11:37 +08:00
caishi 4ba63fd8fa 项目转移-转移权限 2021-04-27 13:50:05 +08:00
caishi e10f9893e0 组织团队-无数据显示错误 2021-04-27 09:46:39 +08:00
caishi 63d7045444 组织团队-无数据显示错误 2021-04-27 09:46:29 +08:00
caishi c0ddd6eaee 组织-项目列表显示name 2021-04-26 17:20:54 +08:00
caishi 0cdb491433 组织基本设置-正则和新建的页面不一致 2021-04-26 16:32:03 +08:00
caishi ac47ba1b29 组织基本设置-正则和新建的页面不一致 2021-04-26 16:31:26 +08:00
caishi 2bd6f9cb1e 组织-新增地址和网址的显示 2021-04-26 16:17:21 +08:00
caishi 0636e0a925 转移项目-修改1 2021-04-26 16:17:04 +08:00
caishi 631b05dfd6 代码库编辑文件-切换到其它目录后要重新将编辑状态改为显示状态 2021-04-26 15:00:31 +08:00
caishi 4e48b0b363 项目转移--整体数据绑定 2021-04-26 14:59:19 +08:00
caishi fb41baacc1 代码库编辑文件-切换到其它目录后要重新将编辑状态改为显示状态 2021-04-25 17:46:38 +08:00
caishi 09065383c1 转移项目-前端页面已画完 2021-04-25 17:38:47 +08:00
caishi c32e215b27 样式覆盖 2021-04-23 18:04:07 +08:00
305 changed files with 15427 additions and 6382 deletions

File diff suppressed because it is too large Load Diff

View File

@ -19,7 +19,8 @@ const getClientEnvironment = require("./env");
let publicPath = "/react/build/";
const publicUrl = publicPath.slice(0, -1);
const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== "false";
// const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== "false";
const shouldUseSourceMap = process.env.NODE_ENV !== "production";
const env = getClientEnvironment(publicPath);
// This is the production configuration.
@ -54,7 +55,8 @@ module.exports = {
},
bail: true,
mode: "production",
devtool: false, //测试版
// devtool: false, //测试版
devtool: shouldUseSourceMap?'source-map':false,
entry: [require.resolve("./polyfills"), paths.appIndexJs],
output: {
path: paths.appBuild,

600
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "forge",
"version": "0.1.0",
"version": "3.0.0",
"private": true,
"dependencies": {
"@monaco-editor/react": "^2.3.0",
@ -14,6 +14,7 @@
"babel-jest": "20.0.3",
"babel-loader": "7.1.2",
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"babel-polyfill": "^6.26.0",
"babel-preset-react-app": "^3.1.1",
"babel-runtime": "6.26.0",
"bizcharts": "^3.5.8",
@ -25,11 +26,13 @@
"code-prettify": "^0.1.0",
"codemirror": "^5.53.0",
"connected-react-router": "4.4.1",
"cross-env": "^7.0.3",
"css-loader": "^3.5.2",
"dompurify": "^2.0.15",
"dotenv": "4.0.0",
"dotenv-expand": "4.2.0",
"echarts": "^4.7.0",
"echarts": "^4.9.0",
"echarts-wordcloud": "^2.0.0",
"editor.md": "^1.5.0",
"eslint": "4.10.0",
"eslint-config-react-app": "^2.1.0",
@ -46,6 +49,7 @@
"install": "^0.12.2",
"jest": "20.0.4",
"js-base64": "^2.5.2",
"js2wordcloud": "^1.1.12",
"katex": "^0.11.1",
"lodash": "^4.17.15",
"loglevel": "^1.6.8",
@ -62,7 +66,7 @@
"postcss-loader": "2.0.8",
"promise": "8.0.1",
"prop-types": "^15.6.1",
"qrcode.react": "^1.0.0",
"qrcode.react": "^1.0.1",
"qs": "^6.9.3",
"quill": "^1.3.7",
"quill-delta-to-html": "^0.11.0",
@ -92,6 +96,7 @@
"react-resizable": "^1.10.1",
"react-router": "^4.2.0",
"react-router-dom": "^4.2.2",
"react-slick": "^0.28.1",
"react-split-pane": "^0.1.91",
"react-url-query": "^1.5.0",
"react-zmage": "^0.8.5-beta.31",
@ -99,9 +104,11 @@
"redux-thunk": "2.3.0",
"rsuite": "^4.3.4",
"sass-loader": "7.3.1",
"save-dev": "0.0.1-security",
"scroll-into-view": "^1.14.2",
"showdown": "^1.9.1",
"showdown-katex": "^0.8.0",
"slick-carousel": "^1.8.1",
"store": "^2.0.12",
"style-loader": "0.19.0",
"styled-components": "^4.4.1",
@ -117,7 +124,7 @@
},
"scripts": {
"start": "node --max_old_space_size=15360 scripts/start.js",
"build": "NODE_ENV=production node --max_old_space_size=15360 scripts/build.js",
"build": "cross-env NODE_ENV=production node --max_old_space_size=15360 scripts/build.js",
"test-build": "NODE_ENV=testBuild node --max_old_space_size=15360 scripts/build.js",
"pre-build": "NODE_ENV=preBuild node --max_old_space_size=15360 scripts/build.js",
"gen_stats": "NODE_ENV=production webpack --profile --config=./config/webpack.config.prod.js --json > stats.json",
@ -188,6 +195,7 @@
"babel-core": "^6.26.0",
"babel-plugin-import": "^1.13.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-polyfill": "^6.26.0",
"babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-2": "^6.24.1",
@ -198,6 +206,7 @@
"node-sass": "^4.12.0",
"optimize-css-assets-webpack-plugin": "^5.0.3",
"purgecss": "^2.1.2",
"react-json-view": "^1.21.3",
"reqwest": "^2.0.5",
"resize-observer-polyfill": "^1.5.1",
"terser-webpack-plugin": "^2.3.5",

File diff suppressed because one or more lines are too long

View File

@ -38,78 +38,6 @@
box-sizing: border-box;
}
.head-nav ul#header-nav li {
float: left;
height: 60px;
line-height: 60px;
margin-right: 30px;
cursor: pointer;
position: relative;
font-size: 16px
}
.head-nav ul#header-nav li a {
display: block;
height: 100%;
width: 100%;
color: #fff
}
.head-nav ul#header-nav li a:hover {
color: #cccccc;
}
.head-nav ul#header-nav li:last-child {
margin-right: 0px
}
.head-nav ul#header-nav li.active a {
color: #459be5 !important;
}
.head-nav ul#header-nav li.active p {
color: #459be5 !important;
}
.head-nav ul#header-nav li p:hover {
color: #cccccc;
}
.head-nav ul#header-nav li p {
display: block;
height: 100%;
width: 100%;
color: #fff
}
.head-nav ul#header-nav li.active div ul li a {
color: #000 !important;
}
.head-nav ul#header-nav li.active div ul li a:hover {
color: #FFF !important;
}
.head-nav ul#header-nav li.active ul li a {
color: #000 !important;
}
.head-nav ul#header-nav li.active ul li a:hover {
color: #FFF !important;
}
.head-nav ul#header-nav li.active:after {
content: '';
position: absolute;
left: 0px;
top: auto;
bottom: 10px;
right: auto;
height: 2px;
width: 14px;
background-color: #459be5;
}
.nav-img {
position: absolute;
top: 2px;

View File

@ -114,14 +114,6 @@ a:visited {
color: #898989;
}
a:hover {
color: #FF7500;
}
a:hover.fa {
color: #FF7500;
}
input,
textarea,
select {

View File

@ -97,10 +97,6 @@ a:visited {
color: #05101a;
}
a:hover {
color: #459be5;
}
ol,
ul,
li {

View File

@ -1,3 +1,4 @@
@charset "utf-8";
/* 头部 */
.header {
width: 100%;
@ -1271,7 +1272,7 @@ html body {
font-size: 14px;
line-height: 2.0;
background: #fafafa;
font-family: "微软雅黑", "宋体";
font-family: "Microsoft YaHei", "SimSun";
color: #05101a;
height: 100%;
position: relative;
@ -1307,6 +1308,7 @@ td,
span {
margin: 0;
padding: 0;
margin-bottom: 0px!important;
}
table,
@ -1363,10 +1365,6 @@ a:visited {
color: #05101a;
}
a:hover {
color: #459be5;
}
ol,
ul,
li {
@ -1473,7 +1471,7 @@ a.edu-txt-w80,
/*隐藏*/
.none {
display: none
display: none!important;
}
.block {
@ -1753,7 +1751,7 @@ a.decoration {
}
.mb15 {
margin-bottom: 15px;
margin-bottom: 15px!important;
}
.mb16 {
@ -2424,13 +2422,23 @@ input::-ms-clear {
.color-grey-c {
color: #ccc !important;
}
a.hoverLine:hover{
text-decoration: underline;
}
.color-grey-cd {
color: #cdcdcd !important;
}
.color-grey-d {
color: #ddd;
}
.color-grey-9 {
color: #999999 !important;
color: #333333 !important;
}
a:hover{
color: #466AFF !important;
}
.color-grey-98 {
@ -2452,7 +2460,7 @@ input::-ms-clear {
.color-grey-B3 {
color: #B3B3B3 !important;
}
`
.color-grey-B4 {
color: #B4B4B4 !important;
}
@ -2465,33 +2473,23 @@ input::-ms-clear {
a.color-grey-name:hover,
a.color-dark:hover,
a.color-grey-6:hover,
a.color-grey-3:hover {
color: #4cacff !important;
}
a.color-grey-9:hover,
a.color-grey-8:hover,
a.color-grey-c:hover {
color: #111C24 !important;
a.color-grey-3:hover,a.color-ooo:hover {
color: #2A61FF !important;
}
/*蓝色*/
.color-blue {
color: #4CACFF !important;
color: #2A61FF !important;
}
.color-blue-file {
color: #4598FA!important;
}
/* 绿色 */
.color-green-file{
color: #28BD6C;
}
/*主*/
.color-blue_4C {
color: #4CACFF !important;
}
a.color-blue:hover,
a.color-blue_4C:hover {
color: #459BE6 !important;
}
/*橙色*/
.color-orange {
@ -3409,7 +3407,7 @@ a.user_bluebg_btn {
}
.cdefault {
cursor: default
cursor: default!important;
}
@ -3584,42 +3582,6 @@ a.user_bluebg_btn {
margin-right: 5px;
}
/*-------------------个人主页:右侧提示区域--------------------------*/
.-task-sidebar {
position: fixed;
width: 40px;
height: 180px;
right: 0;
bottom: 80px;
z-index: 10;
}
.-task-sidebar div {
height: 40px;
line-height: 40px;
box-sizing: border-box;
width: 40px;
background: #4CACFF;
color: #fff;
font-size: 20px;
text-align: center;
margin-bottom: 5px;
border-radius: 4px;
}
.-task-sidebar div i {
color: #fff;
}
.-task-sidebar div i:hover {
color: #fff !important;
}
.gotop {
background-color: rgba(208, 207, 207, 0.5) !important;
padding: 0px !important;
}
/***** loading ******/
/*****载入中******/
@ -3944,11 +3906,21 @@ html>body #ajax-indicator {
max-height: 340px;
}/*头部导航条样式---2018-03-19--by-cs*/
.privateTag{
display: block;
padding:0px 6px;
border-radius: 12px;
border:1px solid #2FC25B;
height: 18px;
line-height: 18px;
font-size: 12px;
margin-left: 10px;
color: #2FC25B;
}
.head-nav {
text-align: center;
height: 70px;
box-sizing: border-box;
min-width: 780px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
@ -3970,7 +3942,7 @@ html>body #ajax-indicator {
cursor: pointer;
position: relative;
font-size: 16px;
padding:0px 20px;
padding-right:40px;
}
.head-nav ul#header-nav li a {
@ -6702,4 +6674,19 @@ 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;
}
.ant-input, .ant-input .ant-input-suffix{
background-color: #fff!important;
}
.has-error .ant-input{
background-color: #FEF1F0!important;
}

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,6 +5,874 @@
"css_prefix_text": "icon-",
"description": "",
"glyphs": [
{
"icon_id": "24378423",
"name": "项目标签",
"font_class": "xiangmubiaoqian",
"unicode": "e8da",
"unicode_decimal": 59610
},
{
"icon_id": "24368060",
"name": "icon",
"font_class": "icon",
"unicode": "e8ce",
"unicode_decimal": 59598
},
{
"icon_id": "24368061",
"name": "tar",
"font_class": "tar",
"unicode": "e8cf",
"unicode_decimal": 59599
},
{
"icon_id": "24289113",
"name": "复制 (2)",
"font_class": "a-fuzhi2",
"unicode": "e8d0",
"unicode_decimal": 59600
},
{
"icon_id": "24289114",
"name": "附件",
"font_class": "fujian1",
"unicode": "e8d1",
"unicode_decimal": 59601
},
{
"icon_id": "24289115",
"name": "编 辑",
"font_class": "a-bianji1",
"unicode": "e8d2",
"unicode_decimal": 59602
},
{
"icon_id": "24289116",
"name": "版本icon",
"font_class": "banbenicon",
"unicode": "e8d3",
"unicode_decimal": 59603
},
{
"icon_id": "24289117",
"name": "删除icon",
"font_class": "shanchuicon2",
"unicode": "e8d4",
"unicode_decimal": 59604
},
{
"icon_id": "24289118",
"name": "垃圾桶_icon@3x",
"font_class": "a-lajitong_icon3x",
"unicode": "e8d5",
"unicode_decimal": 59605
},
{
"icon_id": "24289119",
"name": "下拉按钮",
"font_class": "xialaanniu2",
"unicode": "e8d6",
"unicode_decimal": 59606
},
{
"icon_id": "24289120",
"name": "下载-icon",
"font_class": "xiazai-icon",
"unicode": "e8d7",
"unicode_decimal": 59607
},
{
"icon_id": "24289121",
"name": "master_icon",
"font_class": "master_icon1",
"unicode": "e8d8",
"unicode_decimal": 59608
},
{
"icon_id": "24289122",
"name": "上传icon",
"font_class": "shangchuanicon",
"unicode": "e8d9",
"unicode_decimal": 59609
},
{
"icon_id": "24059956",
"name": "个人资料",
"font_class": "gerenziliao1",
"unicode": "e8c7",
"unicode_decimal": 59591
},
{
"icon_id": "24059409",
"name": "里程碑icon",
"font_class": "lichengbeiicon",
"unicode": "e885",
"unicode_decimal": 59525
},
{
"icon_id": "24059410",
"name": "仓库设置icon",
"font_class": "cangkushezhiicon",
"unicode": "e889",
"unicode_decimal": 59529
},
{
"icon_id": "24059411",
"name": "动态icon",
"font_class": "dongtaiicon",
"unicode": "e88a",
"unicode_decimal": 59530
},
{
"icon_id": "24059412",
"name": "工作流icon",
"font_class": "gongzuoliuicon",
"unicode": "e88b",
"unicode_decimal": 59531
},
{
"icon_id": "24059413",
"name": "易修icon",
"font_class": "yixiuicon1",
"unicode": "e89b",
"unicode_decimal": 59547
},
{
"icon_id": "24059414",
"name": "wiki icon",
"font_class": "a-wikiicon1",
"unicode": "e8c6",
"unicode_decimal": 59590
},
{
"icon_id": "24047186",
"name": "代码库icon",
"font_class": "daimakuicon1",
"unicode": "e8c5",
"unicode_decimal": 59589
},
{
"icon_id": "24047189",
"name": "我的通知",
"font_class": "wodetongzhi",
"unicode": "e8c8",
"unicode_decimal": 59592
},
{
"icon_id": "24047190",
"name": "通知管理",
"font_class": "tongzhiguanli",
"unicode": "e8c9",
"unicode_decimal": 59593
},
{
"icon_id": "24047191",
"name": "选中",
"font_class": "xuanzhong3",
"unicode": "e8ca",
"unicode_decimal": 59594
},
{
"icon_id": "24047192",
"name": "系统通知icon",
"font_class": "xitongtongzhiicon",
"unicode": "e8cb",
"unicode_decimal": 59595
},
{
"icon_id": "24047193",
"name": "消息",
"font_class": "xiaoxi2",
"unicode": "e8cc",
"unicode_decimal": 59596
},
{
"icon_id": "24047194",
"name": "ssh密钥",
"font_class": "sshmiyue",
"unicode": "e8cd",
"unicode_decimal": 59597
},
{
"icon_id": "24014152",
"name": "个人资料",
"font_class": "gerenziliao",
"unicode": "e8c4",
"unicode_decimal": 59588
},
{
"icon_id": "23655968",
"name": "新手指引",
"font_class": "xinshouzhiyin",
"unicode": "e8e4",
"unicode_decimal": 59620
},
{
"icon_id": "23655969",
"name": "新建项目",
"font_class": "xinjianxiangmu",
"unicode": "e8e6",
"unicode_decimal": 59622
},
{
"icon_id": "23658111",
"name": "加入课堂",
"font_class": "jiaruketang1",
"unicode": "e8e9",
"unicode_decimal": 59625
},
{
"icon_id": "23791639",
"name": "项目公告",
"font_class": "xiangmugonggao",
"unicode": "e8c2",
"unicode_decimal": 59586
},
{
"icon_id": "23791640",
"name": "成果",
"font_class": "chengguo",
"unicode": "e8c3",
"unicode_decimal": 59587
},
{
"icon_id": "23791410",
"name": "成交公告",
"font_class": "chengjiaogonggao",
"unicode": "e8c0",
"unicode_decimal": 59584
},
{
"icon_id": "23791411",
"name": "技术资产",
"font_class": "jishuzichan",
"unicode": "e8c1",
"unicode_decimal": 59585
},
{
"icon_id": "23790928",
"name": "废标公告",
"font_class": "feibiaogonggao",
"unicode": "e8bc",
"unicode_decimal": 59580
},
{
"icon_id": "23790929",
"name": "中标公告",
"font_class": "zhongbiaogonggao",
"unicode": "e8bd",
"unicode_decimal": 59581
},
{
"icon_id": "23790930",
"name": "更正公告",
"font_class": "gengzhenggonggao",
"unicode": "e8be",
"unicode_decimal": 59582
},
{
"icon_id": "23790931",
"name": "招标公告",
"font_class": "zhaobiaogonggao",
"unicode": "e8bf",
"unicode_decimal": 59583
},
{
"icon_id": "23732532",
"name": "文件",
"font_class": "wenjian6",
"unicode": "e8ba",
"unicode_decimal": 59578
},
{
"icon_id": "23732533",
"name": "文件夹",
"font_class": "wenjianjia4",
"unicode": "e8bb",
"unicode_decimal": 59579
},
{
"icon_id": "23642443",
"name": "取消关注",
"font_class": "quxiaoguanzhu",
"unicode": "e89a",
"unicode_decimal": 59546
},
{
"icon_id": "23642444",
"name": "点赞_icon",
"font_class": "dianzan_icon",
"unicode": "e8a2",
"unicode_decimal": 59554
},
{
"icon_id": "23639530",
"name": "文件",
"font_class": "wenjian5",
"unicode": "e896",
"unicode_decimal": 59542
},
{
"icon_id": "23639533",
"name": "文件夹",
"font_class": "wenjianjia3",
"unicode": "e8a9",
"unicode_decimal": 59561
},
{
"icon_id": "23639440",
"name": "复制icon",
"font_class": "fuzhiicon",
"unicode": "e886",
"unicode_decimal": 59526
},
{
"icon_id": "23639422",
"name": "主页-fill",
"font_class": "zhuye-fill",
"unicode": "e876",
"unicode_decimal": 59510
},
{
"icon_id": "23639423",
"name": "代码库icon",
"font_class": "daimakuicon",
"unicode": "e884",
"unicode_decimal": 59524
},
{
"icon_id": "23572260",
"name": "新建",
"font_class": "xinjian2",
"unicode": "e8b0",
"unicode_decimal": 59568
},
{
"icon_id": "23567674",
"name": "协议icon",
"font_class": "xieyiicon",
"unicode": "e870",
"unicode_decimal": 59504
},
{
"icon_id": "23567675",
"name": "内存icon",
"font_class": "neicunicon",
"unicode": "e891",
"unicode_decimal": 59537
},
{
"icon_id": "23567676",
"name": "自述文件_icon",
"font_class": "zishuwenjian_icon",
"unicode": "e8a6",
"unicode_decimal": 59558
},
{
"icon_id": "23472253",
"name": "标签icon",
"font_class": "biaoqianicon",
"unicode": "e882",
"unicode_decimal": 59522
},
{
"icon_id": "23472254",
"name": "编 辑",
"font_class": "a-bianji",
"unicode": "e883",
"unicode_decimal": 59523
},
{
"icon_id": "23472258",
"name": "链接icon",
"font_class": "lianjieicon",
"unicode": "e887",
"unicode_decimal": 59527
},
{
"icon_id": "23472259",
"name": "合并请求icon",
"font_class": "hebingqingqiuicon",
"unicode": "e888",
"unicode_decimal": 59528
},
{
"icon_id": "23472263",
"name": "默认点赞_icon",
"font_class": "morendianzan_icon",
"unicode": "e88e",
"unicode_decimal": 59534
},
{
"icon_id": "23472265",
"name": "目录icon",
"font_class": "muluicon",
"unicode": "e894",
"unicode_decimal": 59540
},
{
"icon_id": "23472267",
"name": "设 置",
"font_class": "a-shezhi",
"unicode": "e899",
"unicode_decimal": 59545
},
{
"icon_id": "23472269",
"name": "提交icon",
"font_class": "tijiaoicon",
"unicode": "e89e",
"unicode_decimal": 59550
},
{
"icon_id": "23472270",
"name": "默认关注_ICON",
"font_class": "morenguanzhu_ICON",
"unicode": "e89f",
"unicode_decimal": 59551
},
{
"icon_id": "23472272",
"name": "下拉按钮",
"font_class": "xialaanniu1",
"unicode": "e8a4",
"unicode_decimal": 59556
},
{
"icon_id": "23472276",
"name": "左滑icon",
"font_class": "zuohuaicon",
"unicode": "e8b5",
"unicode_decimal": 59573
},
{
"icon_id": "23472277",
"name": "master_icon",
"font_class": "master_icon",
"unicode": "e8b6",
"unicode_decimal": 59574
},
{
"icon_id": "23472278",
"name": "默认复刻_icon",
"font_class": "morenfuke_icon",
"unicode": "e8b7",
"unicode_decimal": 59575
},
{
"icon_id": "23472279",
"name": "wiki icon",
"font_class": "a-wikiicon",
"unicode": "e8b8",
"unicode_decimal": 59576
},
{
"icon_id": "23472280",
"name": "易修icon",
"font_class": "yixiuicon",
"unicode": "e8b9",
"unicode_decimal": 59577
},
{
"icon_id": "23436350",
"name": "缩放",
"font_class": "suofang",
"unicode": "e87f",
"unicode_decimal": 59519
},
{
"icon_id": "23436351",
"name": "放大icon",
"font_class": "fangdaicon",
"unicode": "e881",
"unicode_decimal": 59521
},
{
"icon_id": "23384231",
"name": "搜索_icon",
"font_class": "sousuo_icon1",
"unicode": "e873",
"unicode_decimal": 59507
},
{
"icon_id": "23384232",
"name": "欢迎_icon",
"font_class": "huanying_icon",
"unicode": "e878",
"unicode_decimal": 59512
},
{
"icon_id": "23384233",
"name": "文件夹",
"font_class": "wenjianjia2",
"unicode": "e879",
"unicode_decimal": 59513
},
{
"icon_id": "23384234",
"name": "删除icon",
"font_class": "shanchuicon1",
"unicode": "e87a",
"unicode_decimal": 59514
},
{
"icon_id": "23261798",
"name": "请求icon",
"font_class": "qingqiuicon",
"unicode": "e871",
"unicode_decimal": 59505
},
{
"icon_id": "23261799",
"name": "响应icon",
"font_class": "xiangyingicon",
"unicode": "e87c",
"unicode_decimal": 59516
},
{
"icon_id": "23144143",
"name": "多选选中",
"font_class": "duoxuanxuanzhong",
"unicode": "e88f",
"unicode_decimal": 59535
},
{
"icon_id": "23144144",
"name": "错误icon",
"font_class": "cuowuicon",
"unicode": "e890",
"unicode_decimal": 59536
},
{
"icon_id": "23144146",
"name": "成功icon",
"font_class": "chenggongicon",
"unicode": "e892",
"unicode_decimal": 59538
},
{
"icon_id": "23144147",
"name": "未选中响应icon",
"font_class": "weixuanzhongxiangyingicon",
"unicode": "e893",
"unicode_decimal": 59539
},
{
"icon_id": "23144149",
"name": "必填icon",
"font_class": "bitianicon",
"unicode": "e895",
"unicode_decimal": 59541
},
{
"icon_id": "23144151",
"name": "未选中项目标签icon",
"font_class": "weixuanzhongxiangmubiaoqianicon",
"unicode": "e897",
"unicode_decimal": 59543
},
{
"icon_id": "23144152",
"name": "列表icon",
"font_class": "liebiaoicon",
"unicode": "e898",
"unicode_decimal": 59544
},
{
"icon_id": "23144158",
"name": "协作者管理icon",
"font_class": "xiezuozheguanliicon",
"unicode": "e8a1",
"unicode_decimal": 59553
},
{
"icon_id": "23144160",
"name": "选中分支icon",
"font_class": "xuanzhongfenzhiicon",
"unicode": "e8a3",
"unicode_decimal": 59555
},
{
"icon_id": "23144162",
"name": "选中基本设置icon",
"font_class": "xuanzhongjibenshezhiicon",
"unicode": "e8a5",
"unicode_decimal": 59557
},
{
"icon_id": "23144165",
"name": "选中项目标签icon",
"font_class": "xuanzhongxiangmubiaoqianicon",
"unicode": "e8aa",
"unicode_decimal": 59562
},
{
"icon_id": "23144167",
"name": "选中webhook icon",
"font_class": "a-xuanzhongwebhookicon",
"unicode": "e8af",
"unicode_decimal": 59567
},
{
"icon_id": "23046290",
"name": "shanchu_tc_icon",
"font_class": "shanchu_tc_icon",
"unicode": "e88c",
"unicode_decimal": 59532
},
{
"icon_id": "23046293",
"name": "wiki_icon",
"font_class": "wiki_icon",
"unicode": "e88d",
"unicode_decimal": 59533
},
{
"icon_id": "23046244",
"name": "导入模版_icon",
"font_class": "daorumoban_icon",
"unicode": "e86f",
"unicode_decimal": 59503
},
{
"icon_id": "23046252",
"name": "错误",
"font_class": "cuowu",
"unicode": "e872",
"unicode_decimal": 59506
},
{
"icon_id": "23046255",
"name": "更多_icon",
"font_class": "gengduo_icon",
"unicode": "e874",
"unicode_decimal": 59508
},
{
"icon_id": "23046258",
"name": "复层关闭_icon",
"font_class": "fucengguanbi_icon",
"unicode": "e875",
"unicode_decimal": 59509
},
{
"icon_id": "23046268",
"name": "删除icon",
"font_class": "shanchuicon",
"unicode": "e877",
"unicode_decimal": 59511
},
{
"icon_id": "23046273",
"name": "搜索_删除icon",
"font_class": "sousuo_shanchuicon",
"unicode": "e87b",
"unicode_decimal": 59515
},
{
"icon_id": "23046275",
"name": "搜索_icon",
"font_class": "sousuo_icon",
"unicode": "e87d",
"unicode_decimal": 59517
},
{
"icon_id": "23046276",
"name": "文档预览_icon",
"font_class": "wendangyulan_icon",
"unicode": "e87e",
"unicode_decimal": 59518
},
{
"icon_id": "23046278",
"name": "下拉按钮",
"font_class": "xialaanniu",
"unicode": "e880",
"unicode_decimal": 59520
},
{
"icon_id": "22906287",
"name": "二次确认_icon",
"font_class": "erciqueren_icon",
"unicode": "e867",
"unicode_decimal": 59495
},
{
"icon_id": "22906288",
"name": "选中ssh_icon",
"font_class": "xuanzhongssh_icon",
"unicode": "e868",
"unicode_decimal": 59496
},
{
"icon_id": "22906289",
"name": "未选中安全设置_icon",
"font_class": "weixuanzhonganquanshezhi_icon",
"unicode": "e869",
"unicode_decimal": 59497
},
{
"icon_id": "22906290",
"name": "未选中ssh_icon",
"font_class": "weixuanzhongssh_icon",
"unicode": "e86a",
"unicode_decimal": 59498
},
{
"icon_id": "22906291",
"name": "选中安全设置_icon",
"font_class": "xuanzhonganquanshezhi_icon",
"unicode": "e86b",
"unicode_decimal": 59499
},
{
"icon_id": "22906292",
"name": "删除_icon",
"font_class": "shanchu_icon",
"unicode": "e86c",
"unicode_decimal": 59500
},
{
"icon_id": "22906293",
"name": "列表ssh_icon",
"font_class": "liebiaossh_icon",
"unicode": "e86e",
"unicode_decimal": 59502
},
{
"icon_id": "17575494",
"name": "file-submodule",
"font_class": "file-submodule",
"unicode": "e866",
"unicode_decimal": 59494
},
{
"icon_id": "7539612",
"name": "nv",
"font_class": "nv1",
"unicode": "e864",
"unicode_decimal": 59492
},
{
"icon_id": "7539613",
"name": "nan",
"font_class": "nan1",
"unicode": "e865",
"unicode_decimal": 59493
},
{
"icon_id": "21936935",
"name": "邮箱",
"font_class": "youxiang",
"unicode": "e8b2",
"unicode_decimal": 59570
},
{
"icon_id": "21936924",
"name": "单位",
"font_class": "danwei",
"unicode": "e8a7",
"unicode_decimal": 59559
},
{
"icon_id": "21936925",
"name": "待办事项",
"font_class": "daibanshixiang",
"unicode": "e8a8",
"unicode_decimal": 59560
},
{
"icon_id": "21936928",
"name": "概览",
"font_class": "gailan",
"unicode": "e8ab",
"unicode_decimal": 59563
},
{
"icon_id": "21936929",
"name": "男",
"font_class": "nan",
"unicode": "e8ac",
"unicode_decimal": 59564
},
{
"icon_id": "21936930",
"name": "女",
"font_class": "nv",
"unicode": "e8ad",
"unicode_decimal": 59565
},
{
"icon_id": "21936931",
"name": "工作流",
"font_class": "gongzuoliu1",
"unicode": "e8ae",
"unicode_decimal": 59566
},
{
"icon_id": "21936934",
"name": "数据统计",
"font_class": "shujutongji",
"unicode": "e8b1",
"unicode_decimal": 59569
},
{
"icon_id": "21936936",
"name": "项目",
"font_class": "xiangmu",
"unicode": "e8b3",
"unicode_decimal": 59571
},
{
"icon_id": "21936937",
"name": "组织",
"font_class": "zuzhi",
"unicode": "e8b4",
"unicode_decimal": 59572
},
{
"icon_id": "14835599",
"name": "右箭头",
"font_class": "arrowRight",
"unicode": "e863",
"unicode_decimal": 59491
},
{
"icon_id": "21151489",
"name": "箭头镂空-左",
"font_class": "jiantouloukong-zuo",
"unicode": "e861",
"unicode_decimal": 59489
},
{
"icon_id": "21151557",
"name": "箭头镂空-右",
"font_class": "jiantouloukong-you",
"unicode": "e862",
"unicode_decimal": 59490
},
{
"icon_id": "21568989",
"name": "分享",
"font_class": "fenxiang1",
"unicode": "e89c",
"unicode_decimal": 59548
},
{
"icon_id": "21568990",
"name": "回到顶部",
"font_class": "huidaodingbu1",
"unicode": "e89d",
"unicode_decimal": 59549
},
{
"icon_id": "21568993",
"name": "帮助",
"font_class": "bangzhu",
"unicode": "e8a0",
"unicode_decimal": 59552
},
{
"icon_id": "991344",
"name": "提交",
@ -4236,7 +5104,7 @@
{
"icon_id": "1004630",
"name": "点赞2",
"font_class": "dianzan1",
"font_class": "dianzaned",
"unicode": "e639",
"unicode_decimal": 58937
},

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 733 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
public/favicon.ico Executable file → Normal file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -1,5 +1,5 @@
<!DOCTYPE html>
<html lang="en">
<html lang="zh-CN" class="notranslate translated-ltr" translate="no">
<head>
<meta charset="utf-8">
<meta name=”Keywords” Content=”trustie,trustieforge,forge,确实让创建更美好,协同开发平台″>

View File

@ -3319,9 +3319,9 @@
text = text.replace(emailReg, function ($1, $2, $3, $4) {
return $1.replace(/@/g, "_#_&#64;_#_");
});
// " + editormd.urls.atLinkBase + "" + $2 + "
text = text.replace(atLinkReg, function ($1, $2) {
return "<a href=\"" + editormd.urls.atLinkBase + "" + $2 + "\" title=\"&#64;" + $2 + "\" class=\"at-link\">" + $1 + "</a>";
return "<span title=\"&#64;" + $2 + "\" class=\"at-link\"> " + $1 + " </span>";
}).replace(/_#_&#64;_#_/g, "@");
}

View File

@ -60,12 +60,13 @@ body {
.ant-progress-textno {
color: #f5222d;
}
.CodeMirror pre.CodeMirror-line{
font-size: 16px!important;
}
/* md多空格 */
.markdown-body p {
margin:10px 0px!important;
font-size: 16px !important;
line-height: 2 !important;
white-space: pre-wrap;
}
@ -87,6 +88,10 @@ body {
border-left: 1px solid rgb(221, 221, 221);
/* 某些情况下被cm盖住了 */
z-index: 99;
padding:8px 8px 50px;
}
.editormd-preview .markdown-body{
padding:0px !important;
}
/* 图片点击放大的场景,隐藏图片链接 */

View File

@ -3,7 +3,7 @@ import './App.css';
import { ConfigProvider } from 'antd'
import zhCN from 'antd/lib/locale-provider/zh_CN';
import {
BrowserRouter as Router,
// BrowserRouter as Router,
Route,
Switch
} from 'react-router-dom';
@ -17,10 +17,9 @@ import marked from './common/marked';
import moment from 'moment'
import { MuiThemeProvider, createMuiTheme } from 'material-ui/styles';
import SiderBar from './forge/Component/SiderBar'
import history from './history';
import { SnackbarHOC } from 'educoder'
import { SnackbarHOC } from 'educoder';
import { initAxiosInterceptors } from './AppConfig'
import { Provider } from 'react-redux';
import configureStore from './redux/stores/configureStore';
@ -40,6 +39,16 @@ const Projects = Loadable({
loader: () => import('./forge/Index'),
loading: Loading,
})
// forge项目详情
const ProjectDetail = Loadable({
loader: () => import("./forge/Main/DetailAdaptor"),
loading: Loading,
});
//forge安全设置
const Security = Loadable({
loader: () => import('./forge/SecuritySetting/Index'),
loading: Loading,
})
//forge项目-devOps详情
const OpsDetail = Loadable({
loader: () => import('./forge/DevOps/opsDetail'),
@ -74,6 +83,27 @@ const EducoderLogin = Loadable({
loader: () => import('./modules/login/EducoderLogin'),
loading: Loading,
})
const Search = Loadable({
loader: () => import('./modules/search/'),
loading: Loading,
})
const WikiPreview = Loadable({
loader: () => import('./forge/Wiki/Preview'),
loading: Loading,
})
const ProjectIndex = Loadable({
loader: () => import("./forge/Index"),
loading: Loading,
});
const CreateMerge = Loadable({
loader: () => import('./forge/Merge/NewMerge'),
loading: Loading,
})
// 此处仅维护前端可能的一级路由,不用进行项目或者组织判断的字段。
const keyWord = ["explore", "settings", "setting", "mulan", "wiki", "issues", "setting", "trending", "code", "projects", "pulls", "mine", "login", "register", "email", "export", "nopage", "404", "403", "500", "501", "search", "organize"];
class App extends Component {
constructor(props) {
@ -84,6 +114,51 @@ class App extends Component {
mydisplay: false,
occupation: 0,
mygetHelmetapi: null,
pathType: null,
pathName: null,
}
}
UNSAFE_componentWillMount() {
initAxiosInterceptors(this.props);
let pathname = window.location.pathname ? window.location.pathname.split('/')[1] : '';
pathname && this.getPathnameType(pathname);
// 添加路由监听,决定组织还是个人
this.unlisten = this.props.history.listen((location) => {
let newPathname = location.pathname.split('/')[1];
if (this.state.pathName !== newPathname) {
// this.setState({ pathType: '' });
newPathname && this.getPathnameType(newPathname);
}
});
}
shouldComponentUpdate(nextProps, nextState) {
// (!keyWord.includes(this.props.location.pathname.split('/')[1])) &&
if (nextProps.location.pathname.split('/')[1] !== this.props.location.pathname.split('/')[1] && nextState.pathType === this.state.pathType) {
return false;
} else {
return true;
}
}
getPathnameType = (pathname) => {
if (!keyWord.includes(pathname)) {
let url = `/owners/${pathname}.json`;
axios.get(url).then((response) => {
if (response && response.status === 200) {
this.setState({
pathType: response.data.type || '404',
pathName: pathname,
})
}
});
}else{
this.setState({
pathType: pathname,
pathName: pathname,
});
}
}
@ -100,43 +175,22 @@ class App extends Component {
Addcoursestypes: false
})
};
ModalCancelsy = () => {
this.setState({
mydisplay: false,
})
window.location.href = "/";
};
ModalshowCancelsy = () => {
this.setState({
mydisplay: true,
})
};
disableVideoContextMenu = () => {
window.$("body").on("mousedown", "video", function (event) {
if (event.which === 3) {
window.$('video').bind('contextmenu', function () { return false; });
} else {
window.$('video').unbind('contextmenu');
}
});
}
componentDidMount() {
document.title = "loading...";
this.disableVideoContextMenu();
history.listen(() => {
this.forceUpdate()
const $ = window.$
$("html").animate({ scrollTop: $('html').scrollTop() - 0 })
});
initAxiosInterceptors(this.props);
this.getAppdata();
window.addEventListener('error', (event) => {
const msg = `${event.type}: ${event.message}`;
});
}
componentWillUnmount() {
this.unlisten && this.unlisten(); // 执行解绑
}
//修改登录方法
Modifyloginvalue = () => {
this.setState({
@ -207,69 +261,139 @@ class App extends Component {
};
render() {
const { mygetHelmetapi, pathType} = this.state;
let personal = mygetHelmetapi && mygetHelmetapi.personal;
return (
<Provider store={store}>
<ConfigProvider locale={zhCN}>
<MuiThemeProvider theme={theme}>
<LoginDialog {...this.props} {...this.state} Modifyloginvalue={() => this.Modifyloginvalue()}></LoginDialog>
<Router>
<Switch>
{/*项目*/}
<Route
path={"/projects/:owner/:projectId/devops/:opsId/detail"}
render={
(props) => {
return (<OpsDetail {...this.props} {...props} {...this.state} />)
}
}>
</Route>
{/*项目*/}
<Route
path={"/projects"}
render={
(props) => {
return (<Projects {...this.props} {...props} {...this.state} />)
}
}>
</Route>
<Route
path="/register"
render={
(props) => {
return (<EducoderLogin {...this.props} {...props} {...this.state} />)
}
}
/>
{/*403*/}
<Route path="/403" component={Shixunauthority} />
<SiderBar />
{/* <Router> */}
<Switch>
{/* wiki预览 */}
<Route path="/:owner/:projectsId/wiki/preview/:projectName/:projectId" render={
(props) => {
return (<WikiPreview {...this.props} {...props} {...this.state} />)
}
} />
<Route path="/500" component={http500} />
<Route path={"/organize"}
render={
(props) => {
return (<OrganizeIndex {...props} {...this.props} {...this.state} />)
}
}>
</Route>
{/*404*/}
<Route path="/nopage" component={Shixunnopage} />
{/* 个人主页 */}
<Route path="/users/:username"
render={
(props) => {
return (<InfosIndex {...this.props} {...this.state} />)
}
}></Route>
<Route exact path="/"
render={
(props) => (
<Projects {...this.props} {...props} {...this.state}></Projects>
)
{/* 项目PR */}
<Route path="/:owner/:projectsId/pulls/new"
render={
(props) => (<ProjectDetail {...this.props} {...props} {...this.state} />)
}
></Route>
{/*项目*/}
<Route
path={"/:owner/:projectId/devops/:opsId/detail"}
render={
(props) => {
return (<OpsDetail {...this.props} {...props} {...this.state} />)
}
/>
<Route component={Shixunnopage} />
</Switch>
</Router>
}>
</Route>
<Route
path={"/settings"}
render={
(props) => {
return (<Security {...this.props} {...props} {...this.state} />)
}
}>
</Route>
<Route
path="/register"
render={
(props) => {
return (<EducoderLogin {...this.props} {...props} {...this.state} />)
}
}
/>
{/*403*/}
<Route path="/403" component={Shixunauthority} />
<Route path="/500" component={http500} />
{/*404*/}
<Route path="/nopage" component={Shixunnopage} />
{/* 查询 */}
<Route path="/search" component={Search} />
<Route exact path="/explore"
render={
(props) => (
<ProjectIndex {...this.props} {...props} />
)
}
/>
{/* 组织 */}
<Route path={"/organize"}
render={
(props) => {
return (<OrganizeIndex {...props} {...this.props} {...this.state} />)
}
}>
</Route>
{/*新建项目等*/}
<Route
path={"/projects"}
render={
(props) => {
return (<Projects {...this.props} {...props} {...this.state} />)
}
}>
</Route>
{/* 判断为用户/组织,并进入对应页面 */}
{
pathType === 'User' ?
<Route exact path="/:username"
render={
(props) => {
return (<InfosIndex {...this.props} {...this.state} />)
}
}
/> : pathType === 'Organization' ? <Route path={"/:OIdentifier"}
render={
(props) => {
return (<OrganizeIndex {...props} {...this.props} {...this.state} />)
}
}>
</Route> : pathType === '404' ? <Route component={Shixunnopage} />:
<Route exact path="/"
render={
(props) => (
personal && personal.length > 0 ?
<InfosIndex {...this.props} {...props} />
:
<ProjectIndex {...this.props} {...props} />
)
}
/>
// <Route path="/" component={Loading} />
// <Route path="/" component={Shixunnopage} />
}
{/* 个人主页 */}
<Route path="/:username"
render={
(props) => {
return (<InfosIndex {...this.props} {...this.state} />)
}
}></Route>
<Route component={Shixunnopage} />
</Switch>
{/* </Router> */}
</MuiThemeProvider>
</ConfigProvider>
</Provider>

View File

@ -58,7 +58,7 @@ export function initAxiosInterceptors(props) {
},
err => {
return Promise.reject(err);
});
});
axios.interceptors.response.use(function (response) {
if (response === undefined) {
@ -85,7 +85,10 @@ export function initAxiosInterceptors(props) {
}
if (response.data.status === 404) {
locationurl('/nopage');
let responseURL = response.request ? response.request.responseURL:'';
if (responseURL.indexOf('/api/users/') === -1 && responseURL.indexOf('/api/organizations/') === -1 ) {
locationurl('/nopage');
}
}
if (response.data.status === 500) {

View File

@ -9,20 +9,7 @@ class Loading extends Component {
}
render() {
return (
<div className="App" style={{ minHeight: '800px', width: "100%" }}>
<style>
{
`
.margintop{
margin-top:20%;
}
`
}
</style>
<Spin size="large" className={"margintop"} />
</div>
);
return ""
}
}

View File

@ -195,7 +195,7 @@ class College extends Component {
align: 'center',
className: "edu-txt-center font-14 maxnamewidth105",
render: (text, record) => (
<a href={`/users/${record.login}`} title={record.name} target="_blank" className="task-hide maxnamewidth105" style={{
<a href={`/${record.login}`} title={record.name} target="_blank" className="task-hide maxnamewidth105" style={{
color:'#007bff',
}}> {

View File

@ -218,7 +218,7 @@ a:hover {
}
.color-blue {
color: #4CACFF;
color: #2A61FF;
}
.color-huang {

View File

@ -1,4 +1,5 @@
import moment from "moment";
import { number } from "prop-types";
// 处理整点 半点
// 取传入时间往后的第一个半点
@ -97,3 +98,41 @@ export function formatDuring(mss){
}
return days + "天" + hours + "小时" + minutes + "分";
}
/*
返回多久以前
backDate以前的某个日期
*/
export function timeAgo(backDate) {
try {
moment(backDate);
} catch (e) {
return '刚刚';
}
if(typeof backDate ==='number'){
backDate=backDate*1000
}else{
backDate= moment(backDate);
}
let time = new Date() - backDate;
var days = Math.floor(time / (1000 * 60 * 60 * 24));
var hours = Math.floor((time % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
var minutes = Math.floor((time % (1000 * 60 * 60)) / (1000 * 60));
var seconds = Math.floor((time % (1000 * 60 * 60)) / 1000);
if (time <= 0) {
return "刚刚";
}
if (days) {
return days + "天前";
}
if (hours) {
return hours + "小时前";
}
if (minutes) {
return minutes + "分前";
}
if (seconds) {
return seconds + "秒前";
}
return "刚刚";
}

View File

@ -18,6 +18,23 @@ export function getImageUrl(path) {
return `${path}`;
}
export function numFormat(num, digits){
let d = digits || 1;
var si = [
{ value: 1, symbol: "" },
{ value: 1E3, symbol: "k" },
{ value: 1E4, symbol: "W" }
];
var rx = /\.0+$|(\.[0-9]*[1-9])0+$/;
var i;
for (i = si.length - 1; i > 0; i--) {
if (num >= si[i].value) {
break;
}
}
return (num / si[i].value).toFixed(d).replace(rx, "$1") + si[i].symbol;
}
export function getImage(path) {
// https://www.educoder.net
// https://testbdweb.trustie.net

View File

@ -3,7 +3,7 @@
// export { default as OrderStateUtil } from '../routes/Order/components/OrderStateUtil';
export {
getUploadLogoActionUrl as getUploadLogoActionUrl,
getUploadLogoActionUrl as getUploadLogoActionUrl,numFormat as numFormat,
getImageUrl as getImageUrl,getImage as getImage, getmyUrl as getmyUrl, getRandomNumber as getRandomNumber, getUrl as getUrl, publicSearchs as publicSearchs, getRandomcode as getRandomcode, getUrlmys as getUrlmys, getUrl2 as getUrl2, setImagesUrl as setImagesUrl
, getUploadActionUrl as getUploadActionUrl, getUploadActionUrltwo as getUploadActionUrltwo, getUploadActionUrlthree as getUploadActionUrlthree, getUploadActionUrlOfAuth as getUploadActionUrlOfAuth
, getTaskUrlById as getTaskUrlById, TEST_HOST, htmlEncode as htmlEncode, getupload_git_file as getupload_git_file, getcdnImageUrl as getcdnImageUrl
@ -27,7 +27,7 @@ export {
markdownToHTML, uploadNameSizeSeperator, appendFileSizeToUploadFile, appendFileSizeToUploadFileAll, isImageExtension,
downloadFile, sortDirections, validateLength, mdJSONParse, exportMdtoHtml
} from './TextUtil'
export { handleDateString, getNextHalfHourOfMoment, formatDuring, formatSeconds } from './DateUtil'
export { handleDateString, getNextHalfHourOfMoment, formatDuring, formatSeconds ,timeAgo} from './DateUtil'
export { configShareForIndex, configShareForPaths, configShareForShixuns, configShareForCourses, configShareForCustom } from './util/ShareUtil'

View File

@ -46,18 +46,18 @@ export default ({
let id = decodeURIComponent(u.split("#")[1]);
let ele = document.getElementById(id);
if(ele){
window.scrollTo(0, ele.offsetTop + 220);
window.scrollTo(0, ele.offsetTop + 120);
}
}
}
},[url])
},[url,html])
const el = useRef();
function onAncherHandler(e) {
let target = e.target
let target = e.target;
if (target.tagName.toUpperCase() === 'A') {
let ancher = target.getAttribute('href')
if (ancher.startsWith('#')) {
let ancher = target.getAttribute('href');
if (ancher && ancher.startsWith('#')) {
e.preventDefault()
let viewEl = document.getElementById(ancher.replace('#', ''))
if (viewEl) {

View File

@ -435,11 +435,11 @@ class TPIContextProvider extends Component {
image_url: "avatars/User/1"
login: "innov"
name: "Coder"
user_url: "/users/innov"
user_url: "/innov"
*/
let user = resData.user;
user.username = resData.user.name;
user.user_url = `/users/${resData.user.login}`;
user.user_url = `/${resData.user.login}`;
// user.image_url = resData.image_url;
user.is_teacher = resData.is_teacher;
resData.user = user;

View File

@ -69,7 +69,7 @@ function Index(props){
<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>
<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>
{
@ -117,7 +117,7 @@ function Index(props){
{content ?
<RenderHtml className="break_word_comments imageLayerParent" value={content} url={props.history.location}/>
:
<div>暂无简介~</div>
<div>暂无概览~</div>
}
{attachments && attachments.length > 0 &&
<Attachments

View File

@ -1,7 +1,7 @@
import React , { Component } from 'react';
import { Dropdown , Menu , Icon , Pagination , Spin } from 'antd';
import '../css/index.scss';
import '../Branch/branch.css';
import '../Branch/branch.scss';
import './activity.css';
import NoneData from '../Nodata';

View File

@ -14,25 +14,25 @@ class ActivityItem extends Component {
{/* 如果是版本发布 */}
{item.trend_type === "VersionRelease" ?
<p className="itemLine">
<Link to={`/projects/${owner}/${projectsId}/version`} className="color-blue font-16">{item.name}</Link>
<Link to={`/${owner}/${projectsId}/releases`} className="color-blue font-16">{item.name}</Link>
<span className="activity_type">{item.trend_type}</span>
</p >
:
// 如果是任务
item.trend_type === "Issue" ?
<p className="itemLine">
<Link to={`/projects/${owner}/${projectsId}/issues/${item.trend_id}/detail`} className="color-blue font-16">{item.name}</Link>
<Link to={`/${owner}/${projectsId}/issues/${item.trend_id}`} className="color-blue font-16">{item.name}</Link>
<span className="activity_type">{item.trend_type}</span>
</p >
:
// 如果是合并请求
<p className="itemLine">
<Link to={`/projects/${owner}/${projectsId}/pulls/${item.trend_id}/Messagecount`} className="color-blue font-16">{item.name}</Link>
<Link to={`/${owner}/${projectsId}/pulls/${item.trend_id}/Messagecount`} className="color-blue font-16">{item.name}</Link>
<span className="activity_type">{item.trend_type}</span>
</p >
}
<p className="itemLine mt10">
<Link to={`/users/${item && item.user_login}`} className="show-user-link">
<Link to={`/${item && item.user_login}`} className="show-user-link">
<img alt="" src={getImageUrl(`/${item.user_avatar}`)} className="createImage" />
<span className="mr20">{item.user_name}</span>
</Link>

View File

@ -1,39 +1,27 @@
import React, { Component } from 'react';
import { Dropdown, Icon, Tooltip } from 'antd';
import "./branch.css";
import React, { useState } from 'react';
import { Menu } from 'antd';
import "./branch.scss";
import CopyTool from '../Component/CopyTool';
class CloneAddress extends Component {
// 点击按钮复制功能
jsCopy = () => {
var e = document.getElementById("copy_rep_content");
e.select();
document.execCommand("Copy");
}
render() {
const { http_url, downloadUrl } = this.props;
return (
<div className="gitAddressClone">
{/* <p className="addressTips"><span>版本库地址已变更,请基于新地址提交代码</span></p> */}
{
http_url && <span>HTTP</span>
}
<input type="text" id="copy_rep_content" value={http_url} />
<Tooltip title="复制链接">
<span className="color-blue" onClick={() => this.jsCopy()}><i className="iconfont icon-fuzhi"></i></span>
</Tooltip>
{
downloadUrl &&
<span>
<Dropdown overlay={downloadUrl} trigger={['click']} placement="bottomRight">
<a className="ant-dropdown-link">
<Icon type="cloud-download" className="font-18 fl color-blue" />
</a>
</Dropdown>
</span>
}
function CloneAddress({http_url , ssh_url , zip_url , tar_url}) {
const [ key , setKey ] = useState("HTTP");
return (
<div className="downMenu">
<div style={{borderBottom:"1px solid #eee"}}>
<Menu className="urlMenu" selectedKeys={[key]} mode={"horizontal"}>
<Menu.Item key="HTTP" onClick={(e)=>{setKey(e.key)}}>HTTP</Menu.Item>
<Menu.Item key="SSH" onClick={(e)=>{setKey(e.key)}}>SSH</Menu.Item>
</Menu>
<div className="gitAddressClone">
<input type="text" id="copy_rep_content" value={key==="HTTP" ? http_url:ssh_url} />
<CopyTool inputId="copy_rep_content" className="copytool"/>
</div>
</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>
)
}
export default CloneAddress;

View File

@ -1,116 +1,36 @@
import React , { useState , useEffect } from 'react';
import { Popover , Input , Spin } from 'antd';
import './branch.css';
import { Popover , Dropdown , Input , Spin } from 'antd';
import './branch.scss';
import { getBranch , getTag } from '../GetData/getData';
import SelectOverlay from './SelectOverlay';
export default (({ projectsId , branch , owner , changeBranch , branchList , tagflag = true })=>{
const [ showValue , setShowValue ] = useState(branch);
const [ inputValue , setInputValue] = useState(undefined);
const [ nav , setNav ] = useState(0);
const [ isSpin , setIsSpin ] = useState(true);
const [ flag , setFlag ] = useState(false);
const [ data , setData ] = useState(undefined);
const [ datas , setDatas ] = useState(undefined);
useEffect(()=>{
setShowValue(branch);
},[branch])
useEffect(()=>{
document.body.addEventListener('click', e => {
let name = e.target.className;
let turn = name === "ant-input OptionsInput" || name === "navli active"|| name === "navli" || name === "padding10 bor-bottom-greyE";
if(turn){
return;
}else{
setFlag(false);
}
})
})
useEffect(()=>{
if(branchList){
setData(branchList);
setDatas(branchList);
setIsSpin(false);
}
},[branchList])
async function getBranchs(id,owner){
let result = await getBranch(id,owner);
setData(result);
setDatas(result);
setIsSpin(false);
}
async function getTags(id,owner){
let result = await getTag(id,owner);
setData(result);
setDatas(result);
setIsSpin(false);
}
function changeInputValue(e){
setInputValue(e.target.value);
let filter = e.target.value ? data && data.length>0 && data.filter(item=>item.name.indexOf(e.target.value)>-1) : data;
setDatas(filter);
}
function changeNav(nav){
setNav(nav);
setIsSpin(true);
if(nav === 0){
getBranchs(projectsId,owner);
}else{
getTags(projectsId,owner);
}
}
function chooseitem(value){
// setShowValue(value);
changeBranch(value);
}
const menu = (
<div>
<div className="padding10 bor-bottom-greyE">
<Input
placeholder="请输入分支或标签名称搜索"
autocomplete="off" className="OptionsInput" value={inputValue}
onChange={changeInputValue} style={{width:"220px"}}
/>
<ul className="navUl">
<li className={nav === 0?"navli active":"navli"} onClick={()=>changeNav(0)}><i className="iconfont icon-fenzhi1 font-14 mr3"></i>分支列表</li>
{ tagflag && <li className={nav === 1?"navli active":"navli"} onClick={()=>changeNav(1)}><i className="iconfont icon-biaoqian3 font-14 mr3"></i>标签列表</li> }
</ul>
</div>
<Spin spinning={isSpin}>
<ul className="OptionsUl" id="ul-btn">
{
datas && datas.length>0 ?
datas.map((item,key)=>{
return(
<li key={key} onClick={()=>chooseitem(item.name)}><a className="task-hide ulALink">{item.name}</a></li>
)
}):
<p className="listTips">暂无{inputValue}{nav === 0 ?"分支":"标签"}~</p>
}
</ul>
</Spin>
</div>
<SelectOverlay
changeBranch={changeBranch}
tagflag={tagflag}
projectsId={projectsId}
owner={owner}
branchList={branchList}
/>
);
return(
<Popover placement='bottomLeft' visible={flag} content={menu} onClick={()=>setFlag(!flag)} overlayClassName="branch-tagBox-list">
<Dropdown placement='bottomLeft' overlay={menu} overlayClassName="branch-tagBox-list" trigger={['click']} >
<div className="branch-tagBox">
{/* {nav === 0 ?"分支":"标签"} */}
<span className="color-grey-9 mr3 ml8"><i className="iconfont icon-fenzhi2 font-18"></i></span>
<a className="ant-dropdown-link">
<span className="ant-dropdown-link task-hide" style={{fontWeight:"500"}}>
{showValue}
</a>
<i className="showtag iconfont icon-xiajiantou font-14 color-grey-9 mr8" />
</span>
<i className="showtag iconfont icon-sanjiaoxing-down font-15 color-grey-9 mr5 ml5 mt1" />
</div>
</Popover>
</Dropdown>
)
})

View File

@ -0,0 +1,84 @@
import React , { useState , useEffect } from 'react';
import { Input , Spin , Menu } from 'antd';
import { getBranch , getTag } from '../GetData/getData';
function SelectOverlay({ changeBranch , tagflag , branchList , projectsId , owner }) {
const [ inputValue , setInputValue] = useState(undefined);
const [ nav , setNav ] = useState(0);
const [ isSpin , setIsSpin ] = useState(true);
const [ data , setData ] = useState(undefined);
const [ datas , setDatas ] = useState(undefined);
const [ keys ,setKeys] = useState("branch");
useEffect(()=>{
if(branchList){
setData(branchList);
setDatas(branchList);
setIsSpin(false);
}
},[branchList])
async function getBranchs(id,owner){
let result = await getBranch(id,owner);
setData(result);
setDatas(result);
setIsSpin(false);
}
async function getTags(id,owner){
let result = await getTag(id,owner);
setData(result);
setDatas(result);
setIsSpin(false);
}
function chooseitem(value){
changeBranch(value);
}
function changeInputValue(e){
setInputValue(e.target.value);
let filter = e.target.value ? data && data.length>0 && data.filter(item=>item.name.indexOf(e.target.value)>-1) : data;
setDatas(filter);
}
function changeNav(e){
setKeys(e.key);
setIsSpin(true);
if(e.key === "branch"){
getBranchs(projectsId,owner);
}else{
getTags(projectsId,owner);
}
}
return(
<div className="overlayBranch">
<div className="padding15" style={{paddingBottom:"0px"}}>
<Input
prefix={<i className="iconfont icon-sousuo_icon1 font-14"></i>}
placeholder="请输入分支或标签名称搜索"
autocomplete="off" className="OptionsInput"
value={inputValue}
onChange={changeInputValue}
/>
</div>
<Menu mode="horizontal" className="navUl" selectedKeys={[keys]} onClick={changeNav}>
<Menu.Item key={"branch"}>分支</Menu.Item>
{ tagflag && <Menu.Item key={"tag"}>标签</Menu.Item> }
</Menu>
<Spin spinning={isSpin}>
<ul className="OptionsUl" id="ul-btn">
{
datas && datas.length>0 ?
datas.map((item,key)=>{
return(
<li key={key} onClick={()=>chooseitem(item.name)}><a className="task-hide ulALink">{item.name}</a></li>
)
}):
<p className="listTips">暂无{inputValue}{nav === 0 ?"分支":"标签"}~</p>
}
</ul>
</Spin>
</div>
)
}
export default SelectOverlay;

View File

@ -1,84 +0,0 @@
.branchDropdown{
border:1px solid #eee;
border-radius: 4px;
display: flex;
justify-content: center;
height: 40px;
line-height: 40px;
min-width: 220px;
}
.branchDropdown .ant-dropdown-trigger{
width: 100%;
padding:0px 15px;
display: flex;
justify-content: space-between;
align-items: center;
cursor: pointer;
}
.branchOptions{
width: 220px;
box-shadow: 0px 0px 3px 1px rgba(134, 134, 134, 0.4);
border-radius: 3px;
background: #fff;
max-height: 300px;
}
.OptionsUl{
max-height: 220px;
overflow-y: auto;
}
.OptionsUl li{
height: 35px;
line-height: 35px;
cursor: pointer;
padding:0px 10px;
}
.OptionsUl li:hover{
background-color: #F0F0F0;
}
.OptionsUl li a{
display: block;
}
.OptionsInput{
height: 32px;
padding-left: 4px;
line-height: 32px;
width: 100%;
}
.branch-tagBox{
border:1px solid #eee;
border-radius: 3px;
height: 40px;
display: flex;
align-items: center;
cursor: pointer;
min-width: 140px;
}
.branch-tagBox-list .ant-popover-arrow{
display: none;
}
.branch-tagBox-list.ant-popover.ant-popover-placement-bottom{
padding-top:0px;
}
.branch-tagBox .ant-dropdown-link{
display: block;
flex:1;
}
.branch-tagBox-list .ant-popover-inner-content{
padding:0px;
}
.navUl{
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 5px;
}
.navUl li{
cursor: pointer;
}
.navUl li.active{
color:#5091FF;
}
.listTips{
padding:20px 0px;
text-align: center;
}

View File

@ -0,0 +1,121 @@
.branchDropdown{
border:1px solid #eee;
border-radius: 4px;
display: flex;
justify-content: center;
height: 40px;
line-height: 40px;
min-width: 220px;
}
.branchDropdown .ant-dropdown-trigger{
width: 100%;
padding:0px 15px;
display: flex;
justify-content: space-between;
align-items: center;
cursor: pointer;
}
.branchOptions{
width: 220px;
box-shadow: 0px 0px 3px 1px rgba(134, 134, 134, 0.4);
border-radius: 3px;
background: #fff;
max-height: 300px;
}
.OptionsUl{
max-height: 220px;
overflow-y: auto;
}
.OptionsUl li{
height: 30px;
line-height: 30px;
cursor: pointer;
padding:0px 20px;
margin:5px 0px;
}
.OptionsUl li:hover{
background-color: #F0F0F0;
}
.OptionsUl li a{
display: block;
}
.OptionsInput{
height: 32px;
padding-left: 4px;
line-height: 32px;
width: 100%;
}
.branch-tagBox{
border:1px solid #D0D0D0;
border-radius: 3px;
height: 32px;
display: flex;
align-items: center;
cursor: pointer;
min-width: 104px;
}
.branch-tagBox:hover{
background-color: #F3F4F6;
}
.branch-tagBox-list{
background: #FFFFFF;
box-shadow: 0px 4px 8px 2px rgba(212, 212, 212, 0.5);
border-radius: 4px;
.ant-popover-arrow{
display: none;
}
&.ant-popover.ant-popover-placement-bottom{
padding-top:0px;
}
.branch-tagBox .ant-dropdown-link{
display: block;
flex:1;
max-width: 105px;
}
.ant-popover-inner-content{
padding:0px;
}
}
.overlayBranch{
width: 325px;
.navUl{
margin-top: 8px;
height: 30px;
line-height: 30px;
li{
height: 30px;
line-height: 30px;
padding:0px 5px;
margin-left: 20px!important;
}
}
}
.listTips{
padding:20px 0px;
text-align: center;
}
.urlMenu{
line-height: 30px;
margin-bottom: 10px;
padding:15px 20px 0px 20px;
border-bottom: none;
li.ant-menu-item{
height: 30px;
line-height: 30px;
padding:0px 5px;
margin-right: 20px!important;
&.ant-menu-item-selected,&.ant-menu-item-active{
color: #333;
}
&.ant-menu-item-selected{
border-color:#1890ff!important;
}
&.ant-menu-item-active{
border-color:transparent ;
}
}
}
.copytool{
margin:0px 10px;
}

View File

@ -55,6 +55,7 @@ function AddGroup({organizeId,getGroupID}){
function addCollaborator(){
getGroupID && getGroupID(id);
setID(undefined);
}
return(

View File

@ -4,7 +4,7 @@ import axios from 'axios';
import { getImageUrl } from 'educoder';
const { Option } = AutoComplete;
function AddMember({getID,login}){
function AddMember({getID,login,showNotification}){
const [ id , setID ] = useState(undefined);
const [ source , setSource ] = useState(undefined);
const [ searchKey , setSearchKey ] = useState(undefined);
@ -45,7 +45,7 @@ function AddMember({getID,login}){
src={getImageUrl(`/${item && item.image_url}`)}
alt=""
/>
<span className="ml10" style={{ "vertical-align": "middle" }}>
<span className="ml10" style={{ verticalAlign: "middle" }}>
{item.username}
<span className="color-grey ml10">({item.login})</span>
</span>
@ -66,7 +66,12 @@ function AddMember({getID,login}){
};
function addCollaborator(){
getID && getID(id);
if(source && source.length>0){
getID && getID(id);
setSearchKey(undefined);
}else{
showNotification("请选择存在的用户!");
}
}
return(

View File

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

View File

@ -113,7 +113,14 @@ li.ant-menu-item{
z-index: 10000;
}
.laterest{
color: #05690d;
background-color: #EF3131;
color: #fff;
font-size: 12px;
margin-left: 10px;
padding:0px 5px;
border-radius: 2px;
height: 18px;
line-height: 18px;
}
@media screen and (max-width: 1800px){
@ -155,41 +162,280 @@ li.ant-menu-item{
margin:0px 20px!important;
}
}
.hoverA{
display:flex;
align-items: center;
max-width: 78px;
&:hover a{
color:#2A61FF !important ;
}
}
.menuPanels{
width: 240px;
height: 180px;
width: 295px;
.leftline{
position: relative;
color: #666;
height: 16px;
margin-left: 14px;
font-size: 12px;
&::before{
position: absolute;
left: -7px;
top:3px;
height: 12px;
width: 1px;
background-color: #999;
content: "";
}
}
.ant-btn{
height: 36px;
line-height: 34px;
width: 83px;
text-align: center;
padding:0px ;
font-weight: 500;
font-size: 14px;
&.currentBtn{
cursor: default;
color: #333;
&:hover{
color: #333;
border-color: #d0d0d0;
}
}
}
.ant-btn-default{
color: #333;
border-color: #d0d0d0;
&:hover{
background: #F3F4F6;
}
}
.ant-btn{
width: 102px;
height: 32px;
line-height: 30px;
}
.ant-btn-primary{
color: #fff;
background-color: #466AFF;
border:none;
&:hover{
background-color: rgba(70,106,255,0.85);
}
}
.focusPanelHeadInfo{
padding:14px 16px;
border-bottom: 1px solid #eee;
}
.ant-popover-content,.ant-popover-inner{
height: 100%;
width: 100%;
}
.ant-popover-inner-content{
padding:0px;
}
}
.halfs{
margin-top: 24px;
padding:24px 0px 0px 0px;
border-top: 1px solid #e8e8e8;
.attrPerson{
padding-bottom: 24px;
}
}
.aboutSubTitle{
display: flex;
align-items: center;
}
.menuMaininfos{
padding:10px 16px 14px;
border-bottom: 1px solid #eee;
}
.menuinfos{
padding:15px 0px;
padding:10px 20px 16px;
&>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;
font-size: 16px;
font-weight: 500;
color: #333;
line-height: 22px;
}
& >span:last-child{
color: #666;
}
&:last-child{
border-right: none;
font-weight: 400;
line-height: 20px;
margin-top: 6px;
}
}
}
}
/*-------------------个人主页:右侧提示区域--------------------------*/
.-task-sidebar {
position: fixed;
width: 40px;
right: 0;
bottom: 80px;
z-index: 10;
}
@media screen and (max-width: 1920px){
.-task-sidebar{
right:220px;
}
}
@media screen and (max-width: 1750px){
.-task-sidebar{
right:160px;
}
}
@media screen and (max-width: 1650px){
.-task-sidebar{
right:115px;
}
}
@media screen and (max-width: 1550px){
.-task-sidebar{
right:90px;
}
}
@media screen and (max-width: 1450px){
.-task-sidebar{
right:45px;
}
}
@media screen and (max-width: 1200px){
.-task-sidebar{
right:0px;
display: none;
}
}
.-task-sidebar>div {
height: 40px;
line-height: 40px;
box-sizing: border-box;
width: 40px;
color: #999;
font-size: 20px;
text-align: center;
margin-bottom: 20px;
border-radius: 50%;
background: #FFFFFF;
box-shadow: 0px 0px 10px 1px #F1F1F1;
}
.-task-sidebar>div i {
color: #999;
}
.-task-sidebar>div:hover i {
color: #fff !important;
}
.-task-sidebar>div:hover{
background: #1890FF;
box-shadow: 0px 0px 10px 2px #B6D0FC;
}
.helpBox{
width: 260px;
z-index: 103;
&.shareContent{
width: 200px;
}
.ant-popover-inner-content{
padding:0px;
}
p.titlecontent{
font-size: 18px;
color: #333;
line-height: 20px;
padding:15px 20px;
}
.faqUl{
padding:0px 20px 10px;
max-height: 230px;
overflow-y: auto;
li{
background: #F5F5F5;
border-radius: 20px;
padding:0px 20px;
color: #333;
height: 34px;
line-height: 34px;
margin-bottom: 10px;
a{
display: block;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
&:hover{
background-color: #D1E9FF;
a{
color: #333!important;
}
}
}
}
.shareUl{
padding:10px 0px;
display: flex;
align-items: center;
.titlecontent{
margin-right: 20px;
}
li > i{
font-size: 32px!important;
}
}
}
.-task-desc {
background: #494949;
width: 90px;
line-height: 36px;
text-align: center;
position: absolute;
color: #fff;
font-size: 13px;
z-index: 999999;
opacity: 0;
}
.-task-desc div {
position: absolute;
top: 10px;
right: -7px;
height: 13px;
}
.-task-desc div img {
float: left
}
.-task-sidebar .scan_ewm {
position: absolute !important;
right: 45px !important;
bottom: 0px !important;
background-color: #494949 !important;
-webkit-box-sizing: border-box !important;
box-sizing: border-box !important;
font-size: 14px !important;
line-height: 16px !important;
display: none;
height: 213px !important;
}
.trangle_right {
position: absolute;
right: -5px;
bottom: 15px;
width: 0;
height: 0px;
border-top: 6px solid transparent;
border-left: 5px solid #494949;
border-bottom: 6px solid transparent
}

View File

@ -1,13 +1,13 @@
import React, { useEffect, useState } from 'react';
import { AlignCenter , FlexAJ } from '../Component/layout';
import { Link } from 'react-router-dom';
import { Popover , Spin } from 'antd';
import { Popover , Spin , Button } from 'antd';
import { getImageUrl } from 'educoder';
import './Component.scss';
import { getUser } from '../GetData/getData';
import axios from 'axios';
function Contributors({contributors,owner,projectsId}){
function Contributors({contributors,owner,projectsId,currentLogin}){
const [ menuList ,setMenuList ]= useState([]);
const [ list , setList ]= useState(undefined);
const [ total , setTotal ]= useState(0);
@ -46,46 +46,60 @@ function Contributors({contributors,owner,projectsId}){
}
}
function renderOrganize(list) {
let str = "";
list.map(i=>{
str = str+i.name + "、";
})
return str && str.substr(0,str.length - 1);
}
function setMenusFunc(data){
if(data){
let ele = (
<Spin spinning={isSpin}>
<FlexAJ>
<FlexAJ className="menuMaininfos">
<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)}
<Link to={`/${data.login}`}><img src={getImageUrl(`/${data.image_url}`)} alt="" className="radius" width="38px" height="38px"/></Link>
<div className="ml10">
<Link to={`/${data.login}`}>{data.name}</Link>
{ data.location && <span className="leftline">{data.location}</span> }
{
data.organizations && data.organizations.length>0&&
<p className="task-hide" style={{maxWidth:"215px"}}>
所属组织{renderOrganize(data.organizations)}
</p>
}
</div>
</AlignCenter>
:""
}
{
data.location && <AlignCenter className="font-12 pt4 pb4"><span>所在地址:</span><span className="ml5">{data.location}</span></AlignCenter>
}
</FlexAJ>
<AlignCenter className="menuinfos">
<Link to={`/${data.login}/projects`}>
<span>{data.projects_count}</span>
<span>项目数</span>
</Link>
<Link to={`/${data.login}/followers`}>
<span>{data.followers_count}</span>
<span>粉丝数</span>
</Link>
<Link to={`/${data.login}/following`}>
<span>{data.following_count}</span>
<span>关注数</span>
</Link>
</AlignCenter>
<div className={"pb20"} style={{display:"flex",justifyContent:'center'}}>
{
currentLogin && (currentLogin === data.login)
?
<Button className="currentBtn">当前用户</Button>
:
data.is_watch ?
<Button type={"default"} onClick={()=>FocusFunc(false,data.login)}>已关注</Button>
:
<Button type={"primary"} onClick={()=>FocusFunc(true,data.login)}>关注TA</Button>
}
</div>
</Spin>
)
setMenu(ele);
@ -135,17 +149,17 @@ function Contributors({contributors,owner,projectsId}){
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>
<Link to={`/${owner}/${projectsId}/contribute`} className="font-16 color-ooo hoverA">
<span>贡献者</span>
{ contributors && contributors.total_count > 0 && <span className="infoCount">{contributors.total_count}</span>}
</Link>
<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}`}>
<Link key={key} to={`/${item.login}`}>
<img src={getImageUrl(`/${item.image_url}`)} alt="" onMouseOver={()=>setVisibleFunc(true,item.login,key)}/>
</Link>
</Popover>

View File

@ -0,0 +1,51 @@
import React, { useState, useCallback, memo } from 'react';
import { Tooltip } from 'antd';
CopyTool.defaultProps = {
beforeText: '复制链接', //
afterText: '复制成功', //
className: '', //svgclass
inputId: 'copyText', //ID
timeOut:true, //beforeText
};
function CopyTool({ beforeText, afterText, className , inputId , timeOut }) {
const [title, setTitle] = useState(() => {
return beforeText;
});
//
const copyUrl = useCallback(() => {
const copyEle = document.querySelector(`#${inputId}`); //
if (!copyEle) {
console.error("您的CopyTool未设置正确的inputId");
return;
}
copyEle.select(); //
if (document.execCommand('copy')) {
document.execCommand('copy');
}
document.getSelection().removeAllRanges();
setTitle(afterText);
if(timeOut){
setTimeout(function(){
setTitle(beforeText);
},1500)
}
}, []);
return (
<Tooltip
placement="top"
title={title}
onVisibleChange={() => { setTitle(beforeText) }}
>
<i className={`iconfont icon-fuzhiicon ${className}`} style={{ color: '#466aff' }} onClick={copyUrl}></i>
</Tooltip>
);
}
export default memo(CopyTool);

View File

@ -0,0 +1,33 @@
import React from 'react';
import { AlignCenter } from '../layout';
import { Button } from 'antd';
import Modals from '../PublicModal/Index';
function DeleteBox({
visible ,
onCancel ,
onSuccess ,
title ,
subTitle,
content
}) {
return(
<Modals
title={title}
btn={
<div>
<Button size={'large'} onClick={onCancel}>取消</Button>
<Button type={"danger"} size={"large"} onClick={onSuccess}>确认删除</Button>
</div>
}
onCancel={onCancel}
visible={visible}
>
<div className="desc">
<AlignCenter className="descMain"><i className="iconfont icon-shanchu_tc_icon mr10"></i>{content}</AlignCenter>
<p>{subTitle}</p>
</div>
</Modals>
)
}
export default DeleteBox;

View File

@ -4,6 +4,12 @@ import './Component.scss';
import axios from 'axios';
const { TreeNode , DirectoryTree } = Tree;
function turnbar(str){
if(str && str.length>0 && str.indexOf("/")>-1){
return str.replaceAll('/','%2F');
}
return str;
}
function DrawerPanel({visible,onClose,branch,owner,projectsId,history, name , list}){
const [ treeData , setTreeData ] = useState(undefined);
const [ isSpin , setIsSpin ] = useState(true);
@ -71,7 +77,8 @@ function DrawerPanel({visible,onClose,branch,owner,projectsId,history, name , li
let dataref = event.node.props.dataRef;
if(dataref.type==="file"){
onClose();
history.push(`/projects/${owner}/${projectsId}/tree/${branch}/${dataref.path}`);
let value = turnbar(branch);
history.push(`/${owner}/${projectsId}/tree/${value}/${dataref.path}`);
}
}

View File

@ -1,9 +1,6 @@
.ant-modal-mask{
z-index: 10000;
z-index: 1031;
}
.ant-modal-wrap{
z-index: 10001;
.ant-form-explain{
position: absolute;
}
z-index: 1032;
}

View File

@ -0,0 +1,41 @@
import React, { useState } from "react";
import { Input ,notification} from "antd";
const { Search } = Input;
export default ({history}) => {
const [openSearch, setOpenSearch] = useState(false);
function onGlobalSearch(value) {
history.push('/search?value=' + value);
// window.location.href = `search?value=` + value;
// history.push({
// pathname:'/search',
// state:value
// })
}
return (
<React.Fragment>
{
openSearch ?
<div
onBlur={() => {
setTimeout(() => {
setOpenSearch(false)
}, 500)
}}
>
<Search placeholder="请输入搜索关键字"
className={`search-input mr20`}
onSearch={onGlobalSearch}
autoFocus={true}
style={{width:'260px'}}
/>
</div>
:
<i className="iconfont icon-sousuo font-18 color-grey-6 ml30" onClick={() => {
setOpenSearch(true)
}} />
}
</React.Fragment>
)
};

View File

@ -25,7 +25,7 @@ function LanguagePower({languages}){
}
return(
<div>
<p className="font-16 color-grey-6">开发语言</p>
<p className="font-16 color-ooo aboutSubTitle">开发语言</p>
<div className="progress">
{
array && array.map((item,key)=>{

View File

@ -45,15 +45,15 @@ 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={`/${user && user.login}`}><Img src={getImageUrl(`/${img}`)} /></Link>
<div className="m-infos">
<Link to={`/users/${user && user.login}`}><Name>{name}</Name></Link>
<Link to={`/${user && user.login}`}><Name>{name}</Name></Link>
<Time><I className="iconfont icon-shijian"></I>加入时间:{time}</Time>
{
is_current_user ?
<Button type="default">当前用户</Button>
:
<FocusButton is_watch={focusStatus} id={login} successFunc={successFunc}/>
<FocusButton is_watch={focusStatus} id={login} successFunc={successFunc} notReset={true}/>
}
</div>
</Div>

View File

@ -0,0 +1,125 @@
/* eslint-disable react/jsx-no-duplicate-props */
import React, { useState } from 'react';
import * as ReactDOM from 'react-dom';
import { Modal, Button } from 'antd';
import './index.scss';
//
InitModal.defaultProps = {
okText: '确认', //
cancelText: '取消', //
className: '', //
inputId: 'copyText', //ID
onCancel:()=>{}, //
onOk:()=>{}, //
title:'提示', //
contentTitle:'', //
content:'', //
afterClose:()=>{}, //
};
// 使
export default function DelModal(props) {
renderModal({ ...props, type: 'delete' })
}
// 使
export function Confirm(props) {
renderModal({ ...props, type: 'confirm' })
}
function renderModal(props) {
const { type, afterClose } = props;
const div = document.createElement('div');
document.body.appendChild(div);
function destroy() {
afterClose && afterClose();
const unmountResult = ReactDOM.unmountComponentAtNode(div);
if (unmountResult && div.parentNode) {
div.parentNode.removeChild(div);
}
}
function modalType(type) {
if (type === 'delete') {
return <InitModal
title="删除"
contentTitle="确定要删除吗?"
okText="确认删除"
{...props}
afterClose={destroy}
contentTitle={<React.Fragment>
<i className="red-circle iconfont icon-shanchu_tc_icon mr3"></i>
{props.contentTitle}
</React.Fragment>}
/>
} else if (type === 'confirm') {
return <InitModal title="选择" afterClose={destroy} {...props} />
} else {
return <InitModal title="选择" afterClose={destroy} {...props} />
}
}
function render() {
setTimeout(() => {
ReactDOM.render(
modalType(type),
div,
);
});
}
render();
}
//
function InitModal({
onCancel,
onOk,
title,
contentTitle,
content,
okText,
cancelText,
afterClose,
className,
}) {
const [visible, setVisible] = useState(true);
function onCancelModal() {
setVisible(false);
onCancel && onCancel()
}
function onSuccess() {
setVisible(false);
onOk && onOk();
}
return (
<Modal
visible={visible}
onCancel={onCancelModal}
afterClose={afterClose}
title={title}
className={`myself-modal ${className}`}
centered
footer={[
<Button type="default" key="back" onClick={onCancelModal}>
{cancelText}
</Button>,
<Button className="foot-submit" key="submit" onClick={onSuccess}>
{okText}
</Button>,
]}
>
<div>
{contentTitle && <p className="content-title">{contentTitle}</p>}
<p className="content-descibe">{content}</p>
</div>
</Modal>
)
}

View File

@ -0,0 +1,63 @@
.myself-modal {
.ant-modal-header {
padding: 9px 24px;
background: #f8f8f8;
border-bottom: 1px solid #eee;
}
.ant-modal-title {
text-align: left;
}
.ant-modal-close {
top: 0px !important;
}
.ant-modal-close-x {
font-size: 24px;
}
.ant-modal-body {
text-align: center;
}
.content-title {
display: flex;
justify-content: center;
align-items: center;
margin: 2rem 0 1rem !important;
font-size: 16px;
color: #333;
letter-spacing: 0;
line-height: 29px;
font-weight: 400;
}
.red-circle {
align-self: flex-start;
color: #ca0002;
font-size: 1.5rem !important;
}
.content-descibe {
font-size: 14px;
color: #666;
line-height: 33px;
font-weight: 400;
}
.ant-modal-footer {
padding: 2rem 0;
text-align: center;
border: 0;
.ant-btn {
width: 6rem;
}
}
.foot-submit {
margin-left: 3rem;
color: #df0002;
&:hover {
border-color: #df0002;
}
}
.ant-btn-default:hover,
.ant-btn-default:active,
.ant-btn-default:focus {
background: #f3f4f6;
color: #333;
border-color: #d0d0d0;
}
}

View File

@ -0,0 +1,62 @@
import React, {useEffect, useRef, useState} from 'react';
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api.js';
import './Component.scss';
function Monaco(props) {
const {
style = { // dom
height: '400px',
},
value = '', //
onChange = () => { //
},
fontSize = 14, //
monacoOptions = {
scrollBeyondLastLine: false,
lineNumbers: "off",
wordWrap: true,
overviewRulerBorder: true,
lineHeight: 24,
readOnly:true
}, // monaco
language = 'html', // js ts sql css json html
} = props;
const editOrRef = useRef();
const ThisEditor = useRef();
useEffect(() => {
ThisEditor.current = monaco.editor.create(editOrRef.current, {
value: value || '',
language,
theme: "vs-grey",
fontSize: fontSize + 'px',
minimap: { //
enabled: false,
},
...monacoOptions,
});
ThisEditor.current.onDidChangeModelContent((e) => {
let newValue = ThisEditor.current.getValue();
onChange(newValue);
});
return () => {
ThisEditor.current.dispose();
ThisEditor.current = undefined; //
}
}, []);
useEffect(() => {
if (ThisEditor.current) {
ThisEditor.current.updateOptions({
fontSize: fontSize + 'px',
})
}
}, [fontSize]);
return (
<div style={style} ref={editOrRef}>
</div>
);
}
export default Monaco;

View File

@ -0,0 +1,72 @@
import React , { useEffect , useState } from 'react';
import Modals from '../PublicModal/Index';
import { Button } from 'antd';
import axios from 'axios';
import ProfileImg from './images/profile.png';
import './Index.scss';
function ProfileModal({visible,onCancel,history}) {
const [ modalVis , setModalVis ] = useState(visible);
const [ addMemberCheck , setAddMemberCheck ] = useState(false);
useEffect(()=>{
axios.interceptors.response.use((response) => {
if (response && (response.data.status === 411 || response.data.status === 412)) {
setModalVis(true);
if(response.data.status === 412){
setAddMemberCheck(true);
}
}
return response;
}, (error) => {
});
},[])
useEffect(()=>{
setModalVis(visible);
},[visible])
function onOk(){
onCancel();
setModalVis(false);
setTimeout(function(){
window.open(`/settings/profile`,"_blank");
},200)
}
function onNo() {
onCancel();
setModalVis(false);
}
return(
<Modals
title="完善资料"
onCancel={onNo}
visible={modalVis}
btn={
addMemberCheck?
<div>
<Button type={'primary'} size={"large"} onClick={onNo}>好的</Button>
</div>
:
<div>
<Button size={"large"} onClick={onNo}>暂不补充</Button>
<Button type={'primary'} size={"large"} onClick={onOk}>好的</Button>
</div>
}
>
<div className="contents">
<img src={ProfileImg} alt=""/>
{
addMemberCheck ?
<p>目标用户个人资料不完整需提醒目标用户补充资料后以进行后续操作</p>
:
<p>您目前的个人资料不完整需要补充资料以进行后续操作是否前往补充个人信息</p>
}
</div>
</Modals>
)
}
export default ProfileModal;

View File

@ -0,0 +1,18 @@
.contents{
display: flex;
align-items: center;
justify-content: center;
margin:10px auto 0px;
img{
margin-right: 13px;
width: 44px;
}
p{
line-height: 29px;
max-width: 327px;
font-size: 16px!important;
}
}
.font-44{
font-size: 44px!important;
}

View File

@ -0,0 +1,17 @@
import React from 'react';
function Profile({children,sureFunc,showCompeleteDialog , completeProfile, className}) {
function checkProfile() {
if(!completeProfile){
showCompeleteDialog && showCompeleteDialog();
}else{
sureFunc();
}
}
return(
<a className={className} onClick={checkProfile}>{children}</a>
)
}
export default Profile;

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

@ -0,0 +1,20 @@
import React from 'react';
import { Modal } from 'antd';
import './Index.scss';
function Modals({title,children,btn,onCancel,visible}) {
return(
<Modal
visible={visible}
onCancel={onCancel}
title={title}
width={"520px"}
footer={btn}
centered={true}
wrapClassName={"deleteBox"}
>
{children}
</Modal>
)
}
export default Modals;

View File

@ -0,0 +1,75 @@
.deleteBox{
z-index: 1033;
.ant-modal-close-x{
font-size: 17px!important;
}
.ant-modal-header{
background-color: #f8f8f8;
padding:10px 30px;
.ant-modal-title{
text-align: left;
font-size: 16px;
font-weight: bold;
}
}
.ant-modal-close{
top:0px !important;
font-size: 24px !important;
}
.ant-modal-body{
padding:30px 50px;
p{
font-size: 14px;
line-height: 26px;
color:#666;
word-break: break-all;
}
.desc{
.descMain{
align-items: center;
justify-content: center;
font-size: 20px;
margin-bottom: 10px;
i.red{
color:#DF0002;
}
}
}
}
.ant-modal-footer{
border-top: none;
text-align: center;
padding-bottom: 40px;
button,a{
width: 96px;
height: 32px;
margin:0px 20px;
font-weight: 400;
font-size: 14px;
&.ant-btn{
border-color: #D0D0D0;
color: #666;
&:hover,&:active,&:focus{
background: #f3f4f6;
}
}
&.ant-btn-danger{
background-color: #fff;
color: #DF0002;
border-color: #D0D0D0;
&:hover,&:active,&:focus{
border-color: #DF0002;
background-color: #fff;
}
}
&.ant-btn.ant-btn-primary{
background-color: #466AFF;
color: #fff;
border-color: #466AFF;
&:hover,&:focus,&:active{
background-color: rgba(70,106,255,0.85);
}
}
}
}
}

View File

@ -1,38 +1,34 @@
import React from 'react';
import { AlignCenter , AlignTop , FlexAJ } from '../Component/layout';
import { AlignTop } from '../Component/layout';
import { Link } from 'react-router-dom';
function Releases({owner,projectsId,releaseVersions}){
function Releases({owner,projectsId,releaseVersions , baseOperate , projectType}){
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>
<Link to={`/${owner}/${projectsId}/releases`} className="font-16 color-ooo hoverA">
<span>发行版</span>
{ releaseVersions && releaseVersions.total_count > 0 && <span className="infoCount">{releaseVersions.total_count}</span>}
</Link>
{
releaseVersions && releaseVersions.total_count>0 ?
releaseVersions.list.map((item,key)=>{
return(
key === 0 &&<AlignTop className="mt10">
<i className="iconfont icon-biaoqian3 color-grey-6 font-18 mr10"></i>
<div>
<p className="font-16 color-grey-6">
<Link to={`/projects/${owner}/${projectsId}/releases/8/update`}>{item.name}</Link>
<Link to={`/${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>
<p className="color-grey-3 font-12">{item.created_at}</p>
</div>
</AlignTop>
)
})
:""
:
<div className="mt8">
您暂未发布任何版本{baseOperate && projectType !==2 && <Link className="color-blue ml20" to={`/${owner}/${projectsId}/releases/new`}>创建新版本</Link>}
</div>
}
</div>

View File

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

View File

@ -0,0 +1,91 @@
import React, { useEffect, useState } from 'react';
import { Popover , Tooltip } from 'antd';
import './Component.scss';
import axios from 'axios';
import ShareModal from './SiderBarShareModal';
const $ = window.$;
$(window).scroll(function () {
if ($(".gotop").length > 0) {
if ($(document).scrollTop() > 0) {
$(".-task-sidebar .gotop").show();
$(".gotop").click(function () {
$("html,body").scrollTop(0);
});
}
if ($(document).scrollTop() === 0) {
$(".-task-sidebar .gotop").hide();
}
}
});
function SiderBar() {
const [ data , setData ] = useState([]);
const [ visible , setVisible ] = useState(false);
useEffect(()=>{
getFAQ();
},[])
function getFAQ(){
const url = `/faqs.json`;
axios.get(url).then(result=>{
if(result && result.data){
setData(result.data);
}
}).catch(error=>{})
}
function content(list){
return <div>
<p className="titlecontent">帮助</p>
<ul className="faqUl">
{
list && list.map((i,k)=>{
return(
<li key={i.question+k}><a href={`${i.url}`} title={i.question} target="_blank">{i.question}</a></li>
)
})
}
</ul>
</div>
}
function shareContent(){
return <div>
<ul className="shareUl">
<p className="titlecontent">分享到</p>
<li onClick={()=>setVisible(true)}><i className="iconfont icon-weixin2" style={{color:"#62b900"}}></i></li>
</ul>
</div>
}
return (
<div className={"-task-sidebar"} >
<ShareModal visible={visible} urlValue={window.location.href} onCancel={()=>setVisible(false)}/>
{
data && data.length > 0 && (data[0] && data[0].question) ?
<Popover content={content(data)} overlayClassName="helpBox" placement={"left"}>
<div className="feedback">
<i className="iconfont icon-bangzhu font-22"></i>
</div>
</Popover>
:""
}
{/* <div className="scan pr" title="">
<span className="inline erweima"><i className="iconfont icon-erweima color-white font-22 fl"></i></span>
</div>*/}
<Popover content={shareContent()} overlayClassName="helpBox shareContent" placement={"left"}>
<div className="consult">
<i className="iconfont icon-fenxiang1"></i>
</div>
</Popover>
<div className="gotop">
<Tooltip title="返回顶部" placement={"right"}>
<a><i className="iconfont icon-huidaodingbu1"></i></a>
</Tooltip>
</div>
</div>
)
}
export default SiderBar;

View File

@ -0,0 +1,27 @@
import React from 'react';
import { Modal } from 'antd';
import QRCode from 'qrcode.react';
function SiderBarShareModal({visible,urlValue,onCancel}) {
return(
<Modal
title={"分享到微信"}
visible={visible}
width="500px"
closable={true}
footer={false}
onCancel={onCancel}
>
<div style={{textAlign:"center"}}>
{urlValue &&<QRCode
value={urlValue}
size={200}
fgColor="#000000"
style={{margin:"20px"}}
/>}
<p>打开微信扫一扫,点击右上角菜单即可将网页分享至朋友圈</p>
</div>
</Modal>
)
}
export default SiderBarShareModal;

View File

@ -2,9 +2,9 @@ import React from 'react';
import {Popover} from 'antd';
import './Component.scss';
export default (({menu , children})=>{
export default (({menu , children, overlayClassName})=>{
return(
<Popover content={menu} trigger={['click']} placement='bottom'>
<Popover content={menu} trigger={['click']} placement='bottom' overlayClassName={overlayClassName}>
{children}
</Popover>
)

View File

@ -20,7 +20,7 @@ export default ({ url , name , column , id , login })=>{
`;
return(
id?
<Link to={`/users/${login}`}>
<Link to={`/${login}`}>
<Img>
{ url && <img src={url} alt=""/> }
<span>{name}</span>

View File

@ -28,6 +28,11 @@ export const AlignTop = styled.div`{
display:flex;
align-items: flex-start;
}`
export const AlignAJBottom = styled.div`{
display:flex;
justify-content: space-between;
align-items: flex-end;
}`
//
export const Box = styled.div`{
display:flex;

View File

@ -149,7 +149,7 @@ function About(props, ref) {
axios.post(url).then(result=>{
setIsSpining(false);
if(result && result.data.status === 0){
props.history.push(`/projects/${owner}/${projectsId}/devops/dispose`);
props.history.push(`/${owner}/${projectsId}/devops`);
// open_devops
let { changeOpenDevops } = props;
changeOpenDevops && changeOpenDevops(true);

View File

@ -96,7 +96,7 @@ function Dispose(props){
setVisible(false);
if(result && result.data){
props.showNotification("流水线新增成功,请进行工作流配置!");
props.history.push(`/projects/${owner}/${projectsId}/devops/dispose/${result.data.id}`);
props.history.push(`/${owner}/${projectsId}/devops/${result.data.id}`);
}else{
props.showNotification("流水线新增失败,请稍后再试!");
}
@ -134,12 +134,12 @@ function Dispose(props){
//
function toModalManage(){
props.history.push(`/projects/${owner}/${projectsId}/devops/mould`);
props.history.push(`/${owner}/${projectsId}/devops/mould`);
}
//
function toparameter(){
props.history.push(`/projects/${owner}/${projectsId}/devops/params`);
props.history.push(`/${owner}/${projectsId}/devops/params`);
}
const operate = current_user && (permission && permission !== "Reporter");

View File

@ -10,6 +10,12 @@ import { Link } from 'react-router-dom';
// killed:"",
// pending:""
// }
function turnbar(str){
if(str && str.length>0 && str.indexOf("/")>-1){
return str.replaceAll('/','%2F');
}
return str;
}
function renderTableStatus(status) {
switch (status) {
case "running":
@ -65,8 +71,9 @@ function List({ list, operate , projectsId , owner , showModal , deleteFunc }){
width:"15%",
ellipsis:true,
render:(value,item)=>{
let v = turnbar(item.branch);
return(
<Link to={`/projects/${owner}/${projectsId}/tree/${item.branch}/${value}`} className="color-blue">{value}</Link>
<Link to={`/${owner}/${projectsId}/tree/${v}/${value}`} className="color-blue">{value}</Link>
)
}
},
@ -110,7 +117,7 @@ function List({ list, operate , projectsId , owner , showModal , deleteFunc }){
return(
<span>
{ operate ?
<Link to={`/projects/${owner}/${projectsId}/devops/dispose/${item.id}`} className="mr10 color-grey-6">
<Link to={`/${owner}/${projectsId}/devops/${item.id}`} className="mr10 color-grey-6">
<i className="iconfont icon-zaibianji font-13 mr3"></i>编辑</Link> :""
}
{ operate ?
@ -118,7 +125,7 @@ function List({ list, operate , projectsId , owner , showModal , deleteFunc }){
<a className="mr10 color-grey-6"><i className="iconfont icon-lajitong font-13 mr3"></i>删除</a>
</Popconfirm>:""
}
<Link to={`/projects/${owner}/${projectsId}/devops/list/${item.branch}`} className="color-grey-6"><i className="iconfont icon-yunhang font-13 mr3"></i>查看运行记录</Link>
<Link to={`/${owner}/${projectsId}/devops/list/${item.branch}`} className="color-grey-6"><i className="iconfont icon-yunhang font-13 mr3"></i>查看运行记录</Link>
</span>
)
}

View File

@ -42,7 +42,7 @@ function PipelineName({visible,onCancel,onOk,value ,branchList}){
</div>
<div className="choosenList mt20">
<span>触发条件:</span>
<Select value={branchValue} style={{width:"150px"}} onChange={(e)=>setBranchValue(e)}>
<Select value={branchValue} style={{width:"150px"}} dropdownClassName="chooseCon" onChange={(e)=>setBranchValue(e)}>
{
branchList && branchList.length>0 && branchList.map((item,key)=>{
return(
@ -51,7 +51,7 @@ function PipelineName({visible,onCancel,onOk,value ,branchList}){
})
}
</Select>
<Select mode="multiple" allowClear value={eventValue} style={{width:"180px",marginLeft:"10px"}} onChange={(e)=>{console.log(e);setEventValue(e)}}>
<Select mode="multiple" allowClear value={eventValue} dropdownClassName="chooseCon" style={{width:"180px",marginLeft:"10px"}} onChange={(e)=>{console.log(e);setEventValue(e)}}>
{
EVENT.map((item,key)=>{
return(

View File

@ -36,39 +36,37 @@ export default ((props)=>{
return(
<WhiteBack className="opsPanel">
<Switch {...props}>
<Route path="/projects/:owner/:projectsId/devops/dispose/:disposeId"
render={
(p) => (<New {...props} {...p}/>)
}
></Route>
<Route path="/projects/:owner/:projectsId/devops/params"
<Route path="/:owner/:projectsId/devops/params"
render={
(p) => (<Params {...props} {...p}/>)
}
></Route>
<Route path="/projects/:owner/:projectsId/devops/mould"
<Route path="/:owner/:projectsId/devops/mould"
render={
(p) => (<Mould {...props} {...p}/>)
}
></Route>
<Route path="/projects/:owner/:projectsId/devops/dispose/new"
<Route path="/:owner/:projectsId/devops/new"
render={
(p) => (<New {...props} {...p}/>)
}
></Route>
<Route path="/projects/:owner/:projectsId/devops/dispose"
render={
(p) => (<Dispose {...props} {...p}/>)
}
></Route>
<Route path="/projects/:owner/:projectsId/devops/list/:branch"
<Route path="/:owner/:projectsId/devops/list/:branch"
render={
(p) => (<Stucture {...props} {...p}/>)
}
></Route>
<Route path="/projects/:owner/:projectsId/devops"
<Route path="/:owner/:projectsId/devops/:disposeId"
render={
(p) => (<About {...props} {...p}/>)
(p) => (<New {...props} {...p}/>)
}
></Route>
{/* 原本的两种合为一个 */}
<Route path="/:owner/:projectsId/devops"
render={
(p) =>{return( p.location.state.open_devops?<Dispose {...props} {...p}/>:<About {...props} {...p}/>)}
}
></Route>
</Switch>

View File

@ -26,7 +26,7 @@ export default ((props)=>{
return(
<div className="disposePanel">
<Banner>
{ permission !=="Reporter" && <Link to={`/projects/${owner}/${props.match.params.projectsId}/devops/dispose`}>工作流配置</Link>}
{ permission !=="Reporter" && <Link to={`/${owner}/${props.match.params.projectsId}/devops`}>工作流配置</Link>}
</Banner>
<Div>
<Dispost {...props}/>

View File

@ -104,7 +104,7 @@ function Params(props){
<Banner>
<FlexAJ>
<span className="font-18">工作流 - 参数管理</span>
<Link to={`/projects/${owner}/${projectsId}/devops/dispose`} className="font-14 color-grey-9 ml20">返回</Link>
<Link to={`/${owner}/${projectsId}/devops`} className="font-14 color-grey-9 ml20">返回</Link>
</FlexAJ>
</Banner>
<Div className="disposeList">

View File

@ -126,7 +126,7 @@ function Mould(props){
<div>
<New wrappedComponentRef={(f) => childRef.current = f} ref={childRef} visible={visible} onCancel={()=>setVisible(false)} onOk={onOk}></New>
<Banner>
<FlexAJ><span>工作流 - 模板管理</span><Link to={`/projects/${owner}/${projectsId}/devops/dispose`} className="font-14 color-grey-9">返回</Link></FlexAJ>
<FlexAJ><span>工作流 - 模板管理</span><Link to={`/${owner}/${projectsId}/devops`} className="font-14 color-grey-9">返回</Link></FlexAJ>
</Banner>
<Div className="disposeList">
<FlexAJ>

View File

@ -2,7 +2,7 @@ import React, { useState, useEffect , useImperativeHandle ,forwardRef } from "re
import { FlexAJ, AlignCenter , Banner } from "../Component/layout";
import { Table, Pagination, Popconfirm } from "antd";
import { truncateCommitId } from "../common/util";
import {getUrl} from 'educoder';
import { getImageUrl } from 'educoder';
import axios from "axios";
import { Link } from 'react-router-dom';
@ -198,7 +198,7 @@ function Structure(props,ref){
}
function clickRows(event,e){
props.history.push(`/projects/${owner}/${projectsId}/devops/${e.number}/detail`);
props.history.push(`/${owner}/${projectsId}/devops/${e.number}/detail`);
}
const column = [
{
@ -245,7 +245,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"}} alt="" src={`${item.image_url && getImageUrl(`/${item.image_url}`)}`} />
<div className="task-hide ml5" style={{ maxWidth: "300px" }}>
{meg.message}
</div>
@ -290,7 +290,7 @@ function Structure(props,ref){
<Banner>
<FlexAJ>
<span>构建列表</span>
<Link to={`/projects/${owner}/${projectsId}/devops/dispose`} className="font-15 color-grey-9">返回</Link>
<Link to={`/${owner}/${projectsId}/devops`} className="font-15 color-grey-9">返回</Link>
</FlexAJ>
</Banner>
<Div>

View File

@ -275,7 +275,7 @@ function disposePipeline(props){
...params
}).then(result=>{
if(result){
props.history.push(`/projects/${owner}/${projectsId}/devops/dispose`);
props.history.push(`/${owner}/${projectsId}/devops`);
}
setLoading(false);
}).catch(error=>{

View File

@ -391,6 +391,9 @@
}
}
}
.chooseCon.ant-select-dropdown{
z-index: 100001;
}
.choosenList{
display: flex;

View File

@ -48,7 +48,7 @@ export default (props) => {
axios.post(url).then((result) => {
if (result && result.data) {
props.showNotification("工作流正在重新构建!");
props.history.push(`/projects/${owner}/${projectId}/devops/${result.data.number}/detail`);
props.history.push(`/${owner}/${projectId}/devops/${result.data.number}/detail`);
}
})
.catch((error) => {
@ -87,7 +87,7 @@ export default (props) => {
</AlignCenter>
<Link
style={{ color: "#ddd" }}
to={`/projects/${owner}/${projectId}/devops/dispose`}
to={`/${owner}/${projectId}/devops`}
>
<i className="iconfont icon-yiguanbi font-15 mr5"></i>退出
</Link>

View File

@ -0,0 +1,176 @@
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)=>{
if(!error){
const url = `/${owner}/${repo}/applied_transfer_projects.json`;
Axios.post(url,{
...values
}).then(result=>{
if(result && result.data.id){
onSuccess(result.data && result.data.owner);
}else{
onSuccess();
}
}).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="仓库标识:" style={{marginBottom:"0px"}}>
{getFieldDecorator("identifier",
{
rules:[
{required:true,message:"请输入仓库标识!"},
{
validator:checkIdentifier
}
]
}
)(
<Input placeholder="请输入仓库标识" autoComplete={"off"}/>
)}
</Form.Item>
<span className="color-grey-9" style={{marginLeft:"120px"}}>请输入当前项目的标识<span className="ml5 mr5 color-grey-3">{repo}</span>进行确认</span>
</Form>
</div>
</Modal>
)
}
export default Form.create()(forwardRef(DivertModal));

View File

@ -0,0 +1,12 @@
.diverModal{
.descUl{
background-color: #fffae6;
border-radius: 4px;
padding:10px 15px;
color: #efc16b;
border:1px solid #efc16b;
}
.ant-form-item-required::before{
content: "";
}
}

View File

@ -0,0 +1,85 @@
import React, { useState , forwardRef, useEffect } from 'react';
import { Form , Modal , Input , Radio } from 'antd';
import Axios from 'axios';
import CheckProfile from '../Component/ProfileModal/Profile';
export default Form.create()(
forwardRef((props)=>{
const { getFieldDecorator, validateFields , setFieldsValue } = props && props.form;
const [ visible , setVisible ] = useState(false);
useEffect(()=>{
if(!visible){
setFieldsValue({
code:undefined,
role:"developer"
})
}
},[visible])
function onOk() {
validateFields((error,values)=>{
if(!error){
const url = `/applied_projects.json`;
Axios.post(url,{
applied_project:{
...values
}
}).then(result=>{
if(result && result.data){
setVisible(false);
props.showNotification("申请加入项目成功,等待审核!");
}
}).catch(error=>{})
}
})
}
function checkValue(rule, value, callback){
if(!value){
callback();
}
if(value.length < 6 || value.length > 6){
callback("请输入6位数的邀请码");
}
callback();
}
return(
<React.Fragment>
<Modal
title="加入项目"
width="480px"
visible={visible}
centered={true}
onOk={onOk}
onCancel={()=>setVisible(false)}
>
<Form layout={'inline'} className="inviteForm">
<Form.Item label="项目邀请码">
{getFieldDecorator("code",{
rules:[
{required:true,message:"请输入6位项目邀请码"},
{validator:checkValue}
]
})(
<Input placeholder="请输入6位项目邀请码" autoComplete={"off"} maxLength="6" style={{width:"300px"}}/>
)}
</Form.Item>
<Form.Item label="选择角色">
{getFieldDecorator("role",{
rules:[{required:true,message:"请选择角色"}]
})(
<Radio.Group defaultValue={"developer"}>
<Radio value="manager">管理员</Radio>
<Radio value="developer">开发者</Radio>
<Radio value="reporter">报告者</Radio>
</Radio.Group>
)}
</Form.Item>
</Form>
</Modal>
<CheckProfile {...props} sureFunc={()=>setVisible(true)}>加入项目</CheckProfile>
</React.Fragment>
)
})
)

View File

@ -0,0 +1,108 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Icon } from 'antd';
import _ from 'lodash';
import Nodata from '../Nodata';
class PullRefresh extends Component {
constructor(props) {
super(props);
this.state = {
}
this.pullRef = {};
//
this.onScrollList = _.throttle(this.handleScroll, 200, {
leading: false,
trailing: true,
});
}
componentDidMount() {
let dom = document.querySelector('.pull-refresh-wrap');
dom && dom.addEventListener('scroll', this.onScrollList);
}
componentWillUnmount() {
let dom = document.querySelector('.pull-refresh-wrap');
dom && dom.removeEventListener('scroll', this.onScrollList)
}
handleScroll = () => {
if (this.props.count < this.props.pageSize) return;
if (this.props.type === 1 || this.props.type === 2) return;
const wrap = this.pullRef;
const currentScroll = wrap.scrollTop + wrap.clientHeight
//
if (currentScroll >= (wrap.scrollHeight - 200)) {
this.loadData()
}
}
handleLoadClick = () => {
this.loadData();
}
loadData = () => {
this.props.onPullRefresh()
}
renderLoading() {
switch (this.props.type) {
case 0: //
return <div className='text-center' onClick={this.handleLoadClick}>显示更多</div>
case 1: //
return (
<div className='text-center'>
<Icon type="loading" />
<span className='text-center'>加载中...</span>
</div>
)
case 2: //
return <div className='text-center'>没有更多了</div>
default:
return <div className='text-center'>没有更多了</div>
}
}
render() {
const { className, count, children } = this.props;
return (
<div
className={`pull-refresh-wrap ${className}`}
ref={dom => { this.pullRef = dom }}
>
{children}
{
count < 1 && <Nodata _html="暂无未读消息"/>
}
{/* 大于分页数据才显示loading */}
{/* {this.props.count >= this.props.pageSize ? this.renderLoading() : null} */}
</div>
)
}
}
PullRefresh.propTypes = {
className: PropTypes.string,
children: PropTypes.any,
onPullRefresh: PropTypes.func.isRequired,
type: PropTypes.oneOf([0, 1, 2]),
count: PropTypes.number.isRequired,
pageSize: PropTypes.number.isRequired,
}
export default PullRefresh

View File

@ -19,7 +19,7 @@ function Footer(){
return(
<div>
<div style={{height:"483px"}}></div>
<div style={{height:"497px"}}></div>
<div className="newFooter edu-txt-center">
{value && showhtml(value)}
{/* <div className="footerInfos">

View File

@ -2,17 +2,18 @@ import React, { Component } from 'react';
import AccountProfile from "../../modules/user/AccountProfile";
import { getImageUrl } from 'educoder'
import axios from 'axios';
import { Modal, Input, message, notification , Dropdown , Menu ,Divider } from 'antd';
import { Input , notification , Dropdown ,Popover, Menu,Badge, Button } from 'antd';
import { Link } from 'react-router-dom';
import LoginDialog from '../../modules/login/LoginDialog';
import GotoQQgroup from '../../modal/GotoQQgroup'
// import 'antd/lib/modal/style/index.css';
// import 'antd/lib/checkbox/style/index.css';
// import 'antd/lib/radio/style/index.css';
// import 'antd/lib/input/style/index.css';
import HeadSearch from '../Component/HeadSearch';
import AddProjectModal from './AddProjectModal';
import '../../modules/tpm/TPMIndex.css';
import logo from '../../modules/tpm/images/logo.png';
import CheckProfile from '../Component/ProfileModal/Profile';
import './header.scss';
import NoticeContent from './NoticeContent';
const $ = window.$
// TODO 这部分脚本从公共脚本中直接调用
const { Search } = Input;
@ -35,11 +36,9 @@ class NewHeader extends Component {
Checkboxteachertype: false,
Checkboxteachingtype: false,
code_notice: false,
checked_notice: false,
RadioGroupvalue: undefined,
submitapplications: false,
isRender: false,
showSearchOpentype: false,
showTrial: false,
setevaluatinghides: false,
occupation: 0,
@ -47,13 +46,12 @@ class NewHeader extends Component {
headtypesonClickbool: false,
headtypess: "/",
settings: null,
goshowqqgtounp: false,
visiblemyss: false,
openSearch:false,
visible:false, //浮动消息框展示控制
}
}
componentDidMount() {
// this.getAppdata();
this.geturlsdata();
window._header_componentHandler = this;
@ -84,36 +82,6 @@ class NewHeader extends Component {
} 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: "提示",
@ -122,168 +90,12 @@ class NewHeader extends Component {
});
};
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({
@ -321,30 +133,11 @@ class NewHeader extends Component {
})
};
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
@ -404,39 +197,13 @@ class NewHeader extends Component {
})
}
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();
}
localStorage.setItem('chromesetting', JSON.stringify(response.data.setting));
localStorage.setItem('chromesettingresponse', JSON.stringify(response));
} else {
this.gettablogourlnull();
}
@ -455,13 +222,14 @@ class NewHeader extends Component {
}
}
}
// 处理弹框
setgoshowqqgtounp = (bool) => {
this.setState({
goshowqqgtounp: bool
})
checkProfile=(url)=>{
const { showCompeleteDialog , completeProfile } = this.props;
if(!completeProfile){
showCompeleteDialog && showCompeleteDialog();
}else{
window.location.href(url);
}
}
addMenu=(list)=>{
@ -472,34 +240,56 @@ class NewHeader extends Component {
{
list.map((item,key)=>{
return(
(item.name !=="加入课堂" && item.name !=="加入开发项目") && <Menu.Item><a href={item.url}>{item.name}</a></Menu.Item>
(item.name !=="加入课堂" && item.name !=="加入开发项目") &&
<Menu.Item key={item.name+key}>
<CheckProfile {...this.props} sureFunc={()=>{window.location.href=item.url}}>{item.name}</CheckProfile>
</Menu.Item>
)
})
}
<Menu.Item>
<AddProjectModal {...this.props} showNotification={this.props.showNotification}/>
</Menu.Item>
</Menu>
</div>
)
}
renderMenu=(personal)=>{
const { current_user } = this.props;
return(
<Menu className="currentMenu">
<Menu.Item>
<span className="currentName" title={current_user && current_user.username}>{current_user && current_user.username}</span>
</Menu.Item>
{
personal && personal.length > 0 && personal.map((item,key)=>{
return(
<li key={key}><a href={item.url} target="_blank">{item.name}</a></li>
)
})
}
<li><Link to={`/settings/profile`}>设置</Link></li>
<Menu.Item><a onClick={() => this.educoderloginysl()}>退出</a></Menu.Item>
</Menu>
)
}
handleVisibleChange = visible => {
this.setState({ visible });
};
render() {
const { match} = this.props;
const { match ,resetUserInfo ,showNotification} = this.props;
let current_user = this.props.user;
let { Addcoursestypes,
tojoinitemtype,
tojoinclasstitle,
code_notice,
checked_notice,
let {
AccountProfiletype,
submitapplications,
submitapplicationsvalue,
user,
isRender,
showSearchOpentype,
headtypesonClickbool,
headtypess,
settings,
goshowqqgtounp,
openSearch,
visible,
} = this.state;
/*用户名称 用户头像url*/
let activeIndex = false;
@ -557,7 +347,7 @@ class NewHeader extends Component {
let shixun = "/shixuns";
let paths = "/paths";
let courses = "/courses";
this.props.mygetHelmetapi.navbar.map((item, key) => {
this.props.mygetHelmetapi && this.props.mygetHelmetapi.navbar && this.props.mygetHelmetapi.navbar.map((item, key) => {
var reg = RegExp(item.link);
if (shixun.match(reg)) {
if (item.hidden === true) {
@ -595,19 +385,14 @@ class NewHeader extends Component {
{...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>
<a href={settings && settings.new_course.default_url} className={"fl mr50"} style={{minWidth:"45px"}}>
<img alt="可控开源社区" className="logoimg" style={{ heigth: "40px" }} src={getImageUrl(`/${settings.nav_logo_url}`)}></img>
</a>
:
<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 ?
@ -615,21 +400,21 @@ class NewHeader extends Component {
{
settings.navbar && settings.navbar.map((item, key) => {
var new_link = item.link;
var user_login = this.props.user && this.props.user.login;
var user_login = current_user && current_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")
new_link = new_link.replace(/courses/g, user_login + "/courses")
} else if (new_link.indexOf("contests") > -1) {
new_link = new_link.replace(/contests/g, "users/" + user_login + "/contests")
new_link = new_link.replace(/contests/g, 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")
new_link = new_link.replace(/homes/g, user_login + "/user_activities")
}
var waiLian = (new_link && str.filter(item=>new_link.indexOf(item)>-1) );
@ -646,51 +431,31 @@ class NewHeader extends Component {
}
</div>
<div className="head-right">
{search_url ? this.SearchInput(openSearch,search_url):""}
{ search_url && <HeadSearch {...this.props}/>}
{
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>
<i className="iconfont icon-tianjiafangda color-grey-6 ml30 mr15"></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>:""
{current_user && current_user.login ?
<Popover
overlayClassName="notice-popover"
placement={`bottomRight`}
content={<NoticeContent visible={visible} current_user={current_user} showNotification={showNotification} resetUserInfo={resetUserInfo}/>}
visible={visible}
onVisibleChange={this.handleVisibleChange}
destroyTooltipOnHide
>
<Link to={"/settings/notice"} className="message-icon">
<Badge count={current_user.message_unread_total}>
<i className="iconfont icon-xiaoxilingdang color-grey-6 ml15 mr15"></i>
</Badge>
</Link>
</Popover>
: ""
}
<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">
@ -701,25 +466,11 @@ class NewHeader extends Component {
}
</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>
<Dropdown placement={`bottomRight`} overlay={this.renderMenu(settings && settings.personal)}>
<a href={`/${this.props.current_user && this.props.current_user.login}`}>
<img alt="头像" src={getImageUrl(`/${user.image_url}`)} className="currentImg"></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>
</Dropdown>
}
</div>
</div>

View File

@ -0,0 +1,262 @@
import React, { useEffect, useState } from 'react';
import { Badge, Menu } from 'antd';
import { Link } from 'react-router-dom';
import axios from 'axios';
import AppPullRefresh from './AppPullRefresh';
import { noticeSourceType } from '../common/static';
import './header.scss';
import '../SecuritySetting/notice/manager/Index.scss';
import '../SecuritySetting/Index.scss';
import '../SecuritySetting/notice/myNotice/Index.scss';
function NoticeContent({ visible, showNotification, resetUserInfo, current_user: { login } }) {
const [initialize, setInitialize] = useState(true);
const [noticeType, setNoticeType] = useState("notification");
const [letterUnreadCount, setLetterUnreadCount] = useState(0);//
const [noticeUnreadCount, setNoticeUnreadCount] = useState(0);//
const [noticePage, setNoticePage] = useState(0);
const [noticeUnreadList, setNoticeUnreadList] = useState([]);//
const [atUnreadCount, setAtUnreadCount] = useState();//@
const [atPage, setAtPage] = useState(0);
const [atUnreadList, setAtUnreadList] = useState([]);//@
useEffect(() => {
resetUserInfo();
}, [noticeUnreadCount,atUnreadCount]);
useEffect(()=>{
setNoticePage(0);
setAtPage(0);
},[visible])
useEffect(() => {
const params = {
type: noticeType,
limit: 10,
page: noticeType === "notification" ? noticePage : noticeType === "atme" ? atPage : "",
status: 1,
}
getMessageList(params);
}, [noticePage, atPage]);
useEffect(() => {
const params = {
type: noticeType,
limit: 10,
page: 0,
status: 1,
};
if (initialize) {
params.type = "atme"
}
visible && getMessageList(params);
}, [visible]);
function getMessageList(params) {
axios.get(`/users/${login}/messages.json`, {
params: params,
}).then((response) => {
if (response && response.data) {
setNoticeUnreadCount(response.data.unread_notification);
setAtUnreadCount(response.data.unread_atme);
if (params.type === "notification") {
let list = response.data.messages;
if (params.page !== 0) {
list = [...noticeUnreadList, ...list];
}
setNoticeUnreadList(list);
if (initialize) {
// tab
setInitialize(false);
if (response.data.unread_notification === 0 && response.data.unread_atme !== 0) {
setNoticeType("atme");
}
}
} else if (params.type === "atme") {
let list = response.data.messages;
if (params.page !== 0) {
list = [...atUnreadList, ...list];
}
setAtUnreadList(list);
}
}
})
}
function readAll() {
axios.post(`/users/${login}/messages/read.json`, {
type: noticeType,
ids: [-1]
}).then((response) => {
let data = response.data;
if (!data) return;
if (data.status === 0) {
changeReadMarkAll(noticeType);
} else {
showNotification(data.message);
}
});
}
function changeReadMarkAll(noticeType) {
if (noticeType === "notification") {
let list = noticeUnreadList.slice();
list.forEach(item => {
item.status = 2;
})
setNoticeUnreadList(list);
setNoticeUnreadCount(0);
} else if (noticeType === "atme") {
let list = atUnreadList.slice();
list.forEach(item => {
item.status = 2;
})
setAtUnreadList(list);
setAtUnreadCount(0);
}
}
// const [letter_unread_list, setLetter_unread_list] = useState([
// {
// id: 122,
// read: 0, //01
// send_name: "", //
// send_login: "jiangYuHang", //login
// content: "", //
// create_time: "2019-03-04 18:08", //
// },
// ]);
function readItem(item) {
axios.post(`/users/${login}/messages/read.json`, {
type: noticeType,
ids: [item.id]
}).then((response) => {
let data = response.data;
if (!data) return;
if (data.status === 0) {
changeReadMark(item);
item.notification_url && window.open(item.notification_url);
} else {
showNotification(data.message);
}
});
}
function changeReadMark(item) {
if (item.type === "notification") {
let list = noticeUnreadList.slice();
let index = noticeUnreadList.indexOf(item);
list[index].status = 2;
setNoticeUnreadList(list);
if (noticeUnreadCount > 0) {
setNoticeUnreadCount(noticeUnreadCount - 1);
}
} else if (item.type === "atme") {
let list = atUnreadList.slice();
let index = atUnreadList.indexOf(item);
list[index].status = 2;
setAtUnreadList(list);
if (atUnreadCount > 0) {
setAtUnreadCount(atUnreadCount - 1);
}
}
}
return (
<div className="messageHoverDiv notice01">
<div className="sshHead hoverNotice-head">
<Menu mode="horizontal" selectedKeys={noticeType} onClick={(e) => setNoticeType(e.key)}>
<Menu.Item key="notification"><Badge count={noticeUnreadCount}>系统通知</Badge></Menu.Item>
{/* <Menu.Item key="1" id="item-private"><Badge count={letterUnreadCount}>私信</Badge></Menu.Item> */}
<Menu.Item key="atme"><Badge count={atUnreadCount}>@</Badge></Menu.Item>
</Menu>
</div>
{/* 系统通知 */}
{noticeType === "notification" && <AppPullRefresh
className='hoverNotice-body' // className
onPullRefresh={() => { setNoticePage(noticePage + 1); }} //ajaxfunction
// type={2} //
count={noticeUnreadList.length} //
pageSize={10} //
>
{
noticeUnreadList.map(item => {
return (
<div key={item.id + Math.random()} className="noticeCont-back" onClick={() => { readItem(item) }}>
<div className={`noticeCont ${item.notification_url?'pointer':''}`}>
<span style={{ visibility: item.status === 1 ? 'visible' : 'hidden' }}>
<Badge color="#FA2020" />
</span>
<i className={"iconfont " + noticeSourceType[item.source]}></i>
<div className="noticeCont-text">
<span className="content-span notice-cont-span" dangerouslySetInnerHTML={{ __html: item.content }}></span>
<span className="timeSpan">{item.time_ago}</span>
</div>
</div>
</div>
)
})
}
</AppPullRefresh>
}
{/* @我 */}
{noticeType === "atme" && <AppPullRefresh
className='hoverNotice-body' // className
onPullRefresh={() => { setAtPage(atPage + 1); }} //ajaxfunction
// type={1} //
count={atUnreadList.length} //
pageSize={10} //
>
{atUnreadList.map(item => {
return (
<div key={item.id + Math.random()} className="noticeCont-back" onClick={() => { readItem(item) }}>
<div className="noticeCont">
<span style={{ visibility: item.status === 1 ? 'visible' : 'hidden' }}>
<Badge color="#FA2020" />
</span>
<div className="noticeCont-text">
<span className="content-span atme-cont-span" dangerouslySetInnerHTML={{ __html: "<b>" + (item.sender ? item.sender.name : '') + "</b>&nbsp;&nbsp;&nbsp;" + item.content + " 中@我" }}></span>
<span className="timeSpan">{item.time_ago}</span>
</div>
</div>
</div>
)
})
}
</AppPullRefresh>
}
{/* 私信 */}
{/* {noticeType === "1" ? letter_unread_list.length > 0 ? letter_unread_list.map(item => {
return (
<div className="noticeCont-back">
<div className="noticeCont" style={{ height: item.content.length >= 30 && item.content.length <= 34 ? '65px' : "" }}>
<Badge color="#FA2020" />
<div className="noticeCont-text">
<span>{item.send_name}</span>
<span className="boldSpan" dangerouslySetInnerHTML={{ __html: item.content.length >= 50 ? item.content.substr(0, 50) + "..." : item.content }}></span>
<span className="timeSpan">{item.create_time ? timeAgo(item.create_time) : "刚刚"}</span>
</div>
</div>
</div>
)
}) : "暂无数据" : ""} */}
<div className="hoverNotice-buttom">
<Link to={{pathname:"/settings/notice",query:{noticeType:noticeType}}}>全部消息</Link>
{noticeUnreadCount > 0 && noticeType === "notification" && <a onClick={readAll}>所有系统消息一键已读</a>}
{atUnreadCount > 0 && noticeType === "atme" && <a onClick={readAll}>所有@我一键已读</a>}
</div>
</div>
)
}
export default NoticeContent;

View File

@ -1,11 +1,70 @@
.dropdownFlex{
display:flex;
padding:5px;
background:#fff;
border-radius: 3px;
.ant-menu-vertical > .ant-menu-item{
border:none
border:none;
height: 35px;
line-height: 35px;
margin:0px;
&.ant-menu-item-selected{
background-color: #fff;
a{color: rgba(0, 0, 0, 0.65)!important;}
}
&.ant-menu-item-active{
a{color: #4cacff!important;}
}
}
.ant-menu-vertical{
border:none;
}
}
.currentImg{
width: 34px;
height: 34px;
border-radius: 50%;
margin-left: 15px;
}
.currentMenu{
width: 120px;
text-align: center;
padding:0px;
.currentName{
padding:0px 8px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
display: block;
}
li{
height: 40px;
line-height: 40px;
padding:0px!important;
cursor: default;
&:hover{
background-color: #fff;
}
&:first-child{
border-bottom: 1px solid #eee;
}
&:last-child{
border-top: 1px solid #eee;
a{
border-radius: 0px 0px 4px 4px;
}
}
a{
padding:0px;
margin:0px;
display: block;
color: #666;
&:hover{
color: #fff;
background: #4CACFF;
}
}
}
}
@ -59,4 +118,148 @@
}
}
}
}
.inviteForm{
.ant-form-item{
margin-right: 0px;
}
.ant-form-item-label{
width: 110px;
text-align: right;
}
}
// 右上角小铃铛单独样式
.notice-popover{
//popover小尖尖
.ant-popover-arrow{
display: none;
}
//popover框
.ant-popover-inner-content {
width: 386px;
height: 446px;
box-shadow: 0px 4px 8px 2px rgba(212, 212, 212, 0.5);
border-radius: 4px;
margin-top: -10px;
padding: 12px 1px 12px 0;
}
}
.messageHoverDiv .ant-menu-item{
margin-right: 24px !important;
}
.hoverNotice-head{
margin-left: 18px;
& .ant-badge{
font-size: 14px !important;
}
&>.ant-menu-horizontal {
border-bottom: 1px solid #e8e8e8 !important;
}
}
.hoverNotice-body{
height: 342px;
overflow-y: scroll;
& b{
font-weight: 400;
text-shadow: 0.5px 0 0 #333;
}
.none_panels{
height: 100%;
}
}
.message-icon{
position: relative;
.ant-scroll-number{
right:12px;
padding: 0 0px;
}
}
.hoverNotice-buttom{
display: flex;
justify-content: space-between;
padding: 12px 18px;
a{
color: #466AFF;
&:hover{
opacity:0.85;
}
}
}
.noticeCont-back{
.pointer{
cursor: pointer;
}
&:hover{
background: #F3F4F6;
}
}
.noticeCont{
display: flex;
margin: 0 16px 0 18px;
padding: 12px 0 10px 0;
line-height: 24px;
border-bottom: 1px solid #EEEEEE;
cursor: default;
i{
font-size: 14px !important;
margin-right: 6px;
color: #333333;
}
.boldSpan{
font-weight: 400;
text-shadow: 0.5px 0 0 #333;
}
.noticeCont-text{
display: flex;
color:#333333;
flex:auto;
justify-content: space-between;
& .content-span{
word-break: break-all;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
& .atme-cont-span{
width: 272px;
}
& .notice-cont-span{
width: 255px;
}
.timeSpan{
font-size: 12px;
color: #666666;
}
.at-name{
margin-right: 12px;
}
}
}
.text-center{
text-align: center;
}

View File

@ -12,8 +12,9 @@ import Loadable from "react-loadable";
import Loading from "../Loading";
import { ImageLayerOfCommentHOC } from "../modules/page/layers/ImageLayerOfCommentHOC";
const ProjectNew = Loadable({
loader: () => import("./New/Index"),
loader: () => import("./New/Index"),
loading: Loading,
});
const ProjectIndex = Loadable({
@ -21,17 +22,23 @@ const ProjectIndex = Loadable({
loading: Loading,
});
const ProjectDetail = Loadable({
loader: () => import("./Main/Detail"),
loading: Loading,
});
// 项目详情放在用户和组织下作为二级菜单存在
// const ProjectDetail = Loadable({
// loader: () => import("./Main/Detail"),
// loading: Loading,
// });
const Infos = Loadable({
loader: () => import("./users/Infos"),
loading: Loading,
});
class Index extends Component {
componentDidUpdate = () => {
this.props.history.listen(() => {
if (document.body.scrollTop || document.documentElement.scrollTop > 0) {
window.scrollTo(0, 0)
}
})
}
render() {
return (
<div className="newMain clearfix">
<Switch {...this.props}>
@ -48,30 +55,27 @@ class Index extends Component {
)}
></Route>
<Route
path="/projects/new"
path="/projects/mirror/new"
render={(props) => (
<ProjectNew {...this.props} {...props} />
)}
></Route>
<Route
path="/projects/:owner/:projectsId"
{/* <Route
path="/:owner/:projectsId"
render={(props) => (
<ProjectDetail {...this.props} {...props} />
)}
></Route>
></Route> */}
<Route
path="/projects"
path="/explore"
render={(props) => (
<ProjectIndex {...this.props} {...props} />
)}
></Route>
<Route
exact
path="/"
render={(props) => (
this.props.current_user && this.props.current_user.login ?
<Infos {...this.props} {...props} />
:
<ProjectIndex {...this.props} {...props} />
)}
></Route>
@ -86,3 +90,10 @@ export default withRouter(
parentSelector: ".newMain",
})(CNotificationHOC()(SnackbarHOC()(TPMIndexHOC(Index))))
);
// export default withRouter(
// ImageLayerOfCommentHOC({
// imgSelector: ".imageLayerParent img, .imageLayerParent .imageTarget",
// parentSelector: ".newMain",
// })(Index)
// );

View File

@ -1,8 +1,9 @@
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 { Dropdown , Menu , Divider , Spin, Button , Typography } from 'antd';
import { getImageUrl } from "educoder";
import { Link } from 'react-router-dom';
import { truncateCommitId } from "../common/util";
import CloneAddress from '../Branch/CloneAddress';
import SelectBranch from '../Branch/Select';
@ -19,12 +20,28 @@ import LanguagePower from '../Component/LanguagePower';
import DrawerPanel from '../Component/DrawerPanel';
import UpdateDescModal from './sub/UpdateDescModal';
import Nodata from '../Nodata';
import Invite from './sub/Invite';
import CheckProfile from '../Component/ProfileModal/Profile';
/**
* projectDetail.type:0是托管项目1是镜像项目2是同步镜像项目(为2时不支持在线创建在线上传在线修改在线删除创建合并请求等功能)
*/
const { Paragraph } = Typography;
function turnbar(str){
if(str && str.length>0 && str.indexOf("/")>-1){
return str.replaceAll('/','%2F');
}
return str;
}
function returnbar(str){
if(str && str.length>0 && str.indexOf("%2F")>-1){
return str.replaceAll('%2F','/');
}
return str;
}
function CoderDepot(props){
const [ projectDetail , setProjectDetail ]= useState(undefined);
const [ inviteCode , setInviteCode ] = useState(undefined);
const [ treeValue , setTreeValue ] = useState(undefined);
const [ treeValuePath , setTreeValuePath ] = useState(undefined);
const [ lastCommit,setLastCommit ] = useState(undefined);
@ -45,19 +62,45 @@ function CoderDepot(props){
const [ desc , setDesc ] = useState(undefined);
const [ website , setWebsite ] = useState(undefined);
const [ lesson_url , setLessonUrl ] = useState(undefined);
const [ readme , setReadme ] = useState(undefined);
const [ defaultBranch , setDefaultBranch ] = useState(undefined);
const [ editReadme , setEditReadme ] = useState(false);
const [ pullsFlag , setPullsFlag ] = useState(true);
const [ issuesFlag , setIssuesFlag ] = useState(true);
const owner = props.match.params.owner;
const projectsId = props.match.params.projectsId;
const branchName = props.match.params.branchName;
let branchName = props.match.params.branchName;
branchName = returnbar(branchName);
const details = props.projectDetail;
let pathname = props.history.location.pathname;
const { bannerList } = props;
useEffect(()=>{
if(props.projectDetail){
setProjectDetail(props.projectDetail);
setDesc(props.projectDetail.description);
setWebsite(props.projectDetail.website);
setLessonUrl(props.projectDetail.lesson_url);
if(bannerList && bannerList.length>0){
let a = bannerList.filter(i=>i.menu_name === "pulls");
let i = bannerList.filter(i=>i.menu_name === "issues");
if(a && a.length === 0){
setPullsFlag(false);
}
if(i && i.length === 0){
setIssuesFlag(false);
}
}
},[props])
},[bannerList])
useEffect(()=>{
if(details){
setProjectDetail(details);
setDesc(details.description);
setWebsite(details.website);
setLessonUrl(details.lesson_url);
setDefaultBranch(details.default_branch);
setInviteCode(details.invite_code);
}
},[details])
useEffect(()=>{
if(treeValue){
@ -67,23 +110,28 @@ function CoderDepot(props){
}
},[treeValue])
useEffect(()=>{
if (pathname && projectDetail){
if(pathname.indexOf(`/projects/${owner}/${projectsId}`) > -1 && pathname.indexOf(`/tree/${branchName}/`) > -1) {
let url = pathname.split(`/tree/${branchName}/`)[1];
if (projectsId && owner && defaultBranch){
let b = turnbar(branchName) ;
if(pathname.indexOf(`/${owner}/${projectsId}`) > -1 && pathname.indexOf(`/tree/${b}/`) > -1) {
let url = pathname.split(`/tree/${b}/`)[1];
setTreeValue(url);
getFileInfo(url,branchName);
setType("file");
}else{
setTreeValue(undefined);
getDirInfo(branchName ||projectDetail.default_branch);
getDirInfo(branchName || defaultBranch);
setType("dir");
}
}
},[pathname,projectDetail])
},[projectsId,owner,pathname,defaultBranch])
//
function getDirInfo(branch){
setIsSpin(true);
const url = `/${owner}/${projectsId}/entries.json`;
axios.get(url, {
params: { ref: branch }
}).then((result) => {
@ -97,6 +145,10 @@ function CoderDepot(props){
setLastCommit(c && c.commit);
setLastCommitAuthor(c && c.committer);
setMainFlag(true);
setReadOnly(true);
setReadme(result.data.readme);
setEditReadme(false);
setHide(true);
}
setTimeout(function(){setIsSpin(false);},500);
}).catch(error=>{setIsSpin(false);})
@ -108,7 +160,7 @@ function CoderDepot(props){
let ele = document.getElementById("ptxt");
if(ele){
let h = ele.offsetHeight;
if( h > 18 ) setHideBtn(true)
if( h > 18 ) setHideBtn(true);
}
}
},[projectDetail,lastCommit])
@ -138,6 +190,8 @@ function CoderDepot(props){
setLastCommit(c && c.commit);
setLastCommitAuthor(c && c.committer);
setMainFlag(false);
setReadOnly(!editReadme);
setHide(true);
}
setTimeout(function(){setIsSpin(false);},500)
}).catch(error=>{setIsSpin(false);})
@ -145,17 +199,26 @@ function CoderDepot(props){
//
function changeBranch(value){
let url = `/projects/${owner}/${projectsId}${value && `/tree/${value}`}${treeValue ? `/${treeValue}`:""}`;
let checkvalue = turnbar(value);
let url = `/${owner}/${projectsId}${value && `/tree/${checkvalue}`}${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>
function fileMenu(){
let b = branchName || defaultBranch;
let checkvalue = turnbar(b);
return (
<Menu className="fileMenu">
<Menu.Item>
<CheckProfile {...props} sureFunc={()=>urlLink(`/${owner}/${projectsId}/${checkvalue}/uploadfile${treeValue === undefined ? "" : `/${treeValue}`}`)}>上传文件</CheckProfile>
</Menu.Item>
<Menu.Item>
<CheckProfile {...props} sureFunc={()=>urlLink(`/${owner}/${projectsId}/${checkvalue}/newfile${treeValue === undefined ? "" : `/${treeValue}`}`)}>新建文件</CheckProfile>
</Menu.Item>
</Menu>
)
)
}
function getPathUrl(array,index){
if(array && array.length>0 && index){
@ -169,27 +232,36 @@ function CoderDepot(props){
//
function returnMain(){
setTreeValue(undefined);
let branch = branchName || (projectDetail && projectDetail.default_branch);
props.history.push(`/projects/${owner}/${projectsId}/tree/${branch}`);
let branch = branchName || defaultBranch;
let checkvalue = turnbar(branch);
props.history.push(`/${owner}/${projectsId}/tree/${checkvalue}`);
};
//
function returnUlr(url){
props.history.push(`/projects/${owner}/${projectsId}/tree${branchName?`/${branchName}`:""}/${url}`);
let enBranch = turnbar(branchName);
props.history.push(`/${owner}/${projectsId}/tree${enBranch?`/${enBranch}`:""}/${url}`);
}
//
function goToSubRoot(path,type,filename){
setType(type);
props.history.push(`/projects/${owner}/${projectsId}${`/tree/${branchName || (projectDetail && projectDetail.default_branch)}`}${path?`/${path}`:""}`);
if(type!=="submodule"){
let enBranch = branchName || defaultBranch;
let checkvalue = turnbar(enBranch);
setType(type);
props.history.push(`/${owner}/${projectsId}${`/tree/${checkvalue}`}${path?`/${path}`:""}`);
}
}
function onEdit(readOnly){
setReadOnly(readOnly);
setEditReadme(false);
}
function ChangeFile(path, readOnly){
//
props.history.push(`/projects/${owner}/${projectsId}/tree/${branchName || (projectDetail && projectDetail.default_branch)}/${path}`);
let enBranch = branchName || defaultBranch;
let checkvalue = turnbar(enBranch);
props.history.push(`/${owner}/${projectsId}/tree/${checkvalue}/${path}`);
setType("file");
setReadOnly(readOnly);
setEditReadme(true);
};
function changeHide(hide){
@ -205,17 +277,12 @@ function CoderDepot(props){
}
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>
<CloneAddress
http_url={projectDetail && projectDetail.clone_url}
ssh_url = {projectDetail && projectDetail.ssh_url}
zip_url={zip_url}
tar_url={tar_url}
showNotification={props.showNotification}/>
)
// website
function okUpdate(d,w,l){
@ -230,10 +297,13 @@ function CoderDepot(props){
}
})
}
let n = fileInfo && fileInfo.name;
const mdFlag = n && n.substring(n.length-3,n.length) === ".md";
const { current_user } = props;
const baseOperate = projectDetail && projectDetail.permission && projectDetail.permission !=="Reporter";
const fileOperate = type === "dir" && projectDetail && projectDetail.type !== 2 && ((projectDetail.permission && projectDetail.permission !=="Reporter") || (current_user && current_user.admin));
return(
<WhiteBack>
<UpdateDescModal desc={desc} website={website} lesson_url={lesson_url} visible={openModal} onCancel={()=>setOpenModal(false)} onOk={okUpdate}/>
@ -246,13 +316,13 @@ function CoderDepot(props){
owner={owner}
projectsId={projectsId}
name={projectDetail && projectDetail.name}
branch={branchName || (projectDetail && projectDetail.default_branch)}
branch={branchName || defaultBranch}
visible={visible}
onClose={()=>setVisible(false)}
list = {mainFlag ? dirInfo : undefined}
/>
<div className="drawerBtn" onClick={()=>setVisible(true)}>
<i className="iconfont icon-youjiantou font-16"></i>
<i className="iconfont icon-zuohuaicon font-14"></i>
<span>目录</span>
</div>
</React.Fragment>
@ -265,66 +335,86 @@ function CoderDepot(props){
<div className="panelmenu">
<FlexAJ>
<AlignCenter>
<div className="mr20">
<div className="mr30">
{
props && props.platform ?
<SelectBranch
repo_id={projectDetail && projectDetail.repo_id}
projectsId={projectsId}
branch={branchName || (projectDetail && projectDetail.default_branch)}
branch={branchName || defaultBranch}
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>
<span>分支<span className="color-grey-6">{branchName || defaultBranch}</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 to={`/${owner}/${projectsId}/branches`} className="iconBtn">
<i className="iconfont icon-master_icon font-16"></i>
<span>分支</span>
<span>{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 to={`/${owner}/${projectsId}/tags`} className="iconBtn">
<i className="iconfont icon-biaoqianicon font-16"></i>
<span>标签</span>
<span>{projectDetail && projectDetail.tags && projectDetail.tags.total_count}</span>
</Link>
</AlignCenter>
</AlignCenter>
<AlignCenter>
<div className="mr20 addOptionBtn">
{
projectDetail.type !== 2 &&
<a onClick={()=>urlLink(`/projects/${owner}/${projectsId}/pulls/new`)} >+ 合并请求</a>
}
<a onClick={()=>urlLink(`/projects/${owner}/${projectsId}/issues/new`)} >+ 任务</a>
</div>
{ type === "dir" && projectDetail.type !== 2 &&
<Dropdown overlay={fileMenu} className="mr20">
<Button type="default">文件 <i className="iconfont icon-sanjiaoxing-down ml3 font-14 color-grey-9"></i></Button>
<AlignCenter className="depotBtn">
{
baseOperate && ((projectDetail.type !== 2 && pullsFlag) || issuesFlag )&&
<div className="addOptionBtn">
{
projectDetail.type !== 2 && pullsFlag &&
<CheckProfile {...props} sureFunc={()=>urlLink(`/${owner}/${projectsId}/pulls/new`)} >+ 合并请求</CheckProfile>
}
{
issuesFlag &&
<CheckProfile {...props} sureFunc={()=>urlLink(`/${owner}/${projectsId}/issues/new`)} >+ 易修</CheckProfile>
}
</div>
}
{ fileOperate &&
<Dropdown
overlay={fileMenu()}
className="mr10"
trigger={['click']}
getPopupContainer={document.parentNode}
>
<a>文件 <i className="iconfont icon-sanjiaoxing-down ml3 font-14 color-grey-6 mr-5"></i></a>
</Dropdown>
}
<Dropdown overlay={downloadMenu} placement="bottomRight">
<Button type={'primary'}>下载 <i className="iconfont icon-sanjiaoxing-down ml3 font-14 color-white"></i></Button>
<Dropdown overlay={downloadMenu} placement="bottomRight" trigger={['click']}>
<Button type={'primary'}>下载 <i className="iconfont icon-sanjiaoxing-down ml3 font-14 color-white mr-3"></i></Button>
</Dropdown>
</AlignCenter>
</FlexAJ>
{
dirInfo || fileInfo ?
(dirInfo && dirInfo.length>0) || fileInfo ?
<div className="listtable">
{
lastCommit &&
<div className="listtablehead">
<User url={getImageUrl(`/${lastCommitAuthor && lastCommitAuthor.image_url}`)} name={lastCommitAuthor && lastCommitAuthor.name} id={lastCommitAuthor && lastCommitAuthor.id} login={lastCommitAuthor && lastCommitAuthor.login}/>
<div className={hideBtn && hide ? "ellipsistxt hide" :"ellipsistxt"}><p id="ptxt">{lastCommit && lastCommit.message}</p></div>
<div onClick={()=>props.history.push(`/${owner}/${projectsId}/commits/${truncateCommitId(lastCommit.sha)}`)} className={hideBtn && hide ? "ellipsistxt hidetxt" :"ellipsistxt"}>
<pre id="ptxt">{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>:"" }
<span className="ml20 color-grey-6 font-12 mt3">{lastCommit.time_from_now}</span>
{
commitCount ?
<Link to={`/${owner}/${projectsId}/commits/branch/${turnbar(branchName || defaultBranch)}`} className="ml20 color-grey-3"style={{height:"28px",lineHeight:"28px"}}>
<i className="iconfont icon-tijiaoicon mr3 font-16"></i><span style={{fontWeight:"500"}}>{commitCount}次提交</span>
</Link>:""
}
</div>
}
<ul className="listtablebody">
@ -359,7 +449,7 @@ function CoderDepot(props){
readOnly={readOnly}
md={mdFlag}
onEdit={onEdit}
currentBranch={branchName || (projectDetail && projectDetail.default_branch)}
currentBranch={branchName || defaultBranch}
type={projectDetail.type}
></CoderRootFileDetail>
}
@ -368,10 +458,10 @@ function CoderDepot(props){
: ""
}
{
(dirInfo && dirInfo.length === 0) && (fileInfo && fileInfo.length === 0) ? <Nodata _html="暂未发现文件"/> :""
(dirInfo && dirInfo.length === 0) && !fileInfo ? <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} /> :"" }
{ dirInfo && (readme && readme.content) ? <ReadMe ChangeFile={ChangeFile} readme={readme} operate={props && (props.isManager || props.isDeveloper) && projectDetail.type !==2 } history={props.history} /> :"" }
</div>
</LongWidth>
{
@ -379,39 +469,49 @@ function CoderDepot(props){
<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 className="font-18 color-ooo mb20" style={{lineHeight:"28px"}}>关于
{
projectDetail.permission && (projectDetail.permission==="Admin" || projectDetail.permission==="Owner" || projectDetail.permission==="Manager") &&
<i onClick={()=>setOpenModal(true)} className="iconfont icon-a-shezhi color-grey-9 font-15"></i>
}
</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>}
{desc && <p className="font-14 color-grey-3 mb15 task-hide-2" style={{lineHeight:"24px",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>
<div className="color-grey-6 df pinfos mb5">
<i className="iconfont icon-lianjie2 font-15 mr10"></i>
<a href={website} target="_blank" style={{wordBreak:"break-all",lineHeight:"20px",marginTop:"5px",textDecoration:"underline"}}>{website}</a>
</p>
</div>
}
<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>
<div className="pinfos mb5">
<i className="iconfont icon-zishuwenjian_icon font-15 mr10"></i>
<a href="#readme">README.md</a>
</div>
<div className="color-grey-6 mb5">
<i className="iconfont icon-neicunicon font-15 mr10"></i>
<span>{projectDetail && projectDetail.size}</span>
</p>
</div>
{
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 className="pinfos">
<i className="iconfont icon-xieyiicon font-16 mr10"></i>
<Link to={`/${owner}/${projectsId}/tree/${branchName || defaultBranch}/LICENSE`} className="color-grey-6">{projectDetail.license_name}</Link>
</div>
}
</div>
{
inviteCode &&
<div>
<Divider />
<Invite code={inviteCode}/>
</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>
<p className="font-16 color-ooo">实践课程</p>
<a href={lesson_url} target="_blank" className="color-grey-6" style={{textDecoration:"underline",wordBreak:"break-all"}}>{lesson_url}</a>
</div>
}
{/* 发布 */}
@ -419,16 +519,23 @@ function CoderDepot(props){
projectDetail && projectDetail.release_versions &&
<React.Fragment>
<Divider />
<Releases owner={owner} projectsId={projectsId} releaseVersions={projectDetail.release_versions} history={props.history}/>
<Releases
owner={owner}
projectsId={projectsId}
releaseVersions={projectDetail.release_versions}
history={props.history}
baseOperate={baseOperate}
projectType={projectDetail.type}
/>
</React.Fragment>
}
{/* 贡献者 */}
{
projectDetail && projectDetail.contributors &&
<Contributors contributors={projectDetail && projectDetail.contributors} owner={owner} projectsId={projectsId} />
projectDetail && projectDetail.contributors && projectDetail.contributors.total_count >0 &&
<Contributors contributors={projectDetail.contributors} owner={owner} projectsId={projectsId} />
}
{/* 语言 */}
{ projectDetail && projectDetail.languages &&
{ projectDetail && projectDetail.languages &&
<React.Fragment>
<Divider />
<LanguagePower languages={projectDetail.languages}/>

View File

@ -2,20 +2,26 @@ import React from 'react';
import { Link } from 'react-router-dom';
import { truncateCommitId } from '../common/util';
const typeIco = {
"submodule":"icon-file-submodule font-17",
"file":'icon-wenjian6 font-15 color-blue-file',
"dir":"icon-wenjianjia4 font-15 color-blue_4C"
}
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 onClick={()=>goToSubRoot(item.path,item.type,item.name)} className={item.type === "submodule" && "submoduleStyle"}>
<i className={`iconfont ${typeIco[`${item.type}`]} mr8`}></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}>
<Link to={`/${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>
<span title={item.commit && item.commit.created_at}>{item.commit && item.commit.time_from_now}</span>
</li>
)
}

View File

@ -1,61 +1,74 @@
import React, { useEffect, useState } from 'react';
import RenderHtml from '../../components/render-html';
import { Dropdown , Menu , Spin } from 'antd';
import { Link } from 'react-router-dom';
import { AlignCenter } from '../Component/layout';
import { Dropdown , Anchor , Spin } from 'antd';
import ReadmeCatelogue from './sub/ReadmeCatelogue';
const $ = window.$;
function CoderDepotReadme({ operate , history , readme , ChangeFile }){
const [ menuList ,setMenuList ] = useState(undefined);
const [ content ,setContent ] = 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);
setContent(readme.content);
}else{
setContent(undefined);
}
},[readme])
useEffect(()=>{
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:`${href}`,text:el.textContent , level:level }
});
setMenuList(items);
},[content])
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>
<ReadmeCatelogue menuList={menuList} hash={history.location.hash}/>
)
}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 className="commonBox readBox" id="readme">
<Anchor offsetTop={70} targetOffset={160}>
<div className="commonBox-title boxTitle">
<AlignCenter>
<Dropdown overlay={menu()} trigger={['hover']} overlayClassName="menuslist">
<span className="catelogue">
<i className="iconfont icon-muluicon font-12 mr5"></i>
<span>目录</span>
</span>
</Dropdown>
<span className="commonBox-title-read"><a href="#readme ">README.md</a></span>
</AlignCenter>
{
operate ?
<a className="ml20 pull-right" onClick={() =>ChangeFile(readme && readme.path, false)}>
<i className="iconfont icon-a-bianji font-17 color-grey-6"></i>
</a>
:""
}
</div>
</Anchor>
{
content &&
<div className="commonBox-info">
<RenderHtml className="break_word_comments imageLayerParent" value={content} url={history.location}/>
</div>
}
</div>
)
}

View File

@ -4,14 +4,20 @@ import { Dropdown , Menu , Icon , Tooltip , Spin } from 'antd';
import { truncateCommitId } from '../common/util';
import { getBranch } from '../GetData/getData';
import Nodata from '../Nodata';
import './list.css';
import './list.scss';
function turnbar(str){
if(str && str.length>0 && str.indexOf("/")>-1){
return str.replaceAll('/','%2F');
}
return str;
}
export default ((props)=>{
const [ data , setData ] =useState(undefined);
const [ isSpin , setIsSpin ] =useState(true);
const { projectsId , owner } = props.match.params;
const { isManager , isDeveloper , projectDetail } = props;
useEffect(()=>{
getBranchs(projectsId, owner);
},[projectsId])
@ -32,15 +38,18 @@ 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={`/${owner}/${projectsId}/tree/${turnbar(item.name)}`} className="color-blue font-15" style={{"maxWidth":"100px"}}>{item.name}</Link>
<p className="f-wrap-alignCenter mt15">
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${item.last_commit.sha}`)}`} className="mr5 commitKey" style={{marginLeft:0}}>{item.last_commit && truncateCommitId(item.last_commit.sha)}</Link>
<Link to={`/${owner}/${projectsId}/commits/${truncateCommitId(`${item.last_commit.sha}`)}`} className="mr5 commitKey" style={{marginLeft:0}}>{item.last_commit && truncateCommitId(item.last_commit.sha)}</Link>
<span className="color-grey-3 hide-1 messages leftPoint">{item.last_commit && item.last_commit.message}</span>
<span className="color-grey-8 ml30">最后更新于{item.last_commit && item.last_commit.time_from_now}</span>
</p>
</div>
<span>
<Link to={`/projects/${owner}/${projectsId}/pulls/new`} className="mr20 color-blue mr30">创建合并请求</Link>
{
(isManager || isDeveloper) && (projectDetail && projectDetail.type!==2) &&
<Link to={`/${owner}/${projectsId}/pulls/new/${item.name}`} className="mr20 color-blue mr30">创建合并请求</Link>
}
<Dropdown overlay={menu(item.zip_url,item.tar_url)} trigger={['click']} placement="bottomRight" className="color-green-file">
<a className="ant-dropdown-link">
<Tooltip title={`下载分支${item.name}`}><Icon type="cloud-download" className="font-18"/></Tooltip>
@ -64,6 +73,7 @@ export default ((props)=>{
<Menu.Item key={'1'}><a href={tar_url}>TAR.GZ</a></Menu.Item>
</Menu>
)
return(
<React.Fragment>
<div className="main">

View File

@ -2,12 +2,19 @@ import React , { Component } from 'react';
import { Spin , Pagination } from 'antd';
import { getImageUrl } from 'educoder';
import { truncateCommitId } from '../common/util';
import { AlignTop } from '../Component/layout';
import SelectBranch from '../Branch/Select';
import Nodata from '../Nodata';
import axios from 'axios';
import {Link} from "react-router-dom";
function returnbar(str){
if(str && str.length>0 && str.indexOf("%2F")>-1){
return str.replaceAll('%2F','/');
}
return str;
}
class CoderRootCommit extends Component{
constructor(props){
super(props)
@ -56,11 +63,12 @@ class CoderRootCommit extends Component{
this.setState({
isSpining:true
})
console.log(returnbar(branch));
const { projectsId , owner } = this.props.match.params;
const url = `/${owner}/${projectsId}/commits.json`;
axios.get(url,{
params:{
sha:branch,
sha:returnbar(branch),
page,
limit
}
@ -93,7 +101,7 @@ class CoderRootCommit extends Component{
// 切换分支 search:tag为根据标签搜索
changeBranch=(value)=>{
const { projectsId , owner } = this.props.match.params;
this.props.history.push(`/projects/${owner}/${projectsId}/commits/branch/${value}`);
this.props.history.push(`/${owner}/${projectsId}/commits/branch/${value}`);
}
ChangePage=(page)=>{
@ -105,10 +113,10 @@ class CoderRootCommit extends Component{
const { commitDatas , dataCount , limit , page , isSpining , branchList } = this.state;
const { projectDetail, commit_class , defaultBranch } = this.props;
const { projectsId , owner , branchName } = this.props.match.params;
let branch = branchName || defaultBranch;
let branch = returnbar(branchName || defaultBranch);
return(
<React.Fragment>
<div className={"main"}>
<div className={"main"}style={{padding:"0px",border:"none"}}>
<div className="f-wrap-between">
<SelectBranch
repo_id={projectDetail && projectDetail.repo_id}
@ -132,14 +140,14 @@ class CoderRootCommit extends Component{
commitDatas && commitDatas.length > 0 && commitDatas.map((item,k)=>{
return(
<div key={k}>
<p className="f-wrap-alignCenter">
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${item.sha}`)}`} className="commitKey" style={{marginLeft:0}}>{truncateCommitId(`${item.sha}`)}</Link>
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${item.sha}`)}`} className="flex1 ml20 font-16 color-grey-3">{item.message}</Link>
</p>
<AlignTop>
<Link to={`/${owner}/${projectsId}/commits/${truncateCommitId(`${item.sha}`)}`} className="commitKey" style={{marginLeft:0,marginTop:"3px"}}>{truncateCommitId(`${item.sha}`)}</Link>
<Link to={`/${owner}/${projectsId}/commits/${truncateCommitId(`${item.sha}`)}`} className="commitDesc">{item.message}</Link>
</AlignTop>
<p className="f-wrap-alignCenter mt15">
{
item.id ?
<Link to={`/users/${item.login}`} className="show-user-link">
<Link to={`/${item.login}`} 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>
</Link>:

View File

@ -1,6 +1,6 @@
import React, { Component } from "react";
import { Popconfirm , Select } from "antd";
import "./list.css";
import "./list.scss";
import axios from "axios";
import Meditor from "../Newfile/m_editor";
import RenderHtml from "../../components/render-html";
@ -149,7 +149,7 @@ class CoderRootFileDetail extends Component {
.then((result) => {
if (result) {
this.props.showNotification("删除成功!");
this.props.history.push(`/projects/${owner}/${projectsId}`);
this.props.history.push(`/${owner}/${projectsId}`);
}
})
.catch((error) => {
@ -285,6 +285,7 @@ class CoderRootFileDetail extends Component {
readOnly={readOnly}
editorType="update"
currentBranch={currentBranch}
descName={detail && `Update ${detail.name}`}
></Meditor>
)}
</div>

View File

@ -87,52 +87,57 @@ class CoderRootIndex extends Component{
<Top {...this.props} {...this.state}/>
<Switch {...this.props}>
{/* 新建文件 */}
<Route path="/projects/:owner/:projectsId/:branch/newfile/:path"
<Route path="/:owner/:projectsId/:branch/newfile/:path"
render={
(props) => (<FileNew {...this.props} {...props} {...this.state} />)
}
></Route>
<Route path="/projects/:owner/:projectsId/:branch/uploadfile"
<Route path="/:owner/:projectsId/:branch/uploadfile"
render={
(props) => (<UploadFile {...this.props} {...props} {...this.state} />)
}
></Route>
<Route path="/projects/:owner/:projectsId/:branch/newfile"
<Route path="/:owner/:projectsId/:branch/newfile"
render={
(props) => (<FileNew {...this.props} {...props} {...this.state} getTopCount={this.getTopCount} />)
}
></Route>
<Route path="/projects/:owner/:projectsId/commits/:sha"
render={
(props) => (<Diff {...this.props} {...props} {...this.state}/>)
}
></Route>
<Route path="/projects/:owner/:projectsId/commits"
<Route path="/:owner/:projectsId/commits/branch/:branchName"
render={
() => (<CoderRootCommit {...this.props} {...this.state} commit_class="main" getTopCount={this.getTopCount} />)
}
></Route>
<Route path="/projects/:owner/:projectsId/releases/:versionId/update"
<Route path="/:owner/:projectsId/commits/:sha"
render={
(props) => (<Diff {...this.props} {...props} {...this.state}/>)
}
></Route>
<Route path="/:owner/:projectsId/commits"
render={
() => (<CoderRootCommit {...this.props} {...this.state} commit_class="main" getTopCount={this.getTopCount} />)
}
></Route>
<Route path="/:owner/:projectsId/releases/:versionId/update"
render={
(props) => (<CoderRootVersionUpdate {...this.props} {...this.state} {...props} />)
}
></Route>
<Route path="/projects/:owner/:projectsId/releases/new"
<Route path="/:owner/:projectsId/releases/new"
render={
() => (<CoderRootVersionNew {...this.props} {...this.state} />)
}
></Route>
<Route path="/projects/:owner/:projectsId/releases"
<Route path="/:owner/:projectsId/releases"
render={
() => (<CoderRootVersion {...this.props} {...this.state} />)
}
></Route>
<Route path="/projects/:owner/:projectsId/tag"
<Route path="/:owner/:projectsId/tags"
render={
() => (<CoderRootTag {...this.props} {...this.state} />)
}
></Route>
<Route path="/projects/:owner/:projectsId/branchs"
<Route path="/:owner/:projectsId/branches"
render={
() => (<CoderRootBranch {...this.props} {...this.state} />)
}

View File

@ -26,7 +26,7 @@ export default (( props, { projectDetail }) => {
}, [owner, projectsId]);
return (
<div className="main">
<div className="main" style={{padding:"0px",border:"none"}}>
<Spin spinning={isSpin}>
<div style={{minHeight:"400px"}}>
{
@ -34,7 +34,7 @@ export default (( props, { projectDetail }) => {
<div className="div_table">
<ul className="ul_thead">
<li>
<span className="flex1"></span>
<span className="flex1"></span>
<span>提交信息</span>
<span className="ul_tbody_forth">下载</span>
</li>
@ -49,7 +49,7 @@ export default (( props, { projectDetail }) => {
<span className="font-16">{item.name}</span>
</span>
<span className="ul_tbody_third">
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${item.id}`)}`} className="commitKey" style={{ "marginLeft": 0 }}>{truncateCommitId(`${item.id}`)}</Link>
<Link to={`/${owner}/${projectsId}/commits/${truncateCommitId(`${item.id}`)}`} className="commitKey" style={{ "marginLeft": 0 }}>{truncateCommitId(`${item.id}`)}</Link>
</span>
<span className="ul_tbody_forth">
<a href={item.tarball_url} style={{ color: "#4CC1DA" }} className="mr30"><i className="iconfont icon-TAR font-18 mr5"></i>TAR</a>

View File

@ -1,10 +1,13 @@
import React, { Component } from 'react';
import { Spin, Tooltip } from 'antd';
import { Link, Route, Switch } from 'react-router-dom';
import { Content } from '../Component/layout';
import { Content, AlignTop } from '../Component/layout';
import DetailBanner from './sub/DetailBanner';
import '../css/index.scss'
import './list.css';
import './list.scss';
import { ImageLayerOfCommentHOC } from "../../modules/page/layers/ImageLayerOfCommentHOC";
import Loadable from 'react-loadable';
import Loading from '../../Loading';
@ -103,12 +106,12 @@ const Contribute = Loadable({
})
const CoderRootCommit = Loadable({
loader: () => import('./CoderRootCommit'),
loading: Loading,
loader: () => import('./CoderRootCommit'),
loading: Loading,
})
const CoderDepot = Loadable({
loader: () => import('./CoderDepot'),
loading: Loading,
loader: () => import('./CoderDepot'),
loading: Loading,
})
const TrendsIndex = Loadable({
@ -127,30 +130,40 @@ const Source = Loadable({
const DevIndex = Loadable({
loader: () => import('../DevOps/Index'),
loading: Loading,
})
});
const Wiki = Loadable({
loader: () => import('../Wiki/Index'),
loading: Loading,
});
const WikiEdit = Loadable({
loader: () => import('../Wiki/EditWiki'),
loading: Loading,
});
/**
* permissionManager:管理员Reporter报告人员(只有读取权限)Developer开发人员除不能设置仓库信息外
*/
function checkPathname(projectsId,owner,pathname){
function checkPathname(projectsId, owner, pathname) {
let name = "";
if(pathname && pathname !== `/projects/${owner}/${projectsId}`){
let url = pathname.split(`/projects/${owner}/${projectsId}`)[1];
if(url.indexOf("/about")>-1){
name="about"
}else if(url.indexOf("/issues")>-1 ||url.indexOf("Milepost") > 0){
if (pathname && pathname !== `/${owner}/${projectsId}`) {
let url = pathname.split(`/${owner}/${projectsId}`)[1] || "";
if (url.indexOf("/about") > -1) {
name = "about"
} else if (url.indexOf("/issues") > -1 || url.indexOf("Milepost") > 0) {
name = "issues";
}else if(url.indexOf("/pulls")>-1){
name="pulls"
}else if(url.indexOf("/milestones")>-1){
name="milestones"
}else if(url.indexOf("/activity")>-1){
name="activity"
}else if(url.indexOf("/setting")>-1){
name="setting"
}else if(url.indexOf(`/devops`)>-1){
name="devops"
}else if(url.indexOf(`/source`)>-1){
name="source"
} else if (url.indexOf("/pulls") > -1) {
name = "pulls"
} else if (url.indexOf("/milestones") > -1) {
name = "milestones"
} else if (url.indexOf("/activity") > -1) {
name = "activity"
} else if (url.indexOf("/settings") > -1) {
name = "settings"
} else if (url.indexOf(`/devops`) > -1) {
name = "devops"
} else if (url.indexOf(`/source`) > -1) {
name = "source"
} else if (url.indexOf(`/wiki`) > -1) {
name = "wiki"
}
}
return name;
@ -173,14 +186,15 @@ class Detail extends Component {
branchs: undefined,
branchList: undefined,
project: null,
firstSync:false,
secondSync:false,
open_devops:false,
firstSync: false,
secondSync: false,
open_devops: false,
forkSpin: false,
// 默认分支
defaultBranch:undefined,
defaultBranch: undefined,
// 非本平台项目
platform:false
platform: false
}
}
@ -197,36 +211,38 @@ class Detail extends Component {
}
getProject = (num) => {
const { projectsId , owner } = this.props.match.params;
const { projectsId, owner } = this.props.match.params;
const url = `/${owner}/${projectsId}/simple.json`;
axios.get(url).then((result) => {
if (result && result.data) {
this.setState({
project: result.data,
open_devops:result.data.open_devops,
platform:result.data.platform && result.data.platform !== 'educoder'
open_devops: result.data.open_devops,
platform: result.data.platform && result.data.platform !== 'educoder'
})
if (result.data.type !== 0 && result.data.mirror_status === 1) {
console.log("--------start channel --------");
// 是镜像项目,且未完成迁移
this.canvasChannel();
if(num){
if (num) {
this.setState({
secondSync:true,
firsrtSync:false
secondSync: true,
firstSync: false
})
}else{
} else {
this.setState({
firstSync:true,
secondSync:false
firstSync: true,
secondSync: false
})
}
}else{
} else if (result.data.mirror_status === 2) {
this.deleteProjectBack();
} else {
this.getDetail();
this.setState({
firsrtSync:false,
secondSync:false
firstSync: false,
secondSync: false
})
}
}
@ -234,19 +250,23 @@ class Detail extends Component {
}
// 工作流激活后修改状态
changeOpenDevops=(flag)=>{
changeOpenDevops = (flag) => {
this.setState({
open_devops:flag
open_devops: flag
})
}
canvasChannel = () => {
/**
*
* @param {*} deleteFlag 同步镜像需要提示成功且未成功的情况下不需要删除项目
*/
canvasChannel = (deleteFlag) => {
const name = window.location.hostname === "localhost" ? "testforgeplus.trustie.net" : window.location.hostname;
const actioncable = require("actioncable");
var project = this.state.project;
var cable = actioncable.createConsumer(`wss://${name}/cable`);
this.canvasChannel1 = cable.subscriptions.create({
channel: `MirrorProjectChannel`,
id: project && project.identifier
id: project && project.id
}, {
connected: () => {
console.log("###### channel connected! ######");
@ -254,16 +274,46 @@ class Detail extends Component {
disconnected: () => { },
received: data => {
console.log(`###### ---received data--- ######`);
console.log(data);
if (data) {
this.getDetail();
if(deleteFlag){
this.props.showNotification("镜像同步成功!");
window.location.reload();
}else{
if (data.project && data.project.mirror_status === 2) {
this.deleteProjectBack();
}
this.getDetail();
}
this.setState({
firstSync: false,
secondSync: false
});
cable.subscriptions.consumer.disconnect();
}
}
})
}
deleteProjectBack = () => {
const { history } = this.props;
const { projectsId, owner } = this.props.match.params;
axios.delete(`/${owner}/${projectsId}.json`).then(res => {
let hash = '/projects/mirror/new';
if (res && res.data) {
history.push({
pathname: hash,
mirror_status: 2
});
}
else {
window.location.hash = hash;
}
});
}
getDetail = () => {
const { projectsId , owner } = this.props.match.params;
const { projectsId, owner } = this.props.match.params;
this.getBanner();
const url = `/${owner}/${projectsId}/detail.json`;
axios.get(url).then((result) => {
@ -280,29 +330,29 @@ class Detail extends Component {
watchers_count: result.data.watchers_count,
praises_count: result.data.praises_count,
forked_count: result.data.forked_count,
defaultBranch:result.data.default_branch
defaultBranch: result.data.default_branch
})
}
}).catch((error) => { })
}
// 获取动态导航栏菜单
getBanner(){
const { projectsId , owner } = this.props.match.params;
getBanner() {
const { projectsId, owner } = this.props.match.params;
const url = `/${owner}/${projectsId}/menu_list.json`;
axios.get(url).then(result=>{
if(result){
axios.get(url).then(result => {
if (result) {
this.setState({
bannerList:result.data
bannerList: result.data
})
}
}).catch(error=>{})
}).catch(error => { })
}
// 关注和取消关注
focusFunc = (flag) => {
const { platform } = this.state;
if(!platform)return;
if (!platform) return;
const { project_id } = this.state;
axios({
@ -317,15 +367,15 @@ class Detail extends Component {
this.setWatchersCount(result.data.watchers_count, result.data.watched);
}
})
.catch(error => {
console.log(error);
});
.catch(error => {
console.log(error);
});
}
// 点赞和取消点赞
pariseFunc = (flag) => {
const { platform } = this.state;
if(!platform)return;
if (!platform) return;
const { project_id } = this.state;
axios({
method: flag ? 'delete' : 'post',
@ -335,9 +385,9 @@ class Detail extends Component {
this.setPraisesCount(result.data.praises_count, result.data.praised)
}
})
.catch(error => {
console.log(error);
});
.catch(error => {
console.log(error);
});
}
setWatchersCount = (count, is_watched) => {
@ -357,30 +407,40 @@ class Detail extends Component {
// fork项目
forkFunc = () => {
const { platform } = this.state;
if(!platform)return;
if (!platform) return;
this.setState({
forkSpin: true
})
const { current_user } = this.props
const { projectsId , owner } = this.props.match.params;
const { projectsId, owner } = this.props.match.params;
const url = `/${owner}/${projectsId}/forks.json`;
axios.post(url).then(result => {
if (result && result.data.status === 0) {
this.props.history.push(`/projects/${current_user && current_user.login}/${result.data.identifier}`);
this.props.history.push(`/${current_user && current_user.login}/${result.data.identifier}`);
this.props.showNotification(result.data.message);
}
this.setState({
forkSpin: false
})
}).catch(error => {
console.log(error);
this.setState({
forkSpin: false
})
})
}
// 同步镜像
synchronismMirror = () => {
const { platform } = this.state;
if(!platform)return;
const { projectsId , owner } = this.props.match.params;
if (!platform) return;
const { projectsId, owner } = this.props.match.params;
const url = `/${owner}/${projectsId}/sync_mirror.json`;
axios.post(url).then(result => {
if (result && result.data && result.data.status === 0) {
this.props.showNotification("镜像同步成功!");
this.getProject(2);
this.setState({
secondSync:true
})
this.canvasChannel(true);
} else {
this.props.showNotification("镜像同步失败!");
}
@ -389,330 +449,352 @@ class Detail extends Component {
})
}
textFunc = (forked_from_project_id, fork_info) => {
let type = fork_info && fork_info.fork_project_user_type;
return forked_from_project_id && fork_info ?
<div className="color-grey-9 df">
<span>复刻自</span>
<Link to={`/${fork_info.fork_project_user_login}`} className="show-user-link color-grey-6 ml5">{fork_info.fork_project_user_name}</Link>
<span> / </span>
<Link to={`/${fork_info.fork_project_user_login}/${fork_info.fork_project_identifier}`} className="color-grey-6 task-hide flex1" style={{ maxWidth: "400px" }} title={fork_info.fork_form_name}>{fork_info.fork_form_name}</Link>
</div> : ""
}
render() {
const { projectDetail, watchers_count, praises_count,
forked_count, firstSync , secondSync ,
isManager, watched, praised,
project , open_devops , platform , defaultBranch , bannerList } = this.state;
const { projectDetail, watchers_count, praises_count,
forked_count, firstSync, secondSync,
isManager, watched, praised,
project, open_devops, platform, defaultBranch, bannerList, forkSpin } = this.state;
const url = this.props.history.location.pathname;
const urlArr = url.split("/");
const urlFlag = (urlArr.length === 3);
const { projectsId , owner } = this.props.match.params;
let pathname = checkPathname(projectsId,owner,url);
const { projectsId, owner } = this.props.match.params;
const { current_user } = this.props;
let pathname = checkPathname(projectsId, owner, url);
const { state } = this.props.history.location;
const text = (
projectDetail && projectDetail.forked_from_project_id && projectDetail.fork_info ?
<React.Fragment>
<span>forked from </span>
<Link to={`/users/${projectDetail.fork_info.fork_project_user_login}`} className="show-user-link color-grey-ccc">{projectDetail.fork_info.fork_project_user_name}</Link>
<span> / </span>
<Link to={`/projects/${projectDetail.fork_info.fork_project_user_login}/${projectDetail.fork_info.fork_project_identifier}`} className="color-grey-ccc">{projectDetail.fork_info.fork_form_name}</Link>
</React.Fragment> : ""
);
const common = {
getDetail: this.getDetail,
changeOpenDevops:this.changeOpenDevops,
changeOpenDevops: this.changeOpenDevops,
defaultBranch
}
return (
<div>
<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" }}>
{project && project.author &&
<Link to={`${project.author.type ==="Organization" ? "/organize":'/users'}/${project.author.login}`} className="show-user-link">
{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>
<AlignTop style={{ padding: "18px 0px 10px", justifyContent: "space-between" }}>
<div>
<AlignTop>
<div className="projectallName">
{project && project.author &&
<Link to={`/${project.author.login}`}>{project.author.name}</Link>
}
<span className="ml5 mr5">/</span>
<Link to={`/${owner}/${projectsId}`} className="projectN mt6">{projectDetail && projectDetail.name}</Link>
</div>
{projectDetail && projectDetail.private && <span className="privateTag mt6">私有</span>}
</AlignTop>
<div className="mt8">
{
projectDetail && projectDetail.forked_from_project_id && projectDetail.fork_info ?
<Tooltip placement={'right'} title={text}>
<Link to={`/projects/${projectDetail.fork_info.fork_project_user_login}/${projectDetail.fork_info.fork_project_identifier}`}
className="ml10" >
<i className="iconfont icon-fork font-18 fl mt6" style={{ color: "#8D90E3" }}></i>
</Link>
</Tooltip> : ""
this.textFunc(projectDetail.forked_from_project_id, projectDetail.fork_info)
: ""
}
{
projectDetail && projectDetail.type && projectDetail.type !== 0 ?
projectDetail.type === 2 ?
<Tooltip title={"镜像自: " + projectDetail.mirror_url} className="ml5" placement={'right'}>
<i className="iconfont icon-banbenku font-18 mt6" style={{ color: "#8D90E3" }}/>
</Tooltip>
:
<Tooltip title={"镜像自: " + projectDetail.mirror_url} className="ml5" placement={'right'}>
<i className="iconfont icon-jingxiang font-18 color-green mt6" />
</Tooltip>
:""
projectDetail && projectDetail.type && projectDetail.type !== 0 ?
<span className="color-grey-9">导入于 <a className="color-grey-6" target="_blank" href={projectDetail.mirror_url}>{projectDetail.mirror_url}</a></span>
: ""
}
</span>
</p>
{
firstSync ? "":
<span className="df mt25">
{
projectDetail && projectDetail.type && projectDetail.type === 2 ?
<a className="synchronism ml30" onClick={this.synchronismMirror}>同步镜像</a> : ""
}
<span className="detail_tag_btn">
<a className="detail_tag_btn_name" style={{cursor:platform?"pointer":"default"}} onClick={() => this.focusFunc(watched)}>
<i className={watched ? "iconfont icon-shixing color-orange font-16 mr3":"iconfont icon-kongxing color-grey-9 font-16 mr3"}></i>
<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)}>
<i className={praised ? "iconfont icon-weibiaoti105 color-orange font-14 mr3":"iconfont icon-guanzhu color-grey-9 font-14 mr3"}></i>
<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>
</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>
</span>
}
</div>
</div>
</div>
<div>
{
firstSync ? "" :
<span className="df">
{
((current_user && current_user.admin) || isManager) && (projectDetail && projectDetail.type && projectDetail.type === 2) ?
<a className="synchronism ml30" onClick={this.synchronismMirror}>同步镜像</a> : ""
}
<span className="detail_tag_btn">
<a className="detail_tag_btn_name" style={{ cursor: platform ? "pointer" : "default" }} onClick={() => this.focusFunc(watched)}>
<i className={watched ? "iconfont icon-shixing color-orange font-16 mr3" : "iconfont icon-kongxing color-grey-9 font-16 mr3"}></i>
<span>{watched ? '取消关注' : '关注'}</span>
</a>
{
watchers_count > 0 ?
platform ?
<Link className="detail_tag_btn_count" style={{ color: `#666` }} to={platform ? { pathname: `/${owner}/${projectsId}/following`, 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)}>
<i className={praised ? "iconfont icon-weibiaoti105 color-orange font-14 mr3" : "iconfont icon-guanzhu color-grey-9 font-14 mr3"}></i>
<span>{praised ? '取消点赞' : '点赞'}</span>
</a>
{
praises_count > 0 ?
platform ?
<Link className="detail_tag_btn_count" style={{ color: `#666` }} to={{ pathname: `/${owner}/${projectsId}/stargazers`, state }}>
{praises_count}
</Link> :
<span className="detail_tag_btn_count">{praises_count}</span>
: ""
}
</span>
<span className="detail_tag_btn" loading={forkSpin}>
<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 font-16"></i><span></span>
</a>
</Tooltip>
{
forked_count > 0 ?
platform ?
<Link className="detail_tag_btn_count" to={{ pathname: `/${owner}/${projectsId}/members`, state }}>
{forked_count}
</Link>
:
<span className="detail_tag_btn_count">{forked_count}</span>
: ""
}
</span>
</span>
}
</div>
</AlignTop>
{
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}
/>
<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>
</div>
{
firstSync ?
<Content className="spincontent">
<Spin className="spinstyle" tip={project && `正在从 ${project.mirror_url} 迁移`} size="large" />
</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={
() => (<DevAbout {...this.props} {...this.state} {...common} />)
}
></Route>
{/* 工作流 */}
<Route path="/projects/:owner/:projectsId/devops"
render={
() => (<DevIndex {...this.props} {...this.state} {...common} />)
}
></Route>
{/* 标签列表 */}
<Route path="/projects/:owner/:projectsId/issues/tags"
render={
(props) => (<TagList {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 仓库设置 */}
<Route path="/projects/:owner/:projectsId/setting"
render={
(props) => (<Setting {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 任务详情 */}
<Route path="/projects/:owner/:projectsId/issues/:orderId/detail"
render={
(props) => (<OrderDetail {...this.props} {...this.state} {...props} {...common} />)
}
></Route>
{/*修改里程碑*/}
<Route path="/projects/:owner/:projectsId/milestones/:meilid/edit"
render={
(props) => (<OrderupdateMilepost {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 新建里程碑 */}
<Route path="/projects/:owner/:projectsId/milestones/new"
render={
(props) => (<OrdernewMilepost {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/*里程碑详情*/}
<Route path="/projects/:owner/:projectsId/milestones/:meilid"
render={
(props) => (<MilepostDetail {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 里程碑 */}
<Route path="/projects/:owner/:projectsId/milestones"
render={
(props) => (<OrderMilepost {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 里程碑页面新建任务 */}
<Route path="/projects/:owner/:projectsId/issues/:milepostId/new"
render={
(props) => (<OrderNew {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 新建任务 */}
<Route path="/projects/:owner/:projectsId/issues/new"
render={
(props) => (<OrderNew {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 修改详情 */}
<Route path="/projects/:owner/:projectsId/issues/:orderId/updatedetail"
render={
(props) => (<OrderupdateDetail {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 复制详情 */}
<Route path="/projects/:owner/:projectsId/issues/:orderId/copyetail"
render={
(props) => (<OrdercopyDetail {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 动态 */}
<Route path="/projects/:owner/:projectsId/activity"
render={
(props) => (<TrendsIndex {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 代码Index */}
<Route path="/projects/:owner/:projectsId/issues"
render={
(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} />)
}
></Route>
<Route path="/projects/:owner/:projectsId/pulls/:mergeId/UpdateMerge"
render={
(props) => (<UpdateMerge {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/projects/:owner/:projectsId/pulls/:mergeId/Messagecount"
render={
(props) => (<MessageCount {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/projects/:owner/:projectsId/pulls/:mergeId/MergeSubmit"
render={
(props) => (<MessageCount {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Content className="spincontent">
<Spin className="spinstyle" tip={project && `正在从 ${project.mirror_url} 迁移`} size="large" />
</Content>
:
<Spin spinning={secondSync} className="spinstyle" tip="正在同步镜像" size="large">
<Switch {...this.props}>
{/* 资源 */}
<Route path="/:owner/:projectsId/source"
render={
() => (<Source {...this.props} {...this.state} {...common} />)
}
></Route>
{/* 主页 */}
<Route path="/:owner/:projectsId/about"
render={
() => (<DevAbout {...this.props} {...this.state} {...common} />)
}
></Route>
{/* wiki新增文件 */}
<Route path="/:owner/:projectsId/wiki/add"
render={
() => (<WikiEdit {...this.props} {...this.state} {...common} />)
}
></Route>
{/* wiki编辑文件 */}
<Route path="/:owner/:projectsId/wiki/edit/:wikiName"
render={
() => (<WikiEdit {...this.props} {...this.state} {...common} />)
}
></Route>
{/* wiki */}
<Route path="/:owner/:projectsId/wiki"
render={
() => (<Wiki {...this.props} {...this.state} {...common} />)
}
></Route>
{/* 工作流 */}
<Route path="/:owner/:projectsId/devops"
render={
() => (<DevIndex {...this.props} {...this.state} {...common} />)
}
></Route>
{/* 标签列表 */}
<Route path="/:owner/:projectsId/issues/tags"
render={
(props) => (<TagList {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 仓库设置 */}
<Route path="/:owner/:projectsId/settings"
render={
(props) => (<Setting {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/*修改里程碑*/}
<Route path="/:owner/:projectsId/milestones/:meilid/edit"
render={
(props) => (<OrderupdateMilepost {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 新建里程碑 */}
<Route path="/:owner/:projectsId/milestones/new"
render={
(props) => (<OrdernewMilepost {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/*里程碑详情*/}
<Route path="/:owner/:projectsId/milestones/:meilid"
render={
(props) => (<MilepostDetail {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 里程碑 */}
<Route path="/:owner/:projectsId/milestones"
render={
(props) => (<OrderMilepost {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 里程碑页面新建任务 */}
<Route path="/:owner/:projectsId/issues/:milepostId/new"
render={
(props) => (<OrderNew {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 新建任务 */}
<Route path="/:owner/:projectsId/issues/new"
render={
(props) => (<OrderNew {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 修改详情 */}
<Route path="/:owner/:projectsId/issues/:orderId/updatedetail"
render={
(props) => (<OrderupdateDetail {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 复制详情 */}
<Route path="/:owner/:projectsId/issues/:orderId/copyetail"
render={
(props) => (<OrdercopyDetail {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 任务详情 */}
<Route path="/:owner/:projectsId/issues/:orderId"
render={
(props) => (<OrderDetail {...this.props} {...this.state} {...props} {...common} />)
}
></Route>
{/* 动态 */}
<Route path="/:owner/:projectsId/activity"
render={
(props) => (<TrendsIndex {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 代码Index */}
<Route path="/:owner/:projectsId/issues"
render={
(props) => (<OrderIndex {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 新建合并请求 */}
<Route path="/:owner/:projectsId/pulls/new/:branch"
render={
(props) => (<CreateMerge {...this.props} {...props} {...this.state} {...common} is_fork={true} />)
}
></Route>
<Route path="/:owner/:projectsId/pulls/new"
render={
(props) => (<CreateMerge {...this.props} {...props} {...this.state} {...common} is_fork={true} />)
}
></Route>
<Route path="/:owner/:projectsId/pulls/:mergeId/UpdateMerge"
render={
(props) => (<UpdateMerge {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/:owner/:projectsId/pulls/:mergeId/Messagecount"
render={
(props) => (<MessageCount {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/:owner/:projectsId/pulls/:mergeId/MergeSubmit"
render={
(props) => (<MessageCount {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/projects/:owner/:projectsId/pulls"
render={
(props) => (<MergeIndexDetail {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/projects/:owner/:projectsId/watchers"
render={
(props) => (<WatchUsers {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/projects/:owner/:projectsId/stargazers"
render={
(props) => (<PraiseUsers {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/projects/:owner/:projectsId/fork_users"
render={
(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="/:owner/:projectsId/pulls"
render={
(props) => (<MergeIndexDetail {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/:owner/:projectsId/following"
render={
(props) => (<WatchUsers {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/:owner/:projectsId/stargazers"
render={
(props) => (<PraiseUsers {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/:owner/:projectsId/members"
render={
(props) => (<ForkUsers {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
{/* 贡献者列表 */}
<Route path="/:owner/:projectsId/contribute"
render={
() => (<Contribute {...this.props} {...this.state} {...common} />)
}
></Route>
{/* 代码库----详情页面 */}
<Route path="/projects/:owner/:projectsId/commits/branch/:branchName"
render={
(props) => (<CoderRootCommit {...this.props} {...props} {...this.state} {...common}/>)
}
></Route>
<Route path="/projects/:owner/:projectsId/tree/:branchName"
render={
(props) => (<CoderDepot {...this.props} {...props} {...this.state} {...common}/>)
}
></Route>
<Route path="/projects/:owner/:projectsId/:subIndex"
render={
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state} {...common}/>)
}
></Route>
<Route path="/projects/:owner/:projectsId"
render={
(props) => (<CoderDepot {...this.props} {...props} {...this.state} {...common}/>)
}
></Route>
</Switch>
</Spin>
{/* 代码库----详情页面 */}
<Route path="/:owner/:projectsId/commits/branch/:branchName"
render={
(props) => (<CoderRootCommit {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/:owner/:projectsId/tree/:branchName"
render={
(props) => (<CoderDepot {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/:owner/:projectsId/:subIndex"
render={
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/:owner/:projectsId"
render={
(props) => (<CoderDepot {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
</Switch>
</Spin>
}
</div>
)
}
}
export default Detail;
export default ImageLayerOfCommentHOC({
imgSelector: ".imageLayerParent img, .imageLayerParent .imageTarget",
parentSelector: ".newContainer",
})(Detail);

View File

@ -0,0 +1,28 @@
import React from 'react';
import { Route, Switch } from "react-router-dom";
import { withRouter } from "react-router";
import Loadable from "react-loadable";
import Loading from "../../Loading";
import { SnackbarHOC } from "educoder";
import { CNotificationHOC } from "../../modules/courses/common/CNotificationHOC";
import { TPMIndexHOC } from "../../modules/tpm/TPMIndexHOC";
// forge项目详情
const ProjectDetail = Loadable({
loader: () => import("../Main/Detail"),
loading: Loading,
});
export default withRouter(
(CNotificationHOC()(SnackbarHOC()(TPMIndexHOC((props) => {
return (
<Switch>
<Route
path="/:owner/:projectsId"
render={(p) => (
<ProjectDetail {...props} {...p} />
)}
></Route>
</Switch>
)
}))))
)

View File

@ -12,19 +12,19 @@ class DetailTop extends Component {
{
platform ?
<React.Fragment>
<Link to={`/projects/${owner}/${projectsId}/commits`} className={pathname.indexOf("/commits") > 0 ? "active" : ""}>
<Link to={`/${owner}/${projectsId}/commits`} className={pathname.indexOf("/commits") > 0 ? "active" : ""}>
<i className="iconfont icon-tijiaojilu font-20 mr3 font-bd"></i>
<span>{(coderCount && coderCount.commits_count) || 0}</span>
</Link>
<Link to={`/projects/${owner}/${projectsId}/branchs`} className={pathname.indexOf("/branchs") > 0 ? "active" : ""}>
<Link to={`/${owner}/${projectsId}/branches`} className={pathname.indexOf("/branches") > 0 ? "active" : ""}>
<i className="iconfont icon-fenzhi1 font-18 mr3"></i>
<span>{(coderCount && coderCount.branches_count) || 0}</span>
</Link>
<Link to={`/projects/${owner}/${projectsId}/tag`} className={pathname.indexOf("/tag") > 0 ? "active" : ""}>
<Link to={`/${owner}/${projectsId}/tags`} className={pathname.indexOf("/tags") > 0 ? "active" : ""}>
<i className="iconfont icon-biaoqian3 font-18 mr3"></i>
<span>{(coderCount && coderCount.tags_count) || 0}</span>
</Link>
<Link to={`/projects/${owner}/${projectsId}/releases`} className={pathname.indexOf("/releases") > 0 ? "active" : ""}>
<Link to={`/${owner}/${projectsId}/releases`} className={pathname.indexOf("/releases") > 0 ? "active" : ""}>
<i className="iconfont icon-fahangban font-18 mr3"></i>
<span>{(coderCount && coderCount.version_releasesed_count) || 0}</span>
</Link>

View File

@ -51,7 +51,7 @@ export default ({ match , history }) => {
}
}, [projectsId , owner, sha]);
return (
<div className="main">
<div className="main" style={{padding:"0px",border:"none"}}>
<Spin spinning={isSpin}>
<Infos>
<div className="commitinfos">
@ -59,7 +59,7 @@ 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(`/${owner}/${projectsId}/tree/${truncateCommitId(sha)}`)}} className="ml30">浏览代码</Button>
</div>
</div>
<div className="f-wrap-between" style={{ alignItems: "center" }}>

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