Compare commits

..

21 Commits

Author SHA1 Message Date
jasder 8b4d4dc893 Merge pull request 'sonar质量分析列表增加获取推荐按钮' (#274) from caishi/forgeplus-react:mulanoss_git_server into mulanoss_git_server 2021-11-19 17:22:41 +08:00
caishi 260239b5d2 sonar质量分析列表增加获取推荐按钮 2021-11-19 17:06:07 +08:00
jasder a58188c662 Merge pull request 'sona列表换行显示' (#269) from caishi/forgeplus-react:mulanoss_git_server into mulanoss_git_server 2021-11-19 10:57:52 +08:00
caishi e33443ba72 sonar-内容换行显示 2021-11-19 10:31:08 +08:00
jasder ec5e27e479 Merge pull request 'webhook新建页面增加两个提示弹框' (#268) from caishi/forgeplus-react:mulanoss_git_server into mulanoss_git_server 2021-11-18 11:33:14 +08:00
caishi 09b6fbed6b 弹框 2021-11-18 11:32:01 +08:00
jasder a8d387869d Merge pull request '代码库质量分析tab' (#265) from caishi/forgeplus-react:mulanoss_git_server into mulanoss_git_server 2021-11-18 09:08:20 +08:00
caishi e543987baa 增加代码质量分析页面 2021-11-17 16:46:59 +08:00
jasder 445ba03195 Merge pull request 'merge代码,且增加sonar质量分析块' (#221) from caishi/forgeplus-react:mulanoss_git_server into mulanoss_git_server 2021-10-22 17:15:50 +08:00
caishi ef3ee596f2 木兰-增加sonar质量分析的url显示 2021-10-22 17:11:46 +08:00
caishi 9d58b363df Merge branch 'mulanoss_git_server' of https://git.trustie.net/Gitlink/forgeplus-react into mulanoss_git_server 2021-10-22 16:56:06 +08:00
caishi ca3c935c56 footer 2021-10-22 16:55:46 +08:00
jasder f2085dc596 Merge pull request 'FIX 合并主干分支功能' (#218) from master into mulanoss_git_server 2021-10-22 16:55:36 +08:00
jasder 1871eb7a5a FIX 合并pre_develop分支代码并处理代码冲突 2021-10-18 16:33:39 +08:00
jasder 13376d82bd Merge pull request '木兰社区,merge forge代码,底部信息全由后台配置' (#154) from caishi/forgeplus-react:mulanoss_git_server into mulanoss_git_server 2021-10-13 11:41:45 +08:00
caishi 35de29c677 底部信息 2021-10-13 11:37:14 +08:00
caishi d768761afb Merge branch 'pre_develop_dev' into mulanoss_git_server 2021-10-13 09:59:33 +08:00
jasder 6ce9777095 Merge pull request '登录弹框-注册按钮根据接口返回字段隐藏、显示' (#95) from caishi/forgeplus-react:mulanoss_git_server into mulanoss_git_server 2021-09-30 11:43:09 +08:00
caishi 73e9de5cef 登录弹框-注册按钮根据接口返回字段隐藏、显示 2021-09-30 11:26:27 +08:00
jasder 4d02dff386 Merge pull request '木兰社区第三方登录logo' (#90) from caishi/forgeplus-react:mulanoss_git_server into mulanoss_git_server 2021-09-29 16:18:16 +08:00
caishi efda2132ae 木兰社区-和forge统一,不包含通知系统、资源库等、第三方登录改为木兰 2021-09-29 15:38:07 +08:00
23 changed files with 5519 additions and 4980 deletions

9818
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -187,7 +187,7 @@
"eslintConfig": { "eslintConfig": {
"extends": "react-app" "extends": "react-app"
}, },
"proxy": "http://localhost:3001", "proxy": "http://localhost:3000",
"port": "3007", "port": "3007",
"devDependencies": { "devDependencies": {
"@babel/runtime": "7.0.0-beta.51", "@babel/runtime": "7.0.0-beta.51",

View File

@ -1,4 +1,4 @@
import React, { useState, useCallback, memo } from 'react'; import React, { useState, useCallback, memo, useEffect } from 'react';
import { Tooltip } from 'antd'; import { Tooltip } from 'antd';
CopyTool.defaultProps = { CopyTool.defaultProps = {
@ -10,16 +10,15 @@ CopyTool.defaultProps = {
}; };
function CopyTool({ beforeText, afterText, className , inputId , timeOut }) { function CopyTool({ beforeText, afterText, className , inputId , timeOut , text }) {
const [title, setTitle] = useState(() => { const [title, setTitle] = useState(() => {
return beforeText; return beforeText;
}); });
// //
const copyUrl = useCallback(() => { const copyUrl = useCallback(() => {
const copyEle = document.querySelector(`#${inputId}`); // const copyEle = document.querySelector(`#${inputId}`); //
if (!copyEle) { if (!copyEle) {
console.error("您的CopyTool未设置正确的inputId"); console.error(`您的CopyTool未设置正确的inputId${inputId}`);
return; return;
} }
copyEle.select(); // copyEle.select(); //
@ -37,12 +36,17 @@ function CopyTool({ beforeText, afterText, className , inputId , timeOut }) {
}, []); }, []);
return ( return (
<Tooltip <Tooltip
placement="top" placement="top"
title={title} title={title}
onVisibleChange={() => { setTitle(beforeText) }} onVisibleChange={() => { setTitle(beforeText) }}
> >
<i className={`iconfont icon-fuzhiicon ${className}`} style={{ color: '#466aff' }} onClick={copyUrl}></i> {text?
<a className="color-blue" onClick={copyUrl}>{text}</a>
:
<i className={`iconfont icon-fuzhiicon ${className}`} style={{ color: '#466aff' }} onClick={copyUrl}></i>
}
</Tooltip> </Tooltip>
); );
} }

View File

@ -16,49 +16,11 @@ function Footer(){
var html = {__html:htmlString}; var html = {__html:htmlString};
return <div dangerouslySetInnerHTML={html}></div> ; return <div dangerouslySetInnerHTML={html}></div> ;
} }
return( return(
<div> <div>
<div style={{height:"543px"}}></div> <div style={{height:"543px"}}></div>
<div className="newFooter edu-txt-center"> <div className="newFooter edu-txt-center">
{value && showhtml(value)} {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>
</div> </div>
) )

View File

@ -23,7 +23,6 @@ import Nodata from '../Nodata';
import Invite from './sub/Invite'; import Invite from './sub/Invite';
import CheckProfile from '../Component/ProfileModal/Profile'; import CheckProfile from '../Component/ProfileModal/Profile';
import RenderHtml from '../../components/render-html'; import RenderHtml from '../../components/render-html';
import Badge from "./sub/Badge";
/** /**
* projectDetail.type:0是托管项目1是镜像项目2是同步镜像项目(为2时不支持在线创建在线上传在线修改在线删除创建合并请求等功能) * projectDetail.type:0是托管项目1是镜像项目2是同步镜像项目(为2时不支持在线创建在线上传在线修改在线删除创建合并请求等功能)
*/ */
@ -64,6 +63,7 @@ function CoderDepot(props){
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 [ lesson_url , setLessonUrl ] = useState(undefined);
const [ sonar_url , setSonarUrl ] = useState(undefined);
const [ readme , setReadme ] = useState(undefined); const [ readme , setReadme ] = useState(undefined);
const [ defaultBranch , setDefaultBranch ] = useState(undefined); const [ defaultBranch , setDefaultBranch ] = useState(undefined);
const [ editReadme , setEditReadme ] = useState(false); const [ editReadme , setEditReadme ] = useState(false);
@ -81,12 +81,6 @@ function CoderDepot(props){
const distribution = details && details.type != 2 && (details.permission === "Admin" || details.permission === "Owner" || details.permission === "Manager"); const distribution = details && details.type != 2 && (details.permission === "Admin" || details.permission === "Owner" || details.permission === "Manager");
const { bannerList } = props; const { bannerList } = props;
// test data
const badges = {badge:[{ "login": "many_stars", "image_url": "https://www.gitlink.org.cn/system/lets/letter_avatars/2/J/236_194_58/120.png", "description": "test description1"}, {"login": "many_stars", "image_url": "https://www.gitlink.org.cn/system/lets/letter_avatars/2/X/181_166_38/120.png", "description": "test description2"}], total_count: 3}
console.log(badges.badge)
console.log(badges.total_count)
useEffect(()=>{ useEffect(()=>{
if(bannerList && bannerList.length>0){ if(bannerList && bannerList.length>0){
let a = bannerList.filter(i=>i.menu_name === "pulls"); let a = bannerList.filter(i=>i.menu_name === "pulls");
@ -107,6 +101,7 @@ function CoderDepot(props){
setDesc(details.description); setDesc(details.description);
setWebsite(details.website); setWebsite(details.website);
setLessonUrl(details.lesson_url); setLessonUrl(details.lesson_url);
setSonarUrl(details.sonar_url);
setDefaultBranch(details.default_branch); setDefaultBranch(details.default_branch);
setInviteCode(details.invite_code); setInviteCode(details.invite_code);
} }
@ -145,7 +140,7 @@ function CoderDepot(props){
if(result && result.data){ if(result && result.data){
const release = { const release = {
"list":result.data.releases, "list":result.data.releases,
"total_count":result.data.releases.length "total_count":result.data.releases ? result.data.releases.length :0
} }
setReleaseVersions(release); setReleaseVersions(release);
} }
@ -341,6 +336,7 @@ function CoderDepot(props){
setDesc(result.data.description); setDesc(result.data.description);
setWebsite(result.data.website); setWebsite(result.data.website);
setLessonUrl(result.data.lesson_url); setLessonUrl(result.data.lesson_url);
setSonarUrl(result.data.sonar_url);
} }
}) })
} }
@ -353,7 +349,6 @@ function CoderDepot(props){
const fileOperate = type === "dir" && projectDetail && projectDetail.type !== 2 && ((projectDetail.permission && projectDetail.permission !=="Reporter") || (current_user && current_user.admin)); 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} lesson_url={lesson_url} 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}>
@ -378,7 +373,6 @@ function CoderDepot(props){
} }
<div style={{minHeight:"500px"}}> <div style={{minHeight:"500px"}}>
{ {
projectDetail && projectDetail &&
<Box className="Panels"> <Box className="Panels">
<LongWidth> <LongWidth>
@ -559,19 +553,6 @@ function CoderDepot(props){
<Invite code={inviteCode}/> <Invite code={inviteCode}/>
</div> </div>
} }
{/*{*/}
{/* inviteCode &&*/}
{/* <div>*/}
{/* <Badge code={inviteCode}/>*/}
{/* </div>*/}
{/*}*/}
{/* 徽章 */}
{
badges && badges.total_count >0 &&
<Badge badges={badges} owner={owner} />
}
{ {
lesson_url && lesson_url &&
<div> <div>
@ -580,6 +561,26 @@ function CoderDepot(props){
<a href={lesson_url} target="_blank" className="color-grey-6" style={{textDecoration:"underline",wordBreak:"break-all"}}>{lesson_url}</a> <a href={lesson_url} target="_blank" className="color-grey-6" style={{textDecoration:"underline",wordBreak:"break-all"}}>{lesson_url}</a>
</div> </div>
} }
{/* {
<div>
<Divider />
<p className="font-16 color-ooo">质量分析</p>
{
sonar_url ?
<a href={sonar_url} target="_blank" className="color-grey-6" style={{textDecoration:"underline",wordBreak:"break-all"}}>{sonar_url}</a>
:
<span>
<span>暂时还没有检测结果</span>
{
projectDetail && projectDetail.permission && projectDetail.permission !=="Reporter" ?
<Link to={`/${owner}/${projectsId}/settings/webhooks/new`} className="color-blue ml20">去检测</Link>
:""
}
</span>
}
</div>
} */}
{/* 发布 */} {/* 发布 */}
{ {
releaseVersions && releaseVersions &&

View File

@ -69,7 +69,11 @@ const MergeIndexDetail = Loadable({
loader: () => import('../Merge/merge'), loader: () => import('../Merge/merge'),
loading: Loading, loading: Loading,
}) })
// 代码质量分析
const Sonar = Loadable({
loader: () => import('../Sonar/Index'),
loading: Loading,
})
const CreateMerge = Loadable({ const CreateMerge = Loadable({
loader: () => import('../Merge/CreateMerge'), loader: () => import('../Merge/CreateMerge'),
loading: Loading, loading: Loading,
@ -167,6 +171,8 @@ function checkPathname(projectsId, owner, pathname) {
name = "source" name = "source"
} else if (url.indexOf(`/wiki`) > -1) { } else if (url.indexOf(`/wiki`) > -1) {
name = "wiki" name = "wiki"
} else if (url.indexOf(`/sonar`) > -1) {
name = "sonar"
} }
} }
return name; return name;
@ -772,6 +778,11 @@ class Detail extends Component {
(props) => (<MergeIndexDetail {...this.props} {...props} {...this.state} {...common} />) (props) => (<MergeIndexDetail {...this.props} {...props} {...this.state} {...common} />)
} }
></Route> ></Route>
<Route path="/:owner/:projectsId/sonar"
render={
(props) => (<Sonar {...this.props} {...props} {...this.state} {...common} />)
}
></Route>
<Route path="/:owner/:projectsId/following" <Route path="/:owner/:projectsId/following"
render={ render={
(props) => (<WatchUsers {...this.props} {...props} {...this.state} {...common} />) (props) => (<WatchUsers {...this.props} {...props} {...this.state} {...common} />)

View File

@ -200,26 +200,6 @@
} }
} }
} }
.attrBadge{
padding-top: 12px;
display: flex;
flex-wrap: wrap;
padding-bottom: 2px;
a{
margin: 0px 17px 10px 0px;
img{
border-radius: 50%;
width: 40px;
height: 40px;
}
&:nth-child(5n){
margin-right: 0px;
}
}
}
.progress{ .progress{
display: flex; display: flex;
border-radius: 2px; border-radius: 2px;

View File

@ -228,7 +228,7 @@
li{ li{
text-align: center; text-align: center;
padding:0px; padding:0px;
margin-right: 40px; margin-right: 35px;
display: flex; display: flex;
& > a{ & > a{
position: relative; position: relative;

View File

@ -1,103 +0,0 @@
import React, { useEffect, useState } from 'react';
import { AlignCenter , FlexAJ } from '/home/gitlink/forgeplus/public/react/forgeplus-react/src/forge/Component/layout';
import { Link } from 'react-router-dom';
import { Popover , Spin , Button } from 'antd';
import { getImageUrl } from 'educoder';
import '/home/gitlink/forgeplus/public/react/forgeplus-react/src/forge/Component/Component.scss';
// projectDetail && projectDetail.contributors && projectDetail.contributors.total_count >0 &&
// <Badge contributors={projectDetail.contributors} owner={owner} projectsId={projectsId} />?
function Badge({badges,owner}){
const [ list , setList ]= useState(undefined);
const [ total , setTotal ]= useState(0);
const [ menu , setMenu ] = useState("");
const [ login , setLogin ] = useState(undefined);
const [ badge , setBadge ] = useState(undefined);
useEffect(()=>{
if(badges && badges.total_count>0){
setTotal(badges.total_count);
setList(badges.badge);
}
},[badges])
useEffect(()=>{
setMenusFunc(badge);
},[badge])
function setMenusFunc(data){
if(data){
let ele = (
<AlignCenter>
<Link to={`/${data.login}`}><img src={data.image_url} alt="" className="radius" width="38px" height="38px"/></Link>
<div className="ml10">
<Link to={`/${data.login}`}>{data.name}</Link>
{ data.description && <span className="leftline">{data.description}</span> }
</div>
</AlignCenter>
)
setMenu(ele);
}
}
function setVisibleFunc(flag,l,index){
if(l !== badge){
setBadge(l);
}
var lx = list.concat();
lx.map(i=>i.visible =false);
if(flag){
lx[index].visible = flag;
}
lx.splice();
setList(lx);
}
// {
// "list": [
// {
// "login": "many_stars",
// "image_url": "User",
// "description": "test description"
// },
// {
// "login": "many_stars",
// "image_url": "User",
// "description": "test description"
// }
// ],
// "total_count": 2
// }
return(
<div className="halfs">
<Link to={`/${owner}/badge`} className="font-16 color-ooo hoverA">
<span>徽章</span>
{ badges && badges.total_count > 0 && <span className="infoCount">{badges.total_count}</span>}
</Link>
<div className="attrBadge" onMouseLeave={()=>setVisibleFunc(false)}>
{
total > 0 ?
list.map((item,key)=>{
return(
<Popover content={menu} visible={item.visible} overlayClassName="menuPanels" placement="top">
<Link key={key} to={`/${item.login}`}>
<img src={item.image_url} alt="" onMouseOver={()=>setVisibleFunc(true,item,key)}/>
</Link>
</Popover>
)
})
:""
}
</div>
</div>
)
}
//{getImageUrl(`/${item.image_url}`)}
export default Badge;

View File

@ -128,6 +128,12 @@ function DetailBanner({ history,list , owner , projectsId , isManager , url , pa
) )
}) })
} }
<li className={pathname==="sonar" ? "active" : ""}>
<Link to={{ pathname: `/${owner}/${projectsId}/sonar`, state }}>
<i className={"iconfont icon-banbenicon color-grey-3 mr5 font-14"}></i>
<span>代码质量分析</span>
</Link>
</li>
</ul> </ul>
: :
<Skeleton paragraph={false} active={true}/> <Skeleton paragraph={false} active={true}/>

View File

@ -11,6 +11,8 @@ function turnbar(str){
} }
return str; return str;
} }
const port = window.location.port;
const hostname = window.location.hostname;
class MergeItem extends Component { class MergeItem extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
@ -166,24 +168,17 @@ class MergeItem extends Component {
)} )}
</li> </li>
<li>{item.version || "--"}</li> <li>{item.version || "--"}</li>
<li> <li>
<div <div className="flex1 df" style={{ justifyContent: "center" }}>
className="flex1 df" {item.journals_count ?
style={{ justifyContent: "center" }}
>
{item.journals_count ? (
<Link <Link
className="mr5 color-grey-8" className="mr5 color-grey-8"
to={`/${owner}/${projectsId}/pulls/${item.pull_request_id}`} to={`/${owner}/${projectsId}/pulls/${item.pull_request_id}`}
> >
<i className="iconfont icon-huifu1 font-15 mr5 ver-middle"></i> <i className="iconfont icon-huifu1 font-15 mr5 ver-middle"></i>{item.journals_count}
{item.journals_count} </Link>:""
</Link> }
) : ( {user_admin_or_developer && item.pull_request_status === 0 &&
""
)}
{user_admin_or_developer && item.pull_request_status === 0 ? (
<div <div
className="milepostleft" className="milepostleft"
style={{ style={{
@ -194,7 +189,7 @@ class MergeItem extends Component {
: "none", : "none",
}} }}
> >
<div className="grid-item mr15 color-grey-9"> <div className="grid-item color-grey-9">
<Link <Link
to={`/${owner}/${projectsId}/pulls/${item.pull_request_id}/edit`} to={`/${owner}/${projectsId}/pulls/${item.pull_request_id}/edit`}
className="color-grey-9" className="color-grey-9"
@ -203,11 +198,10 @@ class MergeItem extends Component {
</Link> </Link>
</div> </div>
</div> </div>
) : ( }
""
)}
</div> </div>
</li> </li>
<li style={{width:"50px",textAlign:"left"}}><a className="color-blue" target="_blank" href={`http://106.75.189.31:5000/result?SrcPR=${port ? `${hostname}:${port}`:`https://${hostname}`}/${owner}/${projectsId}/pulls/${item.pull_request_id}/Messagecount`}>查重</a></li>
</ul> </ul>
</div> </div>
); );

View File

@ -382,6 +382,7 @@ class merge extends Component {
</span> </span>
</Dropdown> </Dropdown>
</li> </li>
<li style={{width:"50px"}}></li>
</ul> </ul>
</div> </div>
<div style={{minHeight:"470px"}}> <div style={{minHeight:"470px"}}>

View File

@ -45,19 +45,6 @@
} }
} }
button {
color: #333333;
background: #FAFBFC;
border: 1px solid #D0D0D0;
border-radius: 4px;
height: 32px;
}
button:hover {
background: #F3F4F6;
}
button:active {
background: #EBECF0;
}
.deleteBut{ .deleteBut{
color: #DF0002; color: #DF0002;

View File

@ -88,8 +88,7 @@
background: #FAFCFF; background: #FAFCFF;
border-radius: 4px 4px 0px 0px; border-radius: 4px 4px 0px 0px;
border: 1px solid rgba(42, 97, 255, 0.23); border: 1px solid rgba(42, 97, 255, 0.23);
height: 50px; padding:5px 20px;
padding:0px 20px;
margin-top: 20px; margin-top: 20px;
display: flex; display: flex;
align-items: center; align-items: center;
@ -169,3 +168,18 @@
} }
} }
} }
.checkModalStyle{
.ant-modal-header{
padding:8px 20px;
.ant-modal-title{
text-align: left;
}
}
.ant-modal-close{
top:0px!important;
}
input{
width: 222px;
border:none;
}
}

View File

@ -6,6 +6,7 @@ import axios from 'axios';
import PushHistory from './sub/PushHistory'; import PushHistory from './sub/PushHistory';
import DeleteBox from '../../Component/DeleteModal/Index'; import DeleteBox from '../../Component/DeleteModal/Index';
import './Index.scss'; import './Index.scss';
import CheckModal from './sub/CheckModal';
// ,"issue_assign","issue_label","issue_milestone","issue_comment","issue_only","fork", // ,"issue_assign","issue_label","issue_milestone","issue_comment","issue_only","fork",
//"pull_request_milestone","pull_request_sync","pull_request_comment","repository","pull_request_label" //"pull_request_milestone","pull_request_sync","pull_request_comment","repository","pull_request_label"
@ -21,6 +22,10 @@ function New({ form , match , showNotification , history }) {
const [ data , setData ] = useState(undefined); const [ data , setData ] = useState(undefined);
const [ eventFlag , setEventFlag ] = useState(false); const [ eventFlag , setEventFlag ] = useState(false);
const [ checkVisible , setCheckVisible ] = useState(false);
const [ checkContent , setCheckContent ] = useState(1);
const { getFieldDecorator, validateFields , setFieldsValue } = form; const { getFieldDecorator, validateFields , setFieldsValue } = form;
const { id , owner , projectsId } = match.params; const { id , owner , projectsId } = match.params;
@ -169,8 +174,18 @@ function New({ form , match , showNotification , history }) {
lineHeight: '30px', lineHeight: '30px',
}; };
function OpenCheckModal(params) {
setCheckContent(params);
setCheckVisible(true);
}
return( return(
<div className="newPanel"> <div className="newPanel">
<CheckModal
visible={checkVisible}
content={checkContent}
onCancel={()=>setCheckVisible(false)}
/>
<DeleteBox <DeleteBox
visible={visible} visible={visible}
onCancel={()=>setVisible(false)} onCancel={()=>setVisible(false)}
@ -185,7 +200,12 @@ function New({ form , match , showNotification , history }) {
<span>{id ? "更新" : "添加"}Webhook</span> <span>{id ? "更新" : "添加"}Webhook</span>
</Banner> </Banner>
<div> <div>
<p className="deschead mg"><span>当webhook被触发时我们将向以下URL发送通知包括已选择事件的详细信息更多信息可查阅<a className="color-blue hoverLine" target="_blank" href="https://forum.trustie.net/forums/3408/detail">webhooks指南</a></span></p> <p className="deschead mg">
<span>当webhook被触发时我们将向以下URL发送通知包括已选择事件的详细信息更多信息可查阅
<a className="color-blue hoverLine" target="_blank" href="https://forum.trustie.net/forums/3408/detail">webhooks指南</a>
<br/><a className="color-blue" onClick={()=>OpenCheckModal(1)}>开源敏感词检测服务设置</a><a className="color-blue" onClick={()=>OpenCheckModal(2)}>PR审阅推荐服务设置</a>
</span>
</p>
<Form> <Form>
<input type="password" style={{display:"none"}} /> <input type="password" style={{display:"none"}} />
<Form.Item label="目标URL" colon={false}> <Form.Item label="目标URL" colon={false}>

View File

@ -0,0 +1,53 @@
import React, { useEffect, useState } from 'react';
import { Modal } from 'antd';
import CopyTool from '../../../Component/CopyTool';
function CheckModal({visible,content,onCancel}) {
const [ type ,setType ] = useState(content);
useEffect(()=>{
setType(content);
},[content])
return(
<Modal
visible={visible}
footer={null}
title="提示"
width="480px"
onCancel={onCancel}
closable={true}
className="checkModalStyle"
>
<div>
{
type===1?
<div>
<p style={{fontWeight:"500"}}>如需使用开源敏感词检测云功能请复制以下内容至指定的输入框中</p>
<p>目标URL<input type="text" id="copy_input_check" value={"https://api.learnerhub.net/mulan"} />
<CopyTool afterText="复制成功" inputId="copy_input_check" timeOut={true} text={"复制"}/>
</p>
<p>webhook密钥默认无须密钥</p>
<p>触发webhook选中自定义事件勾选 推送创建合并请求</p>
<p>分支过滤 默认无须修改</p>
</div>
:
<div>
<p style={{fontWeight:"500"}}>如需使用PR审阅推荐云功能请复制以下内容至指定的输入框中</p>
<p>目标URL
<input type="text" id="copy_input_check" style={{width:"160px"}} value={"http://117.50.99.180:80"} />
<CopyTool afterText="复制成功" inputId="copy_input_check" timeOut={true} text={"复制"}/>
</p>
<p>webhook密钥默认无须密钥</p>
<p>触发webhook选中自定义事件勾选 合并请求</p>
<p>分支过滤 默认无须修改</p>
</div>
}
</div>
</Modal>
)
}
export default CheckModal;

149
src/forge/Sonar/Index.jsx Normal file
View File

@ -0,0 +1,149 @@
import React , { useEffect , useState } from 'react';
import { Table , Pagination } from 'antd';
import { Base64 } from 'js-base64';
import moment from 'moment'
import axios from 'axios';
import Nodata from '../Nodata';
import './Index.scss';
import RecommedModal from './sub/RecommedModal';
const limit = 15;
function Index(props) {
const [ page , setPage ] = useState(1);
const [ total , setTotal ] = useState(0);
const [ data , setData ] = useState(undefined);
const [ visible , setVisible ] = useState(false);
const [ content ,setContent ] = useState(undefined);
const { owner , projectsId } = props.match.params;
useEffect(()=>{
getInit();
},[page])
function getInit() {
// MLh8klm46f_ceshi ${owner}_${projectsId}
const url = `https://sonar.learnerhub.net/api/issues/search?componentKeys=${owner}_${projectsId}&s=FILE_LINE&resolved=false&types=BUG&ps=${limit}&facets=owaspTop10%2CsansTop25%2Cseverities%2CsonarsourceSecurity%2Ctypes&additionalFields=_all&timeZone=Asia%2FShanghai&p=${page}`
axios.get(url,{
headers:{Authorization:`Basic ${Base64.encode('ecae161ce05add6121c6263f843c76d79fcd953c:')}`}
}).then(result=>{
if(result){
setData(result.data.issues);
setTotal(result.data.total);
}
}).catch(error=>{})
}
const columns = [
{
title: '文件',
dataIndex: 'component',
key: 'component',
width:"15%",
render:(v,l,i)=>{
const name = l.component && l.component.split(":")[1];
return(
<span>{name}</span>
)
}
},
{
title: '所在起始行',
dataIndex: 'startLine',
key: 'startLine',
align:"center",
width:"9%",
render:(v,l,i)=>{
return(
<span>{l.textRange && l.textRange.startLine}</span>
)
}
},
{
title: '所在结束行',
dataIndex: 'endLine',
key: 'endLine',
align:"center",
width:"9%",
render:(v,l,i)=>{
return(
<span>{l.textRange && l.textRange.endLine}</span>
)
}
},
// {
// title: '',
// dataIndex: 'type',
// align:"center",
// key: 'type',
// width:"8%",
// },
{
title: '问题信息',
dataIndex: 'message',
key: 'message',
width:"40%"
},
{
title: '创建时间',
dataIndex: 'creationDate',
key: 'creationDate',
align:"center",
render:(v,l,i)=>{
return(
<span>{l.creationDate && moment(l.creationDate).format('YYYY-MM-DD HH:mm:ss')}</span>
)
}
},
{
title: '问题修复推荐',
dataIndex: 'recommend',
key: 'recommend',
align:"center",
render:(v,l,i)=>{
return(
<a className="color-blue" onClick={()=>receiveRecommend(l)}>获取推荐</a>
)
}
},
];
function receiveRecommend(l){
// http://ng.learnerhub.net/mulan/repair
// 线 https://api.learnerhub.net/mulan/repair
const url = `https://api.learnerhub.net/mulan/repair`;
axios.get(url,{
params:{
data:l
}
}).then(result=>{
if(result){
setContent(result.data.data && result.data.data.content);
setVisible(true);
}
}).catch(error=>{})
}
return(
<div className="main" style={{padding:"0px"}}>
<RecommedModal visible={visible} content={content} onCancel={()=>setVisible(false)}/>
{
total > 0 ?
<div style={{minHeight:"300px"}}>
<p style={{padding:"12px 20px"}}>一共存在{total}个问题</p>
<Table className="sonarTable" dataSource={data} columns={columns} pagination={false}/>
</div>
:
<Nodata _html="代码质量非常优秀,没有检测到问题存在!" />
}
{
total > limit &&
<div style={{padding:"15px",textAlign:"center"}}>
<Pagination pageSize={limit} current={page} total={total} onChange={(p)=>setPage(p)}/>
</div>
}
</div>
)
}
export default Index

View File

@ -0,0 +1,16 @@
.sonarTable{
.ant-table-thead > tr > th, .ant-table-tbody > tr > td{
padding:10px 12px;
}
}
.recommendbox{
.ant-modal-body{
padding:0px;
padding-bottom: 20px;
div{
height: 620px;
overflow-y: auto;
padding:20px
}
}
}

View File

@ -0,0 +1,23 @@
import { Modal } from 'antd';
import React from 'react';
import '../Index.scss';
function RecommedModal({content,visible,onCancel}){
return(
<Modal
visible={visible}
footer={null}
width="1000px"
closable={true}
onCancel={onCancel}
title="推荐内容"
centered={true}
className="recommendbox"
>
<div>
<pre style={{whiteSpace: "pre-line"}}>{content}</pre>
</div>
</Modal>
)
}
export default RecommedModal;

View File

@ -240,58 +240,3 @@ ul.ant-menu.menuStyle{
} }
} }
} }
.attrBadge{
padding-top: 12px;
display: flex;
flex-wrap: wrap;
padding-bottom: 2px;
a{
margin: 0px 17px 10px 0px;
img{
border-radius: 50%;
width: 40px;
height: 40px;
}
&:nth-child(5n){
margin-right: 0px;
}
}
}
.attrBadge{
padding-top: 12px;
display: flex;
flex-wrap: wrap;
padding-bottom: 2px;
a{
margin: 0px 17px 10px 0px;
img{
border-radius: 50%;
width: 40px;
height: 40px;
}
&:nth-child(5n){
margin-right: 0px;
}
}
}
.infoCount{
display: inline-block;
width: 24px;
text-align: center;
height: 24px;
line-height: 24px;
background-color:rgba(153, 153, 153, 0.13);;
color:#666;
border-radius: 12px;
margin-left: 6px;
font-size: 12px;
}

View File

@ -1,6 +1,6 @@
import React, { Component } from "react"; import React, { Component } from "react";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import { Button, Spin , Menu, Popover } from "antd"; import { Button, Spin , Menu } from "antd";
import FocusButton from "../UsersList/focus_button"; import FocusButton from "../UsersList/focus_button";
import axios from "axios"; import axios from "axios";
@ -13,10 +13,6 @@ import './Index.scss';
import Loadable from "react-loadable"; import Loadable from "react-loadable";
import Loading from "../../Loading"; import Loading from "../../Loading";
import Badge from "../Main/sub/Badge";
//test data
const badges = {badge:[{ "login": "many_stars", "image_url": "https://testforgeplus.trustie.net//system/lets/letter_avatars/2/G/178_217_57/120.png", "description": "test description1"}, {"login": "many_stars", "image_url": "https://testforgeplus.trustie.net//images/avatars/User/36480?t=1686645429", "description": "test description2"}], total_count: 3}
const UpdateInfo = Loadable({ const UpdateInfo = Loadable({
loader: () => import("./Material/Index"), loader: () => import("./Material/Index"),
@ -74,7 +70,6 @@ class Infos extends Component {
}; };
} }
renderPath=(pathname)=>{ renderPath=(pathname)=>{
const { username } = this.props.match.params; const { username } = this.props.match.params;
if(pathname === `/${username}`){ if(pathname === `/${username}`){
@ -135,9 +130,7 @@ class Infos extends Component {
this.setState({ this.setState({
user: result.data, user: result.data,
isSpin: false, isSpin: false,
undo_events:e, undo_events:e
//测试数据
badges : {badge:[1, 2, 3], total_count: 3}
}); });
}) })
.catch((error) => { .catch((error) => {
@ -201,7 +194,7 @@ class Infos extends Component {
render() { render() {
const { current_user } = this.props; const { current_user } = this.props;
const { username } = this.props.match.params; const { username } = this.props.match.params;
const { user, isSpin, route_type , undo_events , menuKey} = this.state; const { user, isSpin, route_type , undo_events , menuKey } = this.state;
return ( return (
<div className="newMain clearfix"> <div className="newMain clearfix">
<Spin spinning={isSpin}> <Spin spinning={isSpin}>
@ -282,35 +275,7 @@ class Infos extends Component {
</div> </div>
:"" :""
} }
</div> </div>
{
badges && badges.total_count >0 &&
<Badge badges={badges} />
}
{/*{*/}
{/* badges && badges.total_count >0 &&*/}
{/* <div className="list-l-Menu text-center">*/}
{/* {*/}
{/* badges.total_count > 0 ? owner={owner} projectsId={projectsId} */}
{/* badges.badge.map((item,key)=>{*/}
{/* return(*/}
{/* <Popover content={menu} visible={item.visible} overlayClassName="menuPanels" placement="top">*/}
{/* <div>*/}
{/* <span>{item}</span>*/}
{/* <img src={getImageUrl(`/${item.image_url}`)} />*/}
{/* </div>*/}
{/* </Popover>*/}
{/* )*/}
{/* })*/}
{/* :""*/}
{/* }*/}
{/* </div>*/}
{/*}*/}
</div> </div>
</div> </div>
<div className="list-right"> <div className="list-right">

View File

@ -5,6 +5,7 @@ import { notification } from 'antd';
import axios from 'axios'; import axios from 'axios';
import educoderLogo from './educoder.png'; import educoderLogo from './educoder.png';
import mulanLogo from './img/mulan.png';
import './LoginDialog.css'; import './LoginDialog.css';
import { broadcastChannelPostMessage } from 'educoder' import { broadcastChannelPostMessage } from 'educoder'
@ -561,8 +562,14 @@ class LoginDialog extends Component {
</span> </span>
<span className="fr"> <span className="fr">
<a onClick={(url) => this.getloginurl(`${settings && settings.common && settings.common.lost_password}`)} className="mr3 color-grey-9">找回密码</a> <a onClick={(url) => this.getloginurl(`${settings && settings.common && settings.common.lost_password}`)} className="mr3 color-grey-9">找回密码</a>
<em className="vertical-line"></em> {
<a onClick={(url) => this.getloginurl(`${settings && settings.common && settings.common.register}`)} className="color-grey-9">注册</a> settings && settings.common && settings.common.register ?
<React.Fragment>
<em className="vertical-line"></em>
<a onClick={(url) => this.getloginurl(`${settings && settings.common && settings.common.register}`)} className="color-grey-9">注册</a>
</React.Fragment>
:""
}
</span> </span>
</p> </p>
{ {
@ -573,7 +580,7 @@ class LoginDialog extends Component {
{settings.third_party.map((item,key)=>{ {settings.third_party.map((item,key)=>{
return( return(
<a href={`${item.url}`}> <a href={`${item.url}`}>
<img src={item.name === "educoder" ? educoderLogo : ""} width="46px" alt={`${item.name}登录`} /> <img src={item.name === "mulan" ? mulanLogo : ""} width="46px" alt={`${item.name}登录`} />
</a> </a>
) )
}) })

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB