merge 个人中心改版

This commit is contained in:
caishi 2021-05-28 16:19:40 +08:00
parent 3135300fe6
commit 6b20391c72
17 changed files with 1198 additions and 153 deletions

View File

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

View File

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

View File

@ -0,0 +1,95 @@
import React, { useEffect, useState } from "react";
import Nodata from '../Nodata';
import { Pagination , Spin } from 'antd';
import { Link } from 'react-router-dom';
import { getImageUrl } from 'educoder';
import Axios from "axios";
const limit = 15;
function Notify(props){
const username = props.match.params.username;
const [ list , setList ] = useState(undefined);
const [ page , setPage ] = useState(1);
const [ total , setTotal ] = useState(0);
const [ isSpin , setIsSpin ] = useState(true);
useEffect(()=>{
if(username){
setIsSpin(true);
getList();
}
},[username,page])
function getList(){
const url = `/users/${username}/applied_messages.json`;
Axios.get(url,{
params:{
page,per_page:limit
}
}).then(result=>{
if(result){
setList(result.data.applied_messages);
setTotal(result.data.total_count);
setIsSpin(false);
}
}).catch(error=>{})
}
function renderStatus(status,applied){
let { project , owner} = applied
if(status){
switch(status){
case 'canceled':
return <p>取消转移<Link to={`/projects/${project && project.owner && project.owner.login}/${project && project.identifier}`}>{project && project.name}</Link>仓库</p>
case 'common':
return <p>正在将<Link to={`/projects/${project && project.owner && project.owner.login}/${project && project.identifier}`}>{project && project.name}</Link>仓库转移给<Link to={`/users/${owner && owner.login}`}>{owner && owner.name}</Link></p>
case 'successed':
return <p><Link to={`/projects/${project && project.owner && project.owner.login}/${project && project.identifier}`}>{project && project.name}</Link>仓库成功转移给<Link to={`/users/${owner && owner.login}`}>{owner && owner.name}</Link></p>
default:
return <p>拒绝转移<Link to={`/projects/${project && project.owner && project.owner.login}/${project && project.identifier}`}>{project && project.name}</Link>仓库</p>
}
}else{
return ""
}
}
return(
<div>
<Spin spinning={isSpin}>
<div style={{minHeight:"400px"}}>
{
list && list.length > 0 ?
<ul className="notifyList">
{
list.map((i,k)=>{
return(
<li>
<Link to={`/users/${i.login}`}><img src={getImageUrl(`/${i.applied_user && i.applied_user.image_url}`)} alt="" className="notifyImg"/></Link>
<div className="notifyFlex">
<p className="notifyInfos">
<Link to={`/users/${i.applied_user && i.applied_user.login}`} className="font-15 mr20">{i.applied_user && i.applied_user.name}</Link>
<span className="color-grey-9">{i.time_ago}</span>
</p>
{renderStatus(i.status,i.applied)}
</div>
</li>
)
})
}
</ul>
:
""
}
</div>
</Spin>
{list && list.length === 0 && <Nodata _html="暂无通知" />}
{
total > limit &&
<div className="edu-txt-center pt20 pb20">
<Pagination simple pageSize={limit} total={total} current={page} onChange={(p)=>{setPage(p)}}/>
</div>
}
</div>
)
}
export default Notify;

View File

@ -0,0 +1,123 @@
import React, { useEffect, useState } from "react";
import Nodata from '../Nodata';
import { FlexAJ } from '../Component/layout';
import { Pagination , Popconfirm , Spin } from 'antd';
import { Link } from 'react-router-dom';
import { getImageUrl } from 'educoder';
import Axios from 'axios';
const limit = 15;
function UndoEvent(props){
const username = props.match.params.username;
const [ list , setList ] = useState(undefined);
const [ page , setPage ] = useState(1);
const [ total , setTotal ] = useState(0);
const [ isSpin , setIsSpin ] = useState(true);
useEffect(()=>{
if(username){
setIsSpin(true);
getList();
}
},[username,page])
function getList(){
const url = `/users/${username}/applied_transfer_projects.json`;
Axios.get(url,{
params:{
page,per_page:limit
}
}).then(result=>{
if(result){
setList(result.data.applied_transfer_projects);
setTotal(result.data.total_count);
setIsSpin(false);
}
}).catch(error=>{})
}
//
function acceptDivert(id){
const url = `/users/${username}/applied_transfer_projects/${id}/accept.json`;
Axios.post(url).then(result=>{
if(result && result.data){
getList();
props && props.fetchUser();
}
}).catch(error=>{})
}
//
function revertDivert(id){
const url = `/users/${username}/applied_transfer_projects/${id}/refuse.json`;
Axios.post(url).then(result=>{
if(result && result.data){
getList();
props && props.fetchUser();
}
}).catch(error=>{})
}
return(
<div>
<Spin spinning={isSpin}>
<div style={{minHeight:"400px"}}>
{
list && list.length > 0 ?
<ul className="notifyList">
{
list.map((i,k)=>{
return(
<li>
<Link to={`/users/${i.user && i.user.login}`}><img src={getImageUrl(`/${i.user && i.user.image_url}`)} alt="" className="notifyImg"/></Link>
<div className="notifyFlex">
<p className="notifyInfos">
<Link to={`/users/${i.login}`} className="font-15 mr20">{i.user && i.user.name}</Link>
<span className="color-grey-9">{i.time_ago}</span>
</p>
<FlexAJ>
<p className="color-grey-6">请求将仓库<Link to={`/projects/${i.project && i.project.owner && i.project.owner.login}/${i.project && i.project.identifier}`}>{i.project && i.project.name}</Link>
转移给<Link to={`/users/${i.owner && i.owner.login}`}>{i.owner && i.owner.name}</Link>,是否接受</p>
{
i.status === "common" &&
<span>
<Popconfirm title={`确定接受仓库${i.project && i.project.name}`} okText="确定" cancelText="取消" onConfirm={()=>acceptDivert(i.id)}>
<a className="color-blue">接受</a>
</Popconfirm>
<Popconfirm title={`确定拒绝接受仓库${i.project && i.project.name}`} okText="确定" cancelText="取消" onConfirm={()=>revertDivert(i.id)}>
<a className="color-red ml20">拒绝</a>
</Popconfirm>
</span>
}
{
i.status === "canceled" && <span className="color-grey-9">对方已取消转移</span>
}
{
i.status === "accepted" && <span className="color-grey-9">已接受</span>
}
{
i.status === "refused" && <span className="color-grey-9">已拒绝</span>
}
</FlexAJ>
</div>
</li>
)
})
}
</ul>
:
""
}
</div>
</Spin>
{list && list.length === 0 && <Nodata _html="暂无接收信息" />}
{
total > limit &&
<div className="edu-txt-center pt20 pb20">
<Pagination simple pageSize={limit} total={total} current={page} onChange={(p)=>{setPage(p)}}/>
</div>
}
</div>
)
}
export default UndoEvent;

View File

@ -0,0 +1,113 @@
import React ,{ useEffect, useState } from 'react';
import * as echarts from 'echarts';
import moment from 'moment';
import Axios from 'axios';
function Calendar({ userLogin , time , chooseTime }) {
const [ endT, setEndT ] = useState("");
const [ baginT, setBaginT ] = useState("");
useEffect(()=>{
if(time){
let e = `${time}-12-31`;
let b = `${time}-01-01`;
setEndT(e);
setBaginT(b);
}else if(time === ""){
let y = moment().get('year');
let m = moment().get('month');
let d = moment().get('date');
let e = `${y}-${m+1}-${d}`;
let b = `${y-1}-${m+1}-${d}`;
setEndT(e);
setBaginT(b);
}
},[time])
useEffect(()=>{
if(baginT && endT){
getData();
}
},[baginT,endT])
function getData() {
const url = `/users/${userLogin}/headmaps.json`;
Axios.get(url).then(result=>{
if(result && result.data){
let m = result.data.headmaps;
m.sort(compare('contributions'));
let max = m[m.length -1].contributions;
Init(m,max);
}
}).catch(error=>{})
}
function compare(property){
return function(a,b){
var value1 = a[property];
var value2 = b[property];
return value1 - value2;
}
}
function getVirtulData(data) {
var array = [];
for(var i=0;i<data.length;i++){
array.push([data[i].date,data[i].contributions]);
}
return array;
}
function Init(data,max) {
var huan_val = document.getElementById("Calendar");
var myEcharts = echarts.init(huan_val);
let option = {
title: {
show:false
},
tooltip: {},
visualMap: {
min: 0,
max: max,
type: 'piecewise',
orient: 'horizontal',
left: 'center',
bottom: 40,
inRange:{
color:['#C7DBFF', '#5291FF']
}
},
calendar: {
top: 60,
left: 30,
right: 0,
cellSize: ['auto', 13],
range: [baginT, endT],
itemStyle: {
borderWidth: 0.5
},
yearLabel: {show: false},
monthLabel:{
nameMap:"cn"
},
dayLabel:{
nameMap:"cn"
}
},
series: {
type: 'heatmap',
coordinateSystem: 'calendar',
data: getVirtulData(data)
}
};
myEcharts.setOption(option);
myEcharts.on('click', function (params) {
chooseTime(params.data);
});
}
return(
<div id="Calendar" style={{height:"230px"}}></div>
)
}
export default Calendar;

View File

@ -0,0 +1,49 @@
import React ,{ useEffect } from 'react';
import Js2WordCloud from 'js2wordcloud/dist/js2wordcloud.js'
function Cloud({data}) {
useEffect(()=>{
optionChart1();
},[])
function optionChart1(){
var div = new Js2WordCloud(document.getElementById('cloud'))
let textList=['服务', '细致', '意识', '踏实','开发', '反馈']
let cyList=[]
for(let i=0;i<textList.length;i++){
cyList.push([textList[i],textList.length-i])
}
div.setOption({
backgroundColor:'transparent',
shape: 'circle',
ellipticity: 1,//
maxFontSize: 21,//
minFontSize: 16,//
tooltip: {
show: true
},
list: cyList,
color(word, weight, fontSize, distance, theta) { //
switch(fontSize){
case 21:
return "#f8e367"
case 20:
return "#99dfff"
case 19:
return "#ff9e48"
case 18:
return "#5ea6ff"
case 17:
return "#58c0f0"
default:
return "#bcbcbc"
}
},
})
}
return(
<div id="cloud" style={{height:"200px"}}></div>
)
}
export default Cloud;

View File

@ -0,0 +1,101 @@
import React ,{ useEffect } from 'react';
import * as echarts from 'echarts';
function Line({data}) {
useEffect(()=>{
Init();
},[])
useEffect(()=>{
if(data){
Init();
}
},[data])
function Init() {
var huan_val = document.getElementById("Line");
var myEcharts = echarts.init(huan_val);
let option = {
color: ["#f8e367", "#99dfff", "#58c0f0", "#5ea6ff", "#ff9e48", "#bcbcbc"],
title: {
text: '近期活动统计',
left: '3%',
top:"3%"
},
tooltip: {
trigger: 'axis'
},
legend: {
data: ['邮件营销', '联盟广告', '视频广告', '直接访问', '搜索引擎'],
right: 'center',
bottom: '0',
},
grid: {
left: '4%',
right: '4%',
bottom: '12%',
containLabel: true
},
toolbox: {
feature: {
// saveAsImage: {}
}
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
axisTick:{
show:false
}
},
yAxis: {
type: 'value',
axisLine:{
show:false
},
axisTick:{
show:false
}
},
series: [
{
name: '邮件营销',
type: 'line',
stack: '总量',
data: [120, 132, 101, 134, 90, 230, 210]
},
{
name: '联盟广告',
type: 'line',
stack: '总量',
data: [220, 182, 191, 234, 290, 330, 310]
},
{
name: '视频广告',
type: 'line',
stack: '总量',
data: [150, 232, 201, 154, 190, 330, 410]
},
{
name: '直接访问',
type: 'line',
stack: '总量',
data: [320, 332, 301, 334, 390, 330, 320]
},
{
name: '搜索引擎',
type: 'line',
stack: '总量',
data: [820, 932, 901, 934, 1290, 1330, 1320]
}
]
};
myEcharts.setOption(option);
}
return(
<div id="Line" style={{height:"300px"}}></div>
)
}
export default Line;

View File

@ -0,0 +1,25 @@
import React from 'react';
import { Link } from 'react-router-dom';
import { AlignCenter } from '../../Component/layout';
import { TagInfo } from '../../Utils/TagColor';
import { getImageUrl } from 'educoder';
function Activity() {
return(
<ul className="infosActivity">
<li>
<Link to={``}><img src={getImageUrl(`/system/lets/letter_avatars/2/D/169_162_140/120.png`)} alt="" className="aImg"/></Link>
<div className="aInfos">
<AlignCenter>
<Link to={``} className="name">蔡世</Link>
<span className="time">1小时前</span>
{TagInfo("立刻","")}
<span className="status">已关闭</span>
</AlignCenter>
<p className="aDesc">更新了问题状态动态详情动态详情动态详情动态详情动态详情</p>
</div>
</li>
</ul>
)
}
export default Activity;

View File

@ -0,0 +1,98 @@
import React, { useEffect, useState } from 'react';
import { Modal , Checkbox , Pagination , Button , Spin } from 'antd';
import Axios from 'axios';
import { Link } from 'react-router-dom';
import { FlexAJ } from '../../Component/layout';
const limit = 20;
function ConcentrateBox({ visible , onCancel , onSure , username , choosed }) {
const [ page , setPage ]= useState(1);
const [ total , setTotal ]= useState(0);
const [ list , setList ]= useState(undefined);
const [ value , setValue ]= useState([]);
const [ isSpin , setIsSpin ]= useState(true);
const [ disable , setDisable ] = useState(false);
useEffect(()=>{
if(visible){
setIsSpin(true);
getProjectList();
}
},[visible,page])
useEffect(()=>{
if(choosed && choosed.length >0 ){
setValue(choosed);
}
},[choosed])
useEffect(()=>{
if(value && value.length === 6){
setDisable(true);
}else{
setDisable(false);
}
},[value])
function getProjectList() {
const url = `/users/${username}/projects.json`;
Axios.get(url,{
params:{
page,limit,is_public: "public"
}
}).then(result=>{
if(result && result.data){
setTotal(result.data.count);
setList(result.data.projects);
setIsSpin(false);
}
}).catch(error=>{})
}
function onOk() {
onSure && onSure(value);
setValue([]);
}
function chooseProject(params) {
setValue(params);
}
return(
<Modal
visible={visible}
title={'选择精选项目'}
closable={false}
width={500}
className="ConcentrateBox"
footer={
<FlexAJ>
{total > limit &&
<Pagination size={"small"} simple current={page} pageSize={limit} onChange={(p)=>setPage(p)} total={total}/>
}
<span>
<Button onClick={onCancel}>取消</Button>
<Button type={"primary"} className="ml20" onClick={onOk}>确定</Button>
</span>
</FlexAJ>
}
>
<Spin spinning={isSpin}>
{
list && list.length > 0 &&
<Checkbox.Group value={value} onChange={chooseProject} style={{width:"100%"}}>
{
list.map((i,k)=>{
return(
<Checkbox value={i.id} disabled={disable && (value.filter(j=>j === i.id).length===0)}>{i.name}</Checkbox>
)
})
}
</Checkbox.Group>
}
{ list && list.length === 0 && <div style={{textAlign:"center"}}>您还没有公开的项目先去<Link to={`/projects/deposit/new`} className="color-blue">新建项目</Link></div> }
</Spin>
</Modal>
)
}
export default ConcentrateBox;

View File

@ -0,0 +1,86 @@
import React, { useEffect, useState } from 'react';
import { AlignAJBottom , AlignCenter } from '../../Component/layout';
import { Link } from 'react-router-dom';
import { Spin } from 'antd';
import axios from 'axios';
import Box from './ConcentrateBox';
function ConcentrateProject({userLogin,current}) {
const [ list , setList ] = useState(undefined);
const [ visible , setVisible ] = useState(false);
const [ isSpin , setIsSpin ] = useState(false);
const [ value , setValue ] = useState([]);
useEffect(()=>{
setIsSpin(true);
getList();
},[])
function getList() {
const url = `/users/${userLogin}/is_pinned_projects.json`;
axios.get(url).then(result=>{
if(result && result.data){
let p = result.data.projects;
setList(p);
setIsSpin(false);
if(p && p.length > 0){
let array = p.map(i=>{
return i.id
})
setValue(array);
}
}
}).catch(erroer=>{})
}
function onSure(is_pinned_project_ids) {
const url = `/users/${userLogin}/is_pinned_projects/pin.json`;
axios.post(url,{
is_pinned_project_ids
}).then(result=>{
if(result && result.data){
setVisible(false);
setIsSpin(true);
getList();
}
}).catch(error=>{})
}
return(
<Spin spinning={isSpin}>
<Box visible={visible} onCancel={()=>setVisible(false)} onSure={onSure} username={userLogin} choosed={value}/>
{
list && list.length>0 &&
<div className="concentrate">
<AlignAJBottom>
<span className="font-18">精选项目</span>
{ current && <a className="color-blue" onClick={()=>setVisible(true)}>自定义精选项目</a> }
</AlignAJBottom>
<div>
<ul className="concentrateUl">
{
list.map((i,k)=>{
return(
<li>
<Link to={`/projects/${userLogin}/${i.identifier}`} className="name">{i.name}</Link>
<p className="task-hide desc">{i.description}</p>
<AlignCenter>
{ i.category && <span className="tagName">{i.category.name}</span> }
<span className="pariseCount"><i className="iconfont icon-guanzhu"></i>{i.watchers_count}</span>
<span className="forkCount"><i className="iconfont icon-fork"></i>{i.forked_count}</span>
</AlignCenter>
</li>
)
})
}
</ul>
</div>
</div>
}
{
list && list.length === 0 && current && <div className="ConcentrateTip"><i className="iconfont icon-tishi2"></i>你还没有设置精选项目<a onClick={()=>setVisible(true)}>点击设置</a></div>
}
</Spin>
)
}
export default ConcentrateProject;

View File

@ -0,0 +1,55 @@
import React, { useState } from 'react';
import './Index.scss';
import 'echarts/lib/component/tooltip';
import 'echarts/lib/component/title';
import 'echarts/lib/component/legend'
import 'echarts/lib/component/markPoint';
import { Select , Pagination } from 'antd';
import { FlexAJ } from '../../Component/layout';
import Line from '../Echart/Line';
import Calendar from '../Echart/Calendar';
import ConcentrateProject from './ConcentrateProject';
import Activity from './Activity';
const aLimit = 5;
function Index(props) {
const [ page , setPage ] = useState(1);
const [ total , setTotal ] = useState(0);
const username = props.match.params.username;
const current_user = props.current_user;
//
function chooseTime(data) {
if(data){
console.log(data);
}
}
return(
<div>
<div>
<ConcentrateProject userLogin={username} current={current_user && (current_user.login === username)}/>
</div>
<div className="recentStatic">
<Line />
</div>
<div className="calendarStatic">
<FlexAJ>
<span className="font-18">贡献度</span>
<Select style={{width:"200px"}} placeholder="选择年份">
<Select.Option key="2021">2021</Select.Option>
</Select>
</FlexAJ>
<Calendar time={''} userLogin={username} chooseTime={chooseTime}/>
</div>
<div className="activeStatic">
<span className="font-18">动态</span>
<Activity />
{ total > aLimit && <div style={{textAlign:'center',paddingBottom:"30px"}}><Pagination pageSize={aLimit} current={page} total={total} onChange={(p)=>setPage(p)}/></div> }
</div>
</div>
)
}
export default Index;

View File

@ -0,0 +1,128 @@
.concentrate{
padding:20px 30px;
.concentrateUl{
display: flex;
flex-wrap: wrap;
margin-top: 15px;
li{
width: 48.5%;
margin-right: 3%;
margin-bottom: 20px;
display: flex;
flex-direction: column;
justify-content: flex-start;
background-color: #fafafa;
padding:15px 20px;
cursor: default ;
&:nth-child(2n){
margin-right: 0px;
}
.name{
font-size: 16px;
color: #4CACFF;
}
.desc{
color: #999;
}
.tagName{
display: block;
background-color: #f7f5f5;
border-radius: 3px;
color: #666;
padding:0px 10px;
height: 22px;
line-height: 22px;
font-size: 13px;
}
.pariseCount,.forkCount{
i{
font-size: 14px!important;
margin-right: 4px;
}
color: #999;
margin-left: 20px;
}
}
}
}
.ConcentrateTip{
margin:20px 30px;
padding:5px 20px;
border:1px solid rgb(248, 56, 56);
border-radius: 4px;
background-color: rgba(248, 56, 56,0.1);
color: rgb(248, 56, 56);
display: flex;
align-items: center;
a{
color: #4cacff;
}
i{
font-size: 15px!important;
margin-right: 5px;
}
}
.ConcentrateBox{
.ant-modal-body{
min-height: 258px;
}
.ant-checkbox-group{
display: flex;
flex-wrap: wrap;
.ant-checkbox-wrapper{
width: 50%;
margin-left: 0px!important;
display: flex;
.ant-checkbox{
padding-top: 3px;
}
span:last-child{
flex:1;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
}
}
.recentStatic{
padding-bottom: 30px;
}
.calendarStatic,.activeStatic{
padding:0px 30px;
.infosActivity{
padding-bottom: 30px;
&>li{
display: flex;
border-bottom:1px solid #eee;
align-items: center;
padding:20px 0px;
.aImg{
width: 48px;
height: 48px;
margin-right: 20px;
border-radius: 50%;
}
.aInfos{
flex: 1;
span{
margin-left: 20px;
margin-right: 0px;
}
.name{
font-size: 16px;
color:#333;
}
.time,.status{
color: #999;
}
.aDesc{
color: #666;
margin-top: 5px;
line-height: 20px;
}
}
}
}
}

View File

@ -1,6 +1,6 @@
$flex:flex;
.headerbox{
padding:20px 40px;
padding:20px 30px;
border-bottom: 1px solid #E0E0E0;
display: $flex;
align-items: center;
@ -25,7 +25,7 @@ $flex:flex;
}
}
.contentBox{
padding:20px 40px 0px 40px;
padding:20px 30px 0px 30px;
& > div{
margin-bottom: 20px;
display: $flex;
@ -97,6 +97,7 @@ ul.ant-menu.menuStyle{
line-height: 70px;
padding:0px;
margin-right: 30px!important;
border-bottom:transparent!important;
}
}
.disposeInfo{
@ -135,4 +136,31 @@ ul.ant-menu.menuStyle{
padding:28px 0px;
border-bottom: 1px solid #eee;
}
}
.infosRightMenu{
padding:0px 10px;
.ant-menu-item{
padding:0px;
margin:0px 20px!important;
font-size: 17px;
height: 60px;
line-height: 60px;
border-bottom: 2px solid transparent!important;
position: relative;
.menuNum{
font-size: 12px;
margin-left: 3px;
color: #FF6E21;
}
&.ant-menu-item-selected::before{
position: absolute;
width: 16px;
bottom: 7px;
height: 2px;
left: 0px;
background-color: #1890ff;
content:"";
}
}
}

View File

@ -1,6 +1,6 @@
import React, { Component } from "react";
import { Link } from "react-router-dom";
import { Avatar, Tag, Button, Spin } from "antd";
import { Avatar, Tag, Button, Spin , Menu } from "antd";
import FocusButton from "../UsersList/focus_button";
import axios from "axios";
@ -23,6 +23,15 @@ const InfosDevOpsCD = Loadable({
loader: () => import("./devOpsCD"),
loading: Loading,
});
const Statistics = Loadable({
loader: () => import("./Statistics/Index"),
loading: Loading,
});
const GeneralView = Loadable({
loader: () => import("./GeneralView/Index"),
loading: Loading,
});
const InfosUser = Loadable({
loader: () => import("./InfosUser"),
loading: Loading,
@ -41,8 +50,8 @@ const FanUser = Loadable({
loading: Loading,
})
const UndoEvents = Loadable({
loader: () => import("./undo_events"),
const Notice = Loadable({
loader: () => import("../Notice/Index"),
loading: Loading,
})
class Infos extends Component {
@ -52,19 +61,52 @@ class Infos extends Component {
isSpin: false,
user: undefined,
project_type: undefined,
route_type: undefined
route_type: undefined,
undo_events:0,
undo_messages:0,
menuKey:"0"
};
}
renderPath=(pathname)=>{
const { username } = this.props.match.params;
if(pathname === `/users/${username}`){
this.setState({menuKey:"0"});
}else if(pathname === `/users/${username}/statistics`){
this.setState({menuKey:"1"});
}else if(pathname.indexOf(`/users/${username}/projects`)>-1){
this.setState({menuKey:"2"});
}else if(pathname === `/users/${username}/notice`){
this.setState({menuKey:"3"});
}else if(pathname.indexOf(`/users/${username}/devops`)>-1){
this.setState({menuKey:"4"});
}else if(pathname === `/users/${username}/organizes`){
this.setState({menuKey:"5"});
}
}
componentDidMount = () => {
this.fetchUser();
const { pathname } = this.props.location;
this.renderPath(pathname);
};
componentDidUpdate=(prevProps)=>{
const { username } = this.props.match.params;
const prevUser = prevProps.match.params.username;
if(prevUser && username && prevUser !== username){
this.fetchUser();
}
const { pathname } = this.props.location;
const prevPath = prevProps.location.pathname;
if(prevPath && pathname && prevPath !== pathname){
this.renderPath(pathname);
}
this.props.history.listen(()=>{
if (document.body.scrollTop || document.documentElement.scrollTop > 0) {
window.scrollTo(0, 0)
}
})
}
fetchUser = () => {
@ -73,14 +115,22 @@ class Infos extends Component {
});
const { current_user } = this.props;
const { username } = this.props.match.params;
const { pathname } = this.props.location;
const { notice } = this.state;
let url = `/users/${username || (current_user && current_user.login)}.json`;
axios
.get(url)
.then((result) => {
let e = result.data && result.data.undo_events;
let p = result.data && result.data.undo_messages;
let n = notice || pathname === `/users/${username}/notice` ;
this.setState({
user: result.data,
isSpin: false,
undo_events:n ? (e-p) : e,
undo_messages:0,
notice:n
});
})
.catch((error) => {
@ -90,19 +140,19 @@ class Infos extends Component {
});
};
change_project_type = (type) => {
const {user} = this.state
this.setState({
project_type: type ,
route_type: undefined
})
let url = `/users/${user && user.login}`
if (type){
url = `/users/${user && user.login}/projects/${type}`
}
this.props.history.push(url)
// change_project_type = (type) => {
// const {user} = this.state
// this.setState({
// project_type: type ,
// route_type: undefined
// })
// let url = `/users/${user && user.login}`
// if (type){
// url = `/users/${user && user.login}/projects/${type}`
// }
// this.props.history.push(url)
};
// };
change_devops_type=(type)=>{
const {user} = this.state;
@ -114,11 +164,15 @@ class Infos extends Component {
}
undo_link = () => {
const {user} = this.state
const {user } = this.state;
this.setState({
route_type: undefined
route_type: undefined,
project_type:"notice",
notice:true
},()=>{
this.props.history.push(`/users/${user && user.login}/notice`);
this.fetchUser();
})
this.props.history.push(`/users/${user && user.login}/undo_events`)
}
route_link = (type) => {
@ -130,7 +184,8 @@ class Infos extends Component {
organize_link = () => {
const {user} = this.state
this.setState({
route_type: undefined
route_type: undefined,
project_type:"organizes"
})
this.props.history.push(`/users/${user && user.login}/organizes`)
}
@ -140,18 +195,15 @@ class Infos extends Component {
const { current_user, mygetHelmetapi } = this.props;
const { username } = this.props.match.params;
const { user, isSpin, project_type, route_type } = this.state;
const { user, isSpin, project_type, route_type , undo_events , undo_messages , menuKey } = this.state;
return (
<div className="newMain clearfix">
<Spin spinning={isSpin}>
<div className="new-content-flex">
<div className="list-left" style={{border:"none"}}>
<div className="bgcF">
<div className="list-l-Menu text-center pd20 ">
<Avatar
size={110}
src={getImageUrl(`/${user && user.image_url}`)}
/>
<div className="list-l-Menu text-center pd20">
<Avatar size={110} src={getImageUrl(`/${user && user.image_url}`)} />
{user && user.user_identity && (
<div className="mt-n15 position-relative">
<Tag color="#FF6E21" style={{marginRight:"0px"}}>{user && user.user_identity}</Tag>
@ -160,7 +212,6 @@ class Infos extends Component {
<div className="text-center mt15 font-16 fwb">
{user && user.username}
</div>
<div>
{user && current_user && user.login === current_user.login && (
<div className="user-info-star-button ">
@ -211,85 +262,74 @@ class Infos extends Component {
</div>
</div>
</div>
{/* {current_user && user && current_user.id === user.id && (
<div className="bgcF">
<div className="list-l-Menu">
<p className="list-l-p pd20" onClick={() => this.undo_link()}>
{/* <div className="bgcF">
<div className="list-l-Menu">
<li className={project_type && project_type === "notice" ? "active" : ""}>
<p onClick={() => this.undo_link()}>
<span className="font-16 color-grey-3">
<i className="iconfont icon-dahuizhongzuo3x font-15 mr5"></i>
待办事项
</span>
<span className="text-yellow font-16">
{user.undo_events}
{undo_events}
</span>
</p>
</div>
</li>
</div>
)} */}
</div>
<div className="bgcF">
<ul className="list-l-Menu">
<li className="MenuTitle" onClick={() => this.change_project_type(undefined)}>
<i className="iconfont icon-xiangmuleixing font-15 mr5"></i>
项目类型
<i className="iconfont icon-youjiantou font-15 mr20 color-grey-9 pull-right"></i>
</li>
<li className={project_type && project_type === "common" ? "active" : ""} onClick={() => this.change_project_type("common")}>
<p>
<span className="font-16">开源托管项目</span>
<span className="color-blue">
{user && user.common_projects_count}
</span>
</p>
</li>
<li className={project_type && project_type === "mirror" ? "active" : ""} onClick={() => this.change_project_type("mirror")}>
<p>
<span className="font-16">开源镜像项目</span>
<span className="color-blue">
{user && user.mirror_projects_count}
</span>
</p>
</li>
<li className={project_type && project_type === "sync_mirror" ? "active" : ""} onClick={() => this.change_project_type("sync_mirror")}>
<p>
<span className="font-16">镜像托管项目</span>
<span className="color-blue">
{user && user.sync_mirror_projects_count}
</span>
</p>
</li>
</ul>
</div>
<div className="bgcF">
<ul className="list-l-Menu">
<li className="MenuTitle" onClick={() => this.change_project_type(undefined)}>
<i className="iconfont icon-xiangmuleixing font-15 mr5"></i>
项目类型
<li className="MenuTitle">
<i className="iconfont icon-gongzuoliu font-15 mr5"></i>
DevOps工作流
<i className="iconfont icon-youjiantou font-15 mr20 color-grey-9 pull-right"></i>
</li>
<li className={project_type && project_type === "common" ? "active" : ""} onClick={() => this.change_project_type("common")}>
<li className={project_type && project_type === "CIService" ? "active" : ""} onClick={() => this.change_devops_type("CIService")}>
<p>
<span className="font-16">开源托管项目</span>
<span className="color-blue">
{user && user.common_projects_count}
</span>
</p>
</li>
<li className={project_type && project_type === "mirror" ? "active" : ""} onClick={() => this.change_project_type("mirror")}>
<p>
<span className="font-16">开源镜像项目</span>
<span className="color-blue">
{user && user.mirror_projects_count}
</span>
</p>
</li>
<li className={project_type && project_type === "sync_mirror" ? "active" : ""} onClick={() => this.change_project_type("sync_mirror")}>
<p>
<span className="font-16">镜像托管项目</span>
<span className="color-blue">
{user && user.sync_mirror_projects_count}
</span>
<span className="font-16 color-grey-3">CI服务</span>
</p>
</li>
</ul>
</div>
{
current_user && current_user.login && current_user.login === username &&
<div className="bgcF">
<ul className="list-l-Menu">
<li className="MenuTitle">
<i className="iconfont icon-gongzuoliu font-15 mr5"></i>
DevOps工作流
<i className="iconfont icon-youjiantou font-15 mr20 color-grey-9 pull-right"></i>
</li>
<li className={project_type && project_type === "CIService" ? "active" : ""} onClick={() => this.change_devops_type("CIService")}>
<p>
<span className="font-16 color-grey-3">CI服务</span>
</p>
</li>
{/* <li className={project_type && project_type === "CDService" ? "active" : ""} onClick={() => this.change_devops_type("CDService")}>
<p>
<span className="font-16">CD服务</span>
<span className="color-blue">
{user && user.common_projects_count}
</span>
</p>
</li> */}
</ul>
</div>
}
<div className="bgcF">
<div className="list-l-Menu">
<p className="list-l-p pd20" onClick={() => this.organize_link()} >
<div className="bgcF">
<div className="list-l-Menu">
<li className={project_type && project_type === "organizes" ? "active" : ""}>
<p onClick={() => this.organize_link()} >
<span className="font-16 color-grey-3">
<i className="iconfont icon-itsm-liuchengguanli font-15 mr5"></i>
组织
@ -298,72 +338,93 @@ class Infos extends Component {
{user && user.user_org_count}
</span>
</p>
</div>
</li>
</div>
</div> */}
</div>
<div className="list-right">
<Menu selectedKeys={[menuKey]} mode={`horizontal`} className="infosRightMenu">
<Menu.Item key="0"><Link to={`/users/${user && user.login}`}>概览</Link></Menu.Item>
<Menu.Item key="1"><Link to={`/users/${user && user.login}/statistics`}>数据统计</Link></Menu.Item>
<Menu.Item key="2"><Link to={`/users/${user && user.login}/projects/common`}>项目</Link></Menu.Item>
{
current_user && user && user.login === current_user.login ?
<Menu.Item key="3"><Link to={`/users/${user && user.login}/notice`}>待办事项<span className="menuNum">({undo_events})</span></Link></Menu.Item>
:""
}
{
current_user && current_user.login && current_user.login === username ?
<Menu.Item key="4"><Link to={`/users/${user && user.login}/devops/CIService`}>DevOps工作流</Link></Menu.Item>
:""
}
<Menu.Item key="5"><Link to={`/users/${user && user.login}/organizes`}>组织<span className="menuNum">({user && user.user_org_count})</span></Link></Menu.Item>
</Menu>
{user && (
<div>
<Switch {...this.props}>
<Switch {...this.props}>
<Route
path="/users/:username/watchers"
render={() => {
return <WatchsUser {...this.props} {...this.state} userType="watchers" />;
}}
></Route>
<Route
path="/users/:username/watchers"
render={() => {
return <WatchsUser {...this.props} {...this.state} userType="watchers" />;
}}
></Route>
<Route
path="/users/:username/undo_events"
render={() => {
return <UndoEvents {...this.props} {...this.state} />;
}}
></Route>
<Route
path="/users/:username/fan_users"
render={() => {
return <FanUser {...this.props} {...this.state} userType="fan_users"/>;
}}
></Route>
<Route
path="/users/:username/devops/CDService"
render={() => {
return <InfosDevOpsCD {...this.props} {...this.state} />;
}}
></Route>
<Route
path="/users/:username/devops/CIService"
render={() => {
return <InfosDevOps {...this.props} {...this.state} />;
}}
></Route>
<Route
path="/users/:username/projects/:project_type"
render={() => {
return <InfosUser {...this.props} {...this.state} />;
}}
></Route>
<Route
path="/users/:username/organizes"
render={() => {
return <Organize {...this.props} {...this.state} />;
}}
></Route>
<Route
path="/users/:username"
render={(props) => {
return <InfosUser {...this.props} {...this.state} />;
}}
></Route>
<Route
path="/"
render={(props) => {
return <InfosUser {...this.props} {...this.state} />;
}}
></Route>
</Switch>
</div>
path="/users/:username/notice"
render={() => {
return <Notice {...this.props} {...this.state} fetchUser={this.fetchUser}/>;
}}
></Route>
<Route
path="/users/:username/fan_users"
render={() => {
return <FanUser {...this.props} {...this.state} userType="fan_users"/>;
}}
></Route>
<Route
path="/users/:username/devops/CDService"
render={() => {
return <InfosDevOpsCD {...this.props} {...this.state} />;
}}
></Route>
<Route
path="/users/:username/devops/CIService"
render={() => {
return <InfosDevOps {...this.props} {...this.state} />;
}}
></Route>
<Route
path="/users/:username/projects/:project_type"
render={() => {
return <InfosUser {...this.props} {...this.state} />;
}}
></Route>
<Route
path="/users/:username/organizes"
render={() => {
return <Organize {...this.props} {...this.state} />;
}}
></Route>
<Route
path="/users/:username/statistics"
render={(props) => {
return <Statistics {...this.props} {...this.state} />;
}}
></Route>
<Route
path="/users/:username"
render={(props) => {
return <GeneralView {...this.props} {...this.state} />;
}}
></Route>
<Route
path="/"
render={(props) => {
return <GeneralView {...this.props} {...this.state} />;
}}
></Route>
</Switch>
)}
</div>
</div>
</div>
</Spin>
</div>
);

View File

@ -100,9 +100,6 @@ class InfosUser extends Component {
const {is_public} = this.state
const new_is_public = is_public === check_is_public ? undefined : check_is_public
// this.setState({
// is_public: new_is_public
// })
this.state.is_public = new_is_public
this.get_projects(new_is_public);
}

View File

@ -0,0 +1,21 @@
import React from 'react';
import './Index.scss';
import 'echarts/lib/component/tooltip';
import 'echarts/lib/component/title';
import 'echarts/lib/component/legend'
import 'echarts/lib/component/markPoint';
import Pie from '../Echart/Pie';
import Cloud from '../Echart/Cloud';
import Radar from '../Echart/Radar';
function Index() {
return(
<div>
<Pie />
<Cloud />
<Radar />
</div>
)
}
export default Index;

View File