Compare commits

...

245 Commits

Author SHA1 Message Date
caishi 00402ef13d Merge branch 'master' of https://git.trustie.net/jasder/forgeplus-react
# Conflicts:
#	src/forge/Main/sub/UpdateDescModal.jsx
2021-08-09 10:37:23 +08:00
caishi 8f2df90555 代码style 2021-08-09 10:36:15 +08:00
caishi 7530d3f9c4 Merge branch 'develop' 2021-08-06 17:07:54 +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 b7869e5203 Merge branch 'develop' of https://git.trustie.net/jasder/forgeplus-react 2021-08-05 10:48:43 +08:00
hc1913847458 b238bb51ca 限制字符 2021-08-05 10:47:22 +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
hc1913847458 ad7ab189b1 限制字符 2021-08-04 14:42:08 +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 c9802c26a4 Merge branch 'develop' 2021-08-02 10:35:49 +08:00
caishi 47365c0bed webhook-修改一版 2021-08-02 10:35:36 +08:00
caishi 4ec840f252 Merge branch 'develop' 2021-07-30 20:13:49 +08:00
caishi b1ec068663 webhook自动填充 2021-07-30 20:13:34 +08:00
caishi 44a8f806e0 Merge branch 'develop' 2021-07-30 17:44:17 +08:00
caishi 51d34a7667 同上-password-webhook 2021-07-30 17:35:53 +08:00
caishi 9408ad7dcb Merge branch 'develop' 2021-07-30 17:03:19 +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 810ea37bed Merge branch 'develop' 2021-07-26 09:38:44 +08:00
caishi f100875b0f ssh翻页 2021-07-26 09:38:21 +08:00
caishi 6679fe8a48 Merge branch 'develop' 2021-07-22 17:44:30 +08:00
caishi 4f9f5649a9 设置模块-测试版第一版 2021-07-22 17:44:12 +08:00
caishi d31b932efe Merge branch 'develop' 2021-07-21 10:10:53 +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 07852b204c Merge branch 'develop' 2021-07-05 20:35:59 +08:00
caishi 275b7d2015 数据为0时不显示 2021-07-05 20:35:29 +08:00
caishi 9e9e4c07bf 合并请求详情:发布合并请求者跳转链接错误 2021-07-05 15:04:17 +08:00
caishi 934ac61b77 Merge branch 'develop' 2021-07-02 18:19:02 +08:00
caishi f854d2164c 工作流-构建列表-头像地址错误 2021-07-02 18:18:49 +08:00
caishi 95091d0e08 Merge branch 'develop' 2021-07-02 15:37:43 +08:00
caishi e48628389e 镜像地址增加跳转链接 2021-07-02 15:35:43 +08:00
caishi e31ff9bdf3 Merge branch 'develop' 2021-07-01 17:00: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 eba6ed0876 搜索的接口改用正式版对应的服务器地址 2021-06-28 10:44:42 +08:00
caishi db682ace86 Merge branch 'develop' 2021-06-25 18:34:19 +08:00
caishi 1cdf316852 合并请求:冲突文件的显示换行 2021-06-25 18:33:54 +08:00
caishi 777dbd0f43 Merge branch 'develop' 2021-06-25 18:21:48 +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 b44b6530e5 Merge branch 'develop' 2021-06-25 09:14:50 +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 b808bcee99 Merge branch 'develop' 2021-06-18 16:56:18 +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
caishi c0f7c489fb Merge branch 'develop' 2021-06-11 18:11:43 +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 bc64cbb415 Merge branch 'develop' 2021-06-08 14:56:20 +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 fa169b27cd Merge branch 'develop' 2021-05-26 16:48:35 +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 3e0814344f Merge branch 'develop' 2021-05-25 11:25:04 +08:00
caishi ae9b48953e markdown定位问题 2021-05-25 10:05:14 +08:00
caishi eb58f91dbf Merge branch 'develop' 2021-05-21 19:21:32 +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 513255428c Merge branch 'develop'
# Conflicts:
#	package-lock.json
2021-05-14 17:04:57 +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 8baf2cb49c install babel-polyfill 2021-05-08 17:28:14 +08:00
caishi 705bfb07bd Merge branch 'develop' 2021-05-08 16:53:26 +08:00
caishi 202081bbeb 样式 2021-05-08 16:53:16 +08:00
caishi d783d998fc 编辑合并请求-url地址错误 2021-05-08 14:36:12 +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 51925542b8 Merge branch 'develop'
# Conflicts:
#	public/css/edu-purge.css
2021-05-07 16:37:21 +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 ff06efe109 merge develop 2021-05-06 17:15:43 +08:00
caishi c33561c212 新建项目-maxlength 2021-05-06 17:14:42 +08:00
caishi 2deb6f8f9d 设置所有标签的marginbottom为0 2021-05-06 17:14:30 +08:00
caishi 63d69a955e 代码库-提交描述未换行 2021-05-06 17:14:19 +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 4d652d238d 不能修改组织账号 2021-04-27 17:25:00 +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 6da4dbc165 组织团队-无数据显示错误 2021-04-27 09:45:14 +08:00
caishi c0ddd6eaee 组织-项目列表显示name 2021-04-26 17:20:54 +08:00
caishi f65f4c273a 组织基本设置-正则和新建的页面不一致 2021-04-26 16:32:12 +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 1af504825c 代码库编辑文件-切换到其它目录后要重新将编辑状态改为显示状态 2021-04-25 18:00:05 +08:00
caishi fb41baacc1 代码库编辑文件-切换到其它目录后要重新将编辑状态改为显示状态 2021-04-25 17:46:38 +08:00
caishi 09065383c1 转移项目-前端页面已画完 2021-04-25 17:38:47 +08:00
caishi e94cf68cc5 样式覆盖 2021-04-23 18:04:49 +08:00
caishi c32e215b27 样式覆盖 2021-04-23 18:04:07 +08:00
caishi 5fa2fd99b9 Merge branch 'develop' 2021-04-23 14:51:04 +08:00
caishi 2f6597355c +上 关注后不需要提示 2021-04-23 14:50:52 +08:00
caishi 20ab8a6683 Merge branch 'develop' 2021-04-23 14:47:50 +08:00
caishi 1eb3c20af4 +上 贡献者悬浮框里增加的跳转链接不要新开页 2021-04-23 14:47:32 +08:00
caishi afb599f5be 贡献者-悬浮内容增加跳转链接 2021-04-23 14:46:11 +08:00
caishi a7f709a663 Merge branch 'develop' 2021-04-23 14:16:30 +08:00
caishi d6d6df806d imageUrl + / 2021-04-23 14:14:06 +08:00
caishi 6cc97bd039 个人中心关注-关注或者取消关注未更新状态 2021-04-23 11:49:56 +08:00
caishi 037150a63c 贡献者-悬浮卡片-测试版1 2021-04-23 11:15:14 +08:00
caishi 63c2cfed70 Merge branch 'develop' 2021-04-22 10:58:30 +08:00
caishi 52dc63362b 发布评论者头像路径错误 2021-04-22 10:58:11 +08:00
caishi 29e3f0d59d 新建组织-组织账号正则 2021-04-21 16:55:10 +08:00
caishi 233e6a8226 底部样式+新建组织账号正则 2021-04-21 16:54:47 +08:00
caishi 80cd6fbae0 md文件要用Markdown渲染 2021-04-20 15:33:21 +08:00
caishi 8fa31edaae md文件要用Markdown渲染 2021-04-20 15:31:49 +08:00
caishi 49d3db6746 合并请求-提出申请者头像显示问题 2021-04-20 11:18:44 +08:00
caishi ffbb5ba34e 合并请求-提出申请者头像显示问题 2021-04-20 11:17:54 +08:00
caishi bc11ec68e3 注释 2021-04-20 10:57:46 +08:00
caishi 2d2deec224 Merge branch 'develop' 2021-04-20 10:56:50 +08:00
caishi a67cabbfb4 团队项目-团队项目管理-显示的name和跳转的login 2021-04-20 10:54:20 +08:00
caishi ceb1915939 切换左侧目录,选择不同的文件时,文件详情没有更新 2021-04-20 10:30:47 +08:00
caishi 4c65e1981e all-默认头像(首字母加背景颜色) 2021-04-20 09:36:49 +08:00
caishi 09598d0e2c 个人主页头像url 2021-04-19 19:54:57 +08:00
caishi e09490d424 上线后的getImageURL也不用在前面加/ + 一些小样式修改 2021-04-19 18:19:21 +08:00
caishi a42a670146 头像url--接口会返回所有带images的字段值,所以前端不用加固定的内容了 2021-04-19 17:52:01 +08:00
caishi b8d40259e5 readme-文件增加一个目录下拉icon 2021-04-19 16:58:30 +08:00
caishi 487a2f0495 组织团队-新增一个团队标识 2021-04-19 11:53:19 +08:00
caishi ab34369642 新建团队板块无边框 2021-04-19 10:54:02 +08:00
caishi f12228aa51 组织详情显示nickname 2021-04-19 10:35:20 +08:00
caishi 5477c41f78 资源库不需要按引用次数排序 2021-04-14 10:31:33 +08:00
caishi dc05f9ce35 组织-项目-切换协作者管理和团队管理时会重复调用增加成员接口 2021-04-13 17:12:37 +08:00
caishi b601582d15 资源库数量显示错误 2021-04-13 11:14:04 +08:00
caishi 832b18e7f5 组织-团队列表的头像login为undefined 2021-04-13 11:06:09 +08:00
caishi 8c58f77afb 去掉右侧悬浮手册按钮 2021-04-09 14:18:44 +08:00
caishi 2c363965dd 去掉悬浮手册按钮 2021-04-09 13:58:58 +08:00
caishi 60a7f39c16 forge项目暂时不显示命令行功能 2021-04-09 11:45:04 +08:00
caishi 9811276a7c ssh-3(前端固定参数已调通) 2021-04-09 10:12:39 +08:00
caishi a27c74b9aa ssh-2 2021-04-08 18:14:19 +08:00
caishi 80cae93045 ssh-初步 2021-04-08 17:44:31 +08:00
caishi 78aba67917 项目详情右侧增加实践课程链接的显示 2021-04-08 15:37:01 +08:00
caishi 43223c7787 为2时不支持在线创建、在线上传、在线修改、在线删除、创建合并请求等功能 2021-04-08 14:21:35 +08:00
caishi 961587921a projectDetail.type:0是托管项目,1是镜像项目,2是同步镜像项目(为2时不能上传新建文件、下载zip等) 2021-04-08 10:07:55 +08:00
caishi 2f595d750a entries接口传的branch值为undefined 2021-04-07 18:44:20 +08:00
caishi bcaec7a2db 新增组织账号,组织名称增加新的check条件 2021-04-06 18:40:01 +08:00
caishi 70ea6259ae 仓库设置页面增加资源库配置项 2021-04-06 17:34:37 +08:00
caishi 5d6953f2b3 资源库模块测试版第一次上线 2021-04-06 17:17:01 +08:00
caishi c8eda704e5 列表的type字段为头像跳转到个人中心或者组织的判断依据 2021-04-06 11:45:03 +08:00
caishi 5d6b95ab8f 资源库部分接口调试 2021-04-06 11:36:38 +08:00
caishi 426ea3fece 合并请求分页 2021-04-02 18:55:26 +08:00
caishi ab052ebace 第三方登录-修改邮箱和密码 2021-04-02 18:40:59 +08:00
caishi 648c6e235b 第三方账号密码重置 2021-04-02 17:39:13 +08:00
caishi 96253f3f58 列表接口、上传资源 2021-04-02 17:31:15 +08:00
caishi 101478d924 协作者管理删除按钮没显示 2021-04-02 14:08:59 +08:00
caishi dccbd6735d 构建列表里的提交信息,作者头像错误 2021-04-02 11:57:48 +08:00
caishi a0ebba839e tips 2021-04-01 19:03:56 +08:00
caishi 171f14bd2a noticeurl 2021-04-01 16:25:53 +08:00
caishi c3e09f2672 第三方登录-educoder 2021-04-01 15:35:45 +08:00
caishi 6296434527 清理appconfig文件
资源库所有页面排版、数据未绑
2021-04-01 14:41:13 +08:00
caishi e2dbda3083 工作流author 2021-03-31 17:12:31 +08:00
caishi 02f382e6fb 登录框中的找回密码、注册的url 2021-03-31 11:15:41 +08:00
caishi b568aef34e issue 2021-03-30 15:01:25 +08:00
caishi 2c83221376 按钮 2021-03-30 11:50:25 +08:00
caishi 6a4fe4d277 左侧抽屉 2021-03-30 10:26:02 +08:00
228 changed files with 9657 additions and 4422 deletions

513
package-lock.json generated
View File

@ -1,35 +1,40 @@
{ {
"name": "educoder", "name": "forge",
"version": "0.1.0", "version": "3.0.0",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
"@ant-design/colors": { "@ant-design/colors": {
"version": "3.2.2", "version": "3.2.2",
"resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-3.2.2.tgz", "resolved": "https://registry.npm.taobao.org/@ant-design/colors/download/@ant-design/colors-3.2.2.tgz?cache=0&sync_timestamp=1612935637470&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40ant-design%2Fcolors%2Fdownload%2F%40ant-design%2Fcolors-3.2.2.tgz",
"integrity": "sha512-YKgNbG2dlzqMhA9NtI3/pbY16m3Yl/EeWBRa+lB1X1YaYxHrxNexiQYCLTWO/uDvAjLFMEDU+zR901waBtMtjQ==", "integrity": "sha1-WtQ9YZ6RHzSI66wwPWBuZqhCOQM=",
"requires": { "requires": {
"tinycolor2": "^1.4.1" "tinycolor2": "^1.4.1"
} }
}, },
"@ant-design/create-react-context": { "@ant-design/create-react-context": {
"version": "0.2.5", "version": "0.2.5",
"resolved": "https://registry.npmjs.org/@ant-design/create-react-context/-/create-react-context-0.2.5.tgz", "resolved": "https://registry.npm.taobao.org/@ant-design/create-react-context/download/@ant-design/create-react-context-0.2.5.tgz",
"integrity": "sha512-1rMAa4qgP2lfl/QBH9i78+Gjxtj9FTMpMyDGZsEBW5Kih72EuUo9958mV8PgpRkh4uwPSQ7vVZWXeyNZXVAFDg==", "integrity": "sha1-9fWpFjtHcgl3EoNzl60w4i55+Fg=",
"requires": { "requires": {
"gud": "^1.0.0", "gud": "^1.0.0",
"warning": "^4.0.3" "warning": "^4.0.3"
} }
}, },
"@ant-design/css-animation": {
"version": "1.7.3",
"resolved": "https://registry.npm.taobao.org/@ant-design/css-animation/download/@ant-design/css-animation-1.7.3.tgz?cache=0&sync_timestamp=1596106749762&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40ant-design%2Fcss-animation%2Fdownload%2F%40ant-design%2Fcss-animation-1.7.3.tgz",
"integrity": "sha1-YKHJcAFOhrKPlAUQ1p5QPkKPETY="
},
"@ant-design/icons": { "@ant-design/icons": {
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-2.1.1.tgz", "resolved": "https://registry.npm.taobao.org/@ant-design/icons/download/@ant-design/icons-2.1.1.tgz",
"integrity": "sha512-jCH+k2Vjlno4YWl6g535nHR09PwCEmTBKAG6VqF+rhkrSPRLfgpU2maagwbZPLjaHuU5Jd1DFQ2KJpQuI6uG8w==" "integrity": "sha1-e5wI3/1PXUHbZn2dvl4BB9C9mko="
}, },
"@ant-design/icons-react": { "@ant-design/icons-react": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/@ant-design/icons-react/-/icons-react-2.0.1.tgz", "resolved": "https://registry.npm.taobao.org/@ant-design/icons-react/download/@ant-design/icons-react-2.0.1.tgz",
"integrity": "sha512-r1QfoltMuruJZqdiKcbPim3d8LNsVPB733U0gZEUSxBLuqilwsW28K2rCTWSMTjmFX7Mfpf+v/wdiFe/XCqThw==", "integrity": "sha1-F6JRNXGrMXrKKSfljOol3THlNvs=",
"requires": { "requires": {
"@ant-design/colors": "^3.1.0", "@ant-design/colors": "^3.1.0",
"babel-runtime": "^6.26.0" "babel-runtime": "^6.26.0"
@ -446,8 +451,8 @@
}, },
"@types/react-slick": { "@types/react-slick": {
"version": "0.23.4", "version": "0.23.4",
"resolved": "https://registry.npmjs.org/@types/react-slick/-/react-slick-0.23.4.tgz", "resolved": "https://registry.npm.taobao.org/@types/react-slick/download/@types/react-slick-0.23.4.tgz",
"integrity": "sha512-vXoIy4GUfB7/YgqubR4H7RALo+pRdMYCeLgWwV3MPwl5pggTlEkFBTF19R7u+LJc85uMqC7RfsbkqPLMQ4ab+A==", "integrity": "sha1-yX4qnn49GTPGhZO46CdS+rHozlM=",
"requires": { "requires": {
"@types/react": "*" "@types/react": "*"
} }
@ -863,9 +868,9 @@
} }
}, },
"antd": { "antd": {
"version": "3.26.16", "version": "3.26.20",
"resolved": "https://registry.npmjs.org/antd/-/antd-3.26.16.tgz", "resolved": "https://registry.nlark.com/antd/download/antd-3.26.20.tgz",
"integrity": "sha512-EYRwlEf8FCPCVRk5yDcgjSZOC0exu+m75SwlSQU+Mh17f9wGhLeL2/DV7/Sra1r+BZlfiahFdkgrLY7UgMMBEQ==", "integrity": "sha1-8/Vw76qllQoUSULyHrKqqgiOlAc=",
"requires": { "requires": {
"@ant-design/create-react-context": "^0.2.4", "@ant-design/create-react-context": "^0.2.4",
"@ant-design/icons": "~2.1.1", "@ant-design/icons": "~2.1.1",
@ -925,16 +930,16 @@
"dependencies": { "dependencies": {
"raf": { "raf": {
"version": "3.4.1", "version": "3.4.1",
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", "resolved": "https://registry.npm.taobao.org/raf/download/raf-3.4.1.tgz",
"integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", "integrity": "sha1-B0LpmkplUvRF1z4+4DKK8P8e3jk=",
"requires": { "requires": {
"performance-now": "^2.1.0" "performance-now": "^2.1.0"
} }
}, },
"rc-pagination": { "rc-pagination": {
"version": "1.20.14", "version": "1.20.15",
"resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-1.20.14.tgz", "resolved": "https://registry.npm.taobao.org/rc-pagination/download/rc-pagination-1.20.15.tgz",
"integrity": "sha512-sNKwbFrxiqATqcIIShfrFs8BT03n4UUwTAMYae+JhHTmILQmXdvimEnZbVuWcno6G02DAJcLrFpmkn1h2tmEJw==", "integrity": "sha1-zLTNDpvU5H9y8p6kMsA1C/ez2Ac=",
"requires": { "requires": {
"babel-runtime": "6.x", "babel-runtime": "6.x",
"classnames": "^2.2.6", "classnames": "^2.2.6",
@ -944,8 +949,8 @@
}, },
"rc-rate": { "rc-rate": {
"version": "2.5.1", "version": "2.5.1",
"resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.5.1.tgz", "resolved": "https://registry.npm.taobao.org/rc-rate/download/rc-rate-2.5.1.tgz?cache=0&sync_timestamp=1605573559401&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-rate%2Fdownload%2Frc-rate-2.5.1.tgz",
"integrity": "sha512-3iJkNJT8xlHklPCdeZtUZmJmRVUbr6AHRlfSsztfYTXVlHrv2TcPn3XkHsH+12j812WVB7gvilS2j3+ffjUHXg==", "integrity": "sha1-Vfxf0j6p3MciULmoiYA0efSEKWE=",
"requires": { "requires": {
"classnames": "^2.2.5", "classnames": "^2.2.5",
"prop-types": "^15.5.8", "prop-types": "^15.5.8",
@ -955,8 +960,8 @@
}, },
"rc-select": { "rc-select": {
"version": "9.2.3", "version": "9.2.3",
"resolved": "https://registry.npmjs.org/rc-select/-/rc-select-9.2.3.tgz", "resolved": "https://registry.nlark.com/rc-select/download/rc-select-9.2.3.tgz?cache=0&sync_timestamp=1618886345948&other_urls=https%3A%2F%2Fregistry.nlark.com%2Frc-select%2Fdownload%2Frc-select-9.2.3.tgz",
"integrity": "sha512-WhswxOMWiNnkXRbxyrj0kiIvyCfo/BaRPaYbsDetSIAU2yEDwKHF798blCP5u86KLOBKBvtxWLFCkSsQw1so5w==", "integrity": "sha1-ZDQOLW72TovDz8b0aP/ShiVYmsI=",
"requires": { "requires": {
"babel-runtime": "^6.23.0", "babel-runtime": "^6.23.0",
"classnames": "2.x", "classnames": "2.x",
@ -974,8 +979,8 @@
}, },
"rc-tree": { "rc-tree": {
"version": "2.1.4", "version": "2.1.4",
"resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-2.1.4.tgz", "resolved": "https://registry.npm.taobao.org/rc-tree/download/rc-tree-2.1.4.tgz?cache=0&sync_timestamp=1615350038621&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-tree%2Fdownload%2Frc-tree-2.1.4.tgz",
"integrity": "sha512-Xey794Iavgs8YldFlXcZLOhfcIhlX5Oz/yfKufknBXf2AlZCOkc7aHqSM9uTF7fBPtTGPhPxNEfOqHfY7b7xng==", "integrity": "sha1-73WfPnmaIbQ8Hs+ceU6hwU5wtZs=",
"requires": { "requires": {
"@ant-design/create-react-context": "^0.2.4", "@ant-design/create-react-context": "^0.2.4",
"classnames": "2.x", "classnames": "2.x",
@ -985,6 +990,18 @@
"react-lifecycles-compat": "^3.0.4", "react-lifecycles-compat": "^3.0.4",
"warning": "^4.0.3" "warning": "^4.0.3"
} }
},
"react-slick": {
"version": "0.25.2",
"resolved": "https://registry.nlark.com/react-slick/download/react-slick-0.25.2.tgz",
"integrity": "sha1-VjMbZ9R9i8/i3OtqyrHI/VvR9rw=",
"requires": {
"classnames": "^2.2.5",
"enquire.js": "^2.1.6",
"json2mq": "^0.2.0",
"lodash.debounce": "^4.0.8",
"resize-observer-polyfill": "^1.5.0"
}
} }
} }
}, },
@ -1083,8 +1100,8 @@
}, },
"array-tree-filter": { "array-tree-filter": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/array-tree-filter/-/array-tree-filter-2.1.0.tgz", "resolved": "https://registry.npm.taobao.org/array-tree-filter/download/array-tree-filter-2.1.0.tgz",
"integrity": "sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==" "integrity": "sha1-hzrAD+yDdJ8lWsjdCDgUtPYykZA="
}, },
"array-union": { "array-union": {
"version": "1.0.2", "version": "1.0.2",
@ -2062,7 +2079,6 @@
"version": "6.26.0", "version": "6.26.0",
"resolved": "https://registry.npm.taobao.org/babel-polyfill/download/babel-polyfill-6.26.0.tgz", "resolved": "https://registry.npm.taobao.org/babel-polyfill/download/babel-polyfill-6.26.0.tgz",
"integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=", "integrity": "sha1-N5k3q8Z9eJWXCtxiHyhM2WbPIVM=",
"dev": true,
"requires": { "requires": {
"babel-runtime": "^6.26.0", "babel-runtime": "^6.26.0",
"core-js": "^2.5.0", "core-js": "^2.5.0",
@ -2072,8 +2088,7 @@
"regenerator-runtime": { "regenerator-runtime": {
"version": "0.10.5", "version": "0.10.5",
"resolved": "https://registry.npm.taobao.org/regenerator-runtime/download/regenerator-runtime-0.10.5.tgz?cache=0&sync_timestamp=1595456367497&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fregenerator-runtime%2Fdownload%2Fregenerator-runtime-0.10.5.tgz", "resolved": "https://registry.npm.taobao.org/regenerator-runtime/download/regenerator-runtime-0.10.5.tgz?cache=0&sync_timestamp=1595456367497&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fregenerator-runtime%2Fdownload%2Fregenerator-runtime-0.10.5.tgz",
"integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg=", "integrity": "sha1-M2w+/BIgrc7dosn6tntaeVWjNlg="
"dev": true
} }
} }
}, },
@ -2362,6 +2377,12 @@
} }
} }
}, },
"base16": {
"version": "1.0.0",
"resolved": "https://registry.npm.taobao.org/base16/download/base16-1.0.0.tgz",
"integrity": "sha1-4pf2DX7BAUp6lxo568ipjAtoHnA=",
"dev": true
},
"base64-js": { "base64-js": {
"version": "1.3.1", "version": "1.3.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz",
@ -3760,8 +3781,8 @@
}, },
"copy-to-clipboard": { "copy-to-clipboard": {
"version": "3.3.1", "version": "3.3.1",
"resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz", "resolved": "https://registry.npm.taobao.org/copy-to-clipboard/download/copy-to-clipboard-3.3.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcopy-to-clipboard%2Fdownload%2Fcopy-to-clipboard-3.3.1.tgz",
"integrity": "sha512-i13qo6kIHTTpCm8/Wup+0b1mVWETvu2kIMzKoK8FpkLkFxlt0znUAHcMzox+T8sPlqtZXq3CulEjQHsYiGFJUw==", "integrity": "sha1-EVqhqZmP+rYZb5MHatbaO5E2Yq4=",
"requires": { "requires": {
"toggle-selection": "^1.0.6" "toggle-selection": "^1.0.6"
} }
@ -3854,6 +3875,23 @@
"warning": "^4.0.3" "warning": "^4.0.3"
} }
}, },
"cross-fetch": {
"version": "3.1.4",
"resolved": "https://registry.nlark.com/cross-fetch/download/cross-fetch-3.1.4.tgz",
"integrity": "sha1-lyPzo6JHv4uJA586OAqSROj6Lzk=",
"dev": true,
"requires": {
"node-fetch": "2.6.1"
},
"dependencies": {
"node-fetch": {
"version": "2.6.1",
"resolved": "https://registry.nlark.com/node-fetch/download/node-fetch-2.6.1.tgz?cache=0&sync_timestamp=1626684741221&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fnode-fetch%2Fdownload%2Fnode-fetch-2.6.1.tgz",
"integrity": "sha1-BFvTI2Mfdu0uK1VXM5RBa2OaAFI=",
"dev": true
}
}
},
"cross-spawn": { "cross-spawn": {
"version": "5.1.0", "version": "5.1.0",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
@ -3888,11 +3926,6 @@
"randomfill": "^1.0.3" "randomfill": "^1.0.3"
} }
}, },
"crypto-js": {
"version": "4.0.0",
"resolved": "https://registry.npm.taobao.org/crypto-js/download/crypto-js-4.0.0.tgz",
"integrity": "sha1-KQSrJnep0EKFai6i74DekuSjbcw="
},
"crypto-random-string": { "crypto-random-string": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz", "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-1.0.0.tgz",
@ -4852,7 +4885,7 @@
}, },
"dom-closest": { "dom-closest": {
"version": "0.2.0", "version": "0.2.0",
"resolved": "https://registry.npmjs.org/dom-closest/-/dom-closest-0.2.0.tgz", "resolved": "https://registry.npm.taobao.org/dom-closest/download/dom-closest-0.2.0.tgz",
"integrity": "sha1-69n5HRvyLo1vR3h2u80+yQIWwM8=", "integrity": "sha1-69n5HRvyLo1vR3h2u80+yQIWwM8=",
"requires": { "requires": {
"dom-matches": ">=1.0.1" "dom-matches": ">=1.0.1"
@ -4896,7 +4929,7 @@
}, },
"dom-matches": { "dom-matches": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/dom-matches/-/dom-matches-2.0.0.tgz", "resolved": "https://registry.npm.taobao.org/dom-matches/download/dom-matches-2.0.0.tgz",
"integrity": "sha1-0nKLQWqHUzmA6wibhI0lPPI6dYw=" "integrity": "sha1-0nKLQWqHUzmA6wibhI0lPPI6dYw="
}, },
"dom-scroll-into-view": { "dom-scroll-into-view": {
@ -5018,8 +5051,8 @@
}, },
"draft-js": { "draft-js": {
"version": "0.10.5", "version": "0.10.5",
"resolved": "https://registry.npmjs.org/draft-js/-/draft-js-0.10.5.tgz", "resolved": "https://registry.npm.taobao.org/draft-js/download/draft-js-0.10.5.tgz",
"integrity": "sha512-LE6jSCV9nkPhfVX2ggcRLA4FKs6zWq9ceuO/88BpXdNCS7mjRTgs0NsV6piUCJX9YxMsB9An33wnkMmU2sD2Zg==", "integrity": "sha1-v6m+sBj+BTPbsI1mdcNxprCPp0I=",
"requires": { "requires": {
"fbjs": "^0.8.15", "fbjs": "^0.8.15",
"immutable": "~3.7.4", "immutable": "~3.7.4",
@ -5058,13 +5091,18 @@
} }
}, },
"echarts": { "echarts": {
"version": "4.7.0", "version": "4.9.0",
"resolved": "https://registry.npmjs.org/echarts/-/echarts-4.7.0.tgz", "resolved": "https://registry.nlark.com/echarts/download/echarts-4.9.0.tgz",
"integrity": "sha512-NlOTdUcAsIyCCG+N4uh0ZEvXtrPW2jvcuqf03RyqYeCKzyPbiOQ4I3MdKXMhxG3lBdqQNdNXVT71SB4KTQjN0A==", "integrity": "sha1-qbm6oD8Doqcx5jQMVb77V6nhNH0=",
"requires": { "requires": {
"zrender": "4.3.0" "zrender": "4.3.2"
} }
}, },
"echarts-wordcloud": {
"version": "2.0.0",
"resolved": "https://registry.npm.taobao.org/echarts-wordcloud/download/echarts-wordcloud-2.0.0.tgz?cache=0&sync_timestamp=1610779172014&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fecharts-wordcloud%2Fdownload%2Fecharts-wordcloud-2.0.0.tgz",
"integrity": "sha1-Uu+BeJWAH/6emd0brKt2hrLewEo="
},
"editor.md": { "editor.md": {
"version": "1.5.0", "version": "1.5.0",
"resolved": "https://registry.npmjs.org/editor.md/-/editor.md-1.5.0.tgz", "resolved": "https://registry.npmjs.org/editor.md/-/editor.md-1.5.0.tgz",
@ -5149,7 +5187,7 @@
}, },
"enquire.js": { "enquire.js": {
"version": "2.1.6", "version": "2.1.6",
"resolved": "https://registry.npmjs.org/enquire.js/-/enquire.js-2.1.6.tgz", "resolved": "https://registry.npm.taobao.org/enquire.js/download/enquire.js-2.1.6.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fenquire.js%2Fdownload%2Fenquire.js-2.1.6.tgz",
"integrity": "sha1-PoeAybi4NQhMP2DhZtvDwqPImBQ=" "integrity": "sha1-PoeAybi4NQhMP2DhZtvDwqPImBQ="
}, },
"entities": { "entities": {
@ -5668,7 +5706,7 @@
}, },
"eventlistener": { "eventlistener": {
"version": "0.0.1", "version": "0.0.1",
"resolved": "https://registry.npmjs.org/eventlistener/-/eventlistener-0.0.1.tgz", "resolved": "https://registry.npm.taobao.org/eventlistener/download/eventlistener-0.0.1.tgz",
"integrity": "sha1-7Suqu4UiJ68rz4iRUscsY8pTLrg=" "integrity": "sha1-7Suqu4UiJ68rz4iRUscsY8pTLrg="
}, },
"events": { "events": {
@ -6199,6 +6237,41 @@
"bser": "2.1.1" "bser": "2.1.1"
} }
}, },
"fbemitter": {
"version": "3.0.0",
"resolved": "https://registry.npm.taobao.org/fbemitter/download/fbemitter-3.0.0.tgz",
"integrity": "sha1-ALKhr1QRJUqrQWzXX55iib7kv/M=",
"dev": true,
"requires": {
"fbjs": "^3.0.0"
},
"dependencies": {
"fbjs": {
"version": "3.0.0",
"resolved": "https://registry.npm.taobao.org/fbjs/download/fbjs-3.0.0.tgz?cache=0&sync_timestamp=1602048313843&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffbjs%2Fdownload%2Ffbjs-3.0.0.tgz",
"integrity": "sha1-CQcGf7P1enj0XZXx6s/8rNYjwWU=",
"dev": true,
"requires": {
"cross-fetch": "^3.0.4",
"fbjs-css-vars": "^1.0.0",
"loose-envify": "^1.0.0",
"object-assign": "^4.1.0",
"promise": "^7.1.1",
"setimmediate": "^1.0.5",
"ua-parser-js": "^0.7.18"
}
},
"promise": {
"version": "7.3.1",
"resolved": "https://registry.npm.taobao.org/promise/download/promise-7.3.1.tgz",
"integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=",
"dev": true,
"requires": {
"asap": "~2.0.3"
}
}
}
},
"fbjs": { "fbjs": {
"version": "0.8.17", "version": "0.8.17",
"resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz", "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.17.tgz",
@ -6228,6 +6301,12 @@
} }
} }
}, },
"fbjs-css-vars": {
"version": "1.0.2",
"resolved": "https://registry.npm.taobao.org/fbjs-css-vars/download/fbjs-css-vars-1.0.2.tgz",
"integrity": "sha1-IWVRE2rgL+JVkyw+yHdfGOLAeLg=",
"dev": true
},
"fecha": { "fecha": {
"version": "2.3.3", "version": "2.3.3",
"resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz", "resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz",
@ -6672,6 +6751,42 @@
"readable-stream": "^2.3.6" "readable-stream": "^2.3.6"
} }
}, },
"flux": {
"version": "4.0.1",
"resolved": "https://registry.npm.taobao.org/flux/download/flux-4.0.1.tgz",
"integrity": "sha1-eENQKwKEHUqqU0rws3MDSh917lw=",
"dev": true,
"requires": {
"fbemitter": "^3.0.0",
"fbjs": "^3.0.0"
},
"dependencies": {
"fbjs": {
"version": "3.0.0",
"resolved": "https://registry.npm.taobao.org/fbjs/download/fbjs-3.0.0.tgz?cache=0&sync_timestamp=1602048313843&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ffbjs%2Fdownload%2Ffbjs-3.0.0.tgz",
"integrity": "sha1-CQcGf7P1enj0XZXx6s/8rNYjwWU=",
"dev": true,
"requires": {
"cross-fetch": "^3.0.4",
"fbjs-css-vars": "^1.0.0",
"loose-envify": "^1.0.0",
"object-assign": "^4.1.0",
"promise": "^7.1.1",
"setimmediate": "^1.0.5",
"ua-parser-js": "^0.7.18"
}
},
"promise": {
"version": "7.3.1",
"resolved": "https://registry.npm.taobao.org/promise/download/promise-7.3.1.tgz",
"integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=",
"dev": true,
"requires": {
"asap": "~2.0.3"
}
}
}
},
"flv.js": { "flv.js": {
"version": "1.5.0", "version": "1.5.0",
"resolved": "https://registry.npmjs.org/flv.js/-/flv.js-1.5.0.tgz", "resolved": "https://registry.npmjs.org/flv.js/-/flv.js-1.5.0.tgz",
@ -7925,7 +8040,7 @@
}, },
"hammerjs": { "hammerjs": {
"version": "2.0.8", "version": "2.0.8",
"resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz", "resolved": "https://registry.npm.taobao.org/hammerjs/download/hammerjs-2.0.8.tgz",
"integrity": "sha1-BO93hiz/K7edMPdpIJWTAiK/YPE=" "integrity": "sha1-BO93hiz/K7edMPdpIJWTAiK/YPE="
}, },
"handle-thing": { "handle-thing": {
@ -8766,7 +8881,7 @@
}, },
"immutable": { "immutable": {
"version": "3.7.6", "version": "3.7.6",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz", "resolved": "https://registry.npm.taobao.org/immutable/download/immutable-3.7.6.tgz",
"integrity": "sha1-E7TTyxK++hVIKib+Gy665kAHHks=" "integrity": "sha1-E7TTyxK++hVIKib+Gy665kAHHks="
}, },
"import-fresh": { "import-fresh": {
@ -9180,9 +9295,9 @@
} }
}, },
"is-mobile": { "is-mobile": {
"version": "2.2.1", "version": "2.2.2",
"resolved": "https://registry.npmjs.org/is-mobile/-/is-mobile-2.2.1.tgz", "resolved": "https://registry.nlark.com/is-mobile/download/is-mobile-2.2.2.tgz",
"integrity": "sha512-6zELsfVFr326eq2CI53yvqq6YBanOxKBybwDT+MbMS2laBnK6Ez8m5XHSuTQQbnKRfpDzCod1CMWW5q3wZYMvA==" "integrity": "sha1-9snF1Q7gElTOBec5vdg18e1OmVQ="
}, },
"is-npm": { "is-npm": {
"version": "1.0.0", "version": "1.0.0",
@ -9888,6 +10003,11 @@
"esprima": "^4.0.0" "esprima": "^4.0.0"
} }
}, },
"js2wordcloud": {
"version": "1.1.12",
"resolved": "https://registry.npm.taobao.org/js2wordcloud/download/js2wordcloud-1.1.12.tgz",
"integrity": "sha1-8BdC2k5qyzAAsoY1dmQWjvn8o64="
},
"jsbn": { "jsbn": {
"version": "0.1.1", "version": "0.1.1",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
@ -10310,6 +10430,12 @@
"resolved": "https://registry.npmjs.org/lodash.cond/-/lodash.cond-4.5.2.tgz", "resolved": "https://registry.npmjs.org/lodash.cond/-/lodash.cond-4.5.2.tgz",
"integrity": "sha1-9HGh2khr5g9quVXRcRVSPdHSVdU=" "integrity": "sha1-9HGh2khr5g9quVXRcRVSPdHSVdU="
}, },
"lodash.curry": {
"version": "4.1.1",
"resolved": "https://registry.npm.taobao.org/lodash.curry/download/lodash.curry-4.1.1.tgz",
"integrity": "sha1-JI42By7ekGUB11lmIAqG2riyMXA=",
"dev": true
},
"lodash.debounce": { "lodash.debounce": {
"version": "4.0.8", "version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
@ -10320,6 +10446,12 @@
"resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
"integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw="
}, },
"lodash.flow": {
"version": "3.5.0",
"resolved": "https://registry.npm.taobao.org/lodash.flow/download/lodash.flow-3.5.0.tgz",
"integrity": "sha1-h79AKSuM+D5OjOGjrkIJ4gBxZ1o=",
"dev": true
},
"lodash.isequal": { "lodash.isequal": {
"version": "4.5.0", "version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
@ -10354,7 +10486,7 @@
}, },
"lodash.throttle": { "lodash.throttle": {
"version": "4.1.1", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", "resolved": "https://registry.npm.taobao.org/lodash.throttle/download/lodash.throttle-4.1.1.tgz",
"integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=" "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ="
}, },
"lodash.uniq": { "lodash.uniq": {
@ -11409,8 +11541,8 @@
}, },
"omit.js": { "omit.js": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/omit.js/-/omit.js-1.0.2.tgz", "resolved": "https://registry.npm.taobao.org/omit.js/download/omit.js-1.0.2.tgz",
"integrity": "sha512-/QPc6G2NS+8d4L/cQhbk6Yit1WTB6Us2g84A7A/1+w9d/eRGHyEqC5kkQtHVoHZ5NFWGG7tUGgrhVZwgZanKrQ==", "integrity": "sha1-kaFPDrqEBm36AVvzDkdMR/MLyFg=",
"requires": { "requires": {
"babel-runtime": "^6.23.0" "babel-runtime": "^6.23.0"
} }
@ -13950,6 +14082,12 @@
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
}, },
"pure-color": {
"version": "1.3.0",
"resolved": "https://registry.npm.taobao.org/pure-color/download/pure-color-1.3.0.tgz",
"integrity": "sha1-H+Bk+wrIUfDeYTIKi/eWg2Qi8z4=",
"dev": true
},
"purgecss": { "purgecss": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/purgecss/-/purgecss-2.1.2.tgz", "resolved": "https://registry.npmjs.org/purgecss/-/purgecss-2.1.2.tgz",
@ -14024,9 +14162,9 @@
"integrity": "sha1-ys6GOG9ZoNuAUPqQ2baw6IoeNk8=" "integrity": "sha1-ys6GOG9ZoNuAUPqQ2baw6IoeNk8="
}, },
"qrcode.react": { "qrcode.react": {
"version": "1.0.0", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-1.0.0.tgz", "resolved": "https://registry.npm.taobao.org/qrcode.react/download/qrcode.react-1.0.1.tgz",
"integrity": "sha512-jBXleohRTwvGBe1ngV+62QvEZ/9IZqQivdwzo9pJM4LQMoCM2VnvNBnKdjvGnKyDZ/l0nCDgsPod19RzlPvm/Q==", "integrity": "sha1-KDS7UOXidf/lr2kG7/FTkf6eOKU=",
"requires": { "requires": {
"loose-envify": "^1.4.0", "loose-envify": "^1.4.0",
"prop-types": "^15.6.0", "prop-types": "^15.6.0",
@ -14213,9 +14351,9 @@
} }
}, },
"rc-calendar": { "rc-calendar": {
"version": "9.15.10", "version": "9.15.11",
"resolved": "https://registry.npmjs.org/rc-calendar/-/rc-calendar-9.15.10.tgz", "resolved": "https://registry.npm.taobao.org/rc-calendar/download/rc-calendar-9.15.11.tgz",
"integrity": "sha512-xh1A3rYejKskAvkjnd9BcHXFbBnAYsHMGHBdtoAkbwp43B6yEieNL0g0Tzz8s1gApDZV2j5vF1jJ9IIpPYFNLw==", "integrity": "sha1-zh5eqOTXdDW+ZqjHfbEvHw+aNF8=",
"requires": { "requires": {
"babel-runtime": "6.x", "babel-runtime": "6.x",
"classnames": "2.x", "classnames": "2.x",
@ -14228,8 +14366,8 @@
}, },
"rc-cascader": { "rc-cascader": {
"version": "0.17.5", "version": "0.17.5",
"resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-0.17.5.tgz", "resolved": "https://registry.npm.taobao.org/rc-cascader/download/rc-cascader-0.17.5.tgz?cache=0&sync_timestamp=1610107054432&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-cascader%2Fdownload%2Frc-cascader-0.17.5.tgz",
"integrity": "sha512-WYMVcxU0+Lj+xLr4YYH0+yXODumvNXDcVEs5i7L1mtpWwYkubPV/zbQpn+jGKFCIW/hOhjkU4J1db8/P/UKE7A==", "integrity": "sha1-T96R0jt2CMQgJjw47unAaH+A99w=",
"requires": { "requires": {
"array-tree-filter": "^2.1.0", "array-tree-filter": "^2.1.0",
"prop-types": "^15.5.8", "prop-types": "^15.5.8",
@ -14242,8 +14380,8 @@
}, },
"rc-checkbox": { "rc-checkbox": {
"version": "2.1.8", "version": "2.1.8",
"resolved": "https://registry.npmjs.org/rc-checkbox/-/rc-checkbox-2.1.8.tgz", "resolved": "https://registry.npm.taobao.org/rc-checkbox/download/rc-checkbox-2.1.8.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-checkbox%2Fdownload%2Frc-checkbox-2.1.8.tgz",
"integrity": "sha512-6qOgh0/by0nVNASx6LZnhRTy17Etcgav+IrI7kL9V9kcDZ/g7K14JFlqrtJ3NjDq/Kyn+BPI1st1XvbkhfaJeg==", "integrity": "sha1-7t2e+cLzr1s7jlzeUlSqia0aiAo=",
"requires": { "requires": {
"babel-runtime": "^6.23.0", "babel-runtime": "^6.23.0",
"classnames": "2.x", "classnames": "2.x",
@ -14253,8 +14391,8 @@
}, },
"rc-collapse": { "rc-collapse": {
"version": "1.11.8", "version": "1.11.8",
"resolved": "https://registry.npmjs.org/rc-collapse/-/rc-collapse-1.11.8.tgz", "resolved": "https://registry.npm.taobao.org/rc-collapse/download/rc-collapse-1.11.8.tgz?cache=0&sync_timestamp=1606217065785&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-collapse%2Fdownload%2Frc-collapse-1.11.8.tgz",
"integrity": "sha512-8EhfPyScTYljkbRuIoHniSwZagD5UPpZ3CToYgoNYWC85L2qCbPYF7+OaC713FOrIkp6NbfNqXsITNxmDAmxog==", "integrity": "sha1-ZqQAidRpUZ6UJACasckn4hQEHYA=",
"requires": { "requires": {
"classnames": "2.x", "classnames": "2.x",
"css-animation": "1.x", "css-animation": "1.x",
@ -14267,8 +14405,8 @@
}, },
"rc-dialog": { "rc-dialog": {
"version": "7.6.1", "version": "7.6.1",
"resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-7.6.1.tgz", "resolved": "https://registry.npm.taobao.org/rc-dialog/download/rc-dialog-7.6.1.tgz?cache=0&sync_timestamp=1614949683544&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-dialog%2Fdownload%2Frc-dialog-7.6.1.tgz",
"integrity": "sha512-KUKf+2eZ4YL+lnXMG3hR4ZtIhC9glfH27NtTVz3gcoDIPAf3uUvaXVRNoDCiSi+OGKLyIb/b6EoidFh6nQC5Wg==", "integrity": "sha1-EVRczAuUWTT6dgeXJuDYU+UtcF8=",
"requires": { "requires": {
"babel-runtime": "6.x", "babel-runtime": "6.x",
"rc-animate": "2.x", "rc-animate": "2.x",
@ -14277,8 +14415,8 @@
}, },
"rc-drawer": { "rc-drawer": {
"version": "3.1.3", "version": "3.1.3",
"resolved": "https://registry.npmjs.org/rc-drawer/-/rc-drawer-3.1.3.tgz", "resolved": "https://registry.npm.taobao.org/rc-drawer/download/rc-drawer-3.1.3.tgz?cache=0&sync_timestamp=1614159639291&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-drawer%2Fdownload%2Frc-drawer-3.1.3.tgz",
"integrity": "sha512-2z+RdxmzXyZde/1OhVMfDR1e/GBswFeWSZ7FS3Fdd0qhgVdpV1wSzILzzxRaT481ItB5hOV+e8pZT07vdJE8kg==", "integrity": "sha1-y8sE1MB/C2by7OEdhH9KG9gOoLc=",
"requires": { "requires": {
"classnames": "^2.2.6", "classnames": "^2.2.6",
"rc-util": "^4.16.1", "rc-util": "^4.16.1",
@ -14287,8 +14425,8 @@
}, },
"rc-dropdown": { "rc-dropdown": {
"version": "2.4.1", "version": "2.4.1",
"resolved": "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-2.4.1.tgz", "resolved": "https://registry.npm.taobao.org/rc-dropdown/download/rc-dropdown-2.4.1.tgz?cache=0&sync_timestamp=1600332782526&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-dropdown%2Fdownload%2Frc-dropdown-2.4.1.tgz",
"integrity": "sha512-p0XYn0wrOpAZ2fUGE6YJ6U8JBNc5ASijznZ6dkojdaEfQJAeZtV9KMEewhxkVlxGSbbdXe10ptjBlTEW9vEwEg==", "integrity": "sha1-qu9us6UVLN2ZgolcKnjZtfBGzew=",
"requires": { "requires": {
"babel-runtime": "^6.26.0", "babel-runtime": "^6.26.0",
"classnames": "^2.2.6", "classnames": "^2.2.6",
@ -14299,8 +14437,8 @@
}, },
"rc-editor-core": { "rc-editor-core": {
"version": "0.8.10", "version": "0.8.10",
"resolved": "https://registry.npmjs.org/rc-editor-core/-/rc-editor-core-0.8.10.tgz", "resolved": "https://registry.npm.taobao.org/rc-editor-core/download/rc-editor-core-0.8.10.tgz",
"integrity": "sha512-T3aHpeMCIYA1sdAI7ynHHjXy5fqp83uPlD68ovZ0oClTSc3tbHmyCxXlA+Ti4YgmcpCYv7avF6a+TIbAka53kw==", "integrity": "sha1-byFbxd+cM/+p9sWzDKc6favoq3w=",
"requires": { "requires": {
"babel-runtime": "^6.26.0", "babel-runtime": "^6.26.0",
"classnames": "^2.2.5", "classnames": "^2.2.5",
@ -14313,8 +14451,8 @@
}, },
"rc-editor-mention": { "rc-editor-mention": {
"version": "1.1.13", "version": "1.1.13",
"resolved": "https://registry.npmjs.org/rc-editor-mention/-/rc-editor-mention-1.1.13.tgz", "resolved": "https://registry.npm.taobao.org/rc-editor-mention/download/rc-editor-mention-1.1.13.tgz",
"integrity": "sha512-3AOmGir91Fi2ogfRRaXLtqlNuIwQpvla7oUnGHS1+3eo7b+fUp5IlKcagqtwUBB5oDNofoySXkLBxzWvSYNp/Q==", "integrity": "sha1-nxyrEGX4awFSOEAyF5DCqxKsXos=",
"requires": { "requires": {
"babel-runtime": "^6.23.0", "babel-runtime": "^6.23.0",
"classnames": "^2.2.5", "classnames": "^2.2.5",
@ -14342,9 +14480,9 @@
} }
}, },
"rc-hammerjs": { "rc-hammerjs": {
"version": "0.6.9", "version": "0.6.10",
"resolved": "https://registry.npmjs.org/rc-hammerjs/-/rc-hammerjs-0.6.9.tgz", "resolved": "https://registry.npm.taobao.org/rc-hammerjs/download/rc-hammerjs-0.6.10.tgz",
"integrity": "sha512-4llgWO3RgLyVbEqUdGsDfzUDqklRlQW5VEhE3x35IvhV+w//VPRG34SBavK3D2mD/UaLKaohgU41V4agiftC8g==", "integrity": "sha1-GDGjvY8hmXAL/MWtayCjVjCuteA=",
"requires": { "requires": {
"babel-runtime": "6.x", "babel-runtime": "6.x",
"hammerjs": "^2.0.8", "hammerjs": "^2.0.8",
@ -14352,9 +14490,9 @@
} }
}, },
"rc-input-number": { "rc-input-number": {
"version": "4.5.6", "version": "4.5.9",
"resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-4.5.6.tgz", "resolved": "https://registry.nlark.com/rc-input-number/download/rc-input-number-4.5.9.tgz?cache=0&sync_timestamp=1619578110950&other_urls=https%3A%2F%2Fregistry.nlark.com%2Frc-input-number%2Fdownload%2Frc-input-number-4.5.9.tgz",
"integrity": "sha512-AXbL4gtQ1mSQnu6v/JtMv3UbGRCzLvQznmf0a7U/SAtZ8+dCEAqD4JpJhkjv73Wog53eRYhw4l7ApdXflc9ymg==", "integrity": "sha1-HL9zXiT+I8TrmkMBAxcguV8qPj0=",
"requires": { "requires": {
"babel-runtime": "6.x", "babel-runtime": "6.x",
"classnames": "^2.2.0", "classnames": "^2.2.0",
@ -14365,8 +14503,8 @@
}, },
"rc-mentions": { "rc-mentions": {
"version": "0.4.2", "version": "0.4.2",
"resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-0.4.2.tgz", "resolved": "https://registry.npm.taobao.org/rc-mentions/download/rc-mentions-0.4.2.tgz?cache=0&sync_timestamp=1610510822768&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-mentions%2Fdownload%2Frc-mentions-0.4.2.tgz",
"integrity": "sha512-DTZurQzacLXOfVuiHydGzqkq7cFMHXF18l2jZ9PhWUn2cqvOSY3W4osN0Pq29AOMOBpcxdZCzgc7Lb0r/bgkDw==", "integrity": "sha1-wYq3Ae+55LdbOFGgwNLdaYZA4kY=",
"requires": { "requires": {
"@ant-design/create-react-context": "^0.2.4", "@ant-design/create-react-context": "^0.2.4",
"classnames": "^2.2.6", "classnames": "^2.2.6",
@ -14394,8 +14532,8 @@
}, },
"rc-notification": { "rc-notification": {
"version": "3.3.1", "version": "3.3.1",
"resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-3.3.1.tgz", "resolved": "https://registry.npm.taobao.org/rc-notification/download/rc-notification-3.3.1.tgz?cache=0&sync_timestamp=1614675471156&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-notification%2Fdownload%2Frc-notification-3.3.1.tgz",
"integrity": "sha512-U5+f4BmBVfMSf3OHSLyRagsJ74yKwlrQAtbbL5ijoA0F2C60BufwnOcHG18tVprd7iaIjzZt1TKMmQSYSvgrig==", "integrity": "sha1-C6o+cPjUCrAVzo+njCYMSQ/HvrQ=",
"requires": { "requires": {
"babel-runtime": "6.x", "babel-runtime": "6.x",
"classnames": "2.x", "classnames": "2.x",
@ -14416,9 +14554,9 @@
} }
}, },
"rc-progress": { "rc-progress": {
"version": "2.5.2", "version": "2.5.3",
"resolved": "https://registry.npmjs.org/rc-progress/-/rc-progress-2.5.2.tgz", "resolved": "https://registry.npm.taobao.org/rc-progress/download/rc-progress-2.5.3.tgz",
"integrity": "sha512-ajI+MJkbBz9zYDuE9GQsY5gsyqPF7HFioZEDZ9Fmc+ebNZoiSeSJsTJImPFCg0dW/5WiRGUy2F69SX1aPtSJgA==", "integrity": "sha1-APAblb2+GFbTpfgiQgUZAui3qOc=",
"requires": { "requires": {
"babel-runtime": "6.x", "babel-runtime": "6.x",
"prop-types": "^15.5.8" "prop-types": "^15.5.8"
@ -14435,8 +14573,8 @@
}, },
"rc-resize-observer": { "rc-resize-observer": {
"version": "0.1.3", "version": "0.1.3",
"resolved": "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-0.1.3.tgz", "resolved": "https://registry.npm.taobao.org/rc-resize-observer/download/rc-resize-observer-0.1.3.tgz?cache=0&sync_timestamp=1608864858155&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-resize-observer%2Fdownload%2Frc-resize-observer-0.1.3.tgz",
"integrity": "sha512-uzOQEwx83xdQSFOkOAM7x7GHIQKYnrDV4dWxtCxyG1BS1pkfJ4EvDeMfsvAJHSYkQXVBu+sgRHGbRtLG3qiuUg==", "integrity": "sha1-CXGR+cOrGG7ZB7VTum71Zd8Rwkk=",
"requires": { "requires": {
"classnames": "^2.2.1", "classnames": "^2.2.1",
"rc-util": "^4.13.0", "rc-util": "^4.13.0",
@ -14464,8 +14602,8 @@
}, },
"rc-slider": { "rc-slider": {
"version": "8.7.1", "version": "8.7.1",
"resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-8.7.1.tgz", "resolved": "https://registry.npm.taobao.org/rc-slider/download/rc-slider-8.7.1.tgz?cache=0&sync_timestamp=1616675519253&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-slider%2Fdownload%2Frc-slider-8.7.1.tgz",
"integrity": "sha512-WMT5mRFUEcrLWwTxsyS8jYmlaMsTVCZIGENLikHsNv+tE8ThU2lCoPfi/xFNUfJFNFSBFP3MwPez9ZsJmNp13g==", "integrity": "sha1-ntBzYtyTSJo45lSyG4EirXD9PEI=",
"requires": { "requires": {
"babel-runtime": "6.x", "babel-runtime": "6.x",
"classnames": "^2.2.5", "classnames": "^2.2.5",
@ -14479,8 +14617,8 @@
}, },
"rc-steps": { "rc-steps": {
"version": "3.5.0", "version": "3.5.0",
"resolved": "https://registry.npmjs.org/rc-steps/-/rc-steps-3.5.0.tgz", "resolved": "https://registry.npm.taobao.org/rc-steps/download/rc-steps-3.5.0.tgz",
"integrity": "sha512-2Vkkrpa7PZbg7qPsqTNzVDov4u78cmxofjjnIHiGB9+9rqKS8oTLPzbW2uiWDr3Lk+yGwh8rbpGO1E6VAgBCOg==", "integrity": "sha1-NrKn8fSZB7DZA2OISxhiPK+ftgA=",
"requires": { "requires": {
"babel-runtime": "^6.23.0", "babel-runtime": "^6.23.0",
"classnames": "^2.2.3", "classnames": "^2.2.3",
@ -14489,9 +14627,9 @@
} }
}, },
"rc-switch": { "rc-switch": {
"version": "1.9.0", "version": "1.9.2",
"resolved": "https://registry.npmjs.org/rc-switch/-/rc-switch-1.9.0.tgz", "resolved": "https://registry.npm.taobao.org/rc-switch/download/rc-switch-1.9.2.tgz?cache=0&sync_timestamp=1603791200779&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-switch%2Fdownload%2Frc-switch-1.9.2.tgz",
"integrity": "sha512-Isas+egaK6qSk64jaEw4GgPStY4umYDbT7ZY93bZF1Af+b/JEsKsJdNOU2qG3WI0Z6tXo2DDq0kJCv8Yhu0zww==", "integrity": "sha1-eSHHZkEf6aZCZRDDQpAi1rpN/eI=",
"requires": { "requires": {
"classnames": "^2.2.1", "classnames": "^2.2.1",
"prop-types": "^15.5.6", "prop-types": "^15.5.6",
@ -14500,8 +14638,8 @@
}, },
"rc-table": { "rc-table": {
"version": "6.10.15", "version": "6.10.15",
"resolved": "https://registry.npmjs.org/rc-table/-/rc-table-6.10.15.tgz", "resolved": "https://registry.nlark.com/rc-table/download/rc-table-6.10.15.tgz",
"integrity": "sha512-LAr0M/gqt+irOjvPNBLApmQ0CUHNOfKsEBhu1uIuB3OlN1ynA9z+sdoTQyNd9+8NSl0MYnQOOfhtLChAY7nU0A==", "integrity": "sha1-GB9McMT9dPZX7o8jGW5+sIoDZco=",
"requires": { "requires": {
"classnames": "^2.2.5", "classnames": "^2.2.5",
"component-classes": "^1.2.6", "component-classes": "^1.2.6",
@ -14515,8 +14653,8 @@
}, },
"rc-tabs": { "rc-tabs": {
"version": "9.7.0", "version": "9.7.0",
"resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-9.7.0.tgz", "resolved": "https://registry.npm.taobao.org/rc-tabs/download/rc-tabs-9.7.0.tgz?cache=0&sync_timestamp=1608866453009&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-tabs%2Fdownload%2Frc-tabs-9.7.0.tgz",
"integrity": "sha512-kvmgp8/MfLzFZ06hWHignqomFQ5nF7BqKr5O1FfhE4VKsGrep52YSF/1MvS5oe0NPcI9XGNS2p751C5v6cYDpQ==", "integrity": "sha1-rglpW+9ZY9bmTnvBBSHHbf3YRIs=",
"requires": { "requires": {
"@ant-design/create-react-context": "^0.2.4", "@ant-design/create-react-context": "^0.2.4",
"babel-runtime": "6.x", "babel-runtime": "6.x",
@ -14533,8 +14671,8 @@
"dependencies": { "dependencies": {
"raf": { "raf": {
"version": "3.4.1", "version": "3.4.1",
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", "resolved": "https://registry.npm.taobao.org/raf/download/raf-3.4.1.tgz",
"integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", "integrity": "sha1-B0LpmkplUvRF1z4+4DKK8P8e3jk=",
"requires": { "requires": {
"performance-now": "^2.1.0" "performance-now": "^2.1.0"
} }
@ -14543,8 +14681,8 @@
}, },
"rc-time-picker": { "rc-time-picker": {
"version": "3.7.3", "version": "3.7.3",
"resolved": "https://registry.npmjs.org/rc-time-picker/-/rc-time-picker-3.7.3.tgz", "resolved": "https://registry.npm.taobao.org/rc-time-picker/download/rc-time-picker-3.7.3.tgz?cache=0&sync_timestamp=1576572941972&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-time-picker%2Fdownload%2Frc-time-picker-3.7.3.tgz",
"integrity": "sha512-Lv1Mvzp9fRXhXEnRLO4nW6GLNxUkfAZ3RsiIBsWjGjXXvMNjdr4BX/ayElHAFK0DoJqOhm7c5tjmIYpEOwcUXg==", "integrity": "sha1-ZajekECTJQrpyCsCpJBeD5leI+I=",
"requires": { "requires": {
"classnames": "2.x", "classnames": "2.x",
"moment": "2.x", "moment": "2.x",
@ -14556,8 +14694,8 @@
"dependencies": { "dependencies": {
"raf": { "raf": {
"version": "3.4.1", "version": "3.4.1",
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", "resolved": "https://registry.npm.taobao.org/raf/download/raf-3.4.1.tgz",
"integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", "integrity": "sha1-B0LpmkplUvRF1z4+4DKK8P8e3jk=",
"requires": { "requires": {
"performance-now": "^2.1.0" "performance-now": "^2.1.0"
} }
@ -14566,8 +14704,8 @@
}, },
"rc-tooltip": { "rc-tooltip": {
"version": "3.7.3", "version": "3.7.3",
"resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-3.7.3.tgz", "resolved": "https://registry.npm.taobao.org/rc-tooltip/download/rc-tooltip-3.7.3.tgz?cache=0&sync_timestamp=1614588684791&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-tooltip%2Fdownload%2Frc-tooltip-3.7.3.tgz",
"integrity": "sha512-dE2ibukxxkrde7wH9W8ozHKUO4aQnPZ6qBHtrTH9LoO836PjDdiaWO73fgPB05VfJs9FbZdmGPVEbXCeOP99Ww==", "integrity": "sha1-KArsavyqROjf8EgPuv+eh/wArsw=",
"requires": { "requires": {
"babel-runtime": "6.x", "babel-runtime": "6.x",
"prop-types": "^15.5.8", "prop-types": "^15.5.8",
@ -14615,8 +14753,8 @@
}, },
"rc-tree-select": { "rc-tree-select": {
"version": "2.9.4", "version": "2.9.4",
"resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-2.9.4.tgz", "resolved": "https://registry.nlark.com/rc-tree-select/download/rc-tree-select-2.9.4.tgz",
"integrity": "sha512-0HQkXAN4XbfBW20CZYh3G+V+VMrjX42XRtDCpyv6PDUm5vikC0Ob682ZBCVS97Ww2a5Hf6Ajmu0ahWEdIEpwhg==", "integrity": "sha1-aqeU4fDmXGbEBqoKKg50/QpVewk=",
"requires": { "requires": {
"classnames": "^2.2.1", "classnames": "^2.2.1",
"dom-scroll-into-view": "^1.2.1", "dom-scroll-into-view": "^1.2.1",
@ -14633,8 +14771,8 @@
"dependencies": { "dependencies": {
"rc-tree": { "rc-tree": {
"version": "2.1.4", "version": "2.1.4",
"resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-2.1.4.tgz", "resolved": "https://registry.npm.taobao.org/rc-tree/download/rc-tree-2.1.4.tgz?cache=0&sync_timestamp=1615350038621&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-tree%2Fdownload%2Frc-tree-2.1.4.tgz",
"integrity": "sha512-Xey794Iavgs8YldFlXcZLOhfcIhlX5Oz/yfKufknBXf2AlZCOkc7aHqSM9uTF7fBPtTGPhPxNEfOqHfY7b7xng==", "integrity": "sha1-73WfPnmaIbQ8Hs+ceU6hwU5wtZs=",
"requires": { "requires": {
"@ant-design/create-react-context": "^0.2.4", "@ant-design/create-react-context": "^0.2.4",
"classnames": "2.x", "classnames": "2.x",
@ -14647,8 +14785,8 @@
}, },
"rc-trigger": { "rc-trigger": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-3.0.0.tgz", "resolved": "https://registry.nlark.com/rc-trigger/download/rc-trigger-3.0.0.tgz?cache=0&sync_timestamp=1619590696046&other_urls=https%3A%2F%2Fregistry.nlark.com%2Frc-trigger%2Fdownload%2Frc-trigger-3.0.0.tgz",
"integrity": "sha512-hQxbbJpo23E2QnYczfq3Ec5J5tVl2mUDhkqxrEsQAqk16HfADQg+iKNWzEYXyERSncdxfnzYuaBgy764mNRzTA==", "integrity": "sha1-9tmx2oomsrLR2RKgaHbBpIb1mA8=",
"requires": { "requires": {
"babel-runtime": "6.x", "babel-runtime": "6.x",
"classnames": "^2.2.6", "classnames": "^2.2.6",
@ -14660,18 +14798,14 @@
}, },
"dependencies": { "dependencies": {
"rc-animate": { "rc-animate": {
"version": "3.0.0-rc.6", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/rc-animate/-/rc-animate-3.0.0-rc.6.tgz", "resolved": "https://registry.npm.taobao.org/rc-animate/download/rc-animate-3.1.1.tgz?cache=0&sync_timestamp=1601018005635&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Frc-animate%2Fdownload%2Frc-animate-3.1.1.tgz",
"integrity": "sha512-oBLPpiT6Q4t6YvD/pkLcmofBP1p01TX0Otse8Q4+Mxt8J+VSDflLZGIgf62EwkvRwsQUkLPjZVFBsldnPKLzjg==", "integrity": "sha1-3v3YY/VoFsIiU05Nxo/t3s0IE4Y=",
"requires": { "requires": {
"babel-runtime": "6.x", "@ant-design/css-animation": "^1.7.2",
"classnames": "^2.2.5", "classnames": "^2.2.6",
"component-classes": "^1.2.6",
"fbjs": "^0.8.16",
"prop-types": "15.x",
"raf": "^3.4.0", "raf": "^3.4.0",
"rc-util": "^4.5.0", "rc-util": "^4.15.3"
"react-lifecycles-compat": "^3.0.4"
} }
} }
} }
@ -14725,6 +14859,18 @@
"prop-types": "^15.6.2" "prop-types": "^15.6.2"
} }
}, },
"react-base16-styling": {
"version": "0.6.0",
"resolved": "https://registry.npm.taobao.org/react-base16-styling/download/react-base16-styling-0.6.0.tgz",
"integrity": "sha1-7yFW1mz0E5aVyKFniGy2nqZgeSw=",
"dev": true,
"requires": {
"base16": "^1.0.0",
"lodash.curry": "^4.0.1",
"lodash.flow": "^3.3.0",
"pure-color": "^1.2.0"
}
},
"react-beautiful-dnd": { "react-beautiful-dnd": {
"version": "10.1.1", "version": "10.1.1",
"resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-10.1.1.tgz", "resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-10.1.1.tgz",
@ -15090,6 +15236,18 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
}, },
"react-json-view": {
"version": "1.21.3",
"resolved": "https://registry.npm.taobao.org/react-json-view/download/react-json-view-1.21.3.tgz",
"integrity": "sha1-8YQgnujxvzdPsMQbCBPP9UVJxHU=",
"dev": true,
"requires": {
"flux": "^4.0.1",
"react-base16-styling": "^0.6.0",
"react-lifecycles-compat": "^3.0.4",
"react-textarea-autosize": "^8.3.2"
}
},
"react-jss": { "react-jss": {
"version": "8.6.1", "version": "8.6.1",
"resolved": "https://registry.npmjs.org/react-jss/-/react-jss-8.6.1.tgz", "resolved": "https://registry.npmjs.org/react-jss/-/react-jss-8.6.1.tgz",
@ -15110,9 +15268,9 @@
} }
}, },
"react-lazy-load": { "react-lazy-load": {
"version": "3.0.13", "version": "3.1.13",
"resolved": "https://registry.npmjs.org/react-lazy-load/-/react-lazy-load-3.0.13.tgz", "resolved": "https://registry.npm.taobao.org/react-lazy-load/download/react-lazy-load-3.1.13.tgz?cache=0&sync_timestamp=1593654792284&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Freact-lazy-load%2Fdownload%2Freact-lazy-load-3.1.13.tgz",
"integrity": "sha1-OwqS0zbUPT8Nc8vm81sXBQsIuCQ=", "integrity": "sha1-I2lD92twhMyEWHFtljKhyYU+pc0=",
"requires": { "requires": {
"eventlistener": "0.0.1", "eventlistener": "0.0.1",
"lodash.debounce": "^4.0.0", "lodash.debounce": "^4.0.0",
@ -15249,9 +15407,9 @@
} }
}, },
"react-slick": { "react-slick": {
"version": "0.25.2", "version": "0.28.1",
"resolved": "https://registry.npmjs.org/react-slick/-/react-slick-0.25.2.tgz", "resolved": "https://registry.nlark.com/react-slick/download/react-slick-0.28.1.tgz",
"integrity": "sha512-8MNH/NFX/R7zF6W/w+FS5VXNyDusF+XDW1OU0SzODEU7wqYB+ZTGAiNJ++zVNAVqCAHdyCybScaUB+FCZOmBBw==", "integrity": "sha1-EsGNmRtZQy35w3V7pUCiJ7P7hbk=",
"requires": { "requires": {
"classnames": "^2.2.5", "classnames": "^2.2.5",
"enquire.js": "^2.1.6", "enquire.js": "^2.1.6",
@ -15278,6 +15436,34 @@
"prop-types": "^15.5.4" "prop-types": "^15.5.4"
} }
}, },
"react-textarea-autosize": {
"version": "8.3.3",
"resolved": "https://registry.nlark.com/react-textarea-autosize/download/react-textarea-autosize-8.3.3.tgz?cache=0&sync_timestamp=1622628433420&other_urls=https%3A%2F%2Fregistry.nlark.com%2Freact-textarea-autosize%2Fdownload%2Freact-textarea-autosize-8.3.3.tgz",
"integrity": "sha1-9wkTlFNp2kU/1VTBaPa6rNH6BNg=",
"dev": true,
"requires": {
"@babel/runtime": "^7.10.2",
"use-composed-ref": "^1.0.0",
"use-latest": "^1.0.0"
},
"dependencies": {
"@babel/runtime": {
"version": "7.14.8",
"resolved": "https://registry.nlark.com/@babel/runtime/download/@babel/runtime-7.14.8.tgz",
"integrity": "sha1-cRmlb0IQGIUmlCkLn5FICXORtEY=",
"dev": true,
"requires": {
"regenerator-runtime": "^0.13.4"
}
},
"regenerator-runtime": {
"version": "0.13.9",
"resolved": "https://registry.nlark.com/regenerator-runtime/download/regenerator-runtime-0.13.9.tgz?cache=0&sync_timestamp=1626993001371&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fregenerator-runtime%2Fdownload%2Fregenerator-runtime-0.13.9.tgz",
"integrity": "sha1-iSV0Kpj/2QgUmI11Zq0wyjsmO1I=",
"dev": true
}
}
},
"react-transition-group": { "react-transition-group": {
"version": "2.9.0", "version": "2.9.0",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz",
@ -16095,8 +16281,8 @@
}, },
"rmc-feedback": { "rmc-feedback": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/rmc-feedback/-/rmc-feedback-2.0.0.tgz", "resolved": "https://registry.npm.taobao.org/rmc-feedback/download/rmc-feedback-2.0.0.tgz",
"integrity": "sha512-5PWOGOW7VXks/l3JzlOU9NIxRpuaSS8d9zA3UULUCuTKnpwBHNvv1jSJzxgbbCQeYzROWUpgKI4za3X4C/mKmQ==", "integrity": "sha1-y8bLOuY8emNe7w4l5PuvWsNm7qo=",
"requires": { "requires": {
"babel-runtime": "6.x", "babel-runtime": "6.x",
"classnames": "^2.2.5" "classnames": "^2.2.5"
@ -16679,8 +16865,8 @@
}, },
"shallow-equal": { "shallow-equal": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.1.tgz", "resolved": "https://registry.npm.taobao.org/shallow-equal/download/shallow-equal-1.2.1.tgz",
"integrity": "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==" "integrity": "sha1-TBar+lYEOqINBQMk76aJQLDaedo="
}, },
"shallowequal": { "shallowequal": {
"version": "1.1.0", "version": "1.1.0",
@ -17034,6 +17220,11 @@
"is-fullwidth-code-point": "^2.0.0" "is-fullwidth-code-point": "^2.0.0"
} }
}, },
"slick-carousel": {
"version": "1.8.1",
"resolved": "https://registry.npm.taobao.org/slick-carousel/download/slick-carousel-1.8.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fslick-carousel%2Fdownload%2Fslick-carousel-1.8.1.tgz",
"integrity": "sha1-pL+ykBSIe7Zs5Si5C9DNomLMj40="
},
"snapdragon": { "snapdragon": {
"version": "0.8.2", "version": "0.8.2",
"resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
@ -18368,6 +18559,12 @@
"integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==", "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==",
"dev": true "dev": true
}, },
"ts-essentials": {
"version": "2.0.12",
"resolved": "https://registry.nlark.com/ts-essentials/download/ts-essentials-2.0.12.tgz",
"integrity": "sha1-yTA/PXT3X6dSjD1JuA4ImrCdh0U=",
"dev": true
},
"tslib": { "tslib": {
"version": "1.11.1", "version": "1.11.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz",
@ -18877,6 +19074,30 @@
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
"integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==" "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ=="
}, },
"use-composed-ref": {
"version": "1.1.0",
"resolved": "https://registry.npm.taobao.org/use-composed-ref/download/use-composed-ref-1.1.0.tgz",
"integrity": "sha1-kiDk6UqXt7AtfSfq6rCzcDRDi7w=",
"dev": true,
"requires": {
"ts-essentials": "^2.0.3"
}
},
"use-isomorphic-layout-effect": {
"version": "1.1.1",
"resolved": "https://registry.npm.taobao.org/use-isomorphic-layout-effect/download/use-isomorphic-layout-effect-1.1.1.tgz",
"integrity": "sha1-e7ZYkXDNKYehUgQvkIT57/t1wiU=",
"dev": true
},
"use-latest": {
"version": "1.2.0",
"resolved": "https://registry.npm.taobao.org/use-latest/download/use-latest-1.2.0.tgz",
"integrity": "sha1-pE9lcrgojgly7EEb3QhAraNm8jI=",
"dev": true,
"requires": {
"use-isomorphic-layout-effect": "^1.0.0"
}
},
"user-home": { "user-home": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npm.taobao.org/user-home/download/user-home-1.1.1.tgz", "resolved": "https://registry.npm.taobao.org/user-home/download/user-home-1.1.1.tgz",
@ -20480,6 +20701,16 @@
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
"dev": true "dev": true
}, },
"xterm": {
"version": "4.8.1",
"resolved": "https://registry.npm.taobao.org/xterm/download/xterm-4.8.1.tgz",
"integrity": "sha1-FVoXKaQ+Gom0BlJOIsVjQznjnKE="
},
"xterm-addon-fit": {
"version": "0.4.0",
"resolved": "https://registry.npm.taobao.org/xterm-addon-fit/download/xterm-addon-fit-0.4.0.tgz",
"integrity": "sha1-BuDF0KaqrPsAnvVl76HIHpPZAZM="
},
"y18n": { "y18n": {
"version": "3.2.1", "version": "3.2.1",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
@ -20517,9 +20748,9 @@
} }
}, },
"zrender": { "zrender": {
"version": "4.3.0", "version": "4.3.2",
"resolved": "https://registry.npmjs.org/zrender/-/zrender-4.3.0.tgz", "resolved": "https://registry.npm.taobao.org/zrender/download/zrender-4.3.2.tgz",
"integrity": "sha512-Dii6j2bDsPkxQayuVf2DXJeruIB/mKVxxcGRZQ9GExiBd4c3w7+oBuvo1O/JGHeFeA1nCmSDVDs/S7yKZG1nrA==" "integrity": "sha1-7HQy+UFcgsc1hLa3uMR+GwFiCcY="
} }
} }
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "forge", "name": "forge",
"version": "0.1.0", "version": "3.0.0",
"private": true, "private": true,
"dependencies": { "dependencies": {
"@monaco-editor/react": "^2.3.0", "@monaco-editor/react": "^2.3.0",
@ -14,6 +14,7 @@
"babel-jest": "20.0.3", "babel-jest": "20.0.3",
"babel-loader": "7.1.2", "babel-loader": "7.1.2",
"babel-plugin-syntax-dynamic-import": "^6.18.0", "babel-plugin-syntax-dynamic-import": "^6.18.0",
"babel-polyfill": "^6.26.0",
"babel-preset-react-app": "^3.1.1", "babel-preset-react-app": "^3.1.1",
"babel-runtime": "6.26.0", "babel-runtime": "6.26.0",
"bizcharts": "^3.5.8", "bizcharts": "^3.5.8",
@ -29,7 +30,8 @@
"dompurify": "^2.0.15", "dompurify": "^2.0.15",
"dotenv": "4.0.0", "dotenv": "4.0.0",
"dotenv-expand": "4.2.0", "dotenv-expand": "4.2.0",
"echarts": "^4.7.0", "echarts": "^4.9.0",
"echarts-wordcloud": "^2.0.0",
"editor.md": "^1.5.0", "editor.md": "^1.5.0",
"eslint": "4.10.0", "eslint": "4.10.0",
"eslint-config-react-app": "^2.1.0", "eslint-config-react-app": "^2.1.0",
@ -46,6 +48,7 @@
"install": "^0.12.2", "install": "^0.12.2",
"jest": "20.0.4", "jest": "20.0.4",
"js-base64": "^2.5.2", "js-base64": "^2.5.2",
"js2wordcloud": "^1.1.12",
"katex": "^0.11.1", "katex": "^0.11.1",
"lodash": "^4.17.15", "lodash": "^4.17.15",
"loglevel": "^1.6.8", "loglevel": "^1.6.8",
@ -62,7 +65,7 @@
"postcss-loader": "2.0.8", "postcss-loader": "2.0.8",
"promise": "8.0.1", "promise": "8.0.1",
"prop-types": "^15.6.1", "prop-types": "^15.6.1",
"qrcode.react": "^1.0.0", "qrcode.react": "^1.0.1",
"qs": "^6.9.3", "qs": "^6.9.3",
"quill": "^1.3.7", "quill": "^1.3.7",
"quill-delta-to-html": "^0.11.0", "quill-delta-to-html": "^0.11.0",
@ -92,6 +95,7 @@
"react-resizable": "^1.10.1", "react-resizable": "^1.10.1",
"react-router": "^4.2.0", "react-router": "^4.2.0",
"react-router-dom": "^4.2.2", "react-router-dom": "^4.2.2",
"react-slick": "^0.28.1",
"react-split-pane": "^0.1.91", "react-split-pane": "^0.1.91",
"react-url-query": "^1.5.0", "react-url-query": "^1.5.0",
"react-zmage": "^0.8.5-beta.31", "react-zmage": "^0.8.5-beta.31",
@ -102,6 +106,7 @@
"scroll-into-view": "^1.14.2", "scroll-into-view": "^1.14.2",
"showdown": "^1.9.1", "showdown": "^1.9.1",
"showdown-katex": "^0.8.0", "showdown-katex": "^0.8.0",
"slick-carousel": "^1.8.1",
"store": "^2.0.12", "store": "^2.0.12",
"style-loader": "0.19.0", "style-loader": "0.19.0",
"styled-components": "^4.4.1", "styled-components": "^4.4.1",
@ -111,7 +116,9 @@
"webpack-dev-server": "^3.10.3", "webpack-dev-server": "^3.10.3",
"webpack-manifest-plugin": "^2.2.0", "webpack-manifest-plugin": "^2.2.0",
"whatwg-fetch": "2.0.3", "whatwg-fetch": "2.0.3",
"wrap-md-editor": "^0.2.20" "wrap-md-editor": "^0.2.20",
"xterm": "4.8.1",
"xterm-addon-fit": "0.4.0"
}, },
"scripts": { "scripts": {
"start": "node --max_old_space_size=15360 scripts/start.js", "start": "node --max_old_space_size=15360 scripts/start.js",
@ -186,6 +193,7 @@
"babel-core": "^6.26.0", "babel-core": "^6.26.0",
"babel-plugin-import": "^1.13.0", "babel-plugin-import": "^1.13.0",
"babel-plugin-transform-runtime": "^6.23.0", "babel-plugin-transform-runtime": "^6.23.0",
"babel-polyfill": "^6.26.0",
"babel-preset-es2015": "^6.24.1", "babel-preset-es2015": "^6.24.1",
"babel-preset-react": "^6.24.1", "babel-preset-react": "^6.24.1",
"babel-preset-stage-2": "^6.24.1", "babel-preset-stage-2": "^6.24.1",
@ -196,6 +204,7 @@
"node-sass": "^4.12.0", "node-sass": "^4.12.0",
"optimize-css-assets-webpack-plugin": "^5.0.3", "optimize-css-assets-webpack-plugin": "^5.0.3",
"purgecss": "^2.1.2", "purgecss": "^2.1.2",
"react-json-view": "^1.21.3",
"reqwest": "^2.0.5", "reqwest": "^2.0.5",
"resize-observer-polyfill": "^1.5.1", "resize-observer-polyfill": "^1.5.1",
"terser-webpack-plugin": "^2.3.5", "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; 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 { .nav-img {
position: absolute; position: absolute;
top: 2px; top: 2px;

View File

@ -1753,7 +1753,7 @@ a.decoration {
} }
.mb15 { .mb15 {
margin-bottom: 15px; margin-bottom: 15px!important;
} }
.mb16 { .mb16 {
@ -2346,7 +2346,6 @@ input::-ms-clear {
/*中间部分宽度固定为1200*/ /*中间部分宽度固定为1200*/
.newMain { .newMain {
margin: 0 auto; margin: 0 auto;
padding-bottom: 110px;
min-width: 1200px; min-width: 1200px;
} }
@ -2425,10 +2424,16 @@ input::-ms-clear {
.color-grey-c { .color-grey-c {
color: #ccc !important; color: #ccc !important;
} }
a.hoverLine:hover{
text-decoration: underline;
}
.color-grey-cd { .color-grey-cd {
color: #cdcdcd !important; color: #cdcdcd !important;
} }
.color-grey-d {
color: #ddd;
}
.color-grey-9 { .color-grey-9 {
color: #999999 !important; color: #999999 !important;
@ -3410,7 +3415,7 @@ a.user_bluebg_btn {
} }
.cdefault { .cdefault {
cursor: default cursor: default!important;
} }
@ -3585,42 +3590,6 @@ a.user_bluebg_btn {
margin-right: 5px; 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 ******/ /***** loading ******/
/*****载入中******/ /*****载入中******/
@ -3945,11 +3914,21 @@ html>body #ajax-indicator {
max-height: 340px; max-height: 340px;
}/*头部导航条样式---2018-03-19--by-cs*/ }/*头部导航条样式---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 { .head-nav {
text-align: center; text-align: center;
height: 70px; height: 70px;
box-sizing: border-box; box-sizing: border-box;
min-width: 780px;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
@ -3971,7 +3950,7 @@ html>body #ajax-indicator {
cursor: pointer; cursor: pointer;
position: relative; position: relative;
font-size: 16px; font-size: 16px;
padding:0px 20px; padding-right:40px;
} }
.head-nav ul#header-nav li a { .head-nav ul#header-nav li a {
@ -4108,21 +4087,6 @@ em.vertical-line {
/* 右侧内容宽度变化的话需要调整posi-search right的值*/ /* 右侧内容宽度变化的话需要调整posi-search right的值*/
/*底部*/
.newFooter {
max-height: 110px;
}
.newFooter {
position: absolute;
bottom: 0;
width: 100%;
background: #323232;
clear: both;
min-width: 1200px;
z-index: 8;
left: 0px;
}
.footercon { .footercon {
border-bottom: 1px solid #47494d; border-bottom: 1px solid #47494d;
@ -6718,4 +6682,19 @@ ul.count_ul li:not(:last-child):after {
} }
input.ant-input-lg::placeholder{ input.ant-input-lg::placeholder{
font-size: 14px !important; font-size: 14px !important;
}
p{
margin-bottom: 0px!important;
}
.toprightNum{
position: absolute;
right: 0px;
top:4px;
color: #999;
}
.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,475 @@
"css_prefix_text": "icon-", "css_prefix_text": "icon-",
"description": "", "description": "",
"glyphs": [ "glyphs": [
{
"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": "23144154",
"name": "下拉按钮_icon",
"font_class": "xialaanniu_icon",
"unicode": "e89a",
"unicode_decimal": 59546
},
{
"icon_id": "23144155",
"name": "未选中请求icon",
"font_class": "weixuanzhongqingqiuicon",
"unicode": "e89b",
"unicode_decimal": 59547
},
{
"icon_id": "23144158",
"name": "协作者管理icon",
"font_class": "xiezuozheguanliicon",
"unicode": "e8a1",
"unicode_decimal": 59553
},
{
"icon_id": "23144159",
"name": "选中响应icon",
"font_class": "xuanzhongxiangyingicon",
"unicode": "e8a2",
"unicode_decimal": 59554
},
{
"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": "23046282",
"name": "新增目录_悬停icon",
"font_class": "xinzengmulu_xuantingicon",
"unicode": "e884",
"unicode_decimal": 59524
},
{
"icon_id": "23046283",
"name": "新增页面_默认icon",
"font_class": "xinzengyemian_morenicon",
"unicode": "e885",
"unicode_decimal": 59525
},
{
"icon_id": "23046287",
"name": "展开_默认icon",
"font_class": "zhankai_morenicon",
"unicode": "e889",
"unicode_decimal": 59529
},
{
"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": "23046311",
"name": "新增页面_鼠标点击icon",
"font_class": "xinzengyemian_shubiaodianjiicon",
"unicode": "e88e",
"unicode_decimal": 59534
},
{
"icon_id": "23046244",
"name": "导入模版_icon",
"font_class": "daorumoban_icon",
"unicode": "e86f",
"unicode_decimal": 59503
},
{
"icon_id": "23046247",
"name": "导出_悬浮",
"font_class": "daochu_xuanfu",
"unicode": "e870",
"unicode_decimal": 59504
},
{
"icon_id": "23046252",
"name": "错误",
"font_class": "cuowu",
"unicode": "e872",
"unicode_decimal": 59506
},
{
"icon_id": "23046254",
"name": "成功",
"font_class": "chenggong1",
"unicode": "e873",
"unicode_decimal": 59507
},
{
"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": "23046262",
"name": "复制_icon",
"font_class": "fuzhi_icon",
"unicode": "e876",
"unicode_decimal": 59510
},
{
"icon_id": "23046268",
"name": "删除icon",
"font_class": "shanchuicon",
"unicode": "e877",
"unicode_decimal": 59511
},
{
"icon_id": "23046269",
"name": "垃圾桶_icon@3x",
"font_class": "a-lajitong_icon3x",
"unicode": "e878",
"unicode_decimal": 59512
},
{
"icon_id": "23046270",
"name": "收起_默认icon",
"font_class": "shouqi_morenicon",
"unicode": "e879",
"unicode_decimal": 59513
},
{
"icon_id": "23046271",
"name": "欢迎_icon",
"font_class": "huanying_icon",
"unicode": "e87a",
"unicode_decimal": 59514
},
{
"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": "23046277",
"name": "文件夹_icon",
"font_class": "wenjianjia_icon",
"unicode": "e87f",
"unicode_decimal": 59519
},
{
"icon_id": "23046278",
"name": "下拉按钮",
"font_class": "xialaanniu",
"unicode": "e880",
"unicode_decimal": 59520
},
{
"icon_id": "23046280",
"name": "新增目录_默认icon",
"font_class": "xinzengmulu_morenicon",
"unicode": "e882",
"unicode_decimal": 59522
},
{
"icon_id": "23046281",
"name": "新增目录_鼠标点击icon",
"font_class": "xinzengmulu_shubiaodianjiicon",
"unicode": "e883",
"unicode_decimal": 59523
},
{
"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", "icon_id": "991344",
"name": "提交", "name": "提交",
@ -4236,7 +4705,7 @@
{ {
"icon_id": "1004630", "icon_id": "1004630",
"name": "点赞2", "name": "点赞2",
"font_class": "dianzan1", "font_class": "dianzaned",
"unicode": "e639", "unicode": "e639",
"unicode_decimal": 58937 "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> <!DOCTYPE html>
<html lang="en"> <html lang="zh-CN" class="notranslate translated-ltr" translate="no">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name=”Keywords” Content=”trustie,trustieforge,forge,确实让创建更美好,协同开发平台″> <meta name=”Keywords” Content=”trustie,trustieforge,forge,确实让创建更美好,协同开发平台″>

View File

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

View File

@ -17,8 +17,7 @@ import marked from './common/marked';
import moment from 'moment' import moment from 'moment'
import { MuiThemeProvider, createMuiTheme } from 'material-ui/styles'; 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 { initAxiosInterceptors } from './AppConfig'
@ -40,6 +39,11 @@ const Projects = Loadable({
loader: () => import('./forge/Index'), loader: () => import('./forge/Index'),
loading: Loading, loading: Loading,
}) })
//forge安全设置
const Security = Loadable({
loader: () => import('./forge/SecuritySetting/Index'),
loading: Loading,
})
//forge项目-devOps详情 //forge项目-devOps详情
const OpsDetail = Loadable({ const OpsDetail = Loadable({
loader: () => import('./forge/DevOps/opsDetail'), loader: () => import('./forge/DevOps/opsDetail'),
@ -74,7 +78,15 @@ const EducoderLogin = Loadable({
loader: () => import('./modules/login/EducoderLogin'), loader: () => import('./modules/login/EducoderLogin'),
loading: Loading, loading: Loading,
}) })
const Search = Loadable({
loader: () => import('./modules/search/'),
loading: Loading,
})
const ProjectIndex = Loadable({
loader: () => import("./forge/Index"),
loading: Loading,
});
class App extends Component { class App extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
@ -100,36 +112,9 @@ class App extends Component {
Addcoursestypes: false 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() { componentDidMount() {
document.title = "loading..."; document.title = "loading...";
this.disableVideoContextMenu();
history.listen(() => {
this.forceUpdate()
const $ = window.$
$("html").animate({ scrollTop: $('html').scrollTop() - 0 })
});
initAxiosInterceptors(this.props); initAxiosInterceptors(this.props);
this.getAppdata(); this.getAppdata();
@ -207,11 +192,14 @@ class App extends Component {
}; };
render() { render() {
const { mygetHelmetapi } = this.state;
let personal = mygetHelmetapi && mygetHelmetapi.personal;
return ( return (
<Provider store={store}> <Provider store={store}>
<ConfigProvider locale={zhCN}> <ConfigProvider locale={zhCN}>
<MuiThemeProvider theme={theme}> <MuiThemeProvider theme={theme}>
<LoginDialog {...this.props} {...this.state} Modifyloginvalue={() => this.Modifyloginvalue()}></LoginDialog> <LoginDialog {...this.props} {...this.state} Modifyloginvalue={() => this.Modifyloginvalue()}></LoginDialog>
<SiderBar/>
<Router> <Router>
<Switch> <Switch>
{/*项目*/} {/*项目*/}
@ -223,6 +211,14 @@ class App extends Component {
} }
}> }>
</Route> </Route>
<Route
path={"/settings"}
render={
(props) => {
return (<Security {...this.props} {...props} {...this.state} />)
}
}>
</Route>
{/*项目*/} {/*项目*/}
<Route <Route
path={"/projects"} path={"/projects"}
@ -253,6 +249,10 @@ class App extends Component {
</Route> </Route>
{/*404*/} {/*404*/}
<Route path="/nopage" component={Shixunnopage} /> <Route path="/nopage" component={Shixunnopage} />
{/* 查询 */}
<Route path="/search" component={Search} />
{/* 个人主页 */} {/* 个人主页 */}
<Route path="/users/:username" <Route path="/users/:username"
render={ render={
@ -263,7 +263,10 @@ class App extends Component {
<Route exact path="/" <Route exact path="/"
render={ render={
(props) => ( (props) => (
<Projects {...this.props} {...props} {...this.state}></Projects> personal && personal.length > 0 ?
<InfosIndex {...this.props} {...props} />
:
<ProjectIndex {...this.props} {...props} />
) )
} }
/> />

View File

@ -2,7 +2,7 @@ import axios from 'axios';
import { requestProxy } from "./indexEduplus2RequestProxy"; import { requestProxy } from "./indexEduplus2RequestProxy";
import { broadcastChannelOnmessage, isDev, queryString } from 'educoder'; import { broadcastChannelOnmessage, isDev, queryString } from 'educoder';
import { notification } from 'antd'; import { notification } from 'antd';
import cookie from 'react-cookies';
import './index.css'; import './index.css';
let message501 = false; let message501 = false;
@ -11,10 +11,8 @@ broadcastChannelOnmessage('refreshPage', () => {
}) })
function locationurl(list) { function locationurl(list) {
if (window.location.port === "3007") { if (window.location.port !== "3007") {
window.location.href = list
} else {
window.location.href = list
} }
} }
// TODO 开发期多个身份切换 // TODO 开发期多个身份切换
@ -26,53 +24,22 @@ if (isDev) {
parsed = queryString.parse(_search); parsed = queryString.parse(_search);
} }
debugType = window.location.search.indexOf('debug=t') !== -1 ? 'teacher' : debugType = window.location.search.indexOf('debug=t') !== -1 ? 'teacher' :
window.location.search.indexOf('debug=s') !== -1 ? 'student' : window.location.search.indexOf('debug=s') !== -1 ? 'student' :
window.location.search.indexOf('debug=a') !== -1 ? 'admin' : parsed.debug || 'admin' window.location.search.indexOf('debug=a') !== -1 ? 'admin' : parsed.debug || 'admin'
} }
function clearAllCookie() {
cookie.remove('_educoder_session', { path: '/' });
cookie.remove('autologin_trustie', { path: '/' });
setpostcookie()
}
clearAllCookie();
function setpostcookie() {
const str = window.location.pathname;
if (str.indexOf("/wxcode") !== -1) {
cookie.remove('_educoder_session', { path: '/' });
cookie.remove('autologin_trustie', { path: '/' });
const _params = window.location.search;
if (_params) {
let _search = _params.split('?')[1];
let _educoder_sessions = _search.split('&')[0].split('=');
cookie.save('_educoder_session', _educoder_sessions[1], { domain: '.educoder.net', path: '/' });
let autologin_trusties = _search.split('&')[1].split('=');
cookie.save('autologin_trustie', autologin_trusties[1], { domain: '.educoder.net', path: '/' });
}
}
}
setpostcookie();
window._debugType = debugType; window._debugType = debugType;
export function initAxiosInterceptors(props) { export function initAxiosInterceptors(props) {
// 判断网络是否连接
initOnlineOfflineListener(); initOnlineOfflineListener();
var proxy = "http://localhost:3000";
proxy = "https://testforgeplus.trustie.net";
const requestMap = {}; var proxy = "https://testforgeplus.trustie.net";
window.setfalseInRequestMap = function (keyName) {
requestMap[keyName] = false;
}
//响应前的设置 //响应前的设置
axios.interceptors.request.use( axios.interceptors.request.use(
config => { config => {
setpostcookie() if(config.url.indexOf("http") !== -1) {
clearAllCookie()
if (config.url.indexOf(proxy) !== -1) {
return config return config
} }
requestProxy(config) requestProxy(config);
let url = `/api${config.url}`; let url = `/api${config.url}`;
if (`${config[0]}` !== `true`) { if (`${config[0]}` !== `true`) {
@ -86,18 +53,12 @@ export function initAxiosInterceptors(props) {
} else { } else {
config.url = url; config.url = url;
} }
setpostcookie();
}
if (config.url.indexOf('update_file') === -1) {
requestMap[config.url] = true;
window.setTimeout("setfalseInRequestMap('" + config.url + "')", 900)
} }
return config; return config;
}, },
err => { err => {
return Promise.reject(err); return Promise.reject(err);
}); });
axios.interceptors.response.use(function (response) { axios.interceptors.response.use(function (response) {
if (response === undefined) { if (response === undefined) {
@ -146,8 +107,6 @@ export function initAxiosInterceptors(props) {
message501 = false message501 = false
}, 2000); }, 2000);
} }
requestMap[response.config.url] = false;
setpostcookie();
return response; return response;
}, function (error) { }, function (error) {
return Promise.reject(error); return Promise.reject(error);

View File

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

View File

@ -15,7 +15,7 @@ export function getImageUrl(path) {
if (isDev) { if (isDev) {
return `${local}/${path}` return `${local}/${path}`
} }
return `/${path}`; return `${path}`;
} }
export function getImage(path) { export function getImage(path) {
@ -162,28 +162,28 @@ export function getmyUrl(geturl) {
} }
export function getUploadActionUrl(path, goTest) { export function getUploadActionUrl(path, goTest) {
return `${getUrl()}/api/attachments.json?debug=${window._debugType || 'admin'}`; return `${getUrl()}/api/attachments.json${isDev ?`${isDev ?`?debug=${window._debugType || 'admin'}` : ""}` : ""}`;
} }
export function getUploadLogoActionUrl() { export function getUploadLogoActionUrl() {
return `${getUrl()}/api/resumes/logo.json?debug=${window._debugType || 'admin'}`; return `${getUrl()}/api/resumes/logo.json${isDev ?`?debug=${window._debugType || 'admin'}` : ""}`;
} }
export function getUploadActionUrltwo(id) { export function getUploadActionUrltwo(id) {
return `${getUrlmys()}/api/shixuns/${id}/upload_data_sets.json?debug=${window._debugType || 'admin'}` return `${getUrlmys()}/api/shixuns/${id}/upload_data_sets.json${isDev ?`?debug=${window._debugType || 'admin'}` : ""}`
} }
export function getUploadActionUrlthree() { export function getUploadActionUrlthree() {
return `${getUrlmys()}/api/jupyters/import_with_tpm.json?debug=${window._debugType || 'admin'}` return `${getUrlmys()}/api/jupyters/import_with_tpm.json${isDev ?`?debug=${window._debugType || 'admin'}` : ""}`
} }
export function getupload_git_file(id) { export function getupload_git_file(id) {
return `${getUrlmys()}/api/shixuns/${id}/upload_git_file.json?debug=${window._debugType || 'admin'}` return `${getUrlmys()}/api/shixuns/${id}/upload_git_file.json${isDev ?`?debug=${window._debugType || 'admin'}` : ""}`
} }
export function getUploadActionUrlOfAuth(id) { export function getUploadActionUrlOfAuth(id) {
return `${getUrl()}/api/users/accounts/${id}/auth_attachment.json?debug=${window._debugType || 'admin'}` return `${getUrl()}/api/users/accounts/${id}/auth_attachment.json${isDev ?`?debug=${window._debugType || 'admin'}` : ""}`
} }
export function getRandomNumber(type) { export function getRandomNumber(type) {

View File

@ -64,7 +64,7 @@ function CommentItem({
const commentAvatar = (author) => ( const commentAvatar = (author) => (
<img <img
className="item-flex flex-image" className="item-flex flex-image"
src={author.image_url ? getImageUrl(`images/${author.image_url}`) : 'https://b-ssl.duitang.com/uploads/item/201511/13/20151113110434_kyReJ.jpeg'} src={author.image_url ? getImageUrl(`/${author.image_url}`) : 'https://b-ssl.duitang.com/uploads/item/201511/13/20151113110434_kyReJ.jpeg'}
alt="" alt=""
/> />
); );

View File

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

View File

@ -69,7 +69,7 @@ function Index(props){
<div className="aboutPanels"> <div className="aboutPanels">
<div className="aboutContent"> <div className="aboutContent">
<AlignCenterBetween style={{padding:"14px 20px"}}> <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> } { editOpration && !edit && <a onClick={editContent} className="color-blue">编辑</a> }
</AlignCenterBetween> </AlignCenterBetween>
{ {
@ -117,7 +117,7 @@ function Index(props){
{content ? {content ?
<RenderHtml className="break_word_comments imageLayerParent" value={content} url={props.history.location}/> <RenderHtml className="break_word_comments imageLayerParent" value={content} url={props.history.location}/>
: :
<div>暂无简介~</div> <div>暂无概览~</div>
} }
{attachments && attachments.length > 0 && {attachments && attachments.length > 0 &&
<Attachments <Attachments

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
import React , { useState , useEffect } from 'react'; import React , { useState , useEffect } from 'react';
import { Popover , Input , Spin } from 'antd'; import { Popover , Input , Spin } from 'antd';
import './branch.css'; import './branch.scss';
import { getBranch , getTag } from '../GetData/getData'; import { getBranch , getTag } from '../GetData/getData';
@ -102,7 +102,7 @@ export default (({ projectsId , branch , owner , changeBranch , branchList , tag
</div> </div>
); );
return( return(
<Popover placement="bottom" visible={flag} content={menu} onClick={()=>setFlag(!flag)} overlayClassName="branch-tagBox-list"> <Popover placement='bottomLeft' visible={flag} content={menu} onClick={()=>setFlag(!flag)} overlayClassName="branch-tagBox-list">
<div className="branch-tagBox"> <div className="branch-tagBox">
{/* {nav === 0 ?"分支":"标签"} */} {/* {nav === 0 ?"分支":"标签"} */}
<span className="color-grey-9 mr3 ml8"><i className="iconfont icon-fenzhi2 font-18"></i></span> <span className="color-grey-9 mr3 ml8"><i className="iconfont icon-fenzhi2 font-18"></i></span>

View File

@ -81,4 +81,25 @@
.listTips{ .listTips{
padding:20px 0px; padding:20px 0px;
text-align: center; text-align: center;
}
.urlMenu{
line-height: 30px;
margin-bottom: 10px;
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 ;
}
}
} }

View File

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

View File

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

View File

@ -112,6 +112,9 @@ li.ant-menu-item{
right:240px; right:240px;
z-index: 10000; z-index: 10000;
} }
.laterest{
color: #05690d;
}
@media screen and (max-width: 1800px){ @media screen and (max-width: 1800px){
.handleBox{ .handleBox{
@ -151,4 +154,210 @@ li.ant-menu-item{
.ant-tree{ .ant-tree{
margin:0px 20px!important; margin:0px 20px!important;
} }
} }
.menuPanels{
width: 240px;
height: 180px;
.ant-popover-content,.ant-popover-inner{
height: 100%;
width: 100%;
}
}
.halfs{
margin-top: 24px;
padding:24px 0px 0px 0px;
border-top: 1px solid #e8e8e8;
.attrPerson{
padding-bottom: 24px;
}
}
.menuinfos{
padding:15px 0px;
&>a{
display: flex;
flex-direction: column;
align-items: center;
border-right: 1px solid #eee;
flex: 1;
& >span:first-child{
font-size: 18px;
font-weight: 400;
color: #333;
}
& >span:last-child{
color: #666;
}
&:last-child{
border-right: none;
}
}
}
/*-------------------个人主页:右侧提示区域--------------------------*/
.-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,21 +1,154 @@
import React from 'react'; import React, { useEffect, useState } from 'react';
import { AlignCenter , FlexAJ } from '../Component/layout'; import { AlignCenter , FlexAJ } from '../Component/layout';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { Popover , Spin } from 'antd';
import { getImageUrl } from 'educoder'; 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}){
const [ menuList ,setMenuList ]= useState([]);
const [ list , setList ]= useState(undefined);
const [ total , setTotal ]= useState(0);
const [ menu , setMenu ] = useState("");
const [ login , setLogin ] = useState(undefined);
const [ isSpin , setIsSpin ] = useState(false);
useEffect(()=>{
if(contributors && contributors.total_count>0){
setTotal(contributors.total_count);
setList(contributors.list);
}
},[contributors])
useEffect(()=>{
if(login){
getUsers(login);
}else{
setMenu(undefined);
}
},[login])
async function getUsers(login){
setIsSpin(true);
let a = menuList && menuList.filter(i=>i.login === login);
if(a.length === 0){
let result = await getUser(login);
let arr = menuList;
arr.push({...result});
setMenuList(arr);
setMenusFunc(result);
setIsSpin(false);
}else{
setMenusFunc(a[0]);
setIsSpin(false);
}
}
function setMenusFunc(data){
if(data){
let ele = (
<Spin spinning={isSpin}>
<FlexAJ>
<AlignCenter>
<Link to={`/users/${data.login}`}><img src={getImageUrl(`/${data.image_url}`)} alt="" className="radius" width="38px" height="38px"/></Link>
<Link to={`/users/${data.login}`} className="ml10">{data.name}</Link>
</AlignCenter>
{
data.is_watch ? <a className="color-grey-9" onClick={()=>FocusFunc(false,data.login)}>取消关注</a>:<a className="color-blue" onClick={()=>FocusFunc(true,data.login)}>关注</a>
}
</FlexAJ>
<AlignCenter className="menuinfos">
<a href={data.projects_url}>
<span>{data.projects_count}</span>
<span>项目数</span>
</a>
<a href={data.followers_url}>
<span>{data.followers_count}</span>
<span>粉丝数</span>
</a>
<a href={data.following_url}>
<span>{data.following_count}</span>
<span>关注数</span>
</a>
</AlignCenter>
{
data.organizations && data.organizations.length > 0 ?
<AlignCenter className="font-12 pt4 pb4">
<span>所属组织</span>
<div className="task-hide flex1">
{renderArray(data.organizations)}
</div>
</AlignCenter>
:""
}
{
data.location && <AlignCenter className="font-12 pt4 pb4"><span>所在地址:</span><span className="ml5">{data.location}</span></AlignCenter>
}
</Spin>
)
setMenu(ele);
}
}
function FocusFunc(flag,login){
axios({
method: flag ? 'post' : 'delete',
url: `/watchers/${flag ? 'follow' : 'unfollow'}.json`,
params: {target_type: "user",id:login}
}).then(result => {
if (result && (result.data.status === 0 || result.data.status === 2)) {
let a = menuList && menuList.filter(i=>i.login === login);
if(a){
a[0].is_watch = flag;
}
setMenusFunc(a[0]);
}
})
.catch(error => {
console.log(error);
});
}
function renderArray(array){
let str = "";
for(var i = 0;i<array.length;i++){
str += array[i].name +"、";
}
let substr = str.substr(0,str.length-1);
return (<span title={substr}>{substr}</span>)
}
function setVisibleFunc(flag,l,index){
if(l !== login){
setLogin(l);
}
var lx = list.concat();
lx.map(i=>i.visible =false);
if(flag){
lx[index].visible = flag;
}
lx.splice();
setList(lx);
}
return( return(
<div> <div className="halfs">
<FlexAJ> <FlexAJ>
<AlignCenter><span className="font-16 color-grey-6">贡献者</span>{ contributors && contributors.total_count > 0 && <span className="infoCount">{contributors.total_count}</span>}</AlignCenter> <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> <Link className="font-12 color-grey-9" to={`/projects/${owner}/${projectsId}/contribute`}>全部</Link>
</FlexAJ> </FlexAJ>
<div className="attrPerson"> <div className="attrPerson" onMouseLeave={()=>setVisibleFunc(false)}>
{ {
contributors && contributors.total_count > 0 ? total > 0 ?
contributors.list.map((item,key)=>{ list.map((item,key)=>{
return( return(
<Link key={key} to={`/users/${item.login}`}><img src={getImageUrl(`images/${item.image_url}`)} alt=""/></Link> <Popover content={menu} visible={item.visible} overlayClassName="menuPanels" placement="top">
<Link key={key} to={`/users/${item.login}`}>
<img src={getImageUrl(`/${item.image_url}`)} alt="" onMouseOver={()=>setVisibleFunc(true,item.login,key)}/>
</Link>
</Popover>
) )
}) })
:"" :""

View File

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

View File

@ -0,0 +1,45 @@
.deleteBox{
.ant-modal-header{
background-color: #f8f8f8;
border-bottom: none;
.ant-modal-title{
text-align: left;
font-size: 20px;
}
}
.ant-modal-body{
padding:30px 50px;
p{
font-size: 16px;
line-height: 26px;
color:#666;
word-break: break-all;
}
.desc{
.descMain{
align-items: center;
justify-content: center;
font-size: 20px;
margin-bottom: 10px;
i{
font-size: 38px!important;
color:#DF0002
}
}
}
}
.ant-modal-footer{
border-top: none;
text-align: center;
padding-bottom: 40px;
button{
width: 120px;
margin:0px 20px;
&.ant-btn-danger{
background-color: #fff;
color: #DF0002;
border-color: #D0D0D0;
}
}
}
}

View File

@ -4,6 +4,12 @@ import './Component.scss';
import axios from 'axios'; import axios from 'axios';
const { TreeNode , DirectoryTree } = Tree; 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}){ function DrawerPanel({visible,onClose,branch,owner,projectsId,history, name , list}){
const [ treeData , setTreeData ] = useState(undefined); const [ treeData , setTreeData ] = useState(undefined);
const [ isSpin , setIsSpin ] = useState(true); 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; let dataref = event.node.props.dataRef;
if(dataref.type==="file"){ if(dataref.type==="file"){
onClose(); onClose();
history.push(`/projects/${owner}/${projectsId}/tree/${branch}/${dataref.path}`); let value = turnbar(branch);
history.push(`/projects/${owner}/${projectsId}/tree/${value}/${dataref.path}`);
} }
} }

View File

@ -0,0 +1,6 @@
.ant-modal-mask{
z-index: 1001;
}
.ant-modal-wrap{
z-index: 1002;
}

View File

@ -0,0 +1,60 @@
import React , {forwardRef, useEffect} from 'react';
import { Modal , Form , Input , Button } from 'antd';
import './EAccount.scss';
function EducoderAccount({form , visible , onOk , email}){
const { getFieldDecorator, validateFields , setFieldsValue } = form;
useEffect(()=>{
if(email){
setFieldsValue({email})
}
},[email])
function onSure(){
validateFields((error,values)=>{
if(!error){
onOk(values);
}
})
}
const layout = {
labelCol: { span: 5 },
wrapperCol: { span: 18 },
};
return(
<Modal
visible={visible}
title="提示"
width="500px"
closable={false}
footer={
<Button type="primary" onClick={onSure}>确定</Button>
}
centered
>
<div>
<p className="mb15 edu-txt-center" style={{maxWidth:"350px",margin:"0px auto"}}>
为确保您能正常使用平台功能请确认以下信息:
</p>
<Form {...layout}>
<Form.Item label="邮箱">
{getFieldDecorator("email",{
rules:[{required:true,message:"请输入邮箱账号"}]
})(
<Input placeholder="请输入您的邮箱账号" width="220px"/>
)}
</Form.Item>
<Form.Item label="密码">
{getFieldDecorator("password",{
rules:[{required:true,message:"请输入邮箱密码"}]
})(
<Input.Password placeholder="请输入您的邮箱密码" width="220px"/>
)}
</Form.Item>
</Form>
</div>
</Modal>
)
}
export default Form.create()(forwardRef(EducoderAccount));

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

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

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

@ -2,7 +2,7 @@ import React from 'react';
import { AlignCenter , AlignTop , FlexAJ } from '../Component/layout'; import { AlignCenter , AlignTop , FlexAJ } from '../Component/layout';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
function Releases({owner,projectsId,releaseVersions}){ function Releases({owner,projectsId,releaseVersions , baseOperate , projectType}){
return( return(
<div> <div>
@ -10,20 +10,23 @@ function Releases({owner,projectsId,releaseVersions}){
<AlignCenter><span className="font-16 color-grey-6">发行版</span> <AlignCenter><span className="font-16 color-grey-6">发行版</span>
{ releaseVersions && releaseVersions.total_count > 0 && <span className="infoCount">{releaseVersions.total_count}</span>} { releaseVersions && releaseVersions.total_count > 0 && <span className="infoCount">{releaseVersions.total_count}</span>}
</AlignCenter> </AlignCenter>
{ releaseVersions && releaseVersions.total_count > 0 ? { (releaseVersions && releaseVersions.total_count > 0) || projectType ===2 ?
<Link className="font-12 color-grey-9" to={`/projects/${owner}/${projectsId}/releases`}>全部</Link> <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> baseOperate && <Link className="font-12 color-blue" to={`/projects/${owner}/${projectsId}/releases/new`}>新建</Link>
} }
</FlexAJ> </FlexAJ>
{ {
releaseVersions && releaseVersions.total_count>0 ? releaseVersions && releaseVersions.total_count>0 ?
releaseVersions.list.map((item,key)=>{ releaseVersions.list.map((item,key)=>{
return( return(
<AlignTop className="mt10"> key === 0 &&<AlignTop className="mt10">
<i className="iconfont icon-biaoqian3 color-grey-6 font-18 mr10"></i> <i className="iconfont icon-biaoqian3 color-grey-6 font-18 mr10"></i>
<div> <div>
<p className="font-16 color-grey-6"><Link to={`/projects/${owner}/${projectsId}/releases/8/update`}>{item.name}</Link></p> <p className="font-16 color-grey-6">
<Link to={`/projects/${owner}/${projectsId}/releases`}>{item.name}</Link>
<span className="font-12 laterest ml5">最新</span>
</p>
<p className="color-grey-9 font-13">{item.created_at}</p> <p className="color-grey-9 font-13">{item.created_at}</p>
</div> </div>
</AlignTop> </AlignTop>

View File

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

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

@ -1,8 +1,8 @@
import React from 'react'; import React from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
import { Link } from 'react-router-dom';
export default ({ url , name , column , id , login })=>{
export default ({ url , name , column })=>{
const Img = styled.span` const Img = styled.span`
display:flex; display:flex;
${column && "flex-direction: column;text-align:center;"} ${column && "flex-direction: column;text-align:center;"}
@ -19,6 +19,14 @@ export default ({ url , name , column })=>{
} }
`; `;
return( return(
id?
<Link to={`/users/${login}`}>
<Img>
{ url && <img src={url} alt=""/> }
<span>{name}</span>
</Img>
</Link>
:
<Img> <Img>
{ url && <img src={url} alt=""/> } { url && <img src={url} alt=""/> }
<span>{name}</span> <span>{name}</span>

View File

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

View File

@ -36,8 +36,7 @@ function About(props, ref) {
const [ disabled, setDisabled ] = useState(false); const [ disabled, setDisabled ] = useState(false);
const [ typeFlag, setTypeFlag] = useState(false); const [ typeFlag, setTypeFlag] = useState(false);
const AuthorLogin = props.projectDetail && props.projectDetail.author && props.projectDetail.author.login;
const AuthorLogin = props.author && props.author.login;
const CurrentLogin = props.current_user && props.current_user.login; const CurrentLogin = props.current_user && props.current_user.login;
useEffect(()=>{ useEffect(()=>{
if(CurrentLogin === AuthorLogin){ if(CurrentLogin === AuthorLogin){
@ -56,11 +55,6 @@ function About(props, ref) {
setIsSpining(false); setIsSpining(false);
if(result && result.data ){ if(result && result.data ){
setStep(result.data.step); setStep(result.data.step);
// setStep(0);
// setFieldsValue({...result.data.cloud_account});
// if(result.data.cloud_account){
// setDisabled(true);
// }
} }
}).catch(error=>{ }).catch(error=>{
setIsSpining(false); setIsSpining(false);

View File

@ -10,6 +10,12 @@ import { Link } from 'react-router-dom';
// killed:"", // killed:"",
// pending:"" // pending:""
// } // }
function turnbar(str){
if(str && str.length>0 && str.indexOf("/")>-1){
return str.replaceAll('/','%2F');
}
return str;
}
function renderTableStatus(status) { function renderTableStatus(status) {
switch (status) { switch (status) {
case "running": case "running":
@ -65,8 +71,9 @@ function List({ list, operate , projectsId , owner , showModal , deleteFunc }){
width:"15%", width:"15%",
ellipsis:true, ellipsis:true,
render:(value,item)=>{ render:(value,item)=>{
let v = turnbar(item.branch);
return( return(
<Link to={`/projects/${owner}/${projectsId}/tree/${item.branch}/${value}`} className="color-blue">{value}</Link> <Link to={`/projects/${owner}/${projectsId}/tree/${v}/${value}`} className="color-blue">{value}</Link>
) )
} }
}, },

View File

@ -42,7 +42,7 @@ function PipelineName({visible,onCancel,onOk,value ,branchList}){
</div> </div>
<div className="choosenList mt20"> <div className="choosenList mt20">
<span>触发条件:</span> <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)=>{ branchList && branchList.length>0 && branchList.map((item,key)=>{
return( return(
@ -51,7 +51,7 @@ function PipelineName({visible,onCancel,onOk,value ,branchList}){
}) })
} }
</Select> </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)=>{ EVENT.map((item,key)=>{
return( return(

View File

@ -1,7 +1,8 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { Spin } from "antd"; import { Spin , Menu } from "antd";
import { FlexAJ, AlignCenter } from "../Component/layout"; import { FlexAJ, AlignCenter } from "../Component/layout";
import axios from "axios"; import axios from "axios";
import CodeSSH from './ssh/Index';
export default ({ export default ({
data, data,
@ -17,6 +18,8 @@ export default ({
const [spining, setSpining] = useState(true); const [spining, setSpining] = useState(true);
const [stage, setStage] = useState(undefined); const [stage, setStage] = useState(undefined);
const [step, setStep] = useState(undefined); const [step, setStep] = useState(undefined);
const [nav, setNav] = useState("0");
useEffect(() => { useEffect(() => {
setSpining(rightSpin); setSpining(rightSpin);
}, [rightSpin]); }, [rightSpin]);
@ -35,6 +38,7 @@ export default ({
: p[0]; : p[0];
setStep(sub); setStep(sub);
setNav("0");
if (sub && sub.status !== "skipped") { if (sub && sub.status !== "skipped") {
getStep(pre.number, sub.number); getStep(pre.number, sub.number);
} }
@ -65,43 +69,55 @@ export default ({
} }
} }
return ( return (
<Spin spinning={spining}> <React.Fragment>
<div className="rightMainContent"> {/* <Menu className="devopsNav" onClick={(e)=>{setNav(e.key)}} selectedKeys={[nav]} mode="horizontal">
{data && data.status !== "error" ? ( <Menu.Item key={'0'} value="0">开发流水线</Menu.Item>
<div> <Menu.Item key={'1'} value="1">命令行</Menu.Item>
<FlexAJ className="items"> </Menu> */}
<span>{step && step.name}</span> {
<AlignCenter> nav === "0" &&
{step && step.duration_time} <Spin spinning={spining}>
<i className="iconfont icon-sanjiaoxing-down"></i> <div className="rightMainContent">
</AlignCenter> {data && data.status !== "error" ? (
</FlexAJ> <div>
<div> <FlexAJ className="items">
{coders && coders.length > 0 ? ( <span>{step && step.name}</span>
coders.map((item, key) => { <AlignCenter>
return ( {step && step.duration_time}
<i className="iconfont icon-sanjiaoxing-down"></i>
</AlignCenter>
</FlexAJ>
<div>
{coders && coders.length > 0 ? (
coders.map((item, key) => {
return (
<div className="opsDetailOut">
<span>{key + 1}</span>
<p>{item.out}</p>
</div>
);
})
) : empty ? (
<div className="opsDetailOut"> <div className="opsDetailOut">
<span>{key + 1}</span> <span>1</span>
<p>{item.out}</p> <p>
{stage && stage.name} {step && step.name}: Skipped
</p>
</div> </div>
); ) : (
}) ""
) : empty ? ( )}
<div className="opsDetailOut">
<span>1</span>
<p>
{stage && stage.name} {step && step.name}: Skipped
</p>
</div> </div>
) : ( </div>
"" ) : (
)} <div style={{ color: "red" }}>error:{data && data.error}</div>
</div> )}
</div> </div>
) : ( </Spin>
<div style={{ color: "red" }}>error:{data && data.error}</div> }
)} {
</div> nav === "1" && <CodeSSH />
</Spin> }
</React.Fragment>
); );
}; };

View File

@ -2,7 +2,7 @@ import React, { useState, useEffect , useImperativeHandle ,forwardRef } from "re
import { FlexAJ, AlignCenter , Banner } from "../Component/layout"; import { FlexAJ, AlignCenter , Banner } from "../Component/layout";
import { Table, Pagination, Popconfirm } from "antd"; import { Table, Pagination, Popconfirm } from "antd";
import { truncateCommitId } from "../common/util"; import { truncateCommitId } from "../common/util";
import {getUrl} from 'educoder'; import { getImageUrl } from 'educoder';
import axios from "axios"; import axios from "axios";
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
@ -58,6 +58,7 @@ function Structure(props,ref){
return { return {
...item, ...item,
author:item.author && item.author.name, author:item.author && item.author.name,
image_url:item.author && item.author.image_url,
message: { message: {
branch: item.branch_target, branch: item.branch_target,
message: item.message, message: item.message,
@ -244,7 +245,7 @@ function Structure(props,ref){
{meg.sha && <span className="color-orange">{meg.sha}</span>} {meg.sha && <span className="color-orange">{meg.sha}</span>}
</div> </div>
<AlignCenter> <AlignCenter>
<img style={{borderRadius:"50%",marginRight:"10px",width:"25px",height:"25px"}} src={`${current_user && getUrl(`/images/${current_user.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" }}> <div className="task-hide ml5" style={{ maxWidth: "300px" }}>
{meg.message} {meg.message}
</div> </div>

View File

@ -194,6 +194,18 @@
&.rightSection{ &.rightSection{
width:100%; width:100%;
background-color: #081930; background-color: #081930;
.devopsNav{
background-color: #111c24;
border-bottom: none;
.ant-menu-item{
color: #ccc;
padding:0px;
margin:0px 20px!important;
}
.ant-menu-item.ant-menu-item-selected{
color: #1890ff;
}
}
.rightMainContent{ .rightMainContent{
padding:24px 30px; padding:24px 30px;
height:100vh; height:100vh;
@ -379,6 +391,9 @@
} }
} }
} }
.chooseCon.ant-select-dropdown{
z-index: 100001;
}
.choosenList{ .choosenList{
display: flex; display: flex;

View File

@ -0,0 +1,42 @@
import React, { useState, useEffect } from "react";
import XmlPanel from "./XmlPanel";
import mediator from "./mediator";
import axios from "axios";
// const defaulturl = `http://47.111.130.18:48088`;
const defaultValue = {
host: "106.75.231.63",
port: "2021",
ws_url: "wss://pre-webssh.educoder.net/ws",
username: "root",
secret: "Dron_123123",
};
function Index() {
const [sshConfigData, setSshConfigData] = useState(undefined);
useEffect(() => {
if (!sshConfigData) {
init();
}
setTimeout(() => {
mediator.publish("create-socket", 1);
}, 300);
}, [sshConfigData]);
//
function init() {
const url = `/api/ci/pipelines/ssh_server.json`;
axios.get(url).then(result=>{
if(result && result.data){
setSshConfigData({...result.data})
}
}).catch(error=>{})
}
return (
<XmlPanel
sshConfigData={sshConfigData||{}}
sid={1}
/>
);
}
export default Index;

View File

@ -0,0 +1,219 @@
import React, { useRef, useEffect, useState } from 'react';
import { Base64 } from 'js-base64';
import { Terminal } from 'xterm';
import 'xterm/css/xterm.css';
import mediator from './mediator';
import ResizeObserver from 'resize-observer-polyfill';
function getColsAndRows(width, height, term) {
let w = term._core._renderService.dimensions.actualCellWidth || 9.5;
let h = term._core._renderService.dimensions.actualCellHeight || 18;
const rows = Math.floor(height / h);
const cols = Math.floor(width / w);
return [cols, rows];
}
function onLayout(term, el) {
const ro = new ResizeObserver(entries => {
console.log(entries);
for (let entry of entries) {
if (entry.target.offsetHeight > 0 || entry.target.offsetWidth > 0) {
const [cols, rows] = getColsAndRows(
entry.target.offsetWidth,
entry.target.offsetHeight,
term,
);
console.log('cols, rows', cols, rows);
term.resize(cols, rows);
mediator.publish('ssh-xterm-resize', {
columns: cols,
rows: rows,
width: entry.target.offsetWidth,
height: entry.target.offsetHeight,
});
}
}
});
ro.observe(el);
return ro;
}
const TimeTicket = 30000;
// websockt
//
//socket term socket
//mediator id
export default ({ sshConfigData, sid }) => {
const [term, setTerm] = useState(null);
const { ws_url, password, port, secret } = sshConfigData;
const el = useRef();
const socket = useRef();
const isFirstConnected = useRef(false);
//term init
useEffect(() => {
if (el.current && ws_url) {
const term = new Terminal({ fontSize: 16, rendererType: 'dom' });
term.open(el.current);
term.onData(data => {
if (socket.current) {
if (socket.current.readyState === 1) {
socket.current.send(JSON.stringify({ tp: 'client', data: data }));
mediator.publish('on-operating-ssh'); //
} else {
//
// socket.current = null
// mediator.publish('create-socket', sid)
}
}
});
term.write('Connecting...');
setTerm(term);
const ro = onLayout(term, el.current);
return () => {
term.dispose();
ro.unobserve(el.current);
};
}
}, [ws_url, el.current]);
useEffect(() => {
if (term && ws_url) {
function createSocket() {
const socketInstance = new WebSocket(ws_url);
socket.current = socketInstance;
socketInstance.onopen = () => {
let container = term.element.parentElement;
if (container) {
let width = container.offsetWidth;
let height = container.offsetHeight;
console.log('init', {
tp: 'init',
data: {
...sshConfigData,
secret: secret,
width,
height,
rows: term.rows,
columns: term.cols,
},
});
socketInstance.send(
JSON.stringify({
tp: 'init',
data: {
...sshConfigData,
secret: secret,
width,
height,
rows: term.rows,
columns: term.cols,
},
}),
);
}
term.focus();
};
socketInstance.onerror = error => {
console.log(
'------in socket error----',
error,
socketInstance,
ws_url,
);
//
// mediator.publish('on-recreate-socket')
};
socketInstance.onmessage = event => {
if (!isFirstConnected.current) {
term.write('\r');
// term.focus()
setTimeout(() => {
// term.clear();
}, 1000);
}
isFirstConnected.current = true;
console.log('event:', event);
const data = Base64.decode(event.data.toString());
let w = term._core._renderService.dimensions.actualCellWidth || 9.5;
console.log('data:', data, w, term);
term.write(data);
};
socketInstance.onclose = evt => {
if (tid) {
clearInterval(tid);
}
term.write('\r\nconnection closed');
};
}
const tid = setInterval(() => {
if (socket.current) {
socket.current.send(JSON.stringify({ tp: 'h' }));
}
}, TimeTicket);
const unSubCreate = mediator.subscribe('create-socket', id => {
if (sid === id) {
if (socket.current && socket.current.readyState === 1) {
term.focus();
} else {
createSocket();
}
term.focus();
}
});
const unSubClose = mediator.subscribe('close-socket', id => {
if (sid === id) {
if (socket.current) {
socket.current.close();
isFirstConnected.current = false;
term.clear();
}
socket.current = null;
}
});
const unSubResize = mediator.subscribe('ssh-xterm-resize', option => {
if (socket.current && socket.current.readyState === 1) {
socket.current.send(
JSON.stringify({ tp: 'resize', data: { ...option } }),
);
}
});
const unSubAddTime = mediator.subscribe('ssh-add-connect-time', () => {
if (socket.current && socket.current.readyState === 1) {
socket.current.send(JSON.stringify({ tp: 'overtime' }));
}
});
return () => {
unSubClose();
unSubCreate();
unSubResize();
unSubAddTime();
if (socket.current) {
socket.current.close();
isFirstConnected.current = false;
}
};
}
}, [term, ws_url, port]);
return (
<div ref={el} className="xterm-panel" style={{height:"100%"}}>
{!ws_url ? <p style={{ color: '#fff' }}>正在连接命令行服务...</p> : null}
</div>
);
};

View File

@ -0,0 +1,46 @@
function Mediator(obj) {
const channels = {};
const mediator = {
subscribe: function(channel, cb) {
if (!channels[channel]) {
channels[channel] = [];
}
channels[channel].push(cb);
return this.unsubscribe.bind(null, channel, cb);
},
unsubscribe: function(channel, cb) {
let rs = channels[channel];
let index = -1;
if (rs) {
for (let i = 0; i < rs.length; i++) {
if (rs[i].name === cb.name) {
index = i;
break;
}
}
if (index >= 0) {
channels[channel].splice(index, 1);
return true;
}
}
return false;
},
publish: function(channel) {
if (!channels[channel]) {
return false;
}
const args = Array.prototype.slice.call(arguments, 1);
channels[channel].forEach(subscription => {
subscription.apply(null, args);
});
return this;
},
};
return obj ? Object.assign(obj, mediator) : mediator;
}
const mediator = new Mediator();
export default mediator;

View File

@ -0,0 +1,175 @@
import React ,{ forwardRef, useEffect, useState } from 'react';
import { Modal , Form , Input , Radio , Select } from 'antd';
import SearchUser from '../Component/SearchUser';
import './Index.scss';
import Axios from 'axios';
const { Option } = Select;
function DivertModal({form , visible , onSuccess , onCancel,owner,repo}){
const { getFieldDecorator, validateFields , setFieldsValue } = form;
const [ cate , setCate ] = useState(0);
const [ value , setValue ] = useState(undefined);
const [ organizations , setOrganizations ] = useState(undefined);
useEffect(()=>{
setFieldsValue({goal:cate})
},[])
useEffect(()=>{
if(owner && repo && visible===true){
getTeam();
}
if(!visible){
setFieldsValue({
owner_name:undefined,
identifier:undefined
})
setValue(undefined)
}
},[repo,owner,visible])
function getTeam(){
const url = `/${owner}/${repo}/applied_transfer_projects/organizations.json`;
Axios.get(url).then(result=>{
if(result){
setOrganizations(result.data.organizations);
}
}).catch(error=>{})
}
//
function onOk(){
validateFields((error,values)=>{
console.log(...values);
if(!error){
const url = `/${owner}/${repo}/applied_transfer_projects.json`;
Axios.post(url,{
...values
}).then(result=>{
if(result){
onSuccess(result.data && result.data.owner);
}
}).catch(error=>{})
}
})
}
function changeType(e){
setCate(e.target.value);
setFieldsValue({
owner_name:undefined
})
}
function checkIdentifier(rule, value, callback){
if(!value){
callback();
}
if (repo && value !== repo) {
callback("请输入当前项目的标识!");
}
callback();
}
const layout = {
labelCol: { span: 5 },
wrapperCol: { span: 18 },
};
function getUser(id){
setValue(id);
setFieldsValue({
owner_name:id
})
}
return(
<Modal
width="620px"
visible={visible}
title="转移仓库"
onCancel={onCancel}
onOk={onOk}
okText="确认转移"
cancelText={"取消"}
centered
>
<div className="diverModal">
{
cate === 0 ?
<ul className="descUl">
<li>转移需对方确认接受转移成功后你将被移出仓库其他已有成员权限不变</li>
<li>转移成功后仓库的地址将变更至目标用户的命名空间下</li>
<li>已有成员如需继续操作仓库需更新本地仓库的remote使之指向新的地址</li>
</ul>
:
<ul className="descUl">
<li>仓库仅可以转移到您已经加入的组织中不可以转移到未加入的组织中</li>
<li>涉及到仓库改名操作请提前做好仓库备份并且在转移后对本地仓库的remote进行修改</li>
<li>转移仓库到组织后你和组织创建者/管理员同时拥有对该仓库的管理操作</li>
</ul>
}
<Form {...layout} colon={false} layout={"horizontal"}>
<Form.Item label="转移给:" style={{marginBottom:"0px"}}>
{getFieldDecorator("goal",{
rules:[]
})(
<Radio.Group onChange={changeType}>
<Radio value={0}>个人</Radio>
<Radio value={1}>组织</Radio>
</Radio.Group>
)}
</Form.Item>
{
cate === 0 &&
<Form.Item label=" ">
{getFieldDecorator("owner_name",{
rules:[{required:true,message:"请输入目标用户名"}]
})(
// <Input placeholder="" autoComplete={"off"}/>
<SearchUser getUser={getUser} width={"100%"} placeholder="请输入目标用户" value={value}/>
)}
</Form.Item>
}
{
cate === 1 &&
<Form.Item label=" ">
{getFieldDecorator("owner_name",
{rules:[{required:true,message:"请选择目标组织"}]}
)(
<Select placeholder="请选择目标组织" getPopupContainer={trigger => trigger.parentNode}>
{
organizations && organizations.length > 0 ?
organizations.map((i,k)=>{
return(
<Option value={i.name}>{i.nickname}</Option>
)
})
:""
}
</Select>
)}
</Form.Item>
}
<Form.Item label="仓库标识:" 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

@ -14,4 +14,8 @@ export const getHooks = async (id,params)=>{
// //
export const getSubEntries = async (owner,projectsId,params)=>{ export const getSubEntries = async (owner,projectsId,params)=>{
return (await axios.get(`/${owner}/${projectsId}/sub_entries.json`,{params})).data; return (await axios.get(`/${owner}/${projectsId}/sub_entries.json`,{params})).data;
}
//
export const getUser = async (login)=>{
return (await axios.get(`/users/${login}/hovercard.json`)).data;
} }

View File

@ -0,0 +1,84 @@
import React, { useState , forwardRef, useEffect } from 'react';
import { Form , Modal , Input , Radio } from 'antd';
import Axios from 'axios';
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>
<a onClick={()=>setVisible(true)}>加入项目</a>
</React.Fragment>
)
})
)

66
src/forge/Head/Footer.jsx Normal file
View File

@ -0,0 +1,66 @@
import React, { useEffect , useState } from 'react';
import './header.scss';
function Footer(){
const [ value , setValue ] = useState(undefined);
useEffect(()=>{
try {
var chromesettingArray = JSON.parse(localStorage.getItem('chromesetting'));
setValue(chromesettingArray.footer);
} catch (e) {
}
},[])
function showhtml(htmlString){
var html = {__html:htmlString};
return <div dangerouslySetInnerHTML={html}></div> ;
}
return(
<div>
<div style={{height:"497px"}}></div>
<div className="newFooter edu-txt-center">
{value && showhtml(value)}
{/* <div className="footerInfos">
<ul>
<li>社区</li>
<li><a href={`/`} target="_blank">网站首页</a></li>
<li><a href={`https://www.trustie.net/agreement`} target="_blank">服务协议</a></li>
<li><a href={`https://forum.trustie.net/forums/1168/detail`} target="_blank">帮助中心</a></li>
<li><a href={`https://forum.trustie.net/`} target="_blank">问吧交流</a></li>
<li><a href={`https://www.trustie.net/cooperation`} target="_blank">合作伙伴</a></li>
</ul>
<ul>
<li>支持与服务</li>
<li><a href={`https://forgeplus.trustie.net/docs/api`} target="_blank">API文档</a></li>
<li><a href={`https://forum.trustie.net/forums/1168/detail`} target="_blank">帮助中心</a></li>
<li><a href={`https://git-scm.com`} target="_blank">Git常用命令</a></li>
<li><a href={`https://forum.trustie.net/forums/3080/detail`} target="_blank">DevOps使用文档</a></li>
<li><a href={`https://forgeplus.trustie.net/projects/jasder/forgeplus/tree/master/CHANGELOG.md`} target="_blank">日志更新</a></li>
</ul>
<ul>
<li>合作伙伴</li>
<li><a href={`http://www.sei.pku.edu.cn`} target="_blank">北京大学</a></li>
<li><a href={`http://scse.buaa.edu.cn`} target="_blank">北京航空航天大学</a></li>
<li><a href={`https://www.nju.edu.cn`} target="_blank">南京大学</a></li>
<li><a href={`https://www.xtu.edu.cn`} target="_blank">湘潭大学</a></li>
<li><a href={`http://www.iscas.ac.cn`} target="_blank">ISCAS</a></li>
<li><a href={`https://www.ucloud.cn`} target="_blank">UCloud优刻得</a></li>
<li><a href={`http://www.inforbus.com`} target="_blank">中创软件</a></li>
<li><a href={`https://www.inspur.com`} target="_blank">浪潮集团</a></li>
<li><a href={`http://www.copu.org.cn`} target="_blank">中国开源软件推进联盟</a></li>
<li><a href={`https://www.sjtu.edu.cn`} target="_blank">上海交通大学</a></li>
</ul>
<ul>
<li>合作伙伴</li>
<li><span>热线</span></li>
<li><span>QQ群1071514693</span></li>
</ul>
</div>
<p className="footerCopy">© Copyright 2007~2021 国防科技大学Trustie团队 & IntelliDE <a href="https://beian.miit.gov.cn">湘ICP备 17009477</a></p> */}
</div>
</div>
)
}
export default Footer;

View File

@ -2,16 +2,15 @@ import React, { Component } from 'react';
import AccountProfile from "../../modules/user/AccountProfile"; import AccountProfile from "../../modules/user/AccountProfile";
import { getImageUrl } from 'educoder' import { getImageUrl } from 'educoder'
import axios from 'axios'; import axios from 'axios';
import { Modal, Input, message, notification , Dropdown , Menu ,Divider } from 'antd'; import { Input , notification , Dropdown , Menu } from 'antd';
import { Link } from 'react-router-dom';
import LoginDialog from '../../modules/login/LoginDialog'; import LoginDialog from '../../modules/login/LoginDialog';
import GotoQQgroup from '../../modal/GotoQQgroup' import HeadSearch from '../Component/HeadSearch';
// import 'antd/lib/modal/style/index.css';
// import 'antd/lib/checkbox/style/index.css'; import AddProjectModal from './AddProjectModal';
// import 'antd/lib/radio/style/index.css';
// import 'antd/lib/input/style/index.css';
import '../../modules/tpm/TPMIndex.css'; import '../../modules/tpm/TPMIndex.css';
import logo from '../../modules/tpm/images/logo.png';
import './header.scss'; import './header.scss';
const $ = window.$ const $ = window.$
// TODO 这部分脚本从公共脚本中直接调用 // TODO 这部分脚本从公共脚本中直接调用
@ -35,11 +34,9 @@ class NewHeader extends Component {
Checkboxteachertype: false, Checkboxteachertype: false,
Checkboxteachingtype: false, Checkboxteachingtype: false,
code_notice: false, code_notice: false,
checked_notice: false,
RadioGroupvalue: undefined, RadioGroupvalue: undefined,
submitapplications: false, submitapplications: false,
isRender: false, isRender: false,
showSearchOpentype: false,
showTrial: false, showTrial: false,
setevaluatinghides: false, setevaluatinghides: false,
occupation: 0, occupation: 0,
@ -47,13 +44,11 @@ class NewHeader extends Component {
headtypesonClickbool: false, headtypesonClickbool: false,
headtypess: "/", headtypess: "/",
settings: null, settings: null,
goshowqqgtounp: false,
visiblemyss: false, visiblemyss: false,
openSearch:false, openSearch:false,
} }
} }
componentDidMount() { componentDidMount() {
// this.getAppdata();
this.geturlsdata(); this.geturlsdata();
window._header_componentHandler = this; window._header_componentHandler = this;
@ -84,36 +79,6 @@ class NewHeader extends Component {
} catch (e) {} } 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 && item.url}?value=` + value;
}
openNotification = (messge) => { openNotification = (messge) => {
notification.open({ notification.open({
message: "提示", message: "提示",
@ -122,8 +87,6 @@ class NewHeader extends Component {
}); });
}; };
componentWillReceiveProps(newProps, oldProps) { componentWillReceiveProps(newProps, oldProps) {
this.setState({ this.setState({
user: newProps.user user: newProps.user
@ -132,158 +95,7 @@ class NewHeader extends Component {
old_url = newProps.Headertop.old_url 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 = () => { educoderlogin = () => {
//登录账号 //登录账号
this.setState({ 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 = () => { cancelModulationModels = () => {
this.setState({ isRenders: false }) this.setState({ isRenders: false })
} }
setevaluatinghides = () => { setevaluatinghides = () => {
this.setState({ this.setState({
setevaluatinghides: true 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 = () => { geturlsdata = () => {
let url = "/setting.json"; let url = "/setting.json";
axios.get(url).then((response) => { axios.get(url).then((response) => {
if (response && response.data) { if (response && response.data) {
this.setState({ settings: response.data.setting }); this.setState({ settings: response.data.setting });
// localStorage.setItem('chromesetting', JSON.stringify(response.data.setting)); localStorage.setItem('chromesetting', JSON.stringify(response.data.setting));
// localStorage.setItem('chromesettingresponse', JSON.stringify(response)); localStorage.setItem('chromesettingresponse', JSON.stringify(response));
try {
if (response.data.setting.tab_logo_url) {
this.gettablogourldata(response);
} else {
this.gettablogourlnull();
}
} catch (e) {
this.gettablogourlnull();
}
} else { } else {
this.gettablogourlnull(); this.gettablogourlnull();
} }
@ -456,14 +223,6 @@ class NewHeader extends Component {
} }
} }
// 处理弹框
setgoshowqqgtounp = (bool) => {
this.setState({
goshowqqgtounp: bool
})
}
addMenu=(list)=>{ addMenu=(list)=>{
return( return(
list && list.length >0 && list && list.length >0 &&
@ -472,34 +231,45 @@ class NewHeader extends Component {
{ {
list.map((item,key)=>{ list.map((item,key)=>{
return( 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}><a href={item.url}>{item.name}</a></Menu.Item>
) )
}) })
} }
<Menu.Item><AddProjectModal showNotification={this.props.showNotification}/></Menu.Item>
</Menu> </Menu>
</div> </div>
) )
} }
renderMenu=(personal)=>{
const { current_user } = this.props;
return(
<Menu className="currentMenu">
<Menu.Item>
<span 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/SSH`}>设置</Link></li>
<Menu.Item><a onClick={() => this.educoderloginysl()}>退出</a></Menu.Item>
</Menu>
)
}
render() { render() {
const { match} = this.props; const { match} = this.props;
let current_user = this.props.user; let current_user = this.props.user;
let { Addcoursestypes, let {
tojoinitemtype,
tojoinclasstitle,
code_notice,
checked_notice,
AccountProfiletype, AccountProfiletype,
submitapplications,
submitapplicationsvalue,
user, user,
isRender, isRender,
showSearchOpentype,
headtypesonClickbool, headtypesonClickbool,
headtypess, headtypess,
settings, settings,
goshowqqgtounp,
openSearch,
} = this.state; } = this.state;
/*用户名称 用户头像url*/ /*用户名称 用户头像url*/
let activeIndex = false; let activeIndex = false;
@ -557,7 +327,7 @@ class NewHeader extends Component {
let shixun = "/shixuns"; let shixun = "/shixuns";
let paths = "/paths"; let paths = "/paths";
let courses = "/courses"; 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); var reg = RegExp(item.link);
if (shixun.match(reg)) { if (shixun.match(reg)) {
if (item.hidden === true) { if (item.hidden === true) {
@ -577,8 +347,8 @@ class NewHeader extends Component {
}) })
} }
let search_url = settings && settings.common && settings.common.length> 0 && settings.common.filter(item=>item.name==="搜索"); // let search_url = settings && settings.common && settings.common.search;
let notice_url = settings && settings.common && settings.common.length> 0 && settings.common.filter(item=>item.name==="通知"); let notice_url = settings && settings.common && settings.common.notice;
return ( return (
<div className="newHeaders" id="nHeader"> <div className="newHeaders" id="nHeader">
<div className="headerContent"> <div className="headerContent">
@ -595,19 +365,14 @@ class NewHeader extends Component {
{...this.props} {...this.props}
{...this.state} {...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 ? 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"}> <div className="head-nav pr" id={"head-navpre1"}>
{ {
settings && settings.navbar && settings.navbar.length > 0 ? settings && settings.navbar && settings.navbar.length > 0 ?
@ -646,7 +411,8 @@ class NewHeader extends Component {
} }
</div> </div>
<div className="head-right"> <div className="head-right">
{search_url && search_url.length>0 ? this.SearchInput(openSearch,search_url[0]):""} {/* {search_url ? this.SearchInput(openSearch,search_url):""} */}
<HeadSearch {...this.props}/>
{ {
current_user && (current_user.main_site || current_user.login) && (settings && settings.add && settings.add.length>0)? 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"> <Dropdown overlay={this.addMenu(settings && settings.add)} placement="bottomRight">
@ -654,10 +420,10 @@ class NewHeader extends Component {
</Dropdown>:"" </Dropdown>:""
} }
{this.props.user && this.props.user.login && (notice_url && notice_url.length>0) ? {this.props.user && this.props.user.login && notice_url ?
<div className="ml30 edu-menu-panel"> <div className="ml30 edu-menu-panel">
{user && user.login && {user && user.login &&
<a href={`${notice_url[0].url}`} style={{ position: 'relative' }}> <a href={`${notice_url}`} style={{ position: 'relative' }}>
<i className="iconfont icon-xiaoxilingdang color-grey-6"></i> <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 className="newslight" style={{ display: this.props.Headertop === undefined ? "none" : this.props.Headertop.new_message === true ? "block" : "none" }}>
</span> </span>
@ -665,62 +431,21 @@ class NewHeader extends Component {
} }
</div>:"" </div>:""
} }
<Modal
keyboard={false}
title="提示"
visible={submitapplications}
closable={false}
footer={null}
>
<div className="task_popup_con ml30">
<div className="mr15">
<ul>
<div className="task-popup-content">
<p className="task-popup-text-center font-16">
{submitapplicationsvalue}
</p>
</div>
<li className="clearfix mt10 edu-txt-center">
<a className="task-btn mr10"
onClick={this.hidesubmitapplications}>取消</a>
<a
className="task-btn task-btn-orange ml20"
onClick={this.submitsubmitapplications}>确定</a>
</li>
</ul>
</div>
</div>
</Modal>
</div> </div>
{!user || (user && !user.login) ? {!user || (user && !user.login) ?
<span className="font-15 ml30"> <span className="font-15 ml30">
<a onClick={() => this.educoderlogin()} className="mr5 color-grey-6">登录</a> <a onClick={() => this.educoderlogin()} className="mr5 color-grey-6">登录</a>
{ {
settings && settings.new_course && settings.new_course.register_url && settings && settings.common && settings.common.register &&
<span><em className="vertical-line"></em><a className="ml5 color-grey-6" href={`${settings.new_course.register_url}`} target="_blank"></a></span> <span><em className="vertical-line"></em><a className="ml5 color-grey-6" href={`${settings.common.register}`} target="_blank"></a></span>
} }
</span> </span>
: :
<div className="ml30 edu-menu-panel" style={{ height: "70px", lineHeight: "70px" }}> <Dropdown placement={`bottomRight`} overlay={this.renderMenu(settings && settings.personal)}>
<a href={`/users/${this.props.current_user === undefined ? "" : this.props.current_user.login}/courses`}> <a href={`/users/${this.props.current_user && this.props.current_user.login}`}>
<img alt="头像" className="radius" height="34" id="nh_user_logo" name="avatar_image" <img alt="头像" src={getImageUrl(`/${user.image_url}`)} className="currentImg"></img>
src={getImageUrl(`images/` + user.image_url)} width="34">
</img>
</a> </a>
<ul className="edu-menu-list" style={{ top: '60px', textAlign: 'center' }}> </Dropdown>
<li className="bor-bottom-greyE" style={{cursor:"default",background:"#fff"}}>{this.props.current_user.username}</li>
{
settings && settings.personal && settings.personal.length > 0 && settings.personal.map((item,key)=>{
return(
<li key={key}><a href={item.url} target="_blank">{item.name}</a></li>
)
})
}
<li className="bor-top-greyE">
<a onClick={() => this.educoderloginysl()}>退出</a>
</li>
</ul>
</div>
} }
</div> </div>
</div> </div>

View File

@ -1,10 +1,122 @@
.dropdownFlex{ .dropdownFlex{
display:flex; display:flex;
padding:5px;
background:#fff; background:#fff;
border-radius: 3px; border-radius: 3px;
.ant-menu-vertical > .ant-menu-item{ .ant-menu-vertical > .ant-menu-item{
border:none border:none;
height: 35px;
line-height: 35px;
margin:0px;
&.ant-menu-item-selected{
background-color: #fff;
a{color: rgba(0, 0, 0, 0.65)!important;}
}
&.ant-menu-item-active{
a{color: #4cacff!important;}
}
}
.ant-menu-vertical{
border:none;
}
}
.currentImg{
width: 34px;
height: 34px;
border-radius: 50%;
margin-left: 30px;
}
.currentMenu{
width: 120px;
text-align: center;
padding:0px;
li{
height: 40px;
line-height: 40px;
padding:0px!important;
cursor: default;
&:hover{
background-color: #fff;
}
&:first-child{
border-bottom: 1px solid #eee;
}
&:last-child{
border-top: 1px solid #eee;
a{
border-radius: 0px 0px 4px 4px;
}
}
a{
padding:0px;
margin:0px;
display: block;
color: #666;
&:hover{
color: #fff;
background: #4CACFF;
}
}
}
}
.newFooter {
position: absolute;
bottom: 0;
width: 100%;
background: #323232;
clear: both;
min-width: 1200px;
z-index: 8;
left: 0px;
p {
margin-top: 0;
margin-bottom:0px !important;
}
.footerInfos{
display: flex;
max-width: 1200px;
margin:0px auto;
justify-content: space-around;
padding:60px 0px;
& >ul{
padding:0px 40px;
box-sizing: border-box;
max-width: 25%;
text-align: left;
li{
color: #fff;
font-weight: 300;
&:first-child{
font-size: 17px;
}
&>a,&>span{
color: #bbb;
}
&>a:hover{
color: #4cacff;
}
}
}
}
.footerCopy{
color: #bbb;
border-top: 1px solid #4e4e4e;
padding:10px 0px;
a{
color: #bbb;
&:hover{
color: #4cacff;
}
}
}
}
.inviteForm{
.ant-form-item{
margin-right: 0px;
}
.ant-form-item-label{
width: 110px;
text-align: right;
} }
} }

View File

@ -6,7 +6,6 @@ import { withRouter } from "react-router";
import { SnackbarHOC } from "educoder"; import { SnackbarHOC } from "educoder";
import { CNotificationHOC } from "../modules/courses/common/CNotificationHOC"; import { CNotificationHOC } from "../modules/courses/common/CNotificationHOC";
import { TPMIndexHOC } from "../modules/tpm/TPMIndexHOC"; import { TPMIndexHOC } from "../modules/tpm/TPMIndexHOC";
import Handbook from './Component/Handbook';
import "./css/index.scss"; import "./css/index.scss";
import Loadable from "react-loadable"; import Loadable from "react-loadable";
@ -27,15 +26,18 @@ const ProjectDetail = Loadable({
loading: Loading, loading: Loading,
}); });
const Infos = Loadable({
loader: () => import("./users/Infos"),
loading: Loading,
});
class Index extends Component { class Index extends Component {
componentDidUpdate=()=>{
this.props.history.listen(()=>{
if (document.body.scrollTop || document.documentElement.scrollTop > 0) {
window.scrollTo(0, 0)
}
})
}
render() { render() {
return ( return (
<div className="newMain clearfix"> <div className="newMain clearfix">
<Handbook />
<Switch {...this.props}> <Switch {...this.props}>
<Route <Route
path="/projects/:projectsType/new/:OIdentifier" path="/projects/:projectsType/new/:OIdentifier"
@ -68,12 +70,8 @@ class Index extends Component {
)} )}
></Route> ></Route>
<Route <Route
exact
path="/" path="/"
render={(props) => ( render={(props) => (
this.props.current_user && this.props.current_user.login ?
<Infos {...this.props} {...props} />
:
<ProjectIndex {...this.props} {...props} /> <ProjectIndex {...this.props} {...props} />
)} )}
></Route> ></Route>

View File

@ -1,6 +1,6 @@
import React , { useEffect , useState } from 'react'; import React , { useEffect , useState } from 'react';
import { WhiteBack , Box , LongWidth , ShortWidth , Gap , AlignCenter , FlexAJ } from '../Component/layout'; import { WhiteBack , Box , LongWidth , ShortWidth , Gap , AlignCenter , FlexAJ } from '../Component/layout';
import { Dropdown , Menu , Divider , Spin } from 'antd'; import { Dropdown , Menu , Divider , Spin, Button } from 'antd';
import { getImageUrl } from "educoder"; import { getImageUrl } from "educoder";
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import CloneAddress from '../Branch/CloneAddress'; import CloneAddress from '../Branch/CloneAddress';
@ -19,10 +19,27 @@ import LanguagePower from '../Component/LanguagePower';
import DrawerPanel from '../Component/DrawerPanel'; import DrawerPanel from '../Component/DrawerPanel';
import UpdateDescModal from './sub/UpdateDescModal'; import UpdateDescModal from './sub/UpdateDescModal';
import Nodata from '../Nodata'; import Nodata from '../Nodata';
import Invite from './sub/Invite';
/**
* projectDetail.type:0是托管项目1是镜像项目2是同步镜像项目(为2时不支持在线创建在线上传在线修改在线删除创建合并请求等功能)
*/
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){ function CoderDepot(props){
const [ projectDetail , setProjectDetail ]= useState(undefined); const [ projectDetail , setProjectDetail ]= useState(undefined);
const [ inviteCode , setInviteCode ] = useState(undefined);
const [ treeValue , setTreeValue ] = useState(undefined); const [ treeValue , setTreeValue ] = useState(undefined);
const [ treeValuePath , setTreeValuePath ] = useState(undefined); const [ treeValuePath , setTreeValuePath ] = useState(undefined);
const [ lastCommit,setLastCommit ] = useState(undefined); const [ lastCommit,setLastCommit ] = useState(undefined);
@ -42,19 +59,46 @@ function CoderDepot(props){
const [ openModal , setOpenModal ] = useState(false); const [ openModal , setOpenModal ] = useState(false);
const [ desc , setDesc ] = useState(undefined); const [ desc , setDesc ] = useState(undefined);
const [ website , setWebsite ] = 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 owner = props.match.params.owner;
const projectsId = props.match.params.projectsId; 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; let pathname = props.history.location.pathname;
const { bannerList } = props;
useEffect(()=>{ useEffect(()=>{
if(props.projectDetail){ if(bannerList && bannerList.length>0){
setProjectDetail(props.projectDetail); let a = bannerList.filter(i=>i.menu_name === "pulls");
setDesc(props.projectDetail.description); let i = bannerList.filter(i=>i.menu_name === "issues");
setWebsite(props.projectDetail.website); 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(()=>{ useEffect(()=>{
if(treeValue){ if(treeValue){
@ -64,23 +108,28 @@ function CoderDepot(props){
} }
},[treeValue]) },[treeValue])
useEffect(()=>{ useEffect(()=>{
if (pathname){ if (projectsId && owner && defaultBranch){
if(pathname.indexOf(`/projects/${owner}/${projectsId}`) > -1 && pathname.indexOf(`/tree/${branchName}/`) > -1) { let b = turnbar(branchName) ;
let url = pathname.split(`/tree/${branchName}/`)[1]; if(pathname.indexOf(`/projects/${owner}/${projectsId}`) > -1 && pathname.indexOf(`/tree/${b}/`) > -1) {
let url = pathname.split(`/tree/${b}/`)[1];
setTreeValue(url); setTreeValue(url);
getFileInfo(url,branchName); getFileInfo(url,branchName);
setType("file");
}else{ }else{
setTreeValue(undefined); setTreeValue(undefined);
getDirInfo(branchName ||(projectDetail && projectDetail.default_branch)); getDirInfo(branchName || defaultBranch);
setType("dir");
} }
} }
},[pathname]) },[projectsId,owner,pathname,defaultBranch])
// //
function getDirInfo(branch){ function getDirInfo(branch){
setIsSpin(true); setIsSpin(true);
const url = `/${owner}/${projectsId}/entries.json`; const url = `/${owner}/${projectsId}/entries.json`;
axios.get(url, { axios.get(url, {
params: { ref: branch } params: { ref: branch }
}).then((result) => { }).then((result) => {
@ -92,8 +141,12 @@ function CoderDepot(props){
setZip_url(result.data.zip_url); setZip_url(result.data.zip_url);
let c = result.data.last_commit let c = result.data.last_commit
setLastCommit(c && c.commit); setLastCommit(c && c.commit);
setLastCommitAuthor(c && (c.author || (c.commit && c.commit.author))); setLastCommitAuthor(c && c.committer);
setMainFlag(true); setMainFlag(true);
setReadOnly(true);
setReadme(result.data.readme);
setEditReadme(false);
setHide(true);
} }
setTimeout(function(){setIsSpin(false);},500); setTimeout(function(){setIsSpin(false);},500);
}).catch(error=>{setIsSpin(false);}) }).catch(error=>{setIsSpin(false);})
@ -105,7 +158,7 @@ function CoderDepot(props){
let ele = document.getElementById("ptxt"); let ele = document.getElementById("ptxt");
if(ele){ if(ele){
let h = ele.offsetHeight; let h = ele.offsetHeight;
if( h > 18 ) setHideBtn(true) if( h > 18 ) setHideBtn(true);
} }
} }
},[projectDetail,lastCommit]) },[projectDetail,lastCommit])
@ -133,8 +186,10 @@ function CoderDepot(props){
} }
let c = result.data.last_commit let c = result.data.last_commit
setLastCommit(c && c.commit); setLastCommit(c && c.commit);
setLastCommitAuthor(c && (c.author || (c.commit && c.commit.author))); setLastCommitAuthor(c && c.committer);
setMainFlag(false); setMainFlag(false);
setReadOnly(!editReadme);
setHide(true);
} }
setTimeout(function(){setIsSpin(false);},500) setTimeout(function(){setIsSpin(false);},500)
}).catch(error=>{setIsSpin(false);}) }).catch(error=>{setIsSpin(false);})
@ -142,17 +197,22 @@ function CoderDepot(props){
// //
function changeBranch(value){ function changeBranch(value){
let url = `/projects/${owner}/${projectsId}${value && `/tree/${value}`}${treeValue ? `/${treeValue}`:""}`; let checkvalue = turnbar(value);
let url = `/projects/${owner}/${projectsId}${value && `/tree/${checkvalue}`}${treeValue ? `/${treeValue}`:""}`;
props.history.push(url); props.history.push(url);
} }
// //
const fileMenu =( function fileMenu(){
let b = branchName || defaultBranch;
let checkvalue = turnbar(b);
return (
<Menu> <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}/${checkvalue}/uploadfile${treeValue === undefined ? "" : `/${treeValue}`}`)}>上传文件</a></Menu.Item>
<Menu.Item><a onClick={()=>urlLink(`/projects/${owner}/${projectsId}/${branchName || (projectDetail && projectDetail.default_branch)}/newfile${treeValue === undefined ? "" : `/${treeValue}`}`)}>新建文件</a></Menu.Item> <Menu.Item><a onClick={()=>urlLink(`/projects/${owner}/${projectsId}/${checkvalue}/newfile${treeValue === undefined ? "" : `/${treeValue}`}`)}>新建文件</a></Menu.Item>
</Menu> </Menu>
) )
}
function getPathUrl(array,index){ function getPathUrl(array,index){
if(array && array.length>0 && index){ if(array && array.length>0 && index){
@ -166,27 +226,36 @@ function CoderDepot(props){
// //
function returnMain(){ function returnMain(){
setTreeValue(undefined); setTreeValue(undefined);
let branch = branchName || (projectDetail && projectDetail.default_branch); let branch = branchName || defaultBranch;
props.history.push(`/projects/${owner}/${projectsId}/tree/${branch}`); let checkvalue = turnbar(branch);
props.history.push(`/projects/${owner}/${projectsId}/tree/${checkvalue}`);
}; };
// //
function returnUlr(url){ function returnUlr(url){
props.history.push(`/projects/${owner}/${projectsId}/tree${branchName?`/${branchName}`:""}/${url}`); let enBranch = turnbar(branchName);
props.history.push(`/projects/${owner}/${projectsId}/tree${enBranch?`/${enBranch}`:""}/${url}`);
} }
// //
function goToSubRoot(path,type,filename){ function goToSubRoot(path,type,filename){
setType(type); if(type!=="submodule"){
props.history.push(`/projects/${owner}/${projectsId}${`/tree/${branchName || (projectDetail && projectDetail.default_branch)}`}${path?`/${path}`:""}`); let enBranch = branchName || defaultBranch;
let checkvalue = turnbar(enBranch);
setType(type);
props.history.push(`/projects/${owner}/${projectsId}${`/tree/${checkvalue}`}${path?`/${path}`:""}`);
}
} }
function onEdit(readOnly){ function onEdit(readOnly){
setReadOnly(readOnly); setReadOnly(readOnly);
setEditReadme(false);
} }
function ChangeFile(path, readOnly){ 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(`/projects/${owner}/${projectsId}/tree/${checkvalue}/${path}`);
setType("file"); setType("file");
setReadOnly(readOnly); setEditReadme(true);
}; };
function changeHide(hide){ function changeHide(hide){
@ -202,32 +271,35 @@ function CoderDepot(props){
} }
const downloadMenu = ( const downloadMenu = (
<div className="downMenu"> <CloneAddress
<div style={{padding:"20px",borderBottom:"1px solid #eee"}}> http_url={projectDetail && projectDetail.clone_url}
<CloneAddress ssh_url = {projectDetail && projectDetail.ssh_url}
http_url={projectDetail && projectDetail.clone_url} zip_url={zip_url}
showNotification={props.showNotification}/> tar_url={tar_url}
</div> showNotification={props.showNotification}/>
<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>
) )
function okUpdate(d,w){ // website
function okUpdate(d,w,l){
const url = `/${owner}/${projectsId}.json`; const url = `/${owner}/${projectsId}.json`;
axios.put(url,{ axios.put(url,{
description:d,website:w description:d,website:w,lesson_url:l
}).then(result=>{ }).then(result=>{
if(result && result.data && result.data.id){ if(result && result.data && result.data.id){
setDesc(result.data.description); setDesc(result.data.description);
setWebsite(result.data.website); setWebsite(result.data.website);
setLessonUrl(result.data.lesson_url);
} }
}) })
} }
let n = fileInfo && fileInfo.name;
const mdFlag = n && n.substring(n.length-3,n.length) === ".md";
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( return(
<WhiteBack> <WhiteBack>
<UpdateDescModal desc={desc} website={website} visible={openModal} onCancel={()=>setOpenModal(false)} onOk={okUpdate}/> <UpdateDescModal desc={desc} website={website} lesson_url={lesson_url} visible={openModal} onCancel={()=>setOpenModal(false)} onOk={okUpdate}/>
<Spin spinning={isSpin}> <Spin spinning={isSpin}>
{ {
(dirInfo || fileInfo) && (dirInfo || fileInfo) &&
@ -237,12 +309,15 @@ function CoderDepot(props){
owner={owner} owner={owner}
projectsId={projectsId} projectsId={projectsId}
name={projectDetail && projectDetail.name} name={projectDetail && projectDetail.name}
branch={branchName || (projectDetail && projectDetail.default_branch)} branch={branchName || defaultBranch}
visible={visible} visible={visible}
onClose={()=>setVisible(false)} onClose={()=>setVisible(false)}
list = {mainFlag ? dirInfo : undefined} list = {mainFlag ? dirInfo : undefined}
/> />
<div className="drawerBtn" onClick={()=>setVisible(true)}><i className="iconfont icon-youjiantou"></i></div> <div className="drawerBtn" onClick={()=>setVisible(true)}>
<i className="iconfont icon-youjiantou font-16"></i>
<span>目录</span>
</div>
</React.Fragment> </React.Fragment>
} }
<div style={{minHeight:"500px"}}> <div style={{minHeight:"500px"}}>
@ -259,14 +334,14 @@ function CoderDepot(props){
<SelectBranch <SelectBranch
repo_id={projectDetail && projectDetail.repo_id} repo_id={projectDetail && projectDetail.repo_id}
projectsId={projectsId} projectsId={projectsId}
branch={branchName || (projectDetail && projectDetail.default_branch)} branch={branchName || defaultBranch}
changeBranch={changeBranch} changeBranch={changeBranch}
owner={owner} owner={owner}
history={props.history} history={props.history}
branchList={projectDetail && projectDetail.branches && projectDetail.branches.list} branchList={projectDetail && projectDetail.branches && projectDetail.branches.list}
></SelectBranch> ></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> </div>
<AlignCenter className="mr20"> <AlignCenter className="mr20">
@ -283,12 +358,28 @@ function CoderDepot(props){
</AlignCenter> </AlignCenter>
</AlignCenter> </AlignCenter>
<AlignCenter> <AlignCenter>
<div className="mr20 addOptionBtn"> {
<a onClick={()=>urlLink(`/projects/${owner}/${projectsId}/pulls/new`)} >+ 合并请求</a> baseOperate && ((projectDetail.type !== 2 && pullsFlag) || issuesFlag )&&
<a onClick={()=>urlLink(`/projects/${owner}/${projectsId}/issues/new`)} >+ 任务</a> <div className="mr20 addOptionBtn">
</div> {
{ type === "dir" && <Dropdown.Button overlay={fileMenu} className="mr20">文件</Dropdown.Button>} projectDetail.type !== 2 && pullsFlag &&
<Dropdown.Button overlay={downloadMenu} type={'primary'}>下载</Dropdown.Button> <a onClick={()=>urlLink(`/projects/${owner}/${projectsId}/pulls/new`)} >+ 合并请求</a>
}
{
issuesFlag &&
<a onClick={()=>urlLink(`/projects/${owner}/${projectsId}/issues/new`)} >+ 任务</a>
}
</div>
}
{ fileOperate &&
<Dropdown overlay={fileMenu()} className="mr20" trigger={['click']}>
<Button type="default">文件 <i className="iconfont icon-sanjiaoxing-down ml3 font-14 color-grey-9"></i></Button>
</Dropdown>
}
<Dropdown overlay={downloadMenu} placement="bottomRight" trigger={['click']}>
<Button type={'primary'}>下载 <i className="iconfont icon-sanjiaoxing-down ml3 font-14 color-white"></i></Button>
</Dropdown>
</AlignCenter> </AlignCenter>
</FlexAJ> </FlexAJ>
{ {
@ -297,12 +388,16 @@ function CoderDepot(props){
{ {
lastCommit && lastCommit &&
<div className="listtablehead"> <div className="listtablehead">
<User url={getImageUrl(`images/${lastCommitAuthor && lastCommitAuthor.image_url}`)} name={lastCommitAuthor && lastCommitAuthor.name} /> <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 className={hideBtn && hide ? "ellipsistxt hidetxt" :"ellipsistxt"}>
<pre id="ptxt">{lastCommit && lastCommit.message}</pre>
</div>
{ hideBtn && <span className="ellipsis" onClick={()=>changeHide(hide)}><i className="iconfont icon-shenglvehao"></i></span> } { 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> <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>:"" } { commitCount ? <Link to={`/projects/${owner}/${projectsId}/commits/branch/${turnbar(branchName || defaultBranch)}`} className="ml12 color-grey-9">
<i className="iconfont icon-tijiao mr3 font-17 color-grey-9"></i>{commitCount}次提交
</Link>:"" }
</div> </div>
} }
<ul className="listtablebody"> <ul className="listtablebody">
@ -335,8 +430,10 @@ function CoderDepot(props){
{...props} {...props}
detail={fileInfo} detail={fileInfo}
readOnly={readOnly} readOnly={readOnly}
md={mdFlag}
onEdit={onEdit} onEdit={onEdit}
currentBranch={branchName || (projectDetail && projectDetail.default_branch)} currentBranch={branchName || defaultBranch}
type={projectDetail.type}
></CoderRootFileDetail> ></CoderRootFileDetail>
} }
</ul> </ul>
@ -347,7 +444,7 @@ function CoderDepot(props){
(dirInfo && dirInfo.length === 0) && (fileInfo && fileInfo.length === 0) ? <Nodata _html="暂未发现文件"/> :"" (dirInfo && dirInfo.length === 0) && (fileInfo && fileInfo.length === 0) ? <Nodata _html="暂未发现文件"/> :""
} }
{/* readme文件显示(显示文件详情时不显示readme文件) */} {/* readme文件显示(显示文件详情时不显示readme文件) */}
{ dirInfo && (projectDetail && projectDetail.readme) ? <ReadMe ChangeFile={ChangeFile} readme={projectDetail && projectDetail.readme} operate={props && (props.isManager || props.isDeveloper)} 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> </div>
</LongWidth> </LongWidth>
{ {
@ -358,12 +455,12 @@ function CoderDepot(props){
<FlexAJ className="font-18 color-grey-6 mb20" style={{lineHeight:"28px"}}>简介 <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>} {projectDetail.permission && (projectDetail.permission==="Admin" || projectDetail.permission==="Owner") && <i onClick={()=>setOpenModal(true)} className="iconfont icon-anquanshezhi color-grey-9 font-15"></i>}
</FlexAJ> </FlexAJ>
{desc && <p className="font-14 color-grey-9 mb15 task-hide-2" style={{lineHeight:"22px",WebkitLineClamp:"4",textAlign:"justify"}}>{desc}</p>} {desc && <p className="font-14 color-grey-9 mb15 task-hide-2" style={{lineHeight:"22px",WebkitLineClamp:"4",textAlign:"justify",wordBreak:"break-all"}}>{desc}</p>}
{ {
website && website &&
<p className="color-grey-6 df"> <p className="color-grey-6 df">
<i className="iconfont icon-lianjie2 font-15 mr10 color-grey-9"></i> <i className="iconfont icon-lianjie2 font-15 mr10 color-grey-9"></i>
<span style={{wordBreak:"break-all",lineHeight:"20px",marginTop:"5px"}}>{website}</span> <a href={website} className="color-grey-6" target="_blank" style={{wordBreak:"break-all",lineHeight:"20px",marginTop:"5px",textDecoration:"underline"}}>{website}</a>
</p> </p>
} }
<p> <p>
@ -371,32 +468,51 @@ function CoderDepot(props){
<a href="#readme" className="color-grey-6">README.md</a> <a href="#readme" className="color-grey-6">README.md</a>
</p> </p>
<p className="color-grey-6"> <p className="color-grey-6">
<i className="iconfont icon-dataBase font-15 mr10 color-grey-9"></i> <i className="iconfont icon-dataBase font-15 mr10 color-grey-6"></i>
<span>{projectDetail && projectDetail.size}</span> <span>{projectDetail && projectDetail.size}</span>
</p> </p>
{ {
projectDetail && projectDetail.license_name && projectDetail && projectDetail.license_name &&
<p className="color-grey-6"> <p className="color-grey-6">
<i className="iconfont icon-tianping font-16 mr10 color-grey-9"></i> <i className="iconfont icon-tianping font-16 mr10 color-grey-3"></i>
<span>{projectDetail.license_name}</span> <span>{projectDetail.license_name}</span>
</p> </p>
} }
</div> </div>
{
inviteCode &&
<div>
<Divider />
<Invite code={inviteCode} className={"detailsCode"}/>
</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",wordBreak:"break-all"}}>{lesson_url}</a>
</div>
}
{/* 发布 */} {/* 发布 */}
{ {
projectDetail && projectDetail.release_versions && projectDetail && projectDetail.release_versions &&
<React.Fragment> <React.Fragment>
<Divider /> <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> </React.Fragment>
} }
{/* 贡献者 */} {/* 贡献者 */}
{ {
projectDetail && projectDetail.contributors && projectDetail && projectDetail.contributors &&
<React.Fragment> <Contributors contributors={projectDetail && projectDetail.contributors} owner={owner} projectsId={projectsId} />
<Divider />
<Contributors contributors={projectDetail && projectDetail.contributors} owner={owner} projectsId={projectsId}/>
</React.Fragment>
} }
{/* 语言 */} {/* 语言 */}
{ projectDetail && projectDetail.languages && { projectDetail && projectDetail.languages &&

View File

@ -2,12 +2,18 @@ import React from 'react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { truncateCommitId } from '../common/util'; import { truncateCommitId } from '../common/util';
const typeIco = {
"submodule":"icon-file-submodule font-17",
"file":'icon-wenjia font-15',
"dir":"icon-wenjianjia1 font-15"
}
function CoderDepotCatalogue({item , goToSubRoot , owner , projectsId }){ function CoderDepotCatalogue({item , goToSubRoot , owner , projectsId }){
return( return(
<li> <li>
<span> <span>
<a onClick={()=>goToSubRoot(item.path,item.type,item.name)}> <a onClick={()=>goToSubRoot(item.path,item.type,item.name)} className={item.type === "submodule" && "submoduleStyle"}>
<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} <i className={`iconfont ${typeIco[`${item.type}`]} color-green-file mr5`}></i>{item.name}
</a> </a>
</span> </span>
<span title="init project"> <span title="init project">

View File

@ -1,14 +1,63 @@
import React from 'react'; import React, { useEffect, useState } from 'react';
import RenderHtml from '../../components/render-html'; import RenderHtml from '../../components/render-html';
import { AlignCenter } from '../Component/layout';
import { Dropdown , Menu , Spin } from 'antd';
import { Link } from 'react-router-dom';
const $ = window.$;
function CoderDepotReadme({ operate , history , readme , ChangeFile }){ function CoderDepotReadme({ operate , history , readme , ChangeFile }){
const [ menuList ,setMenuList ] = useState(undefined);
const [ content ,setContent ] = useState(undefined);
useEffect(()=>{
if(readme && readme.content){
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:`${path}${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>
)
}else{
return <Spin />
}
}
return( return(
<div className="commonBox" id="readme"> <div className="commonBox" id="readme">
<div className="commonBox-title"> <div className="commonBox-title boxTitle">
<span className="mr10"> <AlignCenter>
<i className="iconfont icon-wenjian1 font-16 color-grey-9 fl mt3"></i> <Dropdown overlay={menu()}>
</span> <span className="catelogue">
<span className="commonBox-title-read">README.md</span> <i className="iconfont icon-zhangjie1 font-14 mr5"></i>
<span>目录</span>
</span>
</Dropdown>
<span className="commonBox-title-read">README.md</span>
</AlignCenter>
{ {
operate ? operate ?
<a className="ml20 pull-right" onClick={() =>ChangeFile(readme && readme.path, false)}> <a className="ml20 pull-right" onClick={() =>ChangeFile(readme && readme.path, false)}>
@ -17,9 +66,12 @@ function CoderDepotReadme({ operate , history , readme , ChangeFile }){
:"" :""
} }
</div> </div>
<div className="commonBox-info"> {
<RenderHtml className="break_word_comments imageLayerParent" value={readme && readme.content} url={history.location}/> content &&
</div> <div className="commonBox-info">
<RenderHtml className="break_word_comments imageLayerParent" value={content} url={history.location}/>
</div>
}
</div> </div>
) )
} }

View File

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

View File

@ -2,12 +2,19 @@ import React , { Component } from 'react';
import { Spin , Pagination } from 'antd'; import { Spin , Pagination } from 'antd';
import { getImageUrl } from 'educoder'; import { getImageUrl } from 'educoder';
import { truncateCommitId } from '../common/util'; import { truncateCommitId } from '../common/util';
import { AlignTop } from '../Component/layout';
import SelectBranch from '../Branch/Select'; import SelectBranch from '../Branch/Select';
import Nodata from '../Nodata'; import Nodata from '../Nodata';
import axios from 'axios'; import axios from 'axios';
import {Link} from "react-router-dom"; 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{ class CoderRootCommit extends Component{
constructor(props){ constructor(props){
super(props) super(props)
@ -56,11 +63,12 @@ class CoderRootCommit extends Component{
this.setState({ this.setState({
isSpining:true isSpining:true
}) })
console.log(returnbar(branch));
const { projectsId , owner } = this.props.match.params; const { projectsId , owner } = this.props.match.params;
const url = `/${owner}/${projectsId}/commits.json`; const url = `/${owner}/${projectsId}/commits.json`;
axios.get(url,{ axios.get(url,{
params:{ params:{
sha:branch, sha:returnbar(branch),
page, page,
limit limit
} }
@ -74,6 +82,7 @@ class CoderRootCommit extends Component{
array.push({ array.push({
name:item.author && item.author.name, name:item.author && item.author.name,
login: item.author && item.author.login, login: item.author && item.author.login,
id: item.author && item.author.id,
image_url:item.author && item.author.image_url, image_url:item.author && item.author.image_url,
sha:item.sha, sha:item.sha,
time_from_now:item.time_from_now, time_from_now:item.time_from_now,
@ -104,10 +113,10 @@ class CoderRootCommit extends Component{
const { commitDatas , dataCount , limit , page , isSpining , branchList } = this.state; const { commitDatas , dataCount , limit , page , isSpining , branchList } = this.state;
const { projectDetail, commit_class , defaultBranch } = this.props; const { projectDetail, commit_class , defaultBranch } = this.props;
const { projectsId , owner , branchName } = this.props.match.params; const { projectsId , owner , branchName } = this.props.match.params;
let branch = branchName || defaultBranch; let branch = returnbar(branchName || defaultBranch);
return( return(
<React.Fragment> <React.Fragment>
<div className={"main"}> <div className={"main"}style={{padding:"0px",border:"none"}}>
<div className="f-wrap-between"> <div className="f-wrap-between">
<SelectBranch <SelectBranch
repo_id={projectDetail && projectDetail.repo_id} repo_id={projectDetail && projectDetail.repo_id}
@ -131,15 +140,23 @@ class CoderRootCommit extends Component{
commitDatas && commitDatas.length > 0 && commitDatas.map((item,k)=>{ commitDatas && commitDatas.length > 0 && commitDatas.map((item,k)=>{
return( return(
<div key={k}> <div key={k}>
<p className="f-wrap-alignCenter"> <AlignTop>
<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="commitKey" style={{marginLeft:0,marginTop:"3px"}}>{truncateCommitId(`${item.sha}`)}</Link>
<Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${item.sha}`)}`} className="flex1 ml20 font-16 color-grey-3">{item.message}</Link> <Link to={`/projects/${owner}/${projectsId}/commits/${truncateCommitId(`${item.sha}`)}`} className="commitDesc">{item.message}</Link>
</p> </AlignTop>
<p className="f-wrap-alignCenter mt15"> <p className="f-wrap-alignCenter mt15">
<Link to={`/users/${item.login}`} className="show-user-link"> {
{item.image_url?<img src={getImageUrl(`images/${item.image_url}`)} alt="" width="28px" height="28px" className="mr15 radius"/>:""} item.id ?
<label className="font-14 color-grey-6" style={{verticalAlign:'middle'}}>{item.name ?`${item.name}:`:""}提交于 {item.time_from_now}</label> <Link to={`/users/${item.login}`} className="show-user-link">
</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>:
<span className="show-user-link">
{item.image_url?<img src={getImageUrl(`/${item.image_url}`)} alt="" width="28px" height="28px" className="mr15 radius"/>:""}
<label className="font-14 color-grey-6" style={{verticalAlign:'middle'}}>{item.name ?`${item.name}:`:""}提交于 {item.time_from_now}</label>
</span>
}
</p> </p>
</div> </div>
) )

View File

@ -24,13 +24,25 @@ class CoderRootFileDetail extends Component {
} }
componentDidMount = () => { componentDidMount = () => {
const { detail } = this.props; const { detail , mdFlag } = this.props;
this.setState({ this.setState({
value: detail.content, value: detail.content,
}); });
this.languages_total(); this.languages_total();
}; };
componentDidUpdate=(prevProps)=>{
const { content } = this.props && this.props.detail;
const prevcontent = prevProps.detail && prevProps.detail.content;
if (content && prevcontent) {
if (prevcontent !== content){
this.setState({
description: content
});
}
}
}
languages_total = () => { languages_total = () => {
const { detail } = this.props; const { detail } = this.props;
const file_name = detail.path.split("/").pop().split(".").pop(); const file_name = detail.path.split("/").pop().split(".").pop();
@ -164,9 +176,10 @@ class CoderRootFileDetail extends Component {
current_user, current_user,
isManager, isManager,
isDeveloper, isDeveloper,
md,
currentBranch, currentBranch,
platform platform,
md,
type
} = this.props; } = this.props;
const { language, languages, description } = this.state; const { language, languages, description } = this.state;
let flag = current_user && current_user.login && (isManager || isDeveloper); let flag = current_user && current_user.login && (isManager || isDeveloper);
@ -185,17 +198,18 @@ class CoderRootFileDetail extends Component {
{readOnly ? ( {readOnly ? (
<span> <span>
{ {
detail.direct_download ? !detail.direct_download?
""
:
<span> <span>
<a onClick={() => this.DownLoadFile(detail.download_url)} className="ml20"> <a onClick={() => this.DownLoadFile(detail.download_url)} className="ml20">
<i className="iconfont icon-xiazai1 font-15 color-grey-6"></i> <i className="iconfont icon-xiazai1 font-15 color-grey-6"></i>
</a> </a>
<a onClick={() => this.EditFile(false)} className="ml20"> {
<i className="iconfont icon-bianji1 font-15 color-grey-6"></i> type !==2 &&
</a> <a onClick={() => this.EditFile(false)} className="ml20">
</span> <i className="iconfont icon-bianji1 font-15 color-grey-6"></i>
</a>
}
</span>:""
} }
</span> </span>
) : ( ) : (
@ -226,18 +240,21 @@ class CoderRootFileDetail extends Component {
</button> </button>
</React.Fragment> </React.Fragment>
)} )}
{
<Popconfirm type !==2 &&
title="确认删除这个文件?" <Popconfirm
className="ml20" title="确认删除这个文件?"
okText="确定" className="ml20"
cancelText="取消" okText="确定"
onConfirm={this.deleteFile} cancelText="取消"
> onConfirm={this.deleteFile}
<a> >
<i className="iconfont icon-shanchu font-15 color-grey-6"></i> <a>
</a> <i className="iconfont icon-shanchu font-15 color-grey-6"></i>
</Popconfirm> </a>
</Popconfirm>
}
</div> </div>
)} )}
</p> </p>
@ -245,11 +262,7 @@ class CoderRootFileDetail extends Component {
<div> <div>
{detail.image_type ? ( {detail.image_type ? (
<div className="edu-txt-center pt20 pb20"> <div className="edu-txt-center pt20 pb20">
<img <img alt="" src={detail.download_url} style={{ maxWidth: "80%" }} />
alt=""
src={detail.download_url}
style={{ maxWidth: "80%" }}
/>
</div> </div>
) : detail.direct_download ? ( ) : detail.direct_download ? (
<div className="mt20 text-center"> <div className="mt20 text-center">
@ -268,10 +281,11 @@ class CoderRootFileDetail extends Component {
{...this.state} {...this.state}
language={language ? language : "javascript"} language={language ? language : "javascript"}
filepath={`/${detail.path}`} filepath={`/${detail.path}`}
content={detail.content} content={description}
readOnly={readOnly} readOnly={readOnly}
editorType="update" editorType="update"
currentBranch={currentBranch} currentBranch={currentBranch}
descName={detail && `Update ${detail.name}`}
></Meditor> ></Meditor>
)} )}
</div> </div>

View File

@ -13,10 +13,6 @@ const UploadFile = Loadable({
loader: () => import('../Newfile/upload_file'), loader: () => import('../Newfile/upload_file'),
loading: Loading, loading: Loading,
}) })
const CoderRootDirectory = Loadable({
loader: () => import('./CoderRootDirectory'),
loading: Loading,
})
const CoderRootCommit = Loadable({ const CoderRootCommit = Loadable({
loader: () => import('./CoderRootCommit'), loader: () => import('./CoderRootCommit'),
loading: Loading, loading: Loading,
@ -106,6 +102,11 @@ class CoderRootIndex extends Component{
(props) => (<FileNew {...this.props} {...props} {...this.state} getTopCount={this.getTopCount} />) (props) => (<FileNew {...this.props} {...props} {...this.state} getTopCount={this.getTopCount} />)
} }
></Route> ></Route>
<Route path="/projects/:owner/:projectsId/commits/branch/:branchName"
render={
() => (<CoderRootCommit {...this.props} {...this.state} commit_class="main" getTopCount={this.getTopCount} />)
}
></Route>
<Route path="/projects/:owner/:projectsId/commits/:sha" <Route path="/projects/:owner/:projectsId/commits/:sha"
render={ render={
(props) => (<Diff {...this.props} {...props} {...this.state}/>) (props) => (<Diff {...this.props} {...props} {...this.state}/>)

View File

@ -26,7 +26,7 @@ export default (( props, { projectDetail }) => {
}, [owner, projectsId]); }, [owner, projectsId]);
return ( return (
<div className="main"> <div className="main" style={{padding:"0px",border:"none"}}>
<Spin spinning={isSpin}> <Spin spinning={isSpin}>
<div style={{minHeight:"400px"}}> <div style={{minHeight:"400px"}}>
{ {

View File

@ -1,7 +1,7 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Spin, Tooltip } from 'antd'; import { Spin, Tooltip , Button } from 'antd';
import { Link, Route, Switch } from 'react-router-dom'; import { Link, Route, Switch } from 'react-router-dom';
import { Content } from '../Component/layout'; import { Content , AlignTop } from '../Component/layout';
import DetailBanner from './sub/DetailBanner'; import DetailBanner from './sub/DetailBanner';
import '../css/index.scss' import '../css/index.scss'
import './list.css'; import './list.css';
@ -176,6 +176,7 @@ class Detail extends Component {
firstSync:false, firstSync:false,
secondSync:false, secondSync:false,
open_devops:false, open_devops:false,
forkSpin:false,
// 默认分支 // 默认分支
defaultBranch:undefined, defaultBranch:undefined,
@ -358,6 +359,9 @@ class Detail extends Component {
forkFunc = () => { forkFunc = () => {
const { platform } = this.state; const { platform } = this.state;
if(!platform)return; if(!platform)return;
this.setState({
forkSpin:true
})
const { current_user } = this.props 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`; const url = `/${owner}/${projectsId}/forks.json`;
@ -366,8 +370,13 @@ class Detail extends Component {
this.props.history.push(`/projects/${current_user && current_user.login}/${result.data.identifier}`); this.props.history.push(`/projects/${current_user && current_user.login}/${result.data.identifier}`);
this.props.showNotification(result.data.message); this.props.showNotification(result.data.message);
} }
this.setState({
forkSpin:false
})
}).catch(error => { }).catch(error => {
console.log(error); this.setState({
forkSpin:false
})
}) })
} }
@ -389,32 +398,33 @@ 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={`${type ==="Organization" ? "/organize":'/users'}/${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={`/projects/${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() { render() {
const { projectDetail, watchers_count, praises_count, const { projectDetail, watchers_count, praises_count,
forked_count, firstSync , secondSync , forked_count, firstSync , secondSync ,
isManager, watched, praised, isManager, watched, praised,
project , open_devops , platform , defaultBranch , bannerList } = this.state; project , open_devops , platform , defaultBranch , bannerList , forkSpin } = this.state;
const url = this.props.history.location.pathname; const url = this.props.history.location.pathname;
const urlArr = url.split("/"); const urlArr = url.split("/");
const urlFlag = (urlArr.length === 3); const urlFlag = (urlArr.length === 3);
const { projectsId , owner } = this.props.match.params; const { projectsId , owner } = this.props.match.params;
const { current_user } = this.props;
let pathname = checkPathname(projectsId,owner,url); let pathname = checkPathname(projectsId,owner,url);
const { state } = this.props.history.location; 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 = { const common = {
getDetail: this.getDetail, getDetail: this.getDetail,
changeOpenDevops:this.changeOpenDevops, changeOpenDevops:this.changeOpenDevops,
@ -424,98 +434,95 @@ class Detail extends Component {
<div> <div>
<div className="detailHeader-wrapper"> <div className="detailHeader-wrapper">
<div className="normal"> <div className="normal">
<div className="f-wrap-between pb15" style={{ position: "relative" }}> <AlignTop style={{padding:"20px 0px 10px",justifyContent:"space-between"}}>
<p className="font-22 df flex-1 lineH2 mt15" style={{ alignItems: "center" }}> <div>
{project && project.author && <AlignTop>
<Link to={`${project.author.type ==="Organization" ? "/organize":'/users'}/${project.author.login}`} className="show-user-link"> <div className="projectallName">
{project.author.name} {project && project.author &&
</Link> <Link to={`${project.author.type ==="Organization" ? "/organize":'/users'}/${project.author.login}`}>{project.author.name}</Link>
} }
<span className="ml5 mr5">/</span> <span className="ml5 mr5">/</span>
<span className="hide-1 flex-1 df"> <Link to={`/projects/${owner}/${projectsId}`} className="projectN mt6">{projectDetail && projectDetail.name}</Link>
<Link to={`/projects/${owner}/${projectsId}`} className="font-22">{project && project.name}</Link> </div>
{ projectDetail && projectDetail.private && <span className="privateTag mt6">私有</span>}
</AlignTop>
<div className="mt8">
{ {
projectDetail && projectDetail.forked_from_project_id && projectDetail.fork_info ? projectDetail && projectDetail.forked_from_project_id && projectDetail.fork_info ?
<Tooltip placement={'right'} title={text}> this.textFunc(projectDetail.forked_from_project_id,projectDetail.fork_info)
<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> : ""
} }
{ {
projectDetail && projectDetail.type && projectDetail.type !== 0 ? projectDetail && projectDetail.type && projectDetail.type !== 0 ?
projectDetail.type === 2 ? <span className="color-grey-9">镜像自 <a className="color-grey-6" target="_blank" href={projectDetail.mirror_url}>{projectDetail.mirror_url}</a></span>
<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>
:"" :""
} }
</span> </div>
</p> </div>
{ <div>
firstSync ? "": {
<span className="df mt25"> firstSync ? "":
{ <span className="df">
projectDetail && projectDetail.type && projectDetail.type === 2 ? {
((current_user && current_user.admin) || isManager) && (projectDetail && projectDetail.type && projectDetail.type === 2) ?
<a className="synchronism ml30" onClick={this.synchronismMirror}>同步镜像</a> : "" <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>
:""
} }
<Button 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>
:""
}
</Button>
<Button 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>
:""
}
</Button>
<Button 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"></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>
:""
}
</Button>
</span> </span>
<span className="detail_tag_btn"> }
<a className="detail_tag_btn_name" style={{cursor:platform?"pointer":"default"}} onClick={() => this.pariseFunc(praised)}> </div>
<i className={praised ? "iconfont icon-weibiaoti105 color-orange font-14 mr3":"iconfont icon-guanzhu color-grey-9 font-14 mr3"}></i> </AlignTop>
<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">
<a className="detail_tag_btn_name" style={{cursor:platform?"pointer":"default"}} onClick={this.forkFunc}>
<i className="iconfont icon-fork color-grey-9 mr3"></i> (Fork)
</a>
{
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>
{ {
firstSync ? "" : firstSync ? "" :
<DetailBanner <DetailBanner
history={this.props.history}
list={bannerList} list={bannerList}
owner={owner} owner={owner}
projectsId={projectsId} projectsId={projectsId}
@ -635,6 +642,11 @@ class Detail extends Component {
} }
></Route> ></Route>
{/* 新建合并请求 */} {/* 新建合并请求 */}
<Route path="/projects/:owner/:projectsId/pulls/new/:branch"
render={
(props) => (<CreateMerge {...this.props} {...props} {...this.state} {...common} is_fork={true} />)
}
></Route>
<Route path="/projects/:owner/:projectsId/pulls/new" <Route path="/projects/:owner/:projectsId/pulls/new"
render={ render={
(props) => (<CreateMerge {...this.props} {...props} {...this.state} {...common} is_fork={true} />) (props) => (<CreateMerge {...this.props} {...props} {...this.state} {...common} is_fork={true} />)

View File

@ -51,7 +51,7 @@ export default ({ match , history }) => {
} }
}, [projectsId , owner, sha]); }, [projectsId , owner, sha]);
return ( return (
<div className="main"> <div className="main" style={{padding:"0px",border:"none"}}>
<Spin spinning={isSpin}> <Spin spinning={isSpin}>
<Infos> <Infos>
<div className="commitinfos"> <div className="commitinfos">
@ -65,7 +65,7 @@ export default ({ match , history }) => {
<div className="f-wrap-between" style={{ alignItems: "center" }}> <div className="f-wrap-between" style={{ alignItems: "center" }}>
<ul className="df"> <ul className="df">
<User <User
url={(committer && getImageUrl(`images/${committer.image_url}`))|| "https://dss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3025493530,1989042357&fm=26&gp=0.jpg"} url={(committer && getImageUrl(`/${committer.image_url}`))|| "https://dss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=3025493530,1989042357&fm=26&gp=0.jpg"}
name={committer && committer.name} name={committer && committer.name}
/> />
{committer && committer.time_from_now && <li className="ml20 mt2">{committer.time_from_now}</li>} {committer && committer.time_from_now && <li className="ml20 mt2">{committer.time_from_now}</li>}

View File

@ -1,7 +1,10 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { Menu, Input , Spin, Pagination , Popover , Select } from 'antd'; import { Menu, Input , Spin, Pagination , Popover , Select } from 'antd';
import { getUrl } from 'educoder'; import Slider from "react-slick";
import { getImageUrl } from 'educoder';
import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";
import '../css/index.scss' import '../css/index.scss'
import './list.css'; import './list.css';
import './Index.scss'; import './Index.scss';
@ -30,6 +33,8 @@ class Index extends Component {
categoryList: undefined, categoryList: undefined,
recommendList:undefined, recommendList:undefined,
recommendOriList:undefined,
languageList:undefined, languageList:undefined,
languageId:undefined languageId:undefined
} }
@ -47,6 +52,8 @@ class Index extends Component {
this.getRecommand(); this.getRecommand();
this.getLanguage(); this.getLanguage();
// this.getRecommandOri();
} }
// 获取语言列表 // 获取语言列表
@ -72,6 +79,17 @@ class Index extends Component {
}).catch(error=>{}) }).catch(error=>{})
} }
getRecommandOri=()=>{
const url = `/organizations/recommend.json`;
axios.get(url).then(result=>{
if(result){
this.setState({
recommendOriList:result.data.organizations
})
}
}).catch(error=>{})
}
// 获取列表 // 获取列表
getListData = (page, limit, search, sort, project_type, category_id,languageId) => { getListData = (page, limit, search, sort, project_type, category_id,languageId) => {
const { current_user } = this.props; const { current_user } = this.props;
@ -256,22 +274,56 @@ class Index extends Component {
const { current_user } = this.props; const { current_user } = this.props;
const { projectsList , recommendList , languageList , languageId , const { projectsList , recommendList , languageList , languageId ,
isSpin, total, search, limit, page, typeList, categoryList } = this.state; isSpin, total, search, limit, page, typeList, categoryList , recommendOriList } = this.state;
const setting={
dots: true,
infinite: true,
speed: 500,
slidesToShow: 5,
slidesToScroll: 5,
autoplay:false,
arrows:false,
adaptiveHeight:true
}
const settings={
dots: true,
infinite: true,
speed: 500,
slidesToShow: 6,
slidesToScroll: 6,
autoplay:false,
arrows:false,
adaptiveHeight:true
}
return ( return (
<div> <div>
<p className="t_project_banner"> <p className="t_project_banner">
<img src={banner} width="100%" alt=""/> <img src={banner} width="100%" alt=""/>
</p> </p>
{/* {
recommendOriList && recommendOriList.length>0?
<Slider {...settings} className="recommandOri">
{
recommendOriList.map((i,k)=>{
return(
<li><Link to={''}><img src={getImageUrl(`/${i.avatar_url}`)} alt={i.name} title={i.name} width="80px"/></Link></li>
)
})
}
</Slider>
:""
} */}
{ {
recommendList && recommendList.length>0 && recommendList && recommendList.length>0 &&
<div className="recommandProjects"> <Slider {...setting} className={recommendList.length>5 ? "recommandProjects":"recommandProjects mb20"}>
{ {
recommendList.map((item,key)=>{ recommendList.map((item,key)=>{
return( return(
<div onClick={()=>this.getoDetail(item.author && item.author.login,item.identifier)}> <div className="items" onClick={()=>this.getoDetail(item.author && item.author.login,item.identifier)}>
<div className="mainInfo"> <div className="mainInfo">
<img src={getUrl(`/images/${item.author && item.author.image_url}`)} alt=""/> <img src={getImageUrl(`/${item.author && item.author.image_url}`)} width="50px" height="50px"alt=""/>
<p className="school">{item.name}</p> <p className="school">{item.name}</p>
<p className="name">{item.author && item.author.name}</p> <p className="name">{item.author && item.author.name}</p>
</div> </div>
@ -283,9 +335,8 @@ class Index extends Component {
) )
}) })
} }
</div> </Slider>
} }
<div className="ProjectListIndex"> <div className="ProjectListIndex">
<div className="list-left"> <div className="list-left">
<ul className="list-l-Menu"> <ul className="list-l-Menu">

View File

@ -1,57 +1,53 @@
.recommandOri.slick-slider{
width: 1300px;
margin:20px auto 40px;
.slick-track{
margin-left: 0px;
}
.slick-slide{
li > a{
display: flex;
align-items: center;
justify-content: center;
}
}
}
/* recommandProjects */ /* recommandProjects */
.recommandProjects{ .recommandProjects.slick-slider{
display: flex; width: 1230px;
max-width: 1200px; margin:20px auto 40px;
margin:20px auto; .slick-track{
} margin-left: 0px;
.recommandProjects >div{
background-color: #fff;
border-radius: 10px;
width: 220px;
margin-right: 25px;
cursor: pointer;
border: 1px solid #eee;
&:last-child{
margin-right: 0px;
} }
} .slick-arrow.slick-prev,.slick-arrow.slick-next{
.recommandProjects > div:hover{ &:before{
box-shadow: 0px 2px 20px 0px rgba(0, 0, 0, 0.1); color: #999;
} }
.recommandProjects > div .mainInfo{ li.slick-active button:before{
display: flex; color: #999;
flex-direction: column; }
align-items: center;
justify-content: center;
min-height: 160px;
border-bottom: 1px solid #eee;
padding:20px;
box-sizing: border-box;
img{
height: 50px;
width:50px;
border-radius: 50%;
} }
.name{ .slick-dots{
font-size: 13px; bottom: -29px;
color: #666; li button:before{
height: 18px; color: #909090;
line-height: 18px; }
margin-top:12px;
} }
.school{ .slick-slide{
margin-top:12px; padding:0px 15px;
color: #333; box-sizing: border-box;
font-size: 16px; & > div{
height: 22px; background-color: #fff;
line-height: 22px; border-radius: 10px;
overflow: hidden; width: 100%;
white-space: nowrap; cursor: pointer;
text-overflow: ellipsis; border: 1px solid #eee;
max-width:100%; &:hover{
box-shadow: 0px 2px 20px 0px rgba(0, 0, 0, 0.1);
}
}
} }
}
.recommandProjects{
.baseInfo{ .baseInfo{
padding:18px 15px; padding:18px 15px;
display: flex; display: flex;
@ -72,8 +68,40 @@
text-align: right; text-align: right;
} }
} }
.mainInfo{
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 160px;
border-bottom: 1px solid #eee;
padding:20px;
box-sizing: border-box;
img{
height: 50px;
width:50px;
border-radius: 50%;
}
.name{
font-size: 13px;
color: #666;
height: 18px;
line-height: 18px;
margin-top:12px;
}
.school{
margin-top:12px;
color: #333;
font-size: 16px;
height: 22px;
line-height: 22px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
max-width:100%;
}
}
} }
// coderDepot // coderDepot
.Panels{ .Panels{
max-width: 1200px; max-width: 1200px;
@ -83,10 +111,10 @@
} }
.addOptionBtn{ .addOptionBtn{
height: 32px; height: 32px;
line-height: 32px; line-height: 30px;
display: flex; display: flex;
border:1px solid #d9d9d9; border:1px solid #d9d9d9;
border-radius: 4px; border-radius: 2px;
a{ a{
padding:0px 13px; padding:0px 13px;
color: rgba(0, 0, 0, 0.65); color: rgba(0, 0, 0, 0.65);
@ -95,6 +123,9 @@
& > a:first-child{ & > a:first-child{
border-right: 1px solid #d9d9d9; border-right: 1px solid #d9d9d9;
} }
& > a:last-child{
border-right: none;
}
} }
.infoCount{ .infoCount{
display: inline-block; display: inline-block;
@ -129,9 +160,7 @@
height: 7px; height: 7px;
margin-top: 12px; margin-top: 12px;
span{ span{
border-left: 1px solid #fff;
&:first-child{ &:first-child{
border-left: none;
border-radius: 10px 0px 0px 10px; border-radius: 10px 0px 0px 10px;
} }
&:last-child{ &:last-child{
@ -177,27 +206,33 @@
border-radius: 4px 4px 0px 0px; border-radius: 4px 4px 0px 0px;
background-color: #FAFBFC; background-color: #FAFBFC;
.ellipsistxt{ .ellipsistxt{
margin-top: 6px;
#ptxt{
margin-bottom: 0px;
word-break: break-all;
overflow: unset;
white-space:pre-wrap; /* css3.0 */
white-space:-moz-pre-wrap; /* Firefox */
white-space:-pre-wrap; /* Opera 4-6 */
white-space:-o-pre-wrap; /* Opera 7 */
word-wrap:break-word;
}
margin-left: 13px; margin-left: 13px;
line-height:18px; line-height:18px;
margin-top:6px;
flex:1; flex:1;
width: 0; width: 0;
color: #666; color: #666;
&>p{ &.hidetxt{
word-break:break-all;
}
&.hide{
height: 18px; height: 18px;
overflow: hidden; overflow: hidden;
position: relative; position: relative;
padding-right:8px; padding-right:8px;
} &::after{
&.hide::after{ position: absolute;
position: absolute; right: 0px;
right: 0px; bottom: 0px;
bottom: 0px; content:"...";
content:"..."; }
} }
} }
.ellipsis{ .ellipsis{
@ -220,8 +255,11 @@
.listtablebody{ .listtablebody{
li.listtablepath{ li.listtablepath{
a{color: #40a9ff;} a{color: #40a9ff;}
p{
margin-bottom: 0px!important;
}
} }
li{ & > li{
height: 42px; height: 42px;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
@ -254,23 +292,82 @@
.drawerBtn{ .drawerBtn{
position: fixed; position: fixed;
left: -13px; left: -13px;
border:1px solid #d9d9d9; border:1px solid rgb(207,205,223);
width: 34px; width: 34px;
border-radius: 0px 12px 12px 0px; border-radius: 0px 12px 12px 0px;
text-align: right;
height: 70px; height: 70px;
line-height: 70px;
top:50%; top:50%;
margin-top: -35px; margin-top: -35px;
cursor: pointer; cursor: pointer;
display: flex;
flex-direction: column;
align-items: flex-end;
justify-content: center;
&:hover{ &:hover{
box-shadow: 1px 0px 7px rgba(0,0,0,0.1); box-shadow: 1px 0px 7px rgba(0,0,0,0.1);
} }
span{
writing-mode: vertical-lr;
color: #202429;
width: 25px;
}
i{ i{
color: #d9d9d9; color: #24292e;
height: 18px;
line-height: 18px;
width: 18px;
} }
} }
.downMenu{ .downMenu{
width: 330px;
box-shadow: 0px 0px 9px rgba(134, 134, 134,0.4); box-shadow: 0px 0px 9px rgba(134, 134, 134,0.4);
background-color: #fff; background-color: #fff;
.ant-menu-vertical .ant-menu-item:hover{
background-color: #e6f7ff;
}
}
.menuslist{
max-height: 200px;
overflow-y: auto;
padding:10px 15px;
border-radius: 4px;
.ant-dropdown-menu-item{
border-radius: 8px;
text-align: left!important;
a{
width: 350px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
.ant-dropdown-menu-item.active{
background-color: #e6f7ff;
}
}
.catelogue{
border:1px solid rgb(211, 211, 211);
font-size: 15px;
font-weight: normal;
border-radius: 5px;
margin-right: 10px;
padding:0px 10px;
height: 30px;
line-height: 30px;
color: #666!important;
display: flex;
align-items: center;
span{
margin-top: 1px;
}
}
.submoduleStyle{
cursor: default;
i{
cursor: default;
}
&:hover{
color: #05101a;
}
} }

View File

@ -1,6 +1,7 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Tooltip } from 'antd'; import { Tooltip } from 'antd';
import { getImageUrl } from 'educoder'; import { getImageUrl } from 'educoder';
import { AlignCenter } from '../Component/layout';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import '../css/index.scss'; import '../css/index.scss';
import Nodata from '../Nodata'; import Nodata from '../Nodata';
@ -17,7 +18,7 @@ class IndexItem extends Component {
render() { render() {
const { projects } = this.props; const { projects } = this.props;
return ( return (
<div className="project-list minH-670"> <div className="project-list minH-670" style={{padding:"0px 20px"}}>
{ projects && projects.length > 0 ? projects.map((item, key) => { { projects && projects.length > 0 ? projects.map((item, key) => {
return ( return (
<div className="p-r-Item" key={key}> <div className="p-r-Item" key={key}>
@ -27,14 +28,17 @@ class IndexItem extends Component {
<img className="p-r-photo" alt="" src={item.author && item.author.image_url} ></img> <img className="p-r-photo" alt="" src={item.author && item.author.image_url} ></img>
</a> </a>
: :
<Link to={`/users/${item.author.login}`} className="show-user-link"> <Link to={item.author && (item.author.type === "Organization" ? `/organize/${item.author.login}`:`/users/${item.author.login}`)} className="show-user-link">
<img className="p-r-photo" alt="" src={getImageUrl(`${item.author && item.author.image_url}`)} ></img> <img className="p-r-photo" alt="" src={getImageUrl(`/${item.author && item.author.image_url}`)} ></img>
</Link> </Link>
} }
<div className="p-r-Infos"> <div className="p-r-Infos">
<div className="p-r-name"> <div className="p-r-name">
<Link to={`/projects/${item.author.login}/${item.identifier}`} className="hide-1 color-grey-3 font-18 task-hide " style={{ whiteSpace: "wrap", display: 'flex', width: 400 }}> <AlignCenter>
{item.author.name}/{item.name} <Link to={`/projects/${item.author.login}/${item.identifier}`} title={`${item.author.name}/${item.name}`} className="color-grey-3 font-18 task-hide " style={{maxWidth: 470 }}>
{item.author.name}/{item.name}
</Link>
{ !item.is_public && <span className="privateTag">私有</span> }
{ {
item.forked_from_project_id ? item.forked_from_project_id ?
<span className="ml5"> <span className="ml5">
@ -43,27 +47,37 @@ class IndexItem extends Component {
: "" : ""
} }
{ {
item.type && item.type !== 0 ? item.type && item.type === 2 ?
item.type === 2 ?
<Tooltip title="该项目是一个镜像" className="ml5"> <Tooltip title="该项目是一个镜像" className="ml5">
<i className="iconfont icon-banbenku font-18 color-green" /> <i className="iconfont icon-banbenku font-18 color-green" />
</Tooltip>: </Tooltip>:""
}
{
item.type && item.type === 1 ?
<span className="ml5"> <span className="ml5">
<i className="iconfont icon-jingxiang font-18 color-green" /> <i className="iconfont icon-jingxiang font-18 color-green" />
</span>:"" </span>:""
} }
</Link> </AlignCenter>
<span className="p-r-tags"> <span className="p-r-tags">
<span className="pariseTag"><img src={img_parise} alt="" className="pariseImg" /> {item.praises_count}</span> {
<span><i className="iconfont icon-fork mr3 font-16" style={{ color: "#1B8FFF" }} />fork {item.forked_count}</span> item.praises_count && item.praises_count>0 ?
<span className="pariseTag">
<img src={img_parise} alt="" className="pariseImg" /> {item.praises_count}
</span>:""
}
{
item.forked_count && item.forked_count>0 ?
<span>
<i className="iconfont icon-fork mr3 font-16" style={{ color: "#1B8FFF" }} />fork {item.forked_count}
</span>:""
}
</span> </span>
</div> </div>
<p className="break_word task-hide-2 mt10" style={{ maxHeight: "44px",lineHeight:"22px" }}>{item.description}</p> <p className="break_word task-hide-2 mt10" style={{ maxHeight: "44px",lineHeight:"22px" }}>{item.description}</p>
<div className="p-r-about"> <div className="p-r-about">
<span className="p-r-detail"> <span className="p-r-detail">
{/* <span><label>浏览量:</label>{item.visits}</span> */}
{/* {item.category && item.category.id && <span>{item.category.name}</span>} */}
{item.last_update_time ? <span><label>更新于</label>{item.time_ago}</span> : ""} {item.last_update_time ? <span><label>更新于</label>{item.time_ago}</span> : ""}
{item.language && item.language.id ? <span className="color-grey-3">{item.language.name}</span> : ""} {item.language && item.language.id ? <span className="color-grey-3">{item.language.name}</span> : ""}
</span> </span>

View File

@ -1,5 +1,5 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import "../Branch/branch.css" import "../Branch/branch.scss"

View File

@ -91,6 +91,7 @@
display: flex; display: flex;
border-bottom:1px solid rgba(238,238,238,1); border-bottom:1px solid rgba(238,238,238,1);
padding:22px 0px; padding:22px 0px;
justify-content: flex-start;
} }
.boxShandow{ .boxShandow{
box-shadow:0px 2px 20px 10px rgba(0,0,0,0.03); box-shadow:0px 2px 20px 10px rgba(0,0,0,0.03);
@ -100,6 +101,7 @@
height: 60px; height: 60px;
border-radius: 50%; border-radius: 50%;
margin-right: 22px; margin-right: 22px;
margin-top: 8px;
} }
.p-r-Infos{ .p-r-Infos{
flex: 1; flex: 1;
@ -108,6 +110,7 @@
.p-r-name{ .p-r-name{
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center;
} }
.p-r-name > p{ .p-r-name > p{
flex: 1; flex: 1;
@ -261,7 +264,10 @@
border:1px solid #f1f1f1; border:1px solid #f1f1f1;
display: flex; display: flex;
align-items: center; align-items: center;
margin-left: 30px margin-left: 30px;
padding:0px;
background-color: transparent;
box-shadow: none;
} }
.ant-tooltip { .ant-tooltip {
max-width: fit-content!important; max-width: fit-content!important;
@ -281,7 +287,6 @@
height:100%; height:100%;
} }
.files-md{ .files-md{
border:1px solid #eee;
padding:20px; padding:20px;
} }
/* 详情-代码 */ /* 详情-代码 */
@ -437,9 +442,6 @@
font-size: 16px; font-size: 16px;
border-bottom: 1px solid #d9d9d9; border-bottom: 1px solid #d9d9d9;
} }
.branchUl{
padding:0px 30px;
}
.branchUl li{ .branchUl li{
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
@ -565,6 +567,10 @@
border-bottom: 1px solid #d9d9d9; border-bottom: 1px solid #d9d9d9;
border-radius: 4px 4px 0px 0px; border-radius: 4px 4px 0px 0px;
} }
.commonBox .commonBox-title.boxTitle{
display: flex;
justify-content: space-between;
}
.synchronism{ .synchronism{
display: block; display: block;
height: 26px; height: 26px;

View File

@ -42,7 +42,7 @@ function Contribute(props){
<WhiteBack> <WhiteBack>
<Spin spinning={isSpin}> <Spin spinning={isSpin}>
<div className="boxPanel"> <div className="boxPanel">
<p className="font-18 mb20">贡献者列表</p> <p className="font-18 padding10-20" style={{borderBottom:"1px solid #eee"}}>贡献者列表</p>
{ {
list && list.length > 0 ? list && list.length > 0 ?
<div className="contrbuteList"> <div className="contrbuteList">
@ -50,7 +50,7 @@ function Contribute(props){
list.map((item,key)=>{ list.map((item,key)=>{
return( return(
<AlignCenter> <AlignCenter>
<img alt="" style={{borderRadius:"50%",marginRight:"10px"}} src={getImageUrl(`images/${item.image_url}`)} width="50px" height="50px"/> <img alt="" style={{borderRadius:"50%",marginRight:"10px"}} src={getImageUrl(`/${item.image_url}`)} width="50px" height="50px"/>
<div> <div>
<Link to={`/users/${item.login}`} className="font-16">{item.name}</Link> <Link to={`/users/${item.login}`} className="font-16">{item.name}</Link>
<p className="font-12 color-grey-9">提交{item.contributions}</p> <p className="font-12 color-grey-9">提交{item.contributions}</p>

View File

@ -1,11 +1,18 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { Skeleton } from 'antd'; import { Skeleton , Tooltip} from 'antd';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
function DetailBanner({ list , owner , projectsId , isManager , url , pathname , state , urlFlag , projectDetail , platform ,open_devops }){ function DetailBanner({ history,list , owner , projectsId , isManager , url , pathname , state , urlFlag , projectDetail , platform ,open_devops }){
const [ menuName , setMenuName ] = useState(undefined); const [ menuName , setMenuName ] = useState(undefined);
useEffect(()=>{ useEffect(()=>{
if(list){ if(list){
// banner
if(pathname && pathname==="source"){
let a = list.filter(item=>item.menu_name === "resources");
if(a && a.length === 0){
history.push(`/projects/${owner}/${projectsId}`);
}
}
setMenuName(list); setMenuName(list);
} }
},[list]); },[list]);
@ -39,11 +46,13 @@ function DetailBanner({ list , owner , projectsId , isManager , url , pathname ,
{ {
item.menu_name === "issues" && item.menu_name === "issues" &&
<li className={pathname==="issues" ? "active" : ""}> <li className={pathname==="issues" ? "active" : ""}>
<Link to={{ pathname: `/projects/${owner}/${projectsId}/issues`, state }}> <Tooltip title="易修是Issue的中文名即问题列表" placement="bottom">
<i className={pathname==="issues" ? "iconfont icon-renwu color-grey-3 mr5 font-14":"iconfont icon-renwu color-grey-6 font-14 mr5"}></i> <Link to={{ pathname: `/projects/${owner}/${projectsId}/issues`, state }}>
<span>易修 (Issue)</span> <i className={pathname==="issues" ? "iconfont icon-renwu color-grey-3 mr5 font-14":"iconfont icon-renwu color-grey-6 font-14 mr5"}></i>
{projectDetail && projectDetail.issues_count ? <span className="num">{projectDetail.issues_count}</span> : ""} <span>易修</span>
</Link> {projectDetail && projectDetail.issues_count ? <span className="num">{projectDetail.issues_count}</span> : ""}
</Link>
</Tooltip>
</li> </li>
} }
{ {
@ -66,8 +75,8 @@ function DetailBanner({ list , owner , projectsId , isManager , url , pathname ,
</li> </li>
:"" :""
} }
{ {/* {
item.menu_name === "source" && item.menu_name === "resources" &&
<li className={pathname==="source" ? "active" : ""}> <li className={pathname==="source" ? "active" : ""}>
<Link to={{ pathname: `/projects/${owner}/${projectsId}/source`, state }}> <Link to={{ pathname: `/projects/${owner}/${projectsId}/source`, state }}>
<i className={pathname==="source" ? "iconfont icon-ziyuanpaihanghetuijian color-grey-3 mr5 font-14":"iconfont icon-ziyuanpaihanghetuijian color-grey-6 font-14 mr5"}></i> <i className={pathname==="source" ? "iconfont icon-ziyuanpaihanghetuijian color-grey-3 mr5 font-14":"iconfont icon-ziyuanpaihanghetuijian color-grey-6 font-14 mr5"}></i>
@ -75,7 +84,7 @@ function DetailBanner({ list , owner , projectsId , isManager , url , pathname ,
{projectDetail && projectDetail.source_count ? <span className="num">{projectDetail.source_count}</span> :""} {projectDetail && projectDetail.source_count ? <span className="num">{projectDetail.source_count}</span> :""}
</Link> </Link>
</li> </li>
} } */}
{ {
item.menu_name === "versions" && item.menu_name === "versions" &&
<li className={pathname==="milestones" ? "active" : ""}> <li className={pathname==="milestones" ? "active" : ""}>
@ -95,19 +104,19 @@ function DetailBanner({ list , owner , projectsId , isManager , url , pathname ,
</Link> </Link>
</li> </li>
} }
{
item.menu_name === "setting" &&
<li className={pathname === "setting" ? "active" : ""}>
<Link to={`/projects/${owner}/${projectsId}/setting`}>
<i className={url && url.indexOf("/setting") > 0 ? "iconfont icon-cangku color-grey-3 mr5 font-14":"iconfont icon-cangku color-grey-6 font-14 mr5"}></i>
<span>仓库设置</span>
</Link>
</li>
}
</React.Fragment> </React.Fragment>
) )
}) })
} }
{
isManager && platform ?
<li className={pathname === "setting" ? "active" : ""}>
<Link to={`/projects/${owner}/${projectsId}/setting`}>
<i className={url && url.indexOf("/setting") > 0 ? "iconfont icon-cangku color-grey-3 mr5 font-14":"iconfont icon-cangku color-grey-6 font-14 mr5"}></i>
<span>仓库设置</span>
</Link>
</li>:""
}
</ul> </ul>
: :
<Skeleton paragraph={false} active={true}/> <Skeleton paragraph={false} active={true}/>

View File

@ -0,0 +1,28 @@
import React from 'react';
import { Tooltip , message } from 'antd';
import './sub.scss';
function Invite({code,className}) {
function jsCopy(id) {
const copyEle = document.querySelector(id); //
const range = document.createRange(); // range
window.getSelection().removeAllRanges(); //selection
range.selectNode(copyEle); //
window.getSelection().addRange(range); //
document.execCommand("Copy"); // copy
message.success('复制成功');
}
return(
<div className={className}>
<span className="font-16 color-grey-6">邀请码</span>
<div>
<span id="devitecode">{code}</span>
<Tooltip title={<p className="edu-txt-center">可以通过邀请码邀请成员加入项目<br/>点击复制邀请码</p>} placement={"bottom"}>
<i className="iconfont icon-fuzhi2 font-16 color-blue ml8" onClick={()=>jsCopy("#devitecode")}></i>
</Tooltip>
</div>
</div>
)
}
export default Invite;

View File

@ -2,13 +2,13 @@ import React , { forwardRef, useEffect } from 'react';
import {Form , Modal , Input } from 'antd'; import {Form , Modal , Input } from 'antd';
import "./sub.scss"; import "./sub.scss";
const { TextArea } = Input; const { TextArea } = Input;
function UpdateDescModal({form , visible , onCancel , onOk,desc,website}){ function UpdateDescModal({form , visible , onCancel , onOk,desc,website,lesson_url}){
const { getFieldDecorator, validateFields , setFieldsValue } = form; const { getFieldDecorator, validateFields , setFieldsValue } = form;
useEffect(()=>{ useEffect(()=>{
if(desc || website){ if(desc || website){
setFieldsValue({ setFieldsValue({
website,desc website,desc,lesson_url
}) })
} }
},[desc,website]) },[desc,website])
@ -17,7 +17,7 @@ function UpdateDescModal({form , visible , onCancel , onOk,desc,website}){
validateFields((err,values)=>{ validateFields((err,values)=>{
if(!err){ if(!err){
onCancel(); onCancel();
onOk(values.desc,values.website) onOk(values.desc,values.website,values.lesson_url)
} }
}) })
} }
@ -35,11 +35,11 @@ function UpdateDescModal({form , visible , onCancel , onOk,desc,website}){
className={"descmodal"} className={"descmodal"}
> >
<Form> <Form>
<Form.Item label="仓库描述"> <Form.Item label="项目简介">
{getFieldDecorator("desc",{ {getFieldDecorator("desc",{
rules:[] rules:[]
})( })(
<TextArea placeholder="仓库描述" rows={4} maxLength={200}/> <TextArea placeholder="请输入项目简介" rows={4} maxLength={200}/>
)} )}
</Form.Item> </Form.Item>
<Form.Item label="website"> <Form.Item label="website">
@ -49,6 +49,13 @@ function UpdateDescModal({form , visible , onCancel , onOk,desc,website}){
<Input placeholder="website链接"/> <Input placeholder="website链接"/>
)} )}
</Form.Item> </Form.Item>
<Form.Item label="实践课程">
{getFieldDecorator("lesson_url",{
rules:[]
})(
<Input placeholder="实践课程链接" />
)}
</Form.Item>
</Form> </Form>
</Modal> </Modal>
) )

View File

@ -1,11 +1,13 @@
.boxPanel{ .boxPanel{
width: 1200px; width: 1200px;
margin:0px auto; margin:20px auto;
padding:20px 0px; border-radius: 4px;
border:1px solid #eee;
min-height: 500px; min-height: 500px;
.contrbuteList{ .contrbuteList{
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
padding:20px;
& > div{ & > div{
width: 20%; width: 20%;
} }
@ -20,4 +22,9 @@
height: 20px; height: 20px;
line-height: 20px; line-height: 20px;
} }
}
.detailsCode{
display: flex;
justify-content: space-between;
} }

View File

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

View File

@ -0,0 +1,21 @@
.i_open{
color: #28BD6C!important;
}
.i_merged{
color: #4C9ED3!important;
}
.i_closed{
color: #FA6400!important;
}
.pr_tags_open{
border:1px solid #28BD6C;
color: #28BD6C;
}
.pr_tags_merged{
border:1px solid #4C9ED3;
color: #4C9ED3;
}
.pr_tags_closed{
border:1px solid #FA6400;
color: #FA6400;
}

View File

@ -1,9 +1,16 @@
import React, { Component } from "react"; import React, { Component } from "react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { Popconfirm, Tag } from "antd"; import { Tag } from "antd";
import { AlignCenter } from '../Component/layout';
import { getImageUrl } from "educoder"; import { getImageUrl } from "educoder";
import "./merge.css"; import "./merge.css";
function turnbar(str){
if(str && str.length>0 && str.indexOf("/")>-1){
return str.replaceAll('/','%2F');
}
return str;
}
class MergeItem extends Component { class MergeItem extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
@ -42,16 +49,18 @@ class MergeItem extends Component {
}; };
render() { render() {
const { issues, project_name, project_author_name } = this.props; const { issues, project_name, project_author_name , user_admin_or_member} = this.props;
const { projectsId , owner } = this.props.match.params; const { projectsId , owner } = this.props.match.params;
const { current_user } = this.props; const { current_user } = this.props;
const renderList = () => { const renderList = () => {
if (issues && issues.length > 0) { if (issues && issues.length > 0) {
return issues.map((item, key) => { return issues.map((item, key) => {
let status = item.pull_request_staus;
return ( return (
<div className="issueItem"> <div className="issueItem">
<div className="flex-1"> <div className="flex-1">
<p className="mb15 df" style={{ alignItems: "center" }}> <p className="mb15 df" style={{ alignItems: "center" }}>
<i className={`iconfont icon-hebingqingqiu1 font-14 mr3 i_${status}`}></i>
<Link <Link
to={`/projects/${owner}/${projectsId}/pulls/${item.pull_request_id}/Messagecount`} to={`/projects/${owner}/${projectsId}/pulls/${item.pull_request_id}/Messagecount`}
className="hide-1 font-15 color-grey-3 fwb lineh-30 mr10" className="hide-1 font-15 color-grey-3 fwb lineh-30 mr10"
@ -59,10 +68,10 @@ class MergeItem extends Component {
> >
{item.name} {item.name}
</Link> </Link>
<Tag className={`pr_tags_${item.pull_request_staus}`}> <Tag className={`pr_tags_${status}`}>
{item.pull_request_staus === "merged" {status === "merged"
? "已合并" ? "已合并"
: item.pull_request_staus === "closed" : status === "closed"
? "已拒绝" ? "已拒绝"
: "开启的"} : "开启的"}
</Tag> </Tag>
@ -74,13 +83,13 @@ class MergeItem extends Component {
> >
<img <img
className="radius" className="radius"
src={getImageUrl(`images/${item && item.avatar_url}`)} src={getImageUrl(`/${item && item.avatar_url}`)}
alt="" alt=""
width="24" width="24"
height="24" height="24"
/> />
</Link> </Link>
<span> <AlignCenter>
<Link <Link
to={`/users/${item && item.author_login}`} to={`/users/${item && item.author_login}`}
className="show-user-link color-grey-8 ml5" className="show-user-link color-grey-8 ml5"
@ -96,35 +105,45 @@ class MergeItem extends Component {
</span> </span>
<span className="color-grey-8">{item.pr_time}</span> <span className="color-grey-8">{item.pr_time}</span>
<span className="ml15"> <span className="ml15">
<Tag className="pr-branch-tag"> {
<Link item.pull_request_head &&
to={`/projects/${item.is_original ? item.fork_project_user : owner}/${ item.is_original ? item.fork_project_identifier : projectsId }/tree/${item.pull_request_head}`} <Tag className="pr-branch-tag">
className="maxW200px hide-1 ver-middle" <Link
> to={`/projects/${item.is_original ? item.fork_project_user : owner}/${ item.is_original ? item.fork_project_identifier : projectsId }/tree/${turnbar(item.pull_request_head)}`}
{item.is_original className="maxW200px hide-1 ver-middle"
? item.fork_project_user >
: project_author_name} {item.is_original
:{item.pull_request_head} ? item.fork_project_user
</Link> : project_author_name}
</Tag> :{item.pull_request_head}
<span className="mr8 ver-middle"> </Link>
<i </Tag>
className={ }
"iconfont icon-youjiang color-grey-c font-16" {
} item.pull_request_base &&
></i> <span className="mr8 ver-middle">
</span> <i
<Tag className="pr-branch-tag"> className={
<Link "iconfont icon-youjiang color-grey-c font-16"
to={`/projects/${owner}/${projectsId}/tree/${item.pull_request_base}`} }
className="maxW200px hide-1 ver-middle" ></i>
> </span>
{/* {item.is_fork ? item.pull_request_base : `${item.author_name}:${item.pull_request_base}`} */} }
{project_author_name}:{item.pull_request_base} {
</Link> item.pull_request_base &&
</Tag> <Tag className="pr-branch-tag">
<Link
to={`/projects/${owner}/${projectsId}/tree/${turnbar(item.pull_request_base)}`}
className="maxW200px hide-1 ver-middle"
>
{/* {item.is_fork ? item.pull_request_base : `${item.author_name}:${item.pull_request_base}`} */}
{project_author_name}:{item.pull_request_base}
</Link>
</Tag>
}
</span> </span>
</span> </AlignCenter>
</p> </p>
</div> </div>
<ul <ul
@ -164,7 +183,7 @@ class MergeItem extends Component {
) : ( ) : (
"" ""
)} )}
{current_user && current_user.login ? ( {user_admin_or_member && item.pull_request_status === 0 ? (
<div <div
className="milepostleft" className="milepostleft"
style={{ style={{
@ -177,7 +196,7 @@ class MergeItem extends Component {
> >
<div className="grid-item mr15 color-grey-9"> <div className="grid-item mr15 color-grey-9">
<Link <Link
to={`/projects/${owner}/${projectsId}/merge/${item.pull_request_id}/updatemerge`} to={`/projects/${owner}/${projectsId}/pulls/${item.pull_request_id}/updatemerge`}
className="color-grey-9" className="color-grey-9"
> >
<i className="iconfont icon-bianji3 font-14 mr5"></i> <i className="iconfont icon-bianji3 font-14 mr5"></i>

View File

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

View File

@ -24,6 +24,12 @@ import MergeFooter from "./merge_footer";
const Option = Select.Option; const Option = Select.Option;
const TextArea = Input.TextArea; const TextArea = Input.TextArea;
function turnbar(str){
if(str && str.length>0 && str.indexOf("/")>-1){
return str.replaceAll('/','%2F');
}
return str;
}
class MessageCount extends Component { class MessageCount extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
@ -41,6 +47,7 @@ class MessageCount extends Component {
edit_spin: false, edit_spin: false,
pr_status: undefined, pr_status: undefined,
pull_request:undefined, pull_request:undefined,
conflict_files:[],
copyVisible:false, copyVisible:false,
}; };
@ -75,7 +82,8 @@ class MessageCount extends Component {
data: result.data, data: result.data,
SpinFlag: false, SpinFlag: false,
pr_status: result.data.pull_request && result.data.pull_request.status, pr_status: result.data.pull_request && result.data.pull_request.status,
pull_request:result.data.pull_request pull_request:result.data.pull_request,
conflict_files:result.data.conflict_files
}); });
} else { } else {
this.setState({ SpinFlag: false }); this.setState({ SpinFlag: false });
@ -102,6 +110,8 @@ class MessageCount extends Component {
isSpin: false, isSpin: false,
pr_status: 2, pr_status: 2,
}); });
const { getDetail } = this.props;
getDetail && getDetail();
} else { } else {
this.setState({ this.setState({
isSpin: false, isSpin: false,
@ -138,6 +148,8 @@ class MessageCount extends Component {
SpinMerge: false, SpinMerge: false,
pr_status: 1, pr_status: 1,
}); });
const { getDetail } = this.props;
getDetail && getDetail();
} else { } else {
this.setState({ SpinMerge: false }); this.setState({ SpinMerge: false });
} }
@ -241,6 +253,49 @@ class MessageCount extends Component {
) )
} }
// 点击按钮复制功能
jsCopy = () => {
const copyEle = document.querySelector('#descContent') // 获取要复制的节点
const range = document.createRange(); // 创造range
window.getSelection().removeAllRanges(); //清除页面中已有的selection
range.selectNode(copyEle); // 选中需要复制的节点
window.getSelection().addRange(range); // 执行选中元素
document.execCommand("Copy"); // 执行copy操作
}
mergeabledMes=()=>{
return(
<div className="clearfix">
<p className="fl">该分支存在冲突无法自动合并你可以尝试通过如下命令手动合并</p>
<i className="iconfont icon-fuzhi font-16 fr" onClick={()=>this.jsCopy()}></i>
</div>
)
}
mergeabledDesc=(base,head,conflict_files)=>{
return(
<div>
<ul id="descContent">
<li>git fetch origin</li>
<li>git checkout -b {`${base}`} origin/{`${base}`}</li>
<li>git merge {`${head}`}</li>
</ul>
{
conflict_files && conflict_files.length>0 &&
<div>
<p className="mt10 font-16 pt10" style={{borderTop:"1px solid #f9d7d5"}}>如下文件有代码冲突</p>
<p>
{
conflict_files.map((i,k)=>{
return <p>{i}</p>
})
}
</p>
</div>
}
</div>
)
}
render() { render() {
const { projectsId, mergeId , owner } = this.props.match.params; const { projectsId, mergeId , owner } = this.props.match.params;
@ -252,7 +307,8 @@ class MessageCount extends Component {
ismesrge, ismesrge,
SpinFlag, SpinFlag,
copyVisible, copyVisible,
pull_request pull_request,
conflict_files
} = this.state; } = this.state;
const { current_user, projectDetail } = this.props; const { current_user, projectDetail } = this.props;
const menu = ( const menu = (
@ -305,10 +361,10 @@ class MessageCount extends Component {
<div className="mt15"> <div className="mt15">
<Tag className="pr-branch-tag"> <Tag className="pr-branch-tag">
<Link <Link
to={`/projects/${owner}/${data.pull_request.is_original?data.project_identifier:projectsId}/tree/${data.pull_request.head}`} to={`/projects/${data.pull_request.is_original ? data.pull_request.fork_project_user : data.issue.project_author_name}/${data.pull_request.is_original?data.project_identifier:projectsId}/tree/${turnbar(data.pull_request && data.pull_request.head)}`}
className="ver-middle" className="ver-middle"
> >
{data.pull_request.is_original ? data.pull_request.fork_project_user : data.issue.project_author_name}:{data.pull_request.head} {data.pull_request.is_original ? data.pull_request.fork_project_user : data.issue.project_author_name}: {turnbar(data.pull_request && data.pull_request.head)}
</Link> </Link>
</Tag> </Tag>
<span className="mr8 ver-middle"> <span className="mr8 ver-middle">
@ -323,7 +379,6 @@ class MessageCount extends Component {
to={`/projects/${owner}/${projectsId}/tree/${data.pull_request.base}`} to={`/projects/${owner}/${projectsId}/tree/${data.pull_request.base}`}
className="ver-middle" className="ver-middle"
> >
{/* {data.pull_request.is_fork ? data.pull_request.base : `${data.pull_request.pull_request_user}:${data.pull_request.base}`} */}
{data.issue.project_author_name}:{data.pull_request.base} {data.issue.project_author_name}:{data.pull_request.base}
</Link> </Link>
</Tag> </Tag>
@ -331,26 +386,14 @@ class MessageCount extends Component {
} }
<div className="mt15"> <div className="mt15">
<Link <Link to={`/users/${data.issue.author_login}`} className="show-user-link">
to={`/users/${data.issue.author_login}`} <img className="mr5" src={getImageUrl(`/${data.issue.author_picture}`)}
className="show-user-link" alt="" width="24" height="24" style={{borderRadius:"50%"}}
>
<img
className="mr5"
src={getImageUrl(
`images/${data.issue.author_picture}`
)}
alt=""
width="24"
height="24"
/> />
</Link> </Link>
<span className="ver-middle"> <span className="ver-middle">
<span className="color-grey-8 mr5"></span> <span className="color-grey-8 mr5"></span>
<Link <Link to={`/users/${data.issue.author_login}`} className="show-user-link color-blue">
to={`/users/${data.issue.author_login}`}
className="show-user-link color-blue"
>
{data.issue.author_name} {data.issue.author_name}
</Link> </Link>
<span className="ml5 color-grey-8"> <span className="ml5 color-grey-8">
@ -400,12 +443,6 @@ class MessageCount extends Component {
</div> </div>
<div className="ml10"> <div className="ml10">
<div className="mt15 text-right" style={{display:"flex",justifyContent:"flex-end"}}> <div className="mt15 text-right" style={{display:"flex",justifyContent:"flex-end"}}>
{/* <span className="composeButton">
<Dropdown overlay={this.copyItem()} visible={copyVisible} onClick={(e)=>this.setCopyVisible(e)}>
<span>复制</span>
</Dropdown>
<span>下载为<i className="iconfont icon-sanjiaoxing-down color-blue"></i></span>
</span> */}
{operate && ( {operate && (
<Button <Button
type="green" type="green"
@ -452,35 +489,40 @@ class MessageCount extends Component {
type="success" type="success"
/> />
)} )}
{pr_status === 0 && projectDetail && projectDetail.permission !=="Reporter" && ( {operate && (
<Spin spinning={SpinFlag}> <Spin spinning={SpinFlag}>
<div <div
style={{ style={{
display: display:
this.state.mergekey === "rebase" this.state.mergekey === "rebase"
? this.state.buttonshow === "none" ? this.state.buttonshow === "none" ? "block" : "none"
? "block" : !ismesrge ? "block" : "none",
: "none"
: !ismesrge
? "block"
: "none",
}} }}
> >
<p className="mb15"> <Dropdown.Button
<Dropdown.Button overlay={menu}
overlay={menu} type="primary"
type="primary" onClick={this.submitmerge}
onClick={this.submitmerge} className="mb15"
icon={<Icon type="caret-down" />} icon={<Icon type="caret-down" />}
> disabled={!pull_request || (pull_request && !pull_request.mergeable) }
{this.state.mergename} >
</Dropdown.Button> {this.state.mergename}
</p> </Dropdown.Button>
<Alert {pull_request && pull_request.mergeable
message="该合并请求可以进行自动合并操作" ?
type="success" <Alert
showIcon message="该合并请求可以进行自动合并操作"
/> type="success"
showIcon
/>:
<Alert
message={this.mergeabledMes()}
type="error"
description={this.mergeabledDesc(pull_request.base,pull_request.head,conflict_files)}
showIcon
/>
}
</div> </div>
<div> <div>
<div <div

View File

@ -9,13 +9,14 @@ const Option = Select.Option;
class NewMerge extends Component { class NewMerge extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
const { branch } = this.props.match.params;
this.state = { this.state = {
data: undefined, data: undefined,
branches: undefined, branches: undefined,
merge_branches: undefined, merge_branches: undefined,
merge_projects: undefined, merge_projects: undefined,
merge: "master", merge: "master",
pull: "master", pull: branch,
id: undefined, id: undefined,
is_fork: false, is_fork: false,
projects_names: undefined, projects_names: undefined,
@ -41,9 +42,10 @@ class NewMerge extends Component {
componentDidUpdate=(preProps)=>{ componentDidUpdate=(preProps)=>{
const { project } = this.props; const { project } = this.props;
const { pull } = this.state;
let oldProject = preProps.project; let oldProject = preProps.project;
if(project && oldProject && (oldProject.id !== project.id)){ if(project && oldProject && (oldProject.id !== project.id)){
this.compareProject(this.state.id,"master","master"); this.compareProject(this.state.id,pull,"master");
} }
} }
// 页面销毁取消监听 // 页面销毁取消监听
@ -77,7 +79,8 @@ class NewMerge extends Component {
this.set_default_pull(result.data.branches); this.set_default_pull(result.data.branches);
this.set_default_merge(result.data.merge_projects); this.set_default_merge(result.data.merge_projects);
} }
this.compareProject(result.data.id,"master","master"); const { pull } = this.state;
this.compareProject(result.data.id,pull||"master","master");
this.setState({isSpin: false}) this.setState({isSpin: false})
}) })
.catch((error) => { .catch((error) => {
@ -104,6 +107,18 @@ class NewMerge extends Component {
} }
axios.get(url).then(result=>{ axios.get(url).then(result=>{
if(result){ if(result){
if (result.data.status === 0) {
this.setState({
isSpin: false,
show_message: false,
});
} else {
this.setState({
isSpin: false,
show_message: true,
default_message: result.data.message,
});
}
this.setState({ this.setState({
comparesData:result.data comparesData:result.data
}) })
@ -113,16 +128,19 @@ class NewMerge extends Component {
} }
set_default_pull = (branches) => { set_default_pull = (branches) => {
if(branches && branches.length>0){ const { branch } = this.props.match.params;
let default_pull = branches.filter((e) => e.name === "master") if(!branch){
if (default_pull.length > 0){ if(branches && branches.length>0){
this.setState({ let default_pull = branches.filter((e) => e.name === "master")
pull:default_pull[0].name if (default_pull.length > 0){
}) this.setState({
}else{ pull:default_pull[0].name
this.setState({ })
pull:"master" }else{
}) this.setState({
pull:"master"
})
}
} }
} }
} }
@ -139,7 +157,7 @@ class NewMerge extends Component {
merge:"master" merge:"master"
}) })
} }
this.ischeckmerge(); // this.ischeckmerge();
} }
} }
@ -163,10 +181,12 @@ class NewMerge extends Component {
}; };
selectBrach = (type, value) => { selectBrach = (type, value) => {
const { projectsId , owner } = this.props.match.params;
this.state[type] = value; this.state[type] = value;
this.ischeckmerge(); // this.ischeckmerge();
let { id ,merge , pull } = this.state; let { id ,merge , pull } = this.state;
if(type==="pull"){ if(type==="pull"){
this.props.history.push(`/projects/${owner}/${projectsId}/pulls/new/${pull}`)
this.compareProject(id,value,merge); this.compareProject(id,value,merge);
}else{ }else{
this.compareProject(id,pull,value); this.compareProject(id,pull,value);
@ -178,7 +198,7 @@ class NewMerge extends Component {
let arr = projects_names && projects_names.filter(item=>item.id===value); let arr = projects_names && projects_names.filter(item=>item.id===value);
let identifier = arr && arr[0].project_id; let identifier = arr && arr[0].project_id;
let login = arr && arr[0].project_user_login; let login = arr && arr[0].project_user_login;
let is_fork_id = parseInt(value) !== parseInt(id) let is_fork_id = parseInt(value) !== parseInt(id);
this.setState({ this.setState({
isSpin: true, isSpin: true,
merge_head: is_fork_id, merge_head: is_fork_id,
@ -193,7 +213,6 @@ class NewMerge extends Component {
}; };
//判断2分支是否可以合并 //判断2分支是否可以合并
ischeckmerge = () => { ischeckmerge = () => {
this.setState({ isSpin: true }); this.setState({ isSpin: true });
const { projectsId , owner } = this.props.match.params; const { projectsId , owner } = this.props.match.params;

View File

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

View File

@ -5,6 +5,7 @@ import "../Order/order.css";
import "../Order/index.scss"; import "../Order/index.scss";
import NoneData from "./no_data"; import NoneData from "./no_data";
import OrderItem from "./MergeItem"; import OrderItem from "./MergeItem";
import './Index.scss';
import axios from "axios"; import axios from "axios";
@ -37,7 +38,7 @@ class merge extends Component {
// page: 1, // page: 1,
search_count: undefined, search_count: undefined,
issue_type: undefined, issue_type: undefined,
status_type: undefined, status_type: "1",
//设置选择高亮 //设置选择高亮
openselect: 1, openselect: 1,
closeselect: undefined, closeselect: undefined,
@ -47,7 +48,7 @@ class merge extends Component {
paix: "排序", paix: "排序",
priority_ids: "优先级", priority_ids: "优先级",
select_params: { select_params: {
status_type: undefined, //开启中和关闭中,默认为开启中的 status_type: "1", //开启中和关闭中,默认为开启中的
assigned_to_id: undefined, // 指派人 assigned_to_id: undefined, // 指派人
fixed_version_id: undefined, fixed_version_id: undefined,
priority_id: undefined, priority_id: undefined,
@ -154,18 +155,14 @@ class merge extends Component {
renderMenu = (array, name, id) => { renderMenu = (array, name, id) => {
return ( return (
<Menu> <Menu className="orderCondition">
<Menu.Item key={"all"} onClick={(e) => this.getOption(e, id, name)}> <Menu.Item key={"all"} onClick={(e) => this.getOption(e, id, name)}>
{name} {name}
</Menu.Item> </Menu.Item>
{array && {array && array.length > 0 && array.map((item, key) => {
array.length > 0 &&
array.map((item, key) => {
return ( return (
<Menu.Item ((!item.permission) || (item.permission && item.permission !== "Reporter")) &&
key={item.id} <Menu.Item key={item.id} onClick={(e) => this.getOption(e, id, item.name)}>
onClick={(e) => this.getOption(e, id, item.name)}
>
{item.name} {item.name}
</Menu.Item> </Menu.Item>
); );
@ -206,23 +203,16 @@ class merge extends Component {
paix: "排序", paix: "排序",
priority_ids: "优先级", priority_ids: "优先级",
}); });
this.state.select_params = { this.state.select_params.status_type = type;
status_type: type, this.state.select_params.page=1;
search: undefined, this.state.select_params.limit=15;
page: 1,
limit: 15,
};
this.getIssueList(); this.getIssueList();
}; };
islogin() { checkOperation() {
const { projectsId,owner } = this.props.match.params; const { projectsId,owner } = this.props.match.params;
if (this.props.checkIfLogin() === false) { this.props.history.push(`/projects/${owner}/${projectsId}/pulls/new`);
this.props.showLoginDialog();
return;
} else {
this.props.history.push(`/projects/${owner}/${projectsId}/pulls/new`);
}
} }
render() { render() {
const { projectsId , owner } = this.props.match.params; const { projectsId , owner } = this.props.match.params;
@ -253,24 +243,6 @@ class merge extends Component {
</Menu.Item> </Menu.Item>
</Menu> </Menu>
); );
const Paginations = (
<React.Fragment>
{search_count > limit ? (
<div className="mt30 mb50 edu-txt-center">
<Pagination
simple
defaultCurrent={page}
total={search_count}
pageSize={limit}
onChange={this.ChangePage}
></Pagination>
</div>
) : (
""
)}
</React.Fragment>
);
return ( return (
<div className="main" style={{padding:"0px"}}> <div className="main" style={{padding:"0px"}}>
<div className="topWrapper" style={{borderBottom:"none",padding:"20px"}}> <div className="topWrapper" style={{borderBottom:"none",padding:"20px"}}>
@ -282,9 +254,12 @@ class merge extends Component {
style={{ width: 300 }} style={{ width: 300 }}
/> />
</div> </div>
<a className="topWrapper_btn ml10" onClick={() => this.islogin()}> {
+&nbsp;新建合并请求 data && data.user_admin_or_member &&
</a> <a className="topWrapper_btn ml10" onClick={() => this.checkOperation()}>
+&nbsp;新建合并请求
</a>
}
</div> </div>
<div className="f-wrap-between screenWrap"> <div className="f-wrap-between screenWrap">
<div className="df"> <div className="df">
@ -300,6 +275,7 @@ class merge extends Component {
className={status_type === "1" ? "active" : ""} className={status_type === "1" ? "active" : ""}
onClick={() => this.openorder("1")} onClick={() => this.openorder("1")}
> >
<i className="iconfont icon-hebingqingqiu1 font-14 mr3 i_open"></i>
<label>开启的</label> <label>开启的</label>
<span>{data && data.open_count}</span> <span>{data && data.open_count}</span>
</li> </li>
@ -307,6 +283,7 @@ class merge extends Component {
className={status_type === "11" ? "active" : ""} className={status_type === "11" ? "active" : ""}
onClick={() => this.openorder("11")} onClick={() => this.openorder("11")}
> >
<i className="iconfont icon-hebingqingqiu1 font-14 mr3 i_merged"></i>
<label>已合并</label> <label>已合并</label>
<span>{data && data.merged_issues_size}</span> <span>{data && data.merged_issues_size}</span>
</li> </li>
@ -314,6 +291,7 @@ class merge extends Component {
className={status_type === "2" ? "active" : ""} className={status_type === "2" ? "active" : ""}
onClick={() => this.openorder("2")} onClick={() => this.openorder("2")}
> >
<i className="iconfont icon-hebingqingqiu1 font-14 mr3 i_closed"></i>
<label>已拒绝</label> <label>已拒绝</label>
<span>{data && data.close_count}</span> <span>{data && data.close_count}</span>
</li> </li>
@ -418,10 +396,23 @@ class merge extends Component {
project_author_name={data.project_author_name} project_author_name={data.project_author_name}
{...this.props} {...this.props}
{...this.state} {...this.state}
user_admin_or_member={data && data.user_admin_or_member}
></OrderItem> ></OrderItem>
{Paginations}
</div> </div>
):""} ):""}
{search_count > select_params.limit ? (
<div className="mt30 mb50 edu-txt-center">
<Pagination
simple
current={select_params.page}
total={search_count}
pageSize={select_params.limit}
onChange={this.ChangePage}
></Pagination>
</div>
) : (
""
)}
{ data && data.issues && data.issues.length === 0 ? <NoneData _html="暂时还没有相关数据!" projectsId={projectsId} owner={owner} /> :""} { data && data.issues && data.issues.length === 0 ? <NoneData _html="暂时还没有相关数据!" projectsId={projectsId} owner={owner} /> :""}
</Spin> </Spin>
</div> </div>

View File

@ -34,17 +34,19 @@ class MergeForm extends Component {
this.set_defatul(); this.set_defatul();
}; };
componentDidUpdate=(prevPros)=>{ componentDidUpdate=(prevPros)=>{
const { projectsId ,owner } = this.props.match.params;
const pId = prevPros.match.params.projectsId;
const oId = prevPros.match.params.owner;
if(pId !== projectsId || oId !== owner ){
// console.log("切换了项目分支···········");
this.get_default_selects();
}
if(prevPros && this.props && !this.props.checkIfLogin()){ if(prevPros && this.props && !this.props.checkIfLogin()){
this.props.history.push("/403") this.props.history.push("/403")
return return
} }
} }
// check_is_login =() =>{
// if(!this.props.checkIfLogin()){
// this.props.history.push("/403")
// return
// }
// };
get_default_selects = () => { get_default_selects = () => {
const { projectsId ,owner } = this.props.match.params; const { projectsId ,owner } = this.props.match.params;
this.setState({ isSpin: true }); this.setState({ isSpin: true });
@ -262,7 +264,7 @@ class MergeForm extends Component {
}, },
], ],
initialValue: title, initialValue: title,
})(<Input placeholder="标题" />)} })(<Input placeholder="标题" maxLength={50} />)}
</Form.Item> </Form.Item>
<MDEditor <MDEditor
placeholder={"请输入合并请求的描述..."} placeholder={"请输入合并请求的描述..."}
@ -344,19 +346,21 @@ class MergeForm extends Component {
</Select> </Select>
)} )}
</Form.Item> </Form.Item>
<Form.Item name="checkbox-group" label="其他"> {/* <Form.Item label="">
<Checkbox.Group> {getFieldDecorator("checkbox-group")(
<div> <Checkbox.Group>
<Checkbox value="A">必须审查代码</Checkbox> <div>
</div> <Checkbox value="A">必须审查代码</Checkbox>
<div> </div>
<Checkbox value="B">合并后删除提交分支</Checkbox> <div>
</div> <Checkbox value="B">合并后删除提交分支</Checkbox>
<div> </div>
<Checkbox value="C">合并后关闭提到的任务</Checkbox> <div>
</div> <Checkbox value="C">合并后关闭提到的任务</Checkbox>
</Checkbox.Group> </div>
</Form.Item> </Checkbox.Group>
)}
</Form.Item> */}
</div> </div>
</div> </div>
</div> </div>

View File

@ -43,7 +43,8 @@ class Index extends Component {
project_language_name: undefined, project_language_name: undefined,
project_category_name: undefined, project_category_name: undefined,
license_name: undefined, license_name: undefined,
ignore_name: undefined ignore_name: undefined,
descNum:0
} }
} }
componentDidMount = () => { componentDidMount = () => {
@ -67,24 +68,30 @@ class Index extends Component {
getOwner=()=>{ getOwner=()=>{
const { OIdentifier } = this.props.match.params; const { OIdentifier } = this.props.match.params;
const { user_id } = this.props && this.props.current_user;
const url = `/owners.json`; const url = `/owners.json`;
axios.get(url).then(result=>{ axios.get(url).then(result=>{
if(result && result.data){ if(result && result.data){
let owner = result.data.owners; let owner = result.data.owners;
this.setState({
OwnerList: owner,
})
if(OIdentifier){ if(OIdentifier){
owner = owner.filter(item=>item.name === OIdentifier); owner = owner.filter(item=>item.name === OIdentifier);
this.props.form.setFieldsValue({ this.props.form.setFieldsValue({
user_id:OIdentifier user_id:OIdentifier
}) })
owner && this.setState({ }else if(user_id){
owners_id:owner[0].id, owner = owner.filter(item=>item.id === user_id);
owners_name:owner[0].name this.props.form.setFieldsValue({
user_id:owner && owner[0].name
}) })
} }
this.setOptionsList(owner, 'owners'); owner && this.setState({
this.setState({ owners_id:owner[0].id,
OwnerList: owner, owners_name:owner[0].name
}) })
this.setOptionsList(owner, 'owners');
} }
}).catch(error=>{}) }).catch(error=>{})
} }
@ -174,14 +181,12 @@ class Index extends Component {
ignore_id, ignore_id,
user_id:owners_id user_id:owners_id
}).then((result) => { }).then((result) => {
if (result) { if (result && result.data.id) {
if (result.data.id) { this.setState({
this.setState({ isSpin: false
isSpin: false })
}) this.props.showNotification(`${projectsType && projectsType === "mirror" ? "镜像" : "托管"}项目创建成功!`);
this.props.showNotification(`${projectsType && projectsType === "mirror" ? "镜像" : "托管"}项目创建成功!`); this.props.history.push(`/projects/${result.data.login}/${result.data.identifier}`);
this.props.history.push(`/projects/${owners_name}/${result.data.identifier}`);
}
} }
}).catch((error) => { }).catch((error) => {
this.setState({ this.setState({
@ -254,6 +259,13 @@ class Index extends Component {
} }
} }
changeDesc=(e)=>{
let value = e.target.value;
this.setState({
descNum:value ? value.length :0
})
}
render() { render() {
const { getFieldDecorator } = this.props.form; const { getFieldDecorator } = this.props.form;
// 项目类型deposit-托管项目mirror-镜像项目 // 项目类型deposit-托管项目mirror-镜像项目
@ -273,7 +285,9 @@ class Index extends Component {
license_list, license_list,
ignore_list, ignore_list,
mirrorCheck mirrorCheck,
descNum
} = this.state; } = this.state;
return ( return (
<div className="main back-white" style={{padding:"0px",border:"none"}}> <div className="main back-white" style={{padding:"0px",border:"none"}}>
@ -361,21 +375,23 @@ class Index extends Component {
required: true, message: '请填写项目名称' required: true, message: '请填写项目名称'
}], }],
})( })(
<Input placeholder="例如:团队协作方法与研究" /> <Input placeholder="例如:团队协作方法与研究" maxLength={50}/>
)}
</Form.Item>
<Form.Item
label="项目简介"
>
{getFieldDecorator('description', {
rules: [{
required: true, message: '请填写项目简介'
}],
})(
<Input.TextArea placeholder="项目的介绍" autoSize={{ minRows: 2, maxRows: 6 }} />
)} )}
</Form.Item> </Form.Item>
<div className="pr">
<span className="toprightNum">{descNum}/200</span>
<Form.Item
label="项目简介"
>
{getFieldDecorator('description', {
rules: [{
required: true, message: '请填写项目简介'
}],
})(
<Input.TextArea maxLength={200} placeholder="项目的介绍" autoSize={{ minRows: 2, maxRows: 6 }} onChange={this.changeDesc}/>
)}
</Form.Item>
</div>
<Form.Item <Form.Item
label="仓库名称" label="仓库名称"
> >
@ -384,7 +400,7 @@ class Index extends Component {
required: true, message: '请填写仓库名称' required: true, message: '请填写仓库名称'
}], }],
})( })(
<Input placeholder="仓库名称请使用与项目相关的英文关键字" /> <Input placeholder="仓库名称请使用与项目相关的英文关键字" maxLength={100} />
)} )}
</Form.Item> </Form.Item>
<Form.Item <Form.Item

View File

@ -73,6 +73,7 @@ class Index extends Component {
content={undefined} content={undefined}
readOnly={false} readOnly={false}
editorType="new" editorType="new"
descName={filename && `Add ${filename}`}
></Meditor> ></Meditor>
</div> </div>
</div> </div>

View File

@ -6,6 +6,20 @@ import "./index.css";
import axios from "axios"; import axios from "axios";
const TextArea = Input.TextArea; const TextArea = Input.TextArea;
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;
}
class UserSubmitComponent extends Component { class UserSubmitComponent extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
@ -16,6 +30,24 @@ class UserSubmitComponent extends Component {
}; };
} }
componentDidMount=()=>{
const { descName } = this.props;
if(descName){
this.props.form.setFieldsValue({
desc:descName
})
}
}
componentDidUpdate=(preProps)=>{
const { descName } = this.props;
if(preProps && descName && preProps.descName !== descName ){
this.props.form.setFieldsValue({
desc:descName
})
}
}
changeSubmittype = (e) => { changeSubmittype = (e) => {
this.setState({ this.setState({
submitType: e.target.value, submitType: e.target.value,
@ -41,7 +73,7 @@ class UserSubmitComponent extends Component {
const url = `/${owner}/${projectsId}/create_file.json`; const url = `/${owner}/${projectsId}/create_file.json`;
axios.post(url, { axios.post(url, {
filepath: filename ? filename : path, filepath: filename ? filename : path,
branch: branch, branch: returnbar(branch),
new_branch: submitType === "1" ? values.branchname : undefined, new_branch: submitType === "1" ? values.branchname : undefined,
content, content,
message: values.desc, message: values.desc,
@ -54,7 +86,7 @@ class UserSubmitComponent extends Component {
const { getTopCount } = this.props; const { getTopCount } = this.props;
getTopCount && getTopCount(values.branchname); getTopCount && getTopCount(values.branchname);
} }
let url = `/projects/${owner}/${projectsId}${values.branchname ? `/tree/${values.branchname}`: (branch ? `/tree/${branch}` : "")}`; let url = `/projects/${owner}/${projectsId}${values.branchname ? `/tree/${turnbar(values.branchname)}`: (branch ? `/tree/${turnbar(branch)}` : "")}`;
this.props.history.push(url); this.props.history.push(url);
} }
}) })
@ -75,12 +107,13 @@ class UserSubmitComponent extends Component {
const { projectsId , owner } = this.props.match.params; const { projectsId , owner } = this.props.match.params;
const { submitType } = this.state; const { submitType } = this.state;
const url = `/${owner}/${projectsId}/update_file.json`; const url = `/${owner}/${projectsId}/update_file.json`;
let b = currentBranch || branch;
this.props.form.validateFieldsAndScroll((err, values) => { this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) { if (!err) {
axios axios
.put(url, { .put(url, {
filepath: detail.path, filepath: detail.path,
branch: submitType === "1" ? undefined : (currentBranch || branch), branch: submitType === "1" ? undefined : returnbar(b),
new_branch: submitType === "1" ? values.branchname : undefined, new_branch: submitType === "1" ? values.branchname : undefined,
content: content, content: content,
sha: detail.sha, sha: detail.sha,
@ -89,7 +122,8 @@ class UserSubmitComponent extends Component {
.then((result) => { .then((result) => {
this.setState({ isSpin: false }); this.setState({ isSpin: false });
if (result.data && result.data.status === 1) { if (result.data && result.data.status === 1) {
let url = `/projects/${owner}/${projectsId}${(values.branchname ? `/tree/${values.branchname}` : ((currentBranch || branch) ? `/tree/${currentBranch || branch}`:""))}`; let b = currentBranch || branch;
let url = `/projects/${owner}/${projectsId}${(values.branchname ? `/tree/${turnbar(values.branchname)}` : (b ? `/tree/${turnbar(b)}`:""))}`;
this.props.history.push(url); this.props.history.push(url);
this.props.showNotification("文件修改成功!"); this.props.showNotification("文件修改成功!");
} }
@ -112,12 +146,13 @@ class UserSubmitComponent extends Component {
const { current_user, filepath, projectDetail , currentBranch } = this.props; const { current_user, filepath, projectDetail , currentBranch } = this.props;
const { editor_type } = this.props; const { editor_type } = this.props;
let b = currentBranch || branch;
return ( return (
<div> <div>
<span className="df" style={{ alignItems: "center" }}> <span className="df" style={{ alignItems: "center" }}>
<Link to={`/users/${current_user && current_user.login}`} className="show-user-link" > <Link to={`/users/${current_user && current_user.login}`} className="show-user-link" >
<img <img
src={getImageUrl(`images/${current_user && current_user.image_url}`)} src={getImageUrl(`/${current_user && current_user.image_url}`)}
alt="" alt=""
className="screwImg" className="screwImg"
/> />
@ -170,7 +205,7 @@ class UserSubmitComponent extends Component {
> >
<Radio value="0" className="mb10"> <Radio value="0" className="mb10">
<i className="iconfont icon-banbenku font-16 mr5"></i> <i className="iconfont icon-banbenku font-16 mr5"></i>
直接提交至<span className="color-orange">{currentBranch || branch}</span> 直接提交至<span className="color-orange">{returnbar(b)}</span>
</Radio> </Radio>
<Radio value="1"> <Radio value="1">
<Icon type="pull-request" className="mr5" /> <Icon type="pull-request" className="mr5" />

View File

@ -12,6 +12,13 @@ class m_editor extends Component {
editorValue: this.props.content, editorValue: this.props.content,
}; };
} }
componentDidUpdate=(prevProps)=>{
if(prevProps && this.props && this.props.content !== prevProps.content){
this.setState({
editorValue:this.props.content
})
}
}
changeEditor = (editorValue) => { changeEditor = (editorValue) => {
this.setState({ this.setState({
editorValue, editorValue,
@ -20,7 +27,7 @@ class m_editor extends Component {
render() { render() {
const { editorValue } = this.state; const { editorValue } = this.state;
const { readOnly, editorType, language , currentBranch } = this.props; const { readOnly, editorType, language , currentBranch , descName } = this.props;
const editor_options = { const editor_options = {
lineNumbers: "on", lineNumbers: "on",
wordWrap: true, //强制换行 wordWrap: true, //强制换行
@ -44,7 +51,7 @@ class m_editor extends Component {
return ( return (
<React.Fragment> <React.Fragment>
<div> <div>
<div className="branchTable"> <div className="branchTable" style={{border:"1px solid #eee"}}>
<Editor <Editor
height="400px" height="400px"
language={language ? language : "plaintext"} language={language ? language : "plaintext"}
@ -57,7 +64,7 @@ class m_editor extends Component {
/> />
</div> </div>
{!readOnly && ( {!readOnly && (
<div style={{padding:"20px",marginTop:"20px",borderTop:"1px solid #d9d9d9"}}> <div style={{marginTop:"20px",padding:"20px"}}>
<UserSubmitComponent <UserSubmitComponent
{...this.props} {...this.props}
{...this.state} {...this.state}
@ -65,6 +72,7 @@ class m_editor extends Component {
content={editorValue} content={editorValue}
editor_type={editorType} editor_type={editorType}
currentBranch={currentBranch} currentBranch={currentBranch}
descName={descName}
></UserSubmitComponent> ></UserSubmitComponent>
</div> </div>
)} )}

View File

@ -60,6 +60,7 @@ class UploadFile extends Component {
filepath={file_path} filepath={file_path}
content={editorValue} content={editorValue}
editor_type={"upload"} editor_type={"upload"}
descName={`ADD file via upload`}
></UserSubmitComponent> ></UserSubmitComponent>
</div> </div>
</div> </div>

114
src/forge/Notice/Apply.jsx Normal file
View File

@ -0,0 +1,114 @@
import React, { useEffect , useState } from 'react';
import Axios from 'axios';
import { Pagination , Spin , Popconfirm }from 'antd';
import { Link } from 'react-router-dom';
import { getImageUrl } from 'educoder';
import Nodata from '../Nodata';
import { FlexAJ } from '../Component/layout';
const limit = 15;
function Apply(props) {
const username = props.match.params.username;
const [ list , setList ] = useState(undefined);
const [ page , setPage ] = useState(1);
const [ total , setTotal ] = useState(0);
const [ isSpin , setIsSpin ] = useState(true);
useEffect(()=>{
if(username){
setIsSpin(true);
getList();
}
},[username])
function getList() {
const url = `/users/${username}/applied_projects.json`;
Axios.get(url).then(result=>{
if(result){
setList(result.data.applied_projects);
setTotal(result.data.total_count);
setIsSpin(false);
}
}).catch(error=>{})
}
//
function acceptDivert(id){
const url = `/users/${username}/applied_projects/${id}/accept.json`;
Axios.post(url).then(result=>{
if(result && result.data){
getList();
props && props.deleteEvent("apply",1);
}
}).catch(error=>{})
}
//
function revertDivert(id){
const url = `/users/${username}/applied_projects/${id}/refuse.json`;
Axios.post(url).then(result=>{
if(result && result.data){
getList();
props && props.deleteEvent("apply",1);
}
}).catch(error=>{})
}
return(
<div>
<Spin spinning={isSpin}>
<div style={{minHeight:"400px"}}>
{
list && list.length > 0 ?
<ul className="notifyList">
{
list.map((i,k)=>{
return(
<li>
<Link to={`/users/${i.user && i.user.login}`}><img src={getImageUrl(`/${i.user && i.user.image_url}`)} alt="" className="notifyImg"/></Link>
<div className="notifyFlex">
<p className="notifyInfos">
<Link to={`/users/${i.user && i.user.login}`} className="font-15 mr20">{i.user && i.user.name}</Link>
<span className="color-grey-9">{i.time_ago}</span>
</p>
<FlexAJ>
<p>申请以{i.role === "developer" ?"开发者":i.role === "manager" ? "管理者":"报告者"}身份加入{i.project && i.project.name}项目是否同意</p>
{
i.status === "common" &&
<span>
<Popconfirm title={`确定同意${i.user && i.user.name}加入【${i.project && i.project.name}】项目?`} okText="确定" cancelText="取消" onConfirm={()=>acceptDivert(i.id)}>
<a className="color-blue">同意</a>
</Popconfirm>
<Popconfirm title={`确定拒绝${i.user && i.user.name}加入【${i.project && i.project.name}】项目?`} okText="确定" cancelText="取消" onConfirm={()=>revertDivert(i.id)}>
<a className="color-red ml20">拒绝</a>
</Popconfirm>
</span>
}
{
i.status === "accepted" && <span className="color-grey-9">已接受</span>
}
{
i.status === "refused" && <span className="color-grey-9">已拒绝</span>
}
</FlexAJ>
</div>
</li>
)
})
}
</ul>
:
""
}
{list && list.length === 0 && <Nodata _html="暂无成员申请" />}
{
total > limit &&
<div className="edu-txt-center pt20 pb20">
<Pagination simple pageSize={limit} total={total} current={page} onChange={(p)=>{setPage(p)}}/>
</div>
}
</div>
</Spin>
</div>
)
}
export default Apply;

128
src/forge/Notice/Index.jsx Normal file
View File

@ -0,0 +1,128 @@
import React, { useEffect, useState } from "react";
import { Link } from 'react-router-dom';
import './Index.scss';
import Loadable from "react-loadable";
import Loading from "../../Loading";
import { Route, Switch } from "react-router-dom";
const Apply = Loadable({
loader: () => import("./Apply"),
loading: Loading,
});
const Notify = Loadable({
loader: () => import("./Notify"),
loading: Loading,
});
const UndoEvent = Loadable({
loader: () => import("./UndoEvent"),
loading: Loading,
});
function Index(props){
const username = props.match.params.username;
const pathname = props.history.location.pathname;
const user = props.user;
const [ menu , setMenu ] = useState("notify");
const [ messagesCount , setMessagesCount ] = useState(0);
const [ transferCount , setTransferCount ] = useState(0);
const [ applyCount , setApplyCount ] = useState(0);
const [ flag , setFlag ] = useState(true);
const { current_user } = props;
useEffect(()=>{
if((username && current_user && (current_user.login !== username))){
props.history.push(`/users/${username}`);
}
},[current_user,username])
useEffect(()=>{
if(user){
setTransferCount(user.undo_transfer_projects);
setApplyCount(user.undo_join_projects);
setMessagesCount(user.undo_messages);
}
},[user])
useEffect(()=>{
if(pathname && username){
if(pathname === `/users/${username}/notice`){
setMenu("notify");
changeNum(user.undo_messages);
}
if(pathname === `/users/${username}/notice/undo`){
setMenu("undo");
}
if(pathname === `/users/${username}/notice/apply`){
setMenu("apply");
}
}
},[pathname,user])
function changeNum(){
if(flag){
messagesCount && props.deleteUndoEvent(messagesCount);
setFlag(false);
}
}
function deleteEvent(type,count) {
let c = count;
if(type==="apply"){
setTransferCount(transferCount-count);
}else if(type==="undo"){
setApplyCount(applyCount-count);
}else{
setMessagesCount(0);
c = messagesCount;
}
(c || c===0) && props.deleteUndoEvent(c);
}
return (
<div>
<ul className="noticeMenu">
<li className={menu === "notify" ? "active":""}>
<Link to={`/users/${username}/notice`} onClick={changeNum}>
<span>通知</span>
{messagesCount ? <span className="unNum">{messagesCount}</span>:""}
</Link>
</li>
<li className={menu === "undo" ? "active":""}>
<Link to={`/users/${username}/notice/undo`}>
<span>接收仓库</span>
{transferCount ? <span className="unNum">{transferCount}</span>:""}
</Link>
</li>
<li className={menu === "apply" ? "active":""}>
<Link to={`/users/${username}/notice/apply`}>
<span>成员申请</span>
{applyCount ? <span className="unNum">{applyCount}</span>:""}
</Link>
</li>
</ul>
<Switch>
<Route
path="/users/:username/notice/apply"
render={(p) => {
return <Apply {...props} {...p} deleteEvent={deleteEvent}/>;
}}
></Route>
<Route
path="/users/:username/notice/undo"
render={(p) => {
return <UndoEvent {...props} {...p} deleteEvent={deleteEvent}/>;
}}
></Route>
<Route
path="/users/:username/notice"
render={(p) => {
return <Notify {...props} {...p} deleteEvent={deleteEvent}/>;
}}
></Route>
</Switch>
</div>
);
}
export default Index;

View File

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

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