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": {
"extends": "react-app"
},
"proxy": "http://localhost:3001",
"proxy": "http://localhost:3000",
"port": "3007",
"devDependencies": {
"@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';
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(() => {
return beforeText;
});
//
const copyUrl = useCallback(() => {
const copyEle = document.querySelector(`#${inputId}`); //
if (!copyEle) {
console.error("您的CopyTool未设置正确的inputId");
console.error(`您的CopyTool未设置正确的inputId${inputId}`);
return;
}
copyEle.select(); //
@ -37,12 +36,17 @@ function CopyTool({ beforeText, afterText, className , inputId , timeOut }) {
}, []);
return (
<Tooltip
placement="top"
title={title}
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>
);
}

View File

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

View File

@ -23,7 +23,6 @@ import Nodata from '../Nodata';
import Invite from './sub/Invite';
import CheckProfile from '../Component/ProfileModal/Profile';
import RenderHtml from '../../components/render-html';
import Badge from "./sub/Badge";
/**
* projectDetail.type:0是托管项目1是镜像项目2是同步镜像项目(为2时不支持在线创建在线上传在线修改在线删除创建合并请求等功能)
*/
@ -64,6 +63,7 @@ function CoderDepot(props){
const [ desc , setDesc ] = useState(undefined);
const [ website , setWebsite ] = useState(undefined);
const [ lesson_url , setLessonUrl ] = useState(undefined);
const [ sonar_url , setSonarUrl ] = useState(undefined);
const [ readme , setReadme ] = useState(undefined);
const [ defaultBranch , setDefaultBranch ] = useState(undefined);
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 { 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(()=>{
if(bannerList && bannerList.length>0){
let a = bannerList.filter(i=>i.menu_name === "pulls");
@ -107,6 +101,7 @@ function CoderDepot(props){
setDesc(details.description);
setWebsite(details.website);
setLessonUrl(details.lesson_url);
setSonarUrl(details.sonar_url);
setDefaultBranch(details.default_branch);
setInviteCode(details.invite_code);
}
@ -145,7 +140,7 @@ function CoderDepot(props){
if(result && result.data){
const release = {
"list":result.data.releases,
"total_count":result.data.releases.length
"total_count":result.data.releases ? result.data.releases.length :0
}
setReleaseVersions(release);
}
@ -341,6 +336,7 @@ function CoderDepot(props){
setDesc(result.data.description);
setWebsite(result.data.website);
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));
return(
<WhiteBack>
<UpdateDescModal desc={desc} website={website} lesson_url={lesson_url} visible={openModal} onCancel={()=>setOpenModal(false)} onOk={okUpdate}/>
<Spin spinning={isSpin}>
@ -377,8 +372,7 @@ function CoderDepot(props){
</React.Fragment>
}
<div style={{minHeight:"500px"}}>
{
{
projectDetail &&
<Box className="Panels">
<LongWidth>
@ -559,19 +553,6 @@ function CoderDepot(props){
<Invite code={inviteCode}/>
</div>
}
{/*{*/}
{/* inviteCode &&*/}
{/* <div>*/}
{/* <Badge code={inviteCode}/>*/}
{/* </div>*/}
{/*}*/}
{/* 徽章 */}
{
badges && badges.total_count >0 &&
<Badge badges={badges} owner={owner} />
}
{
lesson_url &&
<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>
</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 &&

View File

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

View File

@ -228,7 +228,7 @@
li{
text-align: center;
padding:0px;
margin-right: 40px;
margin-right: 35px;
display: flex;
& > a{
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>
:
<Skeleton paragraph={false} active={true}/>

View File

@ -11,6 +11,8 @@ function turnbar(str){
}
return str;
}
const port = window.location.port;
const hostname = window.location.hostname;
class MergeItem extends Component {
constructor(props) {
super(props);
@ -166,24 +168,17 @@ class MergeItem extends Component {
)}
</li>
<li>{item.version || "--"}</li>
<li>
<div
className="flex1 df"
style={{ justifyContent: "center" }}
>
{item.journals_count ? (
<div className="flex1 df" style={{ justifyContent: "center" }}>
{item.journals_count ?
<Link
className="mr5 color-grey-8"
to={`/${owner}/${projectsId}/pulls/${item.pull_request_id}`}
>
<i className="iconfont icon-huifu1 font-15 mr5 ver-middle"></i>
{item.journals_count}
</Link>
) : (
""
)}
{user_admin_or_developer && item.pull_request_status === 0 ? (
<i className="iconfont icon-huifu1 font-15 mr5 ver-middle"></i>{item.journals_count}
</Link>:""
}
{user_admin_or_developer && item.pull_request_status === 0 &&
<div
className="milepostleft"
style={{
@ -194,7 +189,7 @@ class MergeItem extends Component {
: "none",
}}
>
<div className="grid-item mr15 color-grey-9">
<div className="grid-item color-grey-9">
<Link
to={`/${owner}/${projectsId}/pulls/${item.pull_request_id}/edit`}
className="color-grey-9"
@ -203,11 +198,10 @@ class MergeItem extends Component {
</Link>
</div>
</div>
) : (
""
)}
}
</div>
</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>
</div>
);

View File

@ -382,6 +382,7 @@ class merge extends Component {
</span>
</Dropdown>
</li>
<li style={{width:"50px"}}></li>
</ul>
</div>
<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{
color: #DF0002;

View File

@ -88,8 +88,7 @@
background: #FAFCFF;
border-radius: 4px 4px 0px 0px;
border: 1px solid rgba(42, 97, 255, 0.23);
height: 50px;
padding:0px 20px;
padding:5px 20px;
margin-top: 20px;
display: flex;
align-items: center;
@ -168,4 +167,19 @@
}
}
}
}
.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 DeleteBox from '../../Component/DeleteModal/Index';
import './Index.scss';
import CheckModal from './sub/CheckModal';
// ,"issue_assign","issue_label","issue_milestone","issue_comment","issue_only","fork",
//"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 [ eventFlag , setEventFlag ] = useState(false);
const [ checkVisible , setCheckVisible ] = useState(false);
const [ checkContent , setCheckContent ] = useState(1);
const { getFieldDecorator, validateFields , setFieldsValue } = form;
const { id , owner , projectsId } = match.params;
@ -169,8 +174,18 @@ function New({ form , match , showNotification , history }) {
lineHeight: '30px',
};
function OpenCheckModal(params) {
setCheckContent(params);
setCheckVisible(true);
}
return(
<div className="newPanel">
<CheckModal
visible={checkVisible}
content={checkContent}
onCancel={()=>setCheckVisible(false)}
/>
<DeleteBox
visible={visible}
onCancel={()=>setVisible(false)}
@ -185,7 +200,12 @@ function New({ form , match , showNotification , history }) {
<span>{id ? "更新" : "添加"}Webhook</span>
</Banner>
<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>
<input type="password" style={{display:"none"}} />
<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

@ -239,59 +239,4 @@ ul.ant-menu.menuStyle{
content:"";
}
}
}
.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 { 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 axios from "axios";
@ -13,10 +13,6 @@ import './Index.scss';
import Loadable from "react-loadable";
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({
loader: () => import("./Material/Index"),
@ -74,7 +70,6 @@ class Infos extends Component {
};
}
renderPath=(pathname)=>{
const { username } = this.props.match.params;
if(pathname === `/${username}`){
@ -135,9 +130,7 @@ class Infos extends Component {
this.setState({
user: result.data,
isSpin: false,
undo_events:e,
//测试数据
badges : {badge:[1, 2, 3], total_count: 3}
undo_events:e
});
})
.catch((error) => {
@ -201,7 +194,7 @@ class Infos extends Component {
render() {
const { current_user } = this.props;
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 (
<div className="newMain clearfix">
<Spin spinning={isSpin}>
@ -282,35 +275,7 @@ class Infos extends Component {
</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 className="list-right">

View File

@ -5,6 +5,7 @@ import { notification } from 'antd';
import axios from 'axios';
import educoderLogo from './educoder.png';
import mulanLogo from './img/mulan.png';
import './LoginDialog.css';
import { broadcastChannelPostMessage } from 'educoder'
@ -561,8 +562,14 @@ class LoginDialog extends Component {
</span>
<span className="fr">
<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>
</p>
{
@ -573,7 +580,7 @@ class LoginDialog extends Component {
{settings.third_party.map((item,key)=>{
return(
<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>
)
})

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB