diff --git a/public/css/edu-purge.css b/public/css/edu-purge.css index 14ac4a7e..80680009 100644 --- a/public/css/edu-purge.css +++ b/public/css/edu-purge.css @@ -1,4 +1,5 @@ @charset "utf-8"; + /* 头部 */ .header { width: 100%; diff --git a/public/images/loading@2x.fispool b/public/images/loading@2x.fispool new file mode 100644 index 00000000..4fb8f34a Binary files /dev/null and b/public/images/loading@2x.fispool differ diff --git a/public/images/loading@2x.gif b/public/images/loading@2x.gif index bcc021eb..4fb8f34a 100755 Binary files a/public/images/loading@2x.gif and b/public/images/loading@2x.gif differ diff --git a/src/forge/Merge/merge.css b/src/forge/Merge/merge.css index d467300a..a468635e 100644 --- a/src/forge/Merge/merge.css +++ b/src/forge/Merge/merge.css @@ -198,6 +198,12 @@ form .ant-cascader-picker, form .ant-select { .linesContent .lines > span:first-child{ margin-right: 0px; } +.linesContent .lines,.linesContent .linetype,.no-select,.filesInfo{ + -webkit-user-select: none; /* Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE/Edge */ + user-select: none; /* 标准语法 */ +} .linesContent .lines > span{ width: 50%; text-align: right; diff --git a/src/forge/Server/Index.jsx b/src/forge/Server/Index.jsx index 9a6f57e4..63c7ae1d 100644 --- a/src/forge/Server/Index.jsx +++ b/src/forge/Server/Index.jsx @@ -23,6 +23,15 @@ const Pages = Loadable({ loader: () => import('./pages'), loading: Loading, }) +// 开源度量工具 +const Measurement = Loadable({ + loader: () => import('./measurement'), + loading: Loading, +}) +const MeasurementDetail = Loadable({ + loader: () => import('./measurement/dimension'), + loading: Loading, +}) function ServerIndex(props){ const { projectDetail } = props; const { owner , projectsId } = props.match.params; @@ -37,11 +46,21 @@ function ServerIndex(props){ return(
+ () + } + > () } > + () + } + > () diff --git a/src/forge/Server/List.jsx b/src/forge/Server/List.jsx index 5dc33711..212f989f 100644 --- a/src/forge/Server/List.jsx +++ b/src/forge/Server/List.jsx @@ -8,6 +8,7 @@ function Main(props){ const [ has_trace_user , setHas_trace_user ] = useState(false); const { current_user , resetUserInfo, projectDetail, showNotification, isDeveloper, isManager, isReporter } = props; + const privateStatus = projectDetail && projectDetail.private; useEffect(()=>{ // 更新网页标题 @@ -79,6 +80,19 @@ function Main(props){ 查看详情 } + { + !privateStatus && +
  • + + + 开源软件健康度量服务 + +

    支持项目健康度量分析一键生成,协助维护项目健康生态

    + + 查看详情 + +
  • + }
    ) diff --git a/src/forge/Server/img/back.png b/src/forge/Server/img/back.png new file mode 100644 index 00000000..7b7917b4 Binary files /dev/null and b/src/forge/Server/img/back.png differ diff --git a/src/forge/Server/img/blue-large.png b/src/forge/Server/img/blue-large.png new file mode 100644 index 00000000..f4d74274 Binary files /dev/null and b/src/forge/Server/img/blue-large.png differ diff --git a/src/forge/Server/img/blue.png b/src/forge/Server/img/blue.png new file mode 100644 index 00000000..396530a9 Binary files /dev/null and b/src/forge/Server/img/blue.png differ diff --git a/src/forge/Server/img/echartBack.png b/src/forge/Server/img/echartBack.png new file mode 100644 index 00000000..bd3120f7 Binary files /dev/null and b/src/forge/Server/img/echartBack.png differ diff --git a/src/forge/Server/img/index.png b/src/forge/Server/img/index.png new file mode 100644 index 00000000..833b826e Binary files /dev/null and b/src/forge/Server/img/index.png differ diff --git a/src/forge/Server/img/large.png b/src/forge/Server/img/large.png new file mode 100644 index 00000000..192a3dc6 Binary files /dev/null and b/src/forge/Server/img/large.png differ diff --git a/src/forge/Server/img/logo4.png b/src/forge/Server/img/logo4.png new file mode 100644 index 00000000..690316cb Binary files /dev/null and b/src/forge/Server/img/logo4.png differ diff --git a/src/forge/Server/img/middle.png b/src/forge/Server/img/middle.png new file mode 100644 index 00000000..e815a83a Binary files /dev/null and b/src/forge/Server/img/middle.png differ diff --git a/src/forge/Server/img/person.png b/src/forge/Server/img/person.png new file mode 100644 index 00000000..525a3ed2 Binary files /dev/null and b/src/forge/Server/img/person.png differ diff --git a/src/forge/Server/img/small.png b/src/forge/Server/img/small.png new file mode 100644 index 00000000..d55ae6d9 Binary files /dev/null and b/src/forge/Server/img/small.png differ diff --git a/src/forge/Server/img/team.png b/src/forge/Server/img/team.png new file mode 100644 index 00000000..417490ba Binary files /dev/null and b/src/forge/Server/img/team.png differ diff --git a/src/forge/Server/img/trans.png b/src/forge/Server/img/trans.png new file mode 100644 index 00000000..6686c06b Binary files /dev/null and b/src/forge/Server/img/trans.png differ diff --git a/src/forge/Server/img/trans1.png b/src/forge/Server/img/trans1.png new file mode 100644 index 00000000..818cfff9 Binary files /dev/null and b/src/forge/Server/img/trans1.png differ diff --git a/src/forge/Server/img/true.png b/src/forge/Server/img/true.png new file mode 100644 index 00000000..2c554e28 Binary files /dev/null and b/src/forge/Server/img/true.png differ diff --git a/src/forge/Server/index.scss b/src/forge/Server/index.scss index ab9749df..4b8b2018 100644 --- a/src/forge/Server/index.scss +++ b/src/forge/Server/index.scss @@ -461,4 +461,35 @@ .timeBox{ color: rgba(70, 106, 255, 1) } +} +.nullStoreBox{ + background-color:#fafcff; + border-radius:4px 4px 0px 0px; + text-align: center; + color:#333333; + padding-bottom: 65px; + .loBox{width: 68px;} + .introBox{ + color:#666666; + width: 57%; + margin: 15px auto; + word-break: break-all; + } + .borBox{ + width: 45%; + margin: 0 auto 20px; + border-bottom: 1px solid rgba(90, 117, 193, 0.23); + } +} +.headBox{ + height:60px; + line-height: 60px; + background-color:#fafcff; + border:1px solid rgba(42, 97, 255, 0.23); + border-radius:3px 3px 0px 0px; + color:#333333; + position: relative; + em{ + font-family: YouSheBiaoTiHei; + } } \ No newline at end of file diff --git a/src/forge/Server/measurement/componet/companyData.jsx b/src/forge/Server/measurement/componet/companyData.jsx new file mode 100644 index 00000000..0f8f32a7 --- /dev/null +++ b/src/forge/Server/measurement/componet/companyData.jsx @@ -0,0 +1,169 @@ +import React, { useEffect, useState } from 'react'; +import StackImg from './stackImg'; +import Pie from './pie'; +import { Select } from 'antd'; +import Nodata from '../../../Nodata'; + +function CompanyData({ data }){ + + + const [ keys , setKeys ] = useState([]); + const [ values , setValues ] = useState([]); + const [ userDrop , setUserDrop ] = useState([]); + const [ userValue , setUserValue ] = useState([]); + + + const [ c1keys , setC1Keys ] = useState([]); + const [ c1values , setC1Values ] = useState([]); + const [ c1userDrop , setC1UserDrop ] = useState([]); + const [ c1userValue , setC1UserValue ] = useState([]); + + const [ c3keys , setC3Keys ] = useState([]); + const [ c3values , setC3Values ] = useState([]); + const [ c3userDrop , setC3UserDrop ] = useState([]); + const [ c3userValue , setC3UserValue ] = useState([]); + + const [ pieValues , setPieValues ] = useState([]); + + + const { c1 ,c2,c3,c4 } = data; + + + useEffect(()=>{ + if(c1 && c1.length > 0){ + const values = Array.from(new Set(c1.map(i => i.Module || ""))); + setC1UserDrop(values); + setC1UserValue(values[0]); + } + },[c1]) + + useEffect(()=>{ + if(c1userValue && c1 && c1.length > 0){ + let fil = c1.filter(i=> i.Module === c1userValue); + const companyArray = Array.from(new Set(fil.map(i => i.Company))); + let monthList = fil.map(obj => obj.Month); + let valueList = fil.map(obj => obj['Weight Ratio']); + setC1Keys(monthList); + if(companyArray && companyArray.length>0 && fil.length>0){ + const arr = companyArray.map(item=>{ + let v = fil.filter(i=> i.Company == item); + let valueList = v.map(obj => obj['Weight Ratio']); + return {name :item , type: 'line',stack: 'Total',data:valueList} + }) + setC1Values(arr); + }else{ + setC1Values(valueList); + } + } + },[c1,c1userValue]) + + + useEffect(()=>{ + if(c2 && c2.length > 0){ + const values = Array.from(new Set(c2.map(i => i.Company || ""))); + setUserDrop(values); + setUserValue(values[0]); + } + },[c2]) + + useEffect(()=>{ + if(userValue && c2 && c2.length > 0){ + let fil = c2.filter(i=>i.Company === userValue); + let monthList = fil.map(obj => obj.Month); + let valueList = fil.map(obj => obj['Total Weight']); + setKeys(monthList); + setValues(valueList); + } + },[c2,userValue]) + + + useEffect(()=>{ + if(c3 && c3.length > 0){ + const values = Array.from(new Set(c3.map(i => i.Company || ""))); + setC3UserDrop(values); + setC3UserValue(values[0]); + } + },[c3]) + useEffect(()=>{ + if(c3userValue && c3 && c3.length > 0){ + let fil = c3.filter(i=>i.Company === c3userValue); + let monthList = fil.map(obj => obj.Month); + let valueList = fil.map(obj => parseInt(obj['Percentage'])); + setC3Keys(monthList); + setC3Values(valueList); + } + },[c3,c3userValue]) + + + useEffect(()=>{ + if(c4 && c4.length > 0){ + let pieValues = c4.map(i=>{return {name:i['Company'],value:i["Commit Count"]}}); + setPieValues(pieValues) + } + },[c4]) + + return( + (!c1 && !c2 && !c3 && !c4) ?
    +
    + { + c1userValue && c1userDrop && c1userDrop.length>0 && +
    + 公司名: + +
    + } + +
    +
    + { + userValue && userDrop && userDrop.length>0 && +
    + 公司名: + +
    + } + +
    +
    + { + c3userValue && c3userDrop && c3userDrop.length>0 && +
    + 公司名: + +
    + } + +
    +
    + +
    +
    + : + + ) +} +export default CompanyData; \ No newline at end of file diff --git a/src/forge/Server/measurement/componet/dataStack.jsx b/src/forge/Server/measurement/componet/dataStack.jsx new file mode 100644 index 00000000..e68a70db --- /dev/null +++ b/src/forge/Server/measurement/componet/dataStack.jsx @@ -0,0 +1,51 @@ +import React, { useEffect, useState } from 'react'; +import StackImg from './stackImg'; +import { Select } from 'antd'; + +function DataStack({ data }){ + const [ keys , setKeys ] = useState([]); + const [ values , setValues ] = useState([]); + + + const [ userDrop , setUserDrop ] = useState([]); + const [ userValue , setUserValue ] = useState([]); + useEffect(()=>{ + if(data){ + let drop = Object.keys(data); + setUserDrop(drop); + setUserValue(drop[0]); + } + },[data]) + + useEffect(()=>{ + if(data && userValue){ + let arr = data[userValue]; + let ks = arr && Object.keys(arr); + let vs = arr && Object.values(arr); + setKeys(ks); + setValues(vs); + } + },[data,userValue]) + + return( +
    + { + userValue && userDrop && userDrop.length>0 && +
    + 公司名: + +
    + } + +
    + ) +} +export default DataStack; \ No newline at end of file diff --git a/src/forge/Server/measurement/componet/indicator.jsx b/src/forge/Server/measurement/componet/indicator.jsx new file mode 100644 index 00000000..325ca238 --- /dev/null +++ b/src/forge/Server/measurement/componet/indicator.jsx @@ -0,0 +1,54 @@ +import React, { useEffect , useState } from 'react'; +import { Table } from 'antd'; +import { Link } from 'react-router-dom'; +import "../index.scss"; +import { fieldData , thirdData , subField } from '../config'; + +function Indicator({owner , projectsId , data , subCardIndex}){ + const [ dataSource , setDataSource ] = useState([]); + + + useEffect(()=>{ + if(data && data.length > 0 && subCardIndex){ + let name = thirdData[subField[subCardIndex]]; + let s = data.filter(i=>name.includes(i.name)); + setDataSource(s); + } + },[subCardIndex,data]) + + const column = [ + { + title: "指标名称", + dataIndex: "name", + render:(value)=>{ + return( + (value !=="branchNum" && value !== "browseNum") ? + {fieldData[value]} + : + {fieldData[value]} + ) + // return fieldData[value] + } + }, + { + title: "度量得分", + dataIndex: "InitialScore", + align:"center", + render:(v)=>{ + return `${Math.round(v)}` + } + }, + { + title: "权重占比", + align:"center", + dataIndex: "Weight", + render:(v)=>{ + return `${v ? parseFloat(v*100).toFixed(1) : 0}%` + } + }, + ] + return( + + ) +} +export default Indicator; \ No newline at end of file diff --git a/src/forge/Server/measurement/componet/pie.jsx b/src/forge/Server/measurement/componet/pie.jsx new file mode 100644 index 00000000..fc333e71 --- /dev/null +++ b/src/forge/Server/measurement/componet/pie.jsx @@ -0,0 +1,62 @@ +import React, { useEffect, useState } from 'react'; +import * as echarts from 'echarts'; +// title:公司总提交数 +function Pie({values,title}){ + useEffect(()=>{ + if(values && values.length>0){ + Init(values) + } + },[values]) + + function Init(data){ + var huan_val = document.getElementById("Pie"); + var myEcharts = echarts.init(huan_val); + let option = { + title: { + text: title || "", + left: 20, + top:20 + }, + tooltip: { + trigger: 'item' + }, + color:['#5871FF',"#FFBE38","#00bf9a"], + legend: { + orient: 'horizontal', + right: 20, + top:20, + formatter: function (name) { + // 查找对应系列的值 + var data = option.series[0].data; + for (var i = 0; i < data.length; i++) { + if (data[i].name == name) { + return data[i].value === 0 ? name + ' (0)' : name; + } + } + return name; + } + }, + series: [ + { + name: '', + type: 'pie', + radius: '50%', + data: data, + emphasis: { + itemStyle: { + shadowBlur: 10, + shadowOffsetX: 0, + shadowColor: 'rgba(0, 0, 0, 0.5)' + } + }, + center: ['50%', '60%'] + } + ] + }; + myEcharts.setOption(option); + } + return( +
    + ) +} +export default Pie; \ No newline at end of file diff --git a/src/forge/Server/measurement/componet/radar.jsx b/src/forge/Server/measurement/componet/radar.jsx new file mode 100644 index 00000000..640f4e4d --- /dev/null +++ b/src/forge/Server/measurement/componet/radar.jsx @@ -0,0 +1,82 @@ +import React, { useEffect , useState } from 'react'; +import * as echarts from 'echarts'; +import { fieldData } from '../config'; + +function Radar({data, subCardIndex}){ + const [ values , setValues ] = useState([]); + const [ titles , setTitles ] = useState([]); + + + useEffect(()=>{ + if(data && data.length > 0 && subCardIndex){ + let d = [...data]; + let v = []; + d = d.map(i=>{ + v = v.concat(i.InitialScore) + return {name:fieldData[i.name],max:100} + }) + setValues(v); + setTitles(d); + } + },[subCardIndex,data]) + + + useEffect(()=>{ + if(titles && values && values.length>0 &&titles.length>0) + Init(); + },[values,titles]) + + function Init(){ + var huan_val = document.getElementById("radar"); + var myEcharts = echarts.init(huan_val); + let option = { + tooltip: { + trigger: 'item' + }, + title: { + text: '' + }, + color:['#5871FF',"#FFBE38"], + radar: { + // shape: 'circle', + indicator: titles, + radius:'50%', + // splitLine:{ + // lineStyle:{ + // color:'#11B0D3', + // opacity: 0.2 + // }, + // }, + // axisLine:{ + // lineStyle:{ + // color:'#11B0D3', + // opacity: 0.2 + // }, + // }, + // splitArea:{ + // areaStyle:{ + // color: 'none', + // } + // }, + nameGap: 3, + }, + series: [ + { + name: '', + type: 'radar', + data: [ + { + value: values, + name: '' + } + ] + } + ] + }; + myEcharts.setOption(option); + } + return( +
    + ) +} +export default Radar; \ No newline at end of file diff --git a/src/forge/Server/measurement/componet/stack.jsx b/src/forge/Server/measurement/componet/stack.jsx new file mode 100644 index 00000000..fd9edcf0 --- /dev/null +++ b/src/forge/Server/measurement/componet/stack.jsx @@ -0,0 +1,140 @@ +import React, { useEffect, useState } from 'react'; +import * as echarts from 'echarts'; +import { detailByName } from '../config'; +import Pie from './pie'; +import { Select } from 'antd'; + +function Stack({name,data , type , pieData}){ + const [ obj , setObj ] = useState({}); + const [ list , setList ] = useState(data); + + const [ userDrop , setUserDrop ] = useState([]); + const [ userValue , setUserValue ] = useState([]); + + const [pieEchartData,setPieEchartData] = useState([]); + + useEffect(()=>{ + if(name){ + let obj = detailByName[name.replace(/\s/g, '')]; + setObj(obj); + } + },[name]) + + useEffect(()=>{ + if(data && data.length > 0){ + if(obj && obj.user_login){ + const values = Array.from(new Set(data.map(i => i.user_login || ""))); + setUserDrop(values); + setUserValue(values[0]); + }else{ + setList(data); + } + } + },[data,obj && obj.user_login]) + + useEffect(()=>{ + if(userValue){ + let valueData = data && data.filter(i=>i.user_login === userValue); + setList(valueData); + } + },[userValue]) + + useEffect(()=>{ + if(list && list.length > 0){ + let values = []; + const monthList = list.map(obj => obj.month); + values = list.map(obj => Math.round(obj[type] || obj["count"] || obj['commits_number'] || 0)); + Init(monthList,values); + } + },[list]) + + function Init(x,values){ + var huan_val = document.getElementById("line"); + var myEcharts = echarts.init(huan_val); + let option = { + title: { + text: '' + }, + tooltip: { + trigger: 'axis' + }, + color:['#5871FF',"#FFBE38"], + // legend: { + // data: ['Email', 'Union Ads'] + // }, + grid: { + left: '3%', + right: '4%', + bottom: '3%', + containLabel: true + }, + // toolbox: { + // feature: { + // saveAsImage: {} + // } + // }, + xAxis: { + type: 'category', + boundaryGap: false, + data: x + }, + yAxis: { + type: 'value' + }, + series: [ + { + name: name, + type: 'line', + stack: 'Total', + data: values + } + ] + }; + myEcharts.setOption(option); + } + + useEffect(()=>{ + if(pieData){ + let newData = new Array; + for (var i in pieData) { + var json = {}; + if (pieData[i] != "") { + json.name = i; + json.value = pieData[i]; + newData.push(json); + } + } + setPieEchartData(newData) + } + },[pieData]) + + return( +
    +
    + { + obj && obj.user_login && userValue && userDrop && userDrop.length>0 && +
    + 贡献者: + +
    + } +
    +
    + { + pieData && +
    + +
    + } +
    + ) +} +export default Stack; \ No newline at end of file diff --git a/src/forge/Server/measurement/componet/stackImg.jsx b/src/forge/Server/measurement/componet/stackImg.jsx new file mode 100644 index 00000000..89210718 --- /dev/null +++ b/src/forge/Server/measurement/componet/stackImg.jsx @@ -0,0 +1,58 @@ +import React, { useEffect, useState } from 'react'; +import * as echarts from 'echarts'; + +function StackImg({x,values,title,id}){ + useEffect(()=>{ + if(x && values && x.length>0 && values.length>0 && id){ + Init(x,values) + } + },[x,values,id]) + + function Init(xData,data){ + var huan_val = document.getElementById(id); + var myEcharts = echarts.init(huan_val); + let option = { + title: { + text: title || '', + textStyle:{ + fontSize: 17 , + fontWeight: 'normal', + }, + left:20, + top:15 + }, + tooltip: { + trigger: 'axis' + }, + color:['#5871FF',"#FFBE38"], + // legend: { + // data: ['Email', 'Union Ads'] + // }, + grid: { + left: '3%', + right: '4%', + bottom: '3%', + containLabel: true + }, + // toolbox: { + // feature: { + // saveAsImage: {} + // } + // }, + xAxis: { + type: 'category', + boundaryGap: false, + data: xData + }, + yAxis: { + type: 'value' + }, + series: data + }; + myEcharts.setOption(option); + } + return( +
    + ) +} +export default StackImg; \ No newline at end of file diff --git a/src/forge/Server/measurement/config.js b/src/forge/Server/measurement/config.js new file mode 100644 index 00000000..cfd2f8a4 --- /dev/null +++ b/src/forge/Server/measurement/config.js @@ -0,0 +1,83 @@ +export const firstData = ['开发活动', '社区协作','项目影响'] +export const secondData = { + 开发活动:["开发质量","开发效率"], + 社区协作:['个体开发者','商业公司'], + 项目影响:["项目影响"] +} +export const field={ + 社区协作:"communityCooperation", + 开发活动:"developmentActivity", + 项目影响:"influence" +} +export const subField={ + 开发质量:"developmentQuality", + 开发效率:"developmentEfficiency", + 个体开发者:"individual", + 商业公司:"company", + 项目影响:"influence" +} +export const thirdData = { + developmentEfficiency:["PRNum","PRTime","commitNum","issueTime","ProjectActivity"], + developmentQuality:["commitMessageQuality","issueNum"], + individual:["individualLoss","individualNum","longTermIndividualNum"], + company:["companyLead","companyLoss","companyNum","longTermCompanyNum"], + influence:["branchNum","browseNum","forkNum","praiseNum","storeNum"] +} +export const fieldData = { + PRNum:"PR数量", + PRTime:"PR处理间隔", + commitNum:"Commit数量", + issueTime:"Issue处理间隔", + commitMessageQuality:"Commit message质量", + issueNum:"Issue数量", + ProjectActivity:"项目活跃度", + individualLoss:"长期贡献者稳定性", + individualNum:"活跃开发者占比", + longTermIndividualNum:"长期贡献者占比", + companyLead:"公司主导", + companyLoss:"公司贡献者流失预测", + companyNum:"公司贡献者数量", + longTermCompanyNum:"长期公司贡献者数量", + + browseNum:"浏览次数", + forkNum:"Fork次数", + praiseNum:"点赞次数", + storeNum:"关注数量",//followNum + branchNum:"分支数量" +} + +export const detailByName={ + Commitmessage质量:{desc:"可以通过每月新增Poor Message数量和Commit Message质量分布这两个维度对Commit message质量进行度量",radar:true}, + Issue数量:{desc:"通过分析项目每月提交的Issue数量对Issue数量指标进行度量"}, + Commit数量:{desc:"通过分析项目每月提交的三种Commit数量对Commit数量指标进行度量"}, + PR数量:{desc:"通过分析项目每月提交的PR数量对PR数量指标进行度量"}, + PR处理间隔:{desc:"通过分析每个月新增PR的平均处理间隔对PR处理间隔(小时)指标进行度量"}, + Issue处理间隔:{desc:"通过分析每个月新增Issue的平均处理间隔对Issue处理间隔(小时)指标进行度量"}, + + 活跃开发者占比:{desc:"通过分析每个月活跃的个体贡献者数量对个体贡献者数量指标进行度量",descTitle:"个体贡献者数量"},//个体贡献者数量 + 项目活跃度:{desc:"不同类型的贡献者每月/周给master分支的贡献次数",month:true,user_login:true,descTitle:"所有个体开发者贡献历史"},//所有个体开发者贡献历史 + 长期贡献者占比:{desc:"通过分析每个月活跃的长期个体贡献者数量对长期个体贡献者数量指标进行度量",descTitle:"长期个体贡献者数量"},//长期个体贡献者数量 + 长期贡献者稳定性:{desc:"通过分析具体的即将流失的长期贡献者流失概率对个体贡献者流失预测指标进行度量",bar:true,descTitle:"个体贡献者流失预测"},//个体贡献者流失预测 + + 公司贡献者数量:{desc:"通过分析每月做出了贡献的公司贡献者数量对公司贡献者数量指标进行度量"}, + 长期公司贡献者数量:{desc:"通过分析每月的长期对项目做出贡献的公司贡献者数量对长期公司贡献者数量指标进行度量"}, + 公司主导:{desc:"从每月公司贡献占比、每月公司总贡献、每月公司贡献最高模块中总贡献、公司总提交数四个方面对公司主导指标进行度量",radar:true}, + 公司贡献者流失预测:{desc:"通过分析各个公司的流失概率对公司贡献者流失预测指标进行度量"}, + + 浏览次数:{desc:"通过分析每月项目的浏览次数对浏览次数指标进行度量"}, + 点赞次数:{desc:"通过分析每月项目的点赞次数对点赞次数指标进行度量"}, + 关注数量:{desc:"通过分析每月项目的关注数量对关注数量指标进行度量"}, + 分支数量:{desc:"通过分析每月项目的分支数量对分支数量指标进行度量"}, + Fork次数:{desc:"通过分析每月项目的新增Fork数量对Fork数量指标进行度量"}, +} + +export const scoreComp = (score)=>{ + let value = Math.round(score); + return = 80 ? "#466aff" : (value<80 && value>=60) ? "#E18419" :"#F70202"}}>{value} +} + +export const colorsField={ + 社区协作:"#F58400", + 开发活动:"#466AFF", + 项目影响:"#00BF9A" +} \ No newline at end of file diff --git a/src/forge/Server/measurement/dimension.jsx b/src/forge/Server/measurement/dimension.jsx new file mode 100644 index 00000000..719c1f99 --- /dev/null +++ b/src/forge/Server/measurement/dimension.jsx @@ -0,0 +1,152 @@ +import React ,{useEffect, useState} from 'react'; +import { Breadcrumb , Select } from 'antd'; +import { Link } from 'react-router-dom'; +import "./index.scss"; +import LineStack from './componet/stack'; +import DataStack from './componet/dataStack'; +import CompanyData from './componet/companyData'; +import { detailByName , secondData , thirdData , subField ,fieldData , scoreComp} from './config'; +import axios from 'axios'; +import Nodata from '../../Nodata'; + +const dimensionData = { + 开发质量: ['Commit message质量', 'Issue数量'], + 开发效率: ['PR数量', 'PR处理间隔', 'Commit数量', 'Issue处理间隔','项目活跃度'], + 个体开发者:['活跃开发者占比','长期贡献者占比','长期贡献者稳定性'], + 商业公司:['公司主导','公司贡献者流失预测','公司贡献者数量','长期公司贡献者数量'], + 项目影响:['Fork次数','点赞次数','关注数量']//'分支数量','浏览次数', +}; + +function Dimension(props){ + const { type , owner , projectsId } = props.match.params; + const [ data , setData ] = useState([]); + const [ pieData , setPieData ] = useState([]); + const [ score , setScore ] = useState(0); + + const [title, setTitle] = useState(''); + + const [seconds, setSeconds] = useState([]); + const [sValue, setSValue] = useState(''); + + const [ dimensions , setDimensions] = useState([]); + const [dValue, setDValue] = useState(''); + + const findObjKeyByValue = (obj, value) => { + return Object.keys(obj).find(key => obj[key].includes(value)); + }; + const findKeyByValue = (obj, value) => { + return Object.keys(obj).find(key => obj[key].includes(value)); + }; + + useEffect(()=>{ + if(type){ + Init(type==="storeNum" ?"followNum":type); + let find = findObjKeyByValue(thirdData,type); + if(find){ + let sub = findKeyByValue(subField,find); + setSValue(sub); + }else{ + setSValue(seconds[0]) + } + setDValue(fieldData[type]) + } + },[type]) + + + function Init(t){ + const url = `/v1/${owner}/${projectsId}/oss_health_measuring/keyid`; + axios(url,{params:{ + key_id:t + }}).then(res=>{ + if(!res){ + props.history.push(`/${owner}/${projectsId}/service/measurement`) + return; + } + let data = res && res.data; + if(data){ + let d = data[t] ? data[t].value : data.value; + let s = data.score !== undefined ? data.score : data[t].score; + setPieData(data.distribution); + setData(d); + if(t==="companyLoss"){ + d = d.map(i=>{return { month:i.Company , count : (i["Predicted State"] || 0.0)}}); + setData(d); + }else if(t === "companyNum" || t === "longTermCompanyNum" || t==="companyLead"){ + d = Object.keys(data.value).length === 0 ?[]:[Object.assign(data.value)]; + setData(d); + } + setScore(s); + } + }) + } + + useEffect(()=>{ + if(sValue){ + let arr = dimensionData[sValue]; + setDimensions(arr); + let find = findObjKeyByValue(secondData,sValue); + setTitle(find); + let subList = secondData[find]; + setSeconds(subList); + } + },[sValue]) + + + return( +
    + + 首页 + {title} + +
    + {title} + + 度量值:{scoreComp(score)} + {/* 健康度权重比:20% */} + +
    +
    + + +
    +
    +

    {dValue && (detailByName[dValue.replace(/\s/g, '')].descTitle ? detailByName[dValue.replace(/\s/g, '')].descTitle : dValue)}

    +

    {dValue && detailByName[dValue.replace(/\s/g, '')].desc}

    + { + data && data.length > 0 ? +
    + { + type === "companyNum" || type === "longTermCompanyNum" ? +
    + : + type === "companyLead" ? + + : + + } +
    + : + } +
    +
    + ) +} +export default Dimension; \ No newline at end of file diff --git a/src/forge/Server/measurement/index.jsx b/src/forge/Server/measurement/index.jsx new file mode 100644 index 00000000..e474af9c --- /dev/null +++ b/src/forge/Server/measurement/index.jsx @@ -0,0 +1,260 @@ +import React, {useState, useEffect , useRef} from "react"; +import './index.scss'; +import Logo from '../img/logo4.png'; +import { Button , Spin } from 'antd'; +import Large from '../img/large.png'; +import Middle from '../img/middle.png'; +import Small from '../img/small.png'; +import team from '../img/team.png'; +import person from '../img/person.png'; +import Rader from './componet/radar'; +import Indicator from './componet/indicator'; +import { scoreComp , field , firstData , colorsField, secondData , subField , thirdData } from './config'; +import axios from "axios"; +import cookie from 'react-cookies'; +// import res from './xiuos.json'; + + +function Index(props){ + const [ dataLoading , setDataLoading ] = useState(true); + const [cardIndex, setCardIndex] = useState(firstData[0]); + const [ subCardIndex, setSubCardIndex] = useState(1); + const [ loading , setLoading ] = useState(false); + + const { owner , projectsId } = props.match.params; + const [ datas , setDatas ] = useState(); + const [ scoreNormal , setScoreNormal ] = useState(); + + const [ score , setScore ] = useState([]); + const [ scoreNum , setScoreNum ] = useState(0); + + const [ subMenus , setSubMenus ] = useState([]); + const [ subDatas , setSubDatas ] = useState([]); + + const [ fieldDatas , setFieldDatas ] = useState([]); + let interval = undefined; + const count = useRef(); + + + useEffect(()=>{ + if(owner && projectsId){ + console.log(cookie.load("opensource")); + if(cookie.load("opensource") && cookie.load("opensource")===`${owner}_${projectsId}`){ + getReportStart(); + }else{ + checkData(); + } + } + },[owner,projectsId]) + + // 根据接口判断是否已经生成数据报告 + async function checkData(){ + const url = `/v1/${owner}/${projectsId}/oss_health_measuring/can_get`; + axios(url).then(res=>{ + if(res && res.data && res.data.statue === "YES"){ + Init(); + clearInterval(interval); + cookie.remove("opensource"); + }else if(res && res.data && res.data.statue === "NO"){ + setDataLoading(false); + } + }) + } + + // 获取数据接口 + function Init(){ + const url = `/v1/${owner}/${projectsId}/oss_health_measuring/keyid`; + axios(url,{params:{ + key_id:"score" + }}).then(res=>{ + if(res && res.data){ + let data = res.data; + setTimeout(()=>{setDataLoading(false)},300); + setDatas(data); + setScoreNormal(data); + getlist(data); + } + }) + } + // 开始体验,定时调用接口 + function getReportStart(){ + + setLoading(true); + count.current = 20; + checkData(); + interval = setInterval(() => { + if (count.current > 1) { + let old = count.current; + count.current = old - 1; + console.log(count); + checkData(); + } else { + //倒计时结束,提示繁忙 + clearInterval(interval); + setLoading(false); + props.showNotification("当前服务繁忙,请稍后再试"); + } + }, 30000) + } + + // 切换一级维度tab + useEffect(()=>{ + if(score && cardIndex){ + // 获取到二级维度名称以及其效率总分和健康度权重比, + let sub = secondData[cardIndex]; + sub && sub.length > 0 && setSubCardIndex(sub[0]); + let subData = score.filter(i=>i.name === cardIndex); + setSubMenus(sub); + // 以及一级维度的开发活动总分、加权得分 + let value = subData && subData.length > 0 && subData[0]; + if(value){ + setSubDatas(value); + let name = value.name; + let subname = secondData[name]; + let list = subname.map(i=>{ + return subField[i] + }) + let listData = []; + for(var i =0;i{ + return {name:j,...l[j],InitialScore:l[j] ? Math.round(l[j].InitialScore) : 0}; + }) + listData = listData.concat(items); + } + } + setFieldDatas(listData); + } + } + },[cardIndex,score]) + + + // 将一级维度的值转为数组 + function getlist(values){ + let d = firstData.map(i=>{ + return {name:i,...values[field[i]],color:colorsField[i]}; + }) + setScore(d); + let sn = d.reduce((sum, item) => Math.round(sum + Math.round(item.WeightedScore)), 0); + setScoreNum(sn); + } + console.log(subDatas); + + + return( +
    +
    开源软件健康度量服务
    + { dataLoading &&
    } + { + !dataLoading && !datas && +
    + +

    欢迎使用开源软件健康度量服务

    +
    开源软件健康度量服务是一种代码库分析工具,旨在通过深入分析代码库的关键活动数据来评估开源项目的健康状况。该服务通过收集和分析代码库中的贡献者、提交(commit)、合并请求(pullRequest)、疑修(issue)等数据指标,为项目开发者、维护者提供了一个全面的项目健康报告
    +
    + {!loading && } + { loading &&
    服务报告生成中...
    } +
    + } + { + !dataLoading && datas && +
    + { + scoreNormal && +
    +
    + + = 80 ? Large : scoreNum < 60 ? Small : Middle} alt="" width={"100%"}/> +
    + 健康值 + {scoreComp(scoreNum)} +
    +
    +

    本项目开源生态健康度

    +

    开源生态健康度由“开发活动”、“社区协作”、“项目影响”三个总体维度对开源项目的健康状况进行分析并加权求和,用于反馈项目的总体健康状况。您可点击查询每一个维度的度量指标及可视化图表。

    +
    + { + score && +
      + { +
    • + {Math.round(scoreNum)} + 开源生态健康度 +
      + { + score.map((i,k)=>{ + return

      + }) + } +
      + {Math.round(scoreNum)}/100 +
    • + } + { + score.map((i,k)=>{ + return( +
    • + {Math.round(i.WeightedScore)} + {i.name} +
      + {Math.round(i.WeightedScore)}/{i.Weight*100} +
    • + ) + }) + } +
    + } +
    + } +
    +
      + { + firstData.map((i,k)=>{ + return
    • {setCardIndex(i)}}>{k<10 && `0${k+1}`}{i}
    • + }) + } +
    + { + subDatas && +
    +

    + {cardIndex}总分:{scoreComp(subDatas.InitialScore)}/100 + {cardIndex}加权得分:{scoreComp(subDatas.WeightedScore)}/{subDatas.Weight*100} +

    +
    +
      + { + subMenus && subMenus.length > 0 && + subMenus.map((i,k)=>{ + let detail = subDatas[subField[i]]; + return( +
    • setSubCardIndex(i)}> +
      + {i} + {i}总分:{scoreComp(detail ? detail.InitialScore : subDatas.InitialScore)} + 健康度权重比:{(detail ? detail.Weight : subDatas.Weight) *100}% +
      + +
    • + ) + }) + } +
    +
    + +
    + +
    +
    +
    +
    + } +
    +
    + } +
    + ) +} +export default Index; \ No newline at end of file diff --git a/src/forge/Server/measurement/index.scss b/src/forge/Server/measurement/index.scss new file mode 100644 index 00000000..1b2cd9e2 --- /dev/null +++ b/src/forge/Server/measurement/index.scss @@ -0,0 +1,325 @@ +.scorePanel{ + .scoreMain{ + display: flex; + padding:35px 0px; + .scoreimg{ + width: 47%; + padding-right: 80px; + text-align: center; + .s_detail{ + font-weight: 400; + font-size: 15px; + color: #131415; + line-height: 30px; + text-align: left; + } + .scoreValue{ + position: relative; + display: block; + width: 270px; + text-align: center; + margin:0px auto; + .s_content{ + position: absolute; + width: 100%; + bottom: 0px; + text-align: center; + font-weight: 400; + font-size: 13px; + color: #B2C6D9; + display: flex; + flex-direction: column; + .s_num{ + font-family: "YouSheBiaoTiHei"; + font-weight: 400; + font-size: 41px; + color: #466AFF; + height: 50px; + line-height: 50px; + } + } + } + } + .scoreProgress{ + flex: 1; + display: flex; + flex-direction: column; + justify-content: space-between; + padding:20px 0px; + li{ + height: 36px; + width: 100%; + background: #F8F8F8; + padding-right: 28px; + display: flex; + align-items: center; + color: #61708B; + position: relative; + &::before{ + width: 0; + height: 0; + border: 26px solid; + border-color: transparent transparent transparent #F8F8F8; + transform: rotate(45deg); + position: absolute; + left: -26px; + content: ""; + top: 10px; + } + .index{ + width: 56px; + background-image: url(../img/index.png); + background-repeat: no-repeat; + background-size: 100% 100%; + display: block; + text-align: center; + line-height: 36px; + font-family: YouSheBiaoTiHei; + font-weight: 400; + font-size: 16px; + color: #466AFF; + margin-right: 15px; + } + .name{ + width: 120px; + margin-right: 14px; + font-weight: 500; + font-size: 16px; + color: #181818; + } + .progress{ + width: 330px; + height: 16px; + background: #F3F3F3; + position: relative; + display: flex; + margin-right: 15px; + &>span{ + position: absolute; + height: 100%; + left: 0px; + top:0px; + } + &>p{ + border-right: 2px solid #fff; + &:last-child{ + border:none; + } + } + } + } + } + } +} +.typeLi{ + display: flex; + align-items: center; + justify-content: center; + padding:44px 0px; + li{ + height: 62px; + background: #F5F6F7; + border-radius: 8px 8px 8px 8px; + border: 1px solid #DBE0E9; + width: 280px; + font-weight: 500; + font-size: 16px; + color: #212F54; + line-height: 60px; + text-align: center; + margin:0px 25px; + cursor: pointer; + span{ + font-family: YouSheBiaoTiHei; + font-weight: 400; + font-size: 25px; + margin-right: 15px; + position: relative; + &::after{ + content: ""; + right: -8px; + bottom: -3px; + width: 19px; + height: 15px; + background-image: url('../img/trans1.png'); + background-repeat: no-repeat; + position: absolute; + } + } + &.active{ + background-image: url('../img/blue.png'); + border:none; + line-height: 62px; + color: #fff; + span{ + &::after{ + background-image: url('../img/trans.png'); + } + } + } + &:hover{ + border-color: #6F93D4; + } + } +} +.fw500{ + font-weight: 500; +} +.typeContent{ + background: rgba(102,102,102,0.03); + border-radius: 0px 0px 0px 0px; + border: 1px solid rgba(70,106,255,0.13); + padding:40px 30px; + .typeValue{ + font-size: 17px; + color: #181818; + text-align: center; + margin-bottom: 30px!important; + span{ + font-weight: 400; + font-size: 26px; + } + } + .typeEchart{ + display: flex; + } + .echartCate{ + width: 298px; + margin-right: 30px; + .echartNum{ + display: flex; + flex-direction: column; + flex:1; + font-weight: 400; + font-size: 22px; + color: #212F54; + span{ + display: flex; + justify-content: space-between; + } + } + li{ + background-image: url('../img/back.png'); + background-size: 100% 100%; + width: 100%; + height: 170px; + box-shadow: 0px 0px 10px 1px rgba(28,48,175,0.04); + border-radius: 8px 8px 8px 8px; + display: flex; + align-items: center; + padding-left: 30px; + font-weight: 400; + font-size: 15px; + color: #181818; + line-height: 40px; + border: 1px solid #fff; + cursor: pointer; + &.active{ + border-color: #466AFF; + position: relative; + &::after{ + content: ""; + position: absolute; + right: 0px; + top: 0px; + background-image: url("../img/true.png"); + width: 56px; + height: 44px; + } + } + &:first-child{ + margin-bottom: 30px!important; + } + } + } + .echartData{ + background: #FFFFFF; + box-shadow: 0px 0px 10px 1px rgba(28,48,175,0.08); + border-radius: 0px 0px 0px 0px; + flex: 1; + min-height: 370px; + padding:25px; + box-sizing: border-box; + display: flex; + align-items: center; + justify-content: space-between; + } +} +.smalltable{ + border-color: rgba(65,84,241,0.04)!important; + .ant-table-body{ + margin:0px!important; + .ant-table-thead th { + background-color:rgba(65,84,241,0.04)!important; + } + .ant-table-tbody tr td{ + background: #F5F6F7; + } + .ant-table-tbody tr:hover{ + background: #F5F6FA; + } + } +} +.dropTeam{ + background-image: url('../img/blue-large.png'); + background-size: 100% 100%; + background-repeat: no-repeat; + width: 330px; + height: 50px; + margin:40px auto; + color: #fff; + display: flex; + align-items: center; + justify-content: center; + .ant-select-selection{ + border:none; + color: #fff; + background-color: transparent; + box-shadow: none; + .ant-select-arrow .ant-select-arrow-icon svg{ + color: #fff; + } + } + .ant-select{ + position: relative; + &:last-child::before{ + content: ""; + position: absolute; + width: 1px; + height: 14px; + border: 1px solid rgba(255,255,255,0.36); + left: 0px; + top:9px; + } + } +} +.dropEcharts{ + background-image: url('../img/echartBack.png'); + text-align: center; + padding: 30px; + .dropName{ + font-weight: 500; + font-size: 20px; + color: #181818; + } + .dropDesc{ + font-weight: 400; + font-size: 15px; + color: #212F54; + width: 75%; + margin:0px auto; + margin-top: 15px; + } + .dropEchartPanel{ + background: #FFFFFF; + box-shadow: 0px 0px 10px 1px rgba(28,48,175,0.08); + border-radius: 6px 6px 6px 6px; + padding:25px; + width: 75%; + margin:0px auto; + margin-top: 20px; + } +} +.faYou{ + font-family: YouSheBiaoTiHei; +} \ No newline at end of file diff --git a/src/forge/Server/measurement/xiuos.json b/src/forge/Server/measurement/xiuos.json new file mode 100644 index 00000000..1b7067a3 --- /dev/null +++ b/src/forge/Server/measurement/xiuos.json @@ -0,0 +1,1245 @@ +{ + "score": { + "OSSEcologyHealthScore": 83.19999999999999, + "developmentActivity": { + "InitialScore": 90.99999999999999, + "WeightedScore": 36.4, + "Weight": 0.4, + "developmentQuality": { + "InitialScore": 85.99999999999999, + "WeightedScore": 17.2, + "Weight": 0.2, + "commitMessageQuality": { + "InitialScore": 80, + "WeightedScore": 6.4, + "Weight": 0.08 + }, + "issueNum": { + "InitialScore": 90, + "WeightedScore": 10.799999999999999, + "Weight": 0.12 + } + }, + "developmentEfficiency": { + "InitialScore": 95.99999999999999, + "WeightedScore": 19.2, + "Weight": 0.2, + "commitNum": { + "InitialScore": 80, + "WeightedScore": 3.2, + "Weight": 0.04 + }, + "PRNum": { + "InitialScore": 100, + "WeightedScore": 4.0, + "Weight": 0.04 + }, + "PRTime": { + "InitialScore": 100, + "WeightedScore": 6.0, + "Weight": 0.06 + }, + "issueTime": { + "InitialScore": 100, + "WeightedScore": 6.0, + "Weight": 0.06 + } + } + }, + "communityCooperation": { + "InitialScore": 90.0, + "WeightedScore": 36.0, + "Weight": 0.4, + "individual": { + "InitialScore": 100.0, + "WeightedScore": 20.0, + "Weight": 0.2, + "individualNum": { + "InitialScore": 100, + "WeightedScore": 4.0, + "Weight": 0.04 + }, + "individualHistory": { + "InitialScore": 100, + "WeightedScore": 4.0, + "Weight": 0.04 + }, + "longTermIndividualNum": { + "InitialScore": 100, + "WeightedScore": 4.0, + "Weight": 0.04 + }, + "individualLoss": { + "InitialScore": 100, + "WeightedScore": 8.0, + "Weight": 0.08 + } + }, + "company": { + "InitialScore": 80.0, + "WeightedScore": 16.0, + "Weight": 0.2, + "companyNum": { + "InitialScore": 80, + "WeightedScore": 3.2, + "Weight": 0.04 + }, + "longTermCompanyNum": { + "InitialScore": 80, + "WeightedScore": 3.2, + "Weight": 0.04 + }, + "companyLead": { + "InitialScore": 80, + "WeightedScore": 4.0, + "Weight": 0.05 + }, + "companyLoss": { + "InitialScore": 80, + "WeightedScore": 5.6000000000000005, + "Weight": 0.07 + } + } + }, + "influence": { + "InitialScore": 53.99999999999999, + "WeightedScore": 10.799999999999999, + "Weight": 0.2, + "branchNum": { + "InitialScore": 100, + "WeightedScore": 4.0, + "Weight": 0.04 + }, + "praiseNum": { + "InitialScore": 40, + "WeightedScore": 1.6, + "Weight": 0.04 + }, + "storeNum": { + "InitialScore": 40, + "WeightedScore": 1.6, + "Weight": 0.04 + }, + "browseNum": { + "InitialScore": 40, + "WeightedScore": 1.6, + "Weight": 0.04 + }, + "forkNum": { + "InitialScore": 50, + "WeightedScore": 2.0, + "Weight": 0.04 + } + } + }, + "commitMessageQuality": {}, + "issueNum": { + "score": 90, + "issueNum": [ + { + "month": 0, + "issueNum": 5 + } + ] + }, + "commitNum": {}, + "PRNum": { + "score": 100, + "PRNum": [ + { + "month": 0, + "PRNum": 3 + } + ] + }, + "PRTime": { + "score": 100, + "PRTime": [ + { + "month": -1, + "PRNum": -1, + "PRHourInterval": -1 + } + ] + }, + "issueTime": { + "score": 100, + "issueTime": [ + { + "month": -1, + "issueNum": -1, + "issueHourInterval": -1 + } + ] + }, + "individualContributorNum": { + "score": 100, + "individualContributorNum": 45 + }, + "individualContributorHistory": { + "score": 100, + "individualContributorHistory": [ + { + "user_login": "Liu_Weichao", + "month": "2022-10", + "commits_number": 2, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 0 + }, + { + "user_login": "Liu_Weichao", + "month": "2022-11", + "commits_number": 19, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 2 + }, + { + "user_login": "Liu_Weichao", + "month": "2022-12", + "commits_number": 10, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 21 + }, + { + "user_login": "Liu_Weichao", + "month": "2023-01", + "commits_number": 7, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 31 + }, + { + "user_login": "Liu_Weichao", + "month": "2023-02", + "commits_number": 1, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 38 + }, + { + "user_login": "Liu_Weichao", + "month": "2023-03", + "commits_number": 12, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 39 + }, + { + "user_login": "Liu_Weichao", + "month": "2023-04", + "commits_number": 8, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 51 + }, + { + "user_login": "Liu_Weichao", + "month": "2023-05", + "commits_number": 10, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 59 + }, + { + "user_login": "Liu_Weichao", + "month": "2023-06", + "commits_number": 6, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 69 + }, + { + "user_login": "Liu_Weichao", + "month": "2023-07", + "commits_number": 7, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 75 + }, + { + "user_login": "Liu_Weichao", + "month": "2023-08", + "commits_number": 12, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 82 + }, + { + "user_login": "Liu_Weichao", + "month": "2023-09", + "commits_number": 2, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 94 + }, + { + "user_login": "Liu_Weichao", + "month": "2023-10", + "commits_number": 10, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 96 + }, + { + "user_login": "Liu_Weichao", + "month": "2023-11", + "commits_number": 16, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 106 + }, + { + "user_login": "Liu_Weichao", + "month": "2023-12", + "commits_number": 13, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 122 + }, + { + "user_login": "Liu_Weichao", + "month": "2024-01", + "commits_number": 8, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 135 + }, + { + "user_login": "Liu_Weichao", + "month": "2024-02", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 143 + }, + { + "user_login": "Liu_Weichao", + "month": "2024-03", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 143 + }, + { + "user_login": "Liu_Weichao", + "month": "2024-04", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 143 + }, + { + "user_login": "Liu_Weichao", + "month": "2024-05", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 143 + }, + { + "user_login": "Liu_Weichao", + "month": "2024-06", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 143 + }, + { + "user_login": "Liu_Weichao", + "month": "2024-07", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 143 + }, + { + "user_login": "Liu_Weichao", + "month": "2024-08", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 143 + }, + { + "user_login": "Liu_Weichao", + "month": "2024-09", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 143 + }, + { + "user_login": "TXuian", + "month": "2022-11", + "commits_number": 5, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 143 + }, + { + "user_login": "TXuian", + "month": "2022-12", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 5 + }, + { + "user_login": "TXuian", + "month": "2023-01", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 5 + }, + { + "user_login": "TXuian", + "month": "2023-02", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 5 + }, + { + "user_login": "TXuian", + "month": "2023-03", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 5 + }, + { + "user_login": "TXuian", + "month": "2023-04", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 5 + }, + { + "user_login": "TXuian", + "month": "2023-05", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 5 + }, + { + "user_login": "TXuian", + "month": "2023-06", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 5 + }, + { + "user_login": "TXuian", + "month": "2023-07", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 5 + }, + { + "user_login": "TXuian", + "month": "2023-08", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 5 + }, + { + "user_login": "TXuian", + "month": "2023-09", + "commits_number": 2, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 5 + }, + { + "user_login": "TXuian", + "month": "2023-10", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 7 + }, + { + "user_login": "TXuian", + "month": "2023-11", + "commits_number": 3, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 7 + }, + { + "user_login": "TXuian", + "month": "2023-12", + "commits_number": 2, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 10 + }, + { + "user_login": "TXuian", + "month": "2024-01", + "commits_number": 3, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 12 + }, + { + "user_login": "TXuian", + "month": "2024-02", + "commits_number": 2, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 15 + }, + { + "user_login": "TXuian", + "month": "2024-03", + "commits_number": 20, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 17 + }, + { + "user_login": "TXuian", + "month": "2024-04", + "commits_number": 18, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 37 + }, + { + "user_login": "TXuian", + "month": "2024-05", + "commits_number": 60, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 55 + }, + { + "user_login": "TXuian", + "month": "2024-06", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 115 + }, + { + "user_login": "TXuian", + "month": "2024-07", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 115 + }, + { + "user_login": "TXuian", + "month": "2024-08", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 115 + }, + { + "user_login": "wgzAIIT", + "month": "2022-10", + "commits_number": 11, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 115 + }, + { + "user_login": "wgzAIIT", + "month": "2022-11", + "commits_number": 24, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 11 + }, + { + "user_login": "wgzAIIT", + "month": "2022-12", + "commits_number": 6, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 35 + }, + { + "user_login": "wgzAIIT", + "month": "2023-01", + "commits_number": 2, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 41 + }, + { + "user_login": "wgzAIIT", + "month": "2023-02", + "commits_number": 4, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 43 + }, + { + "user_login": "wgzAIIT", + "month": "2023-03", + "commits_number": 3, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 47 + }, + { + "user_login": "wgzAIIT", + "month": "2023-04", + "commits_number": 14, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 50 + }, + { + "user_login": "wgzAIIT", + "month": "2023-05", + "commits_number": 24, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 64 + }, + { + "user_login": "wgzAIIT", + "month": "2023-06", + "commits_number": 20, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 88 + }, + { + "user_login": "wgzAIIT", + "month": "2023-07", + "commits_number": 15, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 108 + }, + { + "user_login": "wgzAIIT", + "month": "2023-08", + "commits_number": 29, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 123 + }, + { + "user_login": "wgzAIIT", + "month": "2023-09", + "commits_number": 24, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 152 + }, + { + "user_login": "wgzAIIT", + "month": "2023-10", + "commits_number": 12, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 176 + }, + { + "user_login": "wgzAIIT", + "month": "2023-11", + "commits_number": 11, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 188 + }, + { + "user_login": "wgzAIIT", + "month": "2023-12", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 199 + }, + { + "user_login": "wgzAIIT", + "month": "2024-01", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 199 + }, + { + "user_login": "wgzAIIT", + "month": "2024-02", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 199 + }, + { + "user_login": "wgzAIIT", + "month": "2024-03", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 199 + }, + { + "user_login": "wgzAIIT", + "month": "2024-04", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 199 + }, + { + "user_login": "wgzAIIT", + "month": "2024-05", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 199 + }, + { + "user_login": "wgzAIIT", + "month": "2024-06", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 199 + }, + { + "user_login": "wgzAIIT", + "month": "2024-07", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 199 + }, + { + "user_login": "wgzAIIT", + "month": "2024-08", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 199 + }, + { + "user_login": "xuedongliang", + "month": "2022-10", + "commits_number": 1, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 199 + }, + { + "user_login": "xuedongliang", + "month": "2022-11", + "commits_number": 11, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 1 + }, + { + "user_login": "xuedongliang", + "month": "2022-12", + "commits_number": 5, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 12 + }, + { + "user_login": "xuedongliang", + "month": "2023-01", + "commits_number": 5, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 17 + }, + { + "user_login": "xuedongliang", + "month": "2023-02", + "commits_number": 4, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 22 + }, + { + "user_login": "xuedongliang", + "month": "2023-03", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 26 + }, + { + "user_login": "xuedongliang", + "month": "2023-04", + "commits_number": 8, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 26 + }, + { + "user_login": "xuedongliang", + "month": "2023-05", + "commits_number": 3, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 34 + }, + { + "user_login": "xuedongliang", + "month": "2023-06", + "commits_number": 2, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 37 + }, + { + "user_login": "xuedongliang", + "month": "2023-07", + "commits_number": 1, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 39 + }, + { + "user_login": "xuedongliang", + "month": "2023-08", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 40 + }, + { + "user_login": "xuedongliang", + "month": "2023-09", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 40 + }, + { + "user_login": "xuedongliang", + "month": "2023-10", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 40 + }, + { + "user_login": "xuedongliang", + "month": "2023-11", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 40 + }, + { + "user_login": "xuedongliang", + "month": "2023-12", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 40 + }, + { + "user_login": "xuedongliang", + "month": "2024-01", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 40 + }, + { + "user_login": "xuedongliang", + "month": "2024-02", + "commits_number": 3, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 40 + }, + { + "user_login": "xuedongliang", + "month": "2024-03", + "commits_number": 4, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 43 + }, + { + "user_login": "xuedongliang", + "month": "2024-04", + "commits_number": 1, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 47 + }, + { + "user_login": "xuedongliang", + "month": "2024-05", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 48 + }, + { + "user_login": "xuedongliang", + "month": "2024-06", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 48 + }, + { + "user_login": "xuedongliang", + "month": "2024-07", + "commits_number": 6, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 48 + }, + { + "user_login": "xuedongliang", + "month": "2024-08", + "commits_number": 0, + "issues_number": 0, + "pr_number": 0, + "issue_comments_number": 0, + "pr_comments_number": 0, + "commit_comments_number": 0, + "history_commit_number": 54 + } + ] + }, + "longTermIndividualContributorNum": { + "score": 100, + "longTermIndividualContributorNum": 4 + }, + "individualContributorLoss": { + "score": 100, + "individualContributorLoss": [] + }, + "companyContributorNum": {}, + "longTermCompanyContributorNum": {}, + "companyLead": {}, + "companyContributorLoss": {}, + "branchNum": { + "score": 100, + "branchNum": { + "branchNum": 8 + } + }, + "praiseNum": { + "score": 40, + "praiseNum": [ + { + "praiseNum": 0 + } + ] + }, + "followNum": { + "score": 40, + "storeNum": [ + { + "storeNum": 0 + } + ] + }, + "browseNum": { + "score": 40, + "browseNum": { + "browseNum": 0 + } + }, + "forkNum": { + "score": 50, + "forkNum": [ + { + "month": 0, + "forkNum": 1 + } + ] + } +} \ No newline at end of file diff --git a/src/forge/Server/reposyncer/index.scss b/src/forge/Server/reposyncer/index.scss index 576c7d26..05467680 100644 --- a/src/forge/Server/reposyncer/index.scss +++ b/src/forge/Server/reposyncer/index.scss @@ -30,15 +30,6 @@ border-color:#1a47ff; } } -.reposyncerBox .headBox, .storeListBox .headBox{ - height:60px; - line-height: 60px; - background-color:#fafcff; - border:1px solid rgba(42, 97, 255, 0.23); - border-radius:3px 3px 0px 0px; - color:#333333; - position: relative; -} .reposyncerBox{ padding-bottom: 60px; .helpBox1{ @@ -53,24 +44,6 @@ align-items: center; cursor: default; } - .nullStoreBox{ - background-color:#fafcff; - border-radius:4px 4px 0px 0px; - text-align: center; - color:#333333; - padding-bottom: 65px; - .loBox{width: 68px;} - .introBox{ - color:#666666; - width: 57%; - margin: 15px auto; - } - .borBox{ - width: 45%; - margin: 0 auto 20px; - border-bottom: 1px solid rgba(90, 117, 193, 0.23); - } - } .rightContentBox{ display: flex; .leftNav{ diff --git a/src/forge/css/index.scss b/src/forge/css/index.scss index 0dfc9860..c4d4c07e 100644 --- a/src/forge/css/index.scss +++ b/src/forge/css/index.scss @@ -1,3 +1,5 @@ + + ul,ol,dl{ margin-bottom: 0px; }