Merge pull request '修改头像、组织添加成员等功能' (#333) from caishi/forgeplus-react:gitlink_server into gitlink_server
This commit is contained in:
commit
7416d9bcb6
|
@ -3934,6 +3934,11 @@
|
||||||
"warning": "^4.0.3"
|
"warning": "^4.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"cropperjs": {
|
||||||
|
"version": "1.5.12",
|
||||||
|
"resolved": "https://registry.npmmirror.com/cropperjs/download/cropperjs-1.5.12.tgz",
|
||||||
|
"integrity": "sha1-2cDbK/uMDXadUXOej5FrvEThD1A="
|
||||||
|
},
|
||||||
"cross-env": {
|
"cross-env": {
|
||||||
"version": "7.0.3",
|
"version": "7.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz",
|
||||||
|
@ -14227,6 +14232,14 @@
|
||||||
"countup.js": "^2.0.8"
|
"countup.js": "^2.0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"react-cropper": {
|
||||||
|
"version": "2.1.8",
|
||||||
|
"resolved": "https://registry.npmmirror.com/react-cropper/download/react-cropper-2.1.8.tgz?cache=0&sync_timestamp=1634379691101&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Freact-cropper%2Fdownload%2Freact-cropper-2.1.8.tgz",
|
||||||
|
"integrity": "sha1-vzWn3mV2n4rTV+iuiE55H+P+khI=",
|
||||||
|
"requires": {
|
||||||
|
"cropperjs": "^1.5.12"
|
||||||
|
}
|
||||||
|
},
|
||||||
"react-datepicker": {
|
"react-datepicker": {
|
||||||
"version": "2.14.1",
|
"version": "2.14.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-2.14.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-2.14.1.tgz",
|
||||||
|
|
|
@ -85,6 +85,7 @@
|
||||||
"react-content-loader": "^3.1.1",
|
"react-content-loader": "^3.1.1",
|
||||||
"react-cookies": "^0.1.1",
|
"react-cookies": "^0.1.1",
|
||||||
"react-countup": "^6.1.0",
|
"react-countup": "^6.1.0",
|
||||||
|
"react-cropper": "^2.1.8",
|
||||||
"react-datepicker": "^2.14.1",
|
"react-datepicker": "^2.14.1",
|
||||||
"react-dev-utils": "^9.2.0-next.80",
|
"react-dev-utils": "^9.2.0-next.80",
|
||||||
"react-dom": "^16.13.1",
|
"react-dom": "^16.13.1",
|
||||||
|
|
|
@ -7,6 +7,8 @@ export const Banner = styled.div`{
|
||||||
border-bottom:1px solid #eee;
|
border-bottom:1px solid #eee;
|
||||||
background-color:#fff;
|
background-color:#fff;
|
||||||
border-radius:5px 5px 0px 0px;
|
border-radius:5px 5px 0px 0px;
|
||||||
|
justify-content: space-between;
|
||||||
|
display: flex;
|
||||||
}`
|
}`
|
||||||
export const AlignCenterBetween = styled.div`{
|
export const AlignCenterBetween = styled.div`{
|
||||||
display:flex;
|
display:flex;
|
||||||
|
|
|
@ -42,8 +42,8 @@ class NewHeader extends Component {
|
||||||
setevaluatinghides: false,
|
setevaluatinghides: false,
|
||||||
occupation: 0,
|
occupation: 0,
|
||||||
mydisplay: false,
|
mydisplay: false,
|
||||||
headtypesonClickbool: false,
|
// headtypesonClickbool: false,
|
||||||
headtypess: "/",
|
// headtypess: "/",
|
||||||
settings: null,
|
settings: null,
|
||||||
visiblemyss: false,
|
visiblemyss: false,
|
||||||
openSearch:false,
|
openSearch:false,
|
||||||
|
@ -137,12 +137,12 @@ class NewHeader extends Component {
|
||||||
AccountProfiletype: false
|
AccountProfiletype: false
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
headtypesonClick = (url, bool) => {
|
// headtypesonClick = (url, bool) => {
|
||||||
this.setState({
|
// this.setState({
|
||||||
headtypess: url,
|
// headtypess: url,
|
||||||
headtypesonClickbool: bool,
|
// headtypesonClickbool: bool,
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
//获取数据为空的时候
|
//获取数据为空的时候
|
||||||
gettablogourlnull = () => {
|
gettablogourlnull = () => {
|
||||||
this.setState({
|
this.setState({
|
||||||
|
@ -295,12 +295,14 @@ class NewHeader extends Component {
|
||||||
{...this.props}
|
{...this.props}
|
||||||
{...this.state}
|
{...this.state}
|
||||||
/> : ""}
|
/> : ""}
|
||||||
{
|
<div style={{width:"78px"}}>
|
||||||
publicNav &&
|
{
|
||||||
<a href={'https://www.ccf.org.cn/'} className={"fl pr15"}>
|
publicNav &&
|
||||||
<img src={MainLogo} alt="ccf" />
|
<a href={'https://www.ccf.org.cn/'} className={"fl"}>
|
||||||
</a>
|
<img src={MainLogo} alt="ccf" />
|
||||||
}
|
</a>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
{
|
{
|
||||||
settings && settings.nav_logo_url ?
|
settings && settings.nav_logo_url ?
|
||||||
<a href={settings && settings.new_course.default_url} className={"fl mr50"}>
|
<a href={settings && settings.new_course.default_url} className={"fl mr50"}>
|
||||||
|
@ -316,26 +318,26 @@ class NewHeader extends Component {
|
||||||
{
|
{
|
||||||
settings.navbar && settings.navbar.map((item, key) => {
|
settings.navbar && settings.navbar.map((item, key) => {
|
||||||
var new_link = item.link;
|
var new_link = item.link;
|
||||||
var user_login = current_user && current_user.login;
|
// var user_login = current_user && current_user.login;
|
||||||
var is_hidden = item.hidden
|
var is_hidden = item.hidden;
|
||||||
if (new_link && (new_link.indexOf("courses") > -1 || new_link.indexOf("contests") > -1)) {
|
// if (new_link && (new_link.indexOf("courses") > -1 || new_link.indexOf("contests") > -1)) {
|
||||||
if (user_login) {
|
// if (user_login) {
|
||||||
if (new_link.indexOf("courses") > -1) {
|
// if (new_link.indexOf("courses") > -1) {
|
||||||
new_link = new_link.replace(/courses/g, user_login + "/courses")
|
// new_link = new_link.replace(/courses/g, user_login + "/courses")
|
||||||
} else if (new_link.indexOf("contests") > -1) {
|
// } else if (new_link.indexOf("contests") > -1) {
|
||||||
new_link = new_link.replace(/contests/g, user_login + "/contests")
|
// new_link = new_link.replace(/contests/g, user_login + "/contests")
|
||||||
}
|
// }
|
||||||
} else {
|
// } else {
|
||||||
is_hidden = true
|
// is_hidden = true
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
if (user_login && (new_link && new_link.indexOf("homes") > -1)) {
|
// if (user_login && (new_link && new_link.indexOf("homes") > -1)) {
|
||||||
new_link = new_link.replace(/homes/g, user_login + "/user_activities")
|
// new_link = new_link.replace(/homes/g, user_login + "/user_activities")
|
||||||
}
|
// }
|
||||||
var waiLian = (new_link && str.filter(item=>new_link.indexOf(item)>-1) );
|
var waiLian = (new_link && str.filter(item=>new_link.indexOf(item)>-1) );
|
||||||
var wl = waiLian && waiLian.length>0;
|
var wl = waiLian && waiLian.length>0;
|
||||||
return (
|
return (
|
||||||
<li key={key} onClick={() => this.headtypesonClick(item.link, true)} className={`${this.matchpaths(new_link) === true ? 'pr active' : 'pr'}`} style={!is_hidden ? { display: 'flex' } : { display: 'none' }}>
|
<li key={key} className={`${this.matchpaths(new_link) === true ? 'pr active' : 'pr'}`} style={{display:!is_hidden ? 'flex' : 'none'} }>
|
||||||
<a href={new_link} target={wl ? "_self":"_blank"}>{item.name}</a>
|
<a href={new_link} target={wl ? "_self":"_blank"}>{item.name}</a>
|
||||||
</li>
|
</li>
|
||||||
)
|
)
|
||||||
|
@ -350,7 +352,6 @@ class NewHeader extends Component {
|
||||||
{
|
{
|
||||||
current_user && (current_user.main_site || current_user.login) && (settings && settings.add && settings.add.length>0)?
|
current_user && (current_user.main_site || current_user.login) && (settings && settings.add && settings.add.length>0)?
|
||||||
<Dropdown overlay={this.addMenu(settings && settings.add)} placement="bottomRight">
|
<Dropdown overlay={this.addMenu(settings && settings.add)} placement="bottomRight">
|
||||||
{/* <i className="iconfont icon-tianjiafangda ml30 mr15"></i> */}
|
|
||||||
<img src={require(`./img/add.png`)} alt="" width="16px" className="mr15 ml30"/>
|
<img src={require(`./img/add.png`)} alt="" width="16px" className="mr15 ml30"/>
|
||||||
</Dropdown>:""
|
</Dropdown>:""
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,8 +36,9 @@ const Infos = styled.div`
|
||||||
}
|
}
|
||||||
& > .f-wrap-between {
|
& > .f-wrap-between {
|
||||||
padding: 14px 20px 14px 16px;
|
padding: 14px 20px 14px 16px;
|
||||||
border-radius: 3px 3px 0px 0px;
|
border-radius: 0px 0px 3px 3px;
|
||||||
border: 1px solid #D0D0D0;
|
border: 1px solid #D0D0D0;
|
||||||
|
border-top: none;
|
||||||
.df{
|
.df{
|
||||||
align-items: center;
|
align-items: center;
|
||||||
& .underline:hover{
|
& .underline:hover{
|
||||||
|
|
|
@ -321,7 +321,7 @@ class MilepostDetail extends Component {
|
||||||
</div>
|
</div>
|
||||||
{
|
{
|
||||||
search_count > limit?
|
search_count > limit?
|
||||||
<div className="mt30 pb30 edu-txt-center">
|
<div className="pt30 pb30 edu-txt-center" style={{borderTop:"1px solid #eee"}}>
|
||||||
<Pagination simple current={page} total={search_count} pageSize={limit} onChange={this.ChangePage}></Pagination>
|
<Pagination simple current={page} total={search_count} pageSize={limit} onChange={this.ChangePage}></Pagination>
|
||||||
</div>:""
|
</div>:""
|
||||||
}
|
}
|
||||||
|
|
|
@ -232,6 +232,9 @@
|
||||||
border-bottom: 1px solid #eee;
|
border-bottom: 1px solid #eee;
|
||||||
padding: 16px 0px 16px 20px;
|
padding: 16px 0px 16px 20px;
|
||||||
}
|
}
|
||||||
|
.issueItem:last-child{
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
.issueNo {
|
.issueNo {
|
||||||
padding: 0px 5px;
|
padding: 0px 5px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
|
|
|
@ -6,7 +6,7 @@ import moment from 'moment';
|
||||||
|
|
||||||
import NoneData from "../Nodata";
|
import NoneData from "../Nodata";
|
||||||
import OrderItem from "./OrderItem";
|
import OrderItem from "./OrderItem";
|
||||||
import CheckProfile from '../Component/ProfileModal/Profile';
|
import cookie from 'react-cookies';
|
||||||
|
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
|
||||||
|
@ -76,6 +76,14 @@ class order extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount = () => {
|
componentDidMount = () => {
|
||||||
|
// const selectParams = cookie.load('selectParams');
|
||||||
|
// let states = selectParams.select_params;
|
||||||
|
// this.setState({
|
||||||
|
// ...states
|
||||||
|
// },()=>{
|
||||||
|
// this.getSelectList();
|
||||||
|
// this.getIssueList('1');
|
||||||
|
// })
|
||||||
this.getSelectList();
|
this.getSelectList();
|
||||||
this.getIssueList('1');
|
this.getIssueList('1');
|
||||||
};
|
};
|
||||||
|
@ -102,11 +110,11 @@ class order extends Component {
|
||||||
|
|
||||||
// 获取列表数据
|
// 获取列表数据
|
||||||
getIssueList = (status_type, begin, end) => {
|
getIssueList = (status_type, begin, end) => {
|
||||||
|
cookie.remove('selectParams');
|
||||||
this.setState({
|
this.setState({
|
||||||
isSpin: true
|
isSpin: true
|
||||||
})
|
})
|
||||||
const { select_params } = this.state;
|
const { select_params } = this.state;
|
||||||
console.log(select_params);
|
|
||||||
const { projectsId, owner } = this.props.match.params;
|
const { projectsId, owner } = this.props.match.params;
|
||||||
const url = `/${owner }/${projectsId}/issues.json`;
|
const url = `/${owner }/${projectsId}/issues.json`;
|
||||||
axios
|
axios
|
||||||
|
@ -120,7 +128,9 @@ class order extends Component {
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
if (result) {
|
if (result) {
|
||||||
const issues = result.data.issues
|
const issues = result.data.issues;
|
||||||
|
// let inFifteenMinutes = new Date(new Date().getTime() + 24 * 3600 * 1000);
|
||||||
|
// cookie.save('selectParams', {states:this.state},{ expires: inFifteenMinutes,path:`/${owner}/${projectsId}/issues` });
|
||||||
this.setState({
|
this.setState({
|
||||||
data: result.data,
|
data: result.data,
|
||||||
issues: issues,
|
issues: issues,
|
||||||
|
@ -193,11 +203,12 @@ class order extends Component {
|
||||||
select_params,
|
select_params,
|
||||||
author_id,
|
author_id,
|
||||||
assigned_to_id
|
assigned_to_id
|
||||||
|
},()=>{
|
||||||
|
if (!toGet) {
|
||||||
|
const { status_type } = this.state;
|
||||||
|
this.getIssueList(status_type);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
if (!toGet) {
|
|
||||||
const { status_type } = this.state;
|
|
||||||
this.getIssueList(status_type);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
renderMenu = (array, name, id, toGet) => {
|
renderMenu = (array, name, id, toGet) => {
|
||||||
|
@ -852,7 +863,7 @@ class order extends Component {
|
||||||
)}
|
)}
|
||||||
{
|
{
|
||||||
search_count > select_params.limit ?
|
search_count > select_params.limit ?
|
||||||
<div className="mt30 mb30 edu-txt-center">
|
<div className="pt30 mb30 edu-txt-center" style={{borderTop:"1px solid #eee"}}>
|
||||||
<Pagination
|
<Pagination
|
||||||
simple
|
simple
|
||||||
defaultCurrent={select_params.page}
|
defaultCurrent={select_params.page}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React from "react";
|
import React, { useState } from "react";
|
||||||
|
|
||||||
import { Route, Switch } from "react-router-dom";
|
import { Route, Switch } from "react-router-dom";
|
||||||
import { withRouter } from "react-router";
|
import { withRouter } from "react-router";
|
||||||
|
@ -11,6 +11,7 @@ import Loading from "../../Loading";
|
||||||
import { Box , Gap , LongWidth } from '../Component/layout';
|
import { Box , Gap , LongWidth } from '../Component/layout';
|
||||||
import { getImageUrl } from 'educoder';
|
import { getImageUrl } from 'educoder';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
import Avatar from '../users/Avatar/Index';
|
||||||
|
|
||||||
import './Index.scss';
|
import './Index.scss';
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
@ -52,18 +53,38 @@ function Index(props){
|
||||||
const { pathname } = props.location;
|
const { pathname } = props.location;
|
||||||
const notice_url = mygetHelmetapi && mygetHelmetapi.common && mygetHelmetapi.common.notice;
|
const notice_url = mygetHelmetapi && mygetHelmetapi.common && mygetHelmetapi.common.notice;
|
||||||
|
|
||||||
|
const [ avatarVisible , setAvatarVisible ] = useState(false);
|
||||||
|
|
||||||
useEffect(()=>{
|
useEffect(()=>{
|
||||||
if(checkIfLogin() === false){
|
if(checkIfLogin() === false){
|
||||||
props.history.push('/login');
|
props.history.push('/login');
|
||||||
}
|
}
|
||||||
},[])
|
},[])
|
||||||
|
|
||||||
|
|
||||||
|
function onCancelAvatar(){
|
||||||
|
setAvatarVisible(false);
|
||||||
|
const { resetUserInfo } = props;
|
||||||
|
resetUserInfo && resetUserInfo();
|
||||||
|
}
|
||||||
return(
|
return(
|
||||||
<div className="newMain clearfix whiteBack">
|
<div className="newMain clearfix whiteBack">
|
||||||
|
{
|
||||||
|
avatarVisible &&
|
||||||
|
<Avatar
|
||||||
|
onCancel={onCancelAvatar}
|
||||||
|
avatarImg={getImageUrl(`/${current_user && current_user.image_url}`)}
|
||||||
|
login={current_user && current_user.login}
|
||||||
|
/>
|
||||||
|
}
|
||||||
<div className="boies">
|
<div className="boies">
|
||||||
<Box>
|
<Box>
|
||||||
<div className="shortW">
|
<div className="shortW">
|
||||||
<div className="userDetail">
|
<div className="userDetail">
|
||||||
<img src={getImageUrl(`/${current_user && current_user.image_url}`)} alt=""/>
|
<div className="userHeadPhoto">
|
||||||
|
<img src={getImageUrl(`/${current_user && current_user.image_url}`)} alt=""/>
|
||||||
|
<span className="userUpdateBox"onClick={()=>setAvatarVisible(true)}>修改头像</span>
|
||||||
|
</div>
|
||||||
<span>{current_user && current_user.username}</span>
|
<span>{current_user && current_user.username}</span>
|
||||||
</div>
|
</div>
|
||||||
<ul className="securityUl ul-border-buttom">
|
<ul className="securityUl ul-border-buttom">
|
||||||
|
|
|
@ -193,4 +193,31 @@
|
||||||
}
|
}
|
||||||
.blue-Purple{
|
.blue-Purple{
|
||||||
color: #466AFF !important;
|
color: #466AFF !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.userHeadPhoto{
|
||||||
|
width: 48px;
|
||||||
|
position: relative;
|
||||||
|
margin:0px auto;
|
||||||
|
.userUpdateBox{
|
||||||
|
font-size: 11px!important;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
line-height: 48px;
|
||||||
|
text-align: center;
|
||||||
|
position: absolute;
|
||||||
|
left: 0px;
|
||||||
|
top:0px;
|
||||||
|
background-color: rgba(0, 0, 0, 0.2);
|
||||||
|
display: none!important;
|
||||||
|
color: white!important;
|
||||||
|
transition: 1s;
|
||||||
|
border-radius: 50%;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
&:hover{
|
||||||
|
.userUpdateBox{
|
||||||
|
display: block!important;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -76,10 +76,8 @@ function Index(props) {
|
||||||
subTitle={`删除后未来事件将不会推送至此Webhook地址:${url}`}
|
subTitle={`删除后未来事件将不会推送至此Webhook地址:${url}`}
|
||||||
/>
|
/>
|
||||||
<Banner>
|
<Banner>
|
||||||
<FlexAJ>
|
<span>Webhooks(网络钩子)</span>
|
||||||
<span>Webhooks(网络钩子)</span>
|
<Button type="primary" size="large" onClick={addFunc}>添加Webhook</Button>
|
||||||
<Button type="primary" size="large" onClick={addFunc}>添加Webhook</Button>
|
|
||||||
</FlexAJ>
|
|
||||||
</Banner>
|
</Banner>
|
||||||
<div className="hookpanel">
|
<div className="hookpanel">
|
||||||
<p className="color-grey-3">每当特定事件(如push代码,合并请求被编辑)发生时,我们将通过webhook给您提供的远程URL发送post请求。您可以在我们的<a className="color-blue hoverLine" target="_blank" href="https://forum.trustie.net/forums/3408/detail">webhooks指南</a>中了解更多信息</p>
|
<p className="color-grey-3">每当特定事件(如push代码,合并请求被编辑)发生时,我们将通过webhook给您提供的远程URL发送post请求。您可以在我们的<a className="color-blue hoverLine" target="_blank" href="https://forum.trustie.net/forums/3408/detail">webhooks指南</a>中了解更多信息</p>
|
||||||
|
|
|
@ -287,10 +287,10 @@ function New({ form , match , showNotification , history }) {
|
||||||
<Checkbox value="pull_request_label">合并请求标签</Checkbox>
|
<Checkbox value="pull_request_label">合并请求标签</Checkbox>
|
||||||
<span>合并请求的标签被更新或清除</span>
|
<span>合并请求的标签被更新或清除</span>
|
||||||
</span> */}
|
</span> */}
|
||||||
<span>
|
{/* <span>
|
||||||
<Checkbox value="pull_request_review">合并请求审查</Checkbox>
|
<Checkbox value="pull_request_review">合并请求审查</Checkbox>
|
||||||
<span>合并请求被批准、拒绝或提出审查意见,审查人员的修改,审查线程已解决或未解决</span>
|
<span>合并请求被批准、拒绝或提出审查意见,审查人员的修改,审查线程已解决或未解决</span>
|
||||||
</span>
|
</span> */}
|
||||||
{/* <span>
|
{/* <span>
|
||||||
<Checkbox value="pull_request_sync">合并请求被同步</Checkbox>
|
<Checkbox value="pull_request_sync">合并请求被同步</Checkbox>
|
||||||
<span>合并请求被同步</span>
|
<span>合并请求被同步</span>
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
import React ,{ useState , useEffect } from 'react';
|
||||||
|
import { Modal , Spin } from 'antd';
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
function AddMemberBox({className,orzId,history,OIdentifier}){
|
||||||
|
const [ visible , setVisible ] = useState(false);
|
||||||
|
const [ isSpin , setIsSpin ] = useState(true);
|
||||||
|
const [ list , setList ] = useState(undefined);
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
if(visible && orzId){
|
||||||
|
InitData();
|
||||||
|
}
|
||||||
|
},[orzId,visible])
|
||||||
|
|
||||||
|
function InitData(){
|
||||||
|
const url = `/organizations/${orzId}/teams.json`;
|
||||||
|
axios.get(url,{
|
||||||
|
params:{
|
||||||
|
is_full:true
|
||||||
|
}
|
||||||
|
}).then(result=>{
|
||||||
|
if(result){
|
||||||
|
setList(result.data.teams);
|
||||||
|
setIsSpin(false);
|
||||||
|
}
|
||||||
|
}).catch(error=>{})
|
||||||
|
}
|
||||||
|
|
||||||
|
function chooseGroup(id){
|
||||||
|
history.push(`/${OIdentifier}/teams/${id}/setting/member`);
|
||||||
|
}
|
||||||
|
return(
|
||||||
|
<div>
|
||||||
|
<Modal
|
||||||
|
visible={visible}
|
||||||
|
width="600px"
|
||||||
|
centered
|
||||||
|
title="添加成员"
|
||||||
|
onCancel={()=>setVisible(false)}
|
||||||
|
footer={null}
|
||||||
|
className="addMemberBody"
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
<p className="font-16 pt40 pb20 edu-txt-center">请选择想要添加成员的组织团队</p>
|
||||||
|
<Spin spinning={isSpin}>
|
||||||
|
<div className="addForGroupList">
|
||||||
|
{
|
||||||
|
list && list.length > 0 ?
|
||||||
|
<ul>
|
||||||
|
{
|
||||||
|
list.map((i,k)=>{
|
||||||
|
return(
|
||||||
|
<li onClick={()=>chooseGroup(i.id)}>{i.nickname}</li>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
:""
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</Spin>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
<a className={className} onClick={()=>setVisible(true)}>+ 添加成员</a>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default AddMemberBox;
|
|
@ -369,4 +369,48 @@
|
||||||
}
|
}
|
||||||
.hide{
|
.hide{
|
||||||
display: none;
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.addMemberBtn{
|
||||||
|
display: flex;
|
||||||
|
height: 34px;
|
||||||
|
line-height: 32px;
|
||||||
|
padding:0px 14px;
|
||||||
|
border-radius: 3px;
|
||||||
|
border:1px solid #d0d0d0;
|
||||||
|
font-size: 14px;
|
||||||
|
&:hover{
|
||||||
|
border-color: #466AFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.addMemberBody{
|
||||||
|
.ant-modal-body{
|
||||||
|
padding:0px;
|
||||||
|
}
|
||||||
|
.addForGroupList{
|
||||||
|
padding:20px 40px;
|
||||||
|
max-height: 315px;
|
||||||
|
overflow-y: auto;
|
||||||
|
ul{
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
width: 450px;
|
||||||
|
margin:0px auto;
|
||||||
|
}
|
||||||
|
li{
|
||||||
|
cursor: pointer;
|
||||||
|
border:1px solid #d0d0d0;
|
||||||
|
border-radius:4px;
|
||||||
|
margin:0px 10px 15px 10px!important;
|
||||||
|
height: 40px;
|
||||||
|
line-height: 40px;
|
||||||
|
width: 130px;
|
||||||
|
text-align: center;
|
||||||
|
&.active,&:hover{
|
||||||
|
color: #fff;
|
||||||
|
background-color: rgba(65, 84, 241, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -7,6 +7,7 @@ import styled from 'styled-components';
|
||||||
import { getImageUrl } from 'educoder';
|
import { getImageUrl } from 'educoder';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
import AddMemberBox from '../Component/AddMemberBox';
|
||||||
|
|
||||||
const Img = styled.img`{
|
const Img = styled.img`{
|
||||||
width:30px;
|
width:30px;
|
||||||
|
@ -14,7 +15,8 @@ const Img = styled.img`{
|
||||||
border-radius:50%;
|
border-radius:50%;
|
||||||
}`
|
}`
|
||||||
const limit = 15;
|
const limit = 15;
|
||||||
export default (({organizeDetail})=>{
|
export default (({organizeDetail,history,match})=>{
|
||||||
|
const OIdentifier = match.params.OIdentifier;
|
||||||
const [ page , setPage ] = useState(1);
|
const [ page , setPage ] = useState(1);
|
||||||
const [ total , setTotal ] = useState(0);
|
const [ total , setTotal ] = useState(0);
|
||||||
const [ search , setSearch ] = useState(undefined);
|
const [ search , setSearch ] = useState(undefined);
|
||||||
|
@ -116,6 +118,12 @@ export default (({organizeDetail})=>{
|
||||||
<SearchUser getUser={getUser}/>
|
<SearchUser getUser={getUser}/>
|
||||||
<Blueline className="ml30">+ 添加用户</Blueline>
|
<Blueline className="ml30">+ 添加用户</Blueline>
|
||||||
</AlignCenter> */}
|
</AlignCenter> */}
|
||||||
|
<AddMemberBox
|
||||||
|
className="addMemberBtn"
|
||||||
|
orzId={organizeDetail && organizeDetail.id}
|
||||||
|
history={history}
|
||||||
|
OIdentifier={OIdentifier}
|
||||||
|
/>
|
||||||
</Title>
|
</Title>
|
||||||
<FlexAJ className="padding20-30">
|
<FlexAJ className="padding20-30">
|
||||||
<div style={{width:"580px"}}>
|
<div style={{width:"580px"}}>
|
||||||
|
|
|
@ -4,9 +4,11 @@ import Cards from '../Component/MemberCards';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import Nodata from '../Nodata';
|
import Nodata from '../Nodata';
|
||||||
import { Pagination , Spin } from 'antd';
|
import { Pagination , Spin } from 'antd';
|
||||||
|
import AddMemberBox from './Component/AddMemberBox';
|
||||||
|
|
||||||
const limit = 15;
|
const limit = 15;
|
||||||
function TeamMember({organizeDetail,current_user}){
|
function TeamMember({organizeDetail,current_user,history,match}){
|
||||||
|
const OIdentifier = match.params.OIdentifier;
|
||||||
const [ page , setPage ] = useState(1);
|
const [ page , setPage ] = useState(1);
|
||||||
const [ total , setTotal ] = useState(0);
|
const [ total , setTotal ] = useState(0);
|
||||||
const [ isSpin , setIsSpin ] = useState(true);
|
const [ isSpin , setIsSpin ] = useState(true);
|
||||||
|
@ -34,7 +36,17 @@ function TeamMember({organizeDetail,current_user}){
|
||||||
|
|
||||||
return(
|
return(
|
||||||
<WhiteBack style={{marginBottom:"30px",border:'1px solid #eee'}}>
|
<WhiteBack style={{marginBottom:"30px",border:'1px solid #eee'}}>
|
||||||
<Banner>组织成员</Banner>
|
<Banner>组织成员
|
||||||
|
{
|
||||||
|
organizeDetail && organizeDetail.is_admin &&
|
||||||
|
<AddMemberBox
|
||||||
|
className="addMemberBtn"
|
||||||
|
orzId={organizeDetail && organizeDetail.id}
|
||||||
|
history={history}
|
||||||
|
OIdentifier={OIdentifier}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
</Banner>
|
||||||
<Spin spinning={isSpin}>
|
<Spin spinning={isSpin}>
|
||||||
<div style={{minHeight:"400px"}}>
|
<div style={{minHeight:"400px"}}>
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,102 @@
|
||||||
|
import React ,{useEffect, useRef, useState} from 'react';
|
||||||
|
import './Index.scss';
|
||||||
|
import { Modal , message } from 'antd';
|
||||||
|
import Cropper from 'react-cropper';
|
||||||
|
import 'cropperjs/dist/cropper.css';
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
function Index({onCancel,avatarImg,login}){
|
||||||
|
|
||||||
|
const [ avatarPhoto , setAvatarPhoto ] = useState(avatarImg);
|
||||||
|
|
||||||
|
useEffect(()=>{
|
||||||
|
if(avatarImg){
|
||||||
|
setAvatarPhoto(avatarImg);
|
||||||
|
}
|
||||||
|
},[avatarImg])
|
||||||
|
|
||||||
|
const cropper = useRef();
|
||||||
|
|
||||||
|
const saveAvatar = async () => {
|
||||||
|
const imgUrl = cropper.current.cropper.getCroppedCanvas().toDataURL("image/jpeg");
|
||||||
|
if (!imgUrl) {
|
||||||
|
message.info('请先上传图片');
|
||||||
|
}
|
||||||
|
const url = `/users/${login}/update_image.json`;
|
||||||
|
axios.put(url,{
|
||||||
|
image:imgUrl
|
||||||
|
}).then(result=>{
|
||||||
|
if(result){
|
||||||
|
message.success("头像修改成功!");
|
||||||
|
onCancel(true);
|
||||||
|
}
|
||||||
|
}).catch(error=>{})
|
||||||
|
}
|
||||||
|
|
||||||
|
function onChange(e){
|
||||||
|
|
||||||
|
let files;
|
||||||
|
if (e.dataTransfer) {
|
||||||
|
files = e.dataTransfer.files;
|
||||||
|
} else if (e.target) {
|
||||||
|
files = e.target.files;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!files || (files && files.length===0)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const file = files[0];
|
||||||
|
if (!/^image\/\w+/.test(file.type)) {
|
||||||
|
message.info('请选择一个图片格式的文件');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file.size > 2 * 1024 * 1024) {
|
||||||
|
message.info('仅支持文件大小小于2M的文件');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = () => {
|
||||||
|
setAvatarPhoto(reader.result);
|
||||||
|
};
|
||||||
|
reader.readAsDataURL(files[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(
|
||||||
|
<Modal
|
||||||
|
visible={true}
|
||||||
|
width="638px"
|
||||||
|
footer={null}
|
||||||
|
centered
|
||||||
|
title="修改头像"
|
||||||
|
onCancel={()=>onCancel(false)}
|
||||||
|
className="avatarBox"
|
||||||
|
>
|
||||||
|
<div className="avatarDiv">
|
||||||
|
<div>
|
||||||
|
<Cropper
|
||||||
|
style={{ height: 320, width: 320 }}
|
||||||
|
src={avatarPhoto}
|
||||||
|
guides={false}
|
||||||
|
preview="#updateAvatarImg"
|
||||||
|
ref={cropper}
|
||||||
|
aspectRatio={1}
|
||||||
|
/>
|
||||||
|
{/* <span className={"tips"}>仅支持JPG、GIF、PNG,且文件小于2M</span> */}
|
||||||
|
</div>
|
||||||
|
<div className="previewBox">
|
||||||
|
<div className={"previewImg"} id="updateAvatarImg"></div>
|
||||||
|
<div className="uploadBtn">
|
||||||
|
<label className={"uploadButton"} id="uploadBtn" htmlFor="inputImage">
|
||||||
|
<input type="file" className="sr-only" id="inputImage" name="file" accept="image/*" style={{ display: "none" }} onChange={onChange}></input>
|
||||||
|
点击上传
|
||||||
|
</label>
|
||||||
|
<a onClick={saveAvatar}>保存头像</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default Index;
|
|
@ -0,0 +1,66 @@
|
||||||
|
.avatarBox{
|
||||||
|
position: relative;
|
||||||
|
.ant-modal-header{
|
||||||
|
background-color: rgba(242, 242, 255, 1);
|
||||||
|
.ant-modal-title{
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-modal-body{
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.avatarDiv{
|
||||||
|
display: flex;
|
||||||
|
.previewBox{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-left: 30px;
|
||||||
|
.uploadBtn{
|
||||||
|
margin-bottom: 30px;
|
||||||
|
display: flex;
|
||||||
|
a,label{
|
||||||
|
cursor: pointer;
|
||||||
|
display: block;
|
||||||
|
height: 32px;
|
||||||
|
line-height: 30px;
|
||||||
|
margin:0px 10px;
|
||||||
|
width: 100px;
|
||||||
|
border:1px solid rgba(208, 208, 208, 1);
|
||||||
|
background-color: white;
|
||||||
|
border-radius:4px;
|
||||||
|
text-align: center;
|
||||||
|
color:#666666;
|
||||||
|
span{
|
||||||
|
display: block;
|
||||||
|
.ant-upload.ant-upload-select {
|
||||||
|
width: 100%;
|
||||||
|
height: 32px;
|
||||||
|
}
|
||||||
|
.ant-upload-list{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a{
|
||||||
|
background-color: rgba(65, 84, 241, 1);
|
||||||
|
color: white;
|
||||||
|
border-color: rgba(65, 84, 241, 1);
|
||||||
|
&:hover{
|
||||||
|
color: white!important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.previewImg{
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 50%;
|
||||||
|
text-align: center;
|
||||||
|
width: 100px!important;
|
||||||
|
height: 100px!important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -137,7 +137,6 @@
|
||||||
.infoBox span {
|
.infoBox span {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.headimg {
|
.headimg {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -150,8 +149,7 @@
|
||||||
.headimg span {
|
.headimg span {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: -6px;
|
bottom: -6px;
|
||||||
right: 0px;
|
right: -16px;
|
||||||
left: 65px;
|
|
||||||
}
|
}
|
||||||
.headimg span i {
|
.headimg span i {
|
||||||
font-size: 25px !important;
|
font-size: 25px !important;
|
||||||
|
|
|
@ -133,6 +133,32 @@ $flex:flex;
|
||||||
margin-left:10px ;
|
margin-left:10px ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.headimg-div{
|
||||||
|
width: 110px;
|
||||||
|
height: 110px;
|
||||||
|
margin:0px auto;
|
||||||
|
position: relative;
|
||||||
|
.updateAvatar{
|
||||||
|
cursor: pointer;
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 50%;
|
||||||
|
content: "";
|
||||||
|
left: 0px;
|
||||||
|
top:0px;
|
||||||
|
background-color: rgba(0,0,0,0.2);
|
||||||
|
display: none;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: white;
|
||||||
|
transition: 1s;
|
||||||
|
}
|
||||||
|
&:hover .updateAvatar{
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
.headimg{
|
.headimg{
|
||||||
position: relative;
|
position: relative;
|
||||||
display: block;
|
display: block;
|
||||||
|
@ -145,7 +171,7 @@ $flex:flex;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: -6px;
|
bottom: -6px;
|
||||||
right: 0px;
|
right: 0px;
|
||||||
left: 65px;
|
z-index: 11;
|
||||||
i{
|
i{
|
||||||
font-size: 25px!important;
|
font-size: 25px!important;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
import React, { Component } from "react";
|
import React, { Component } from "react";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { Button, Spin , Menu } from "antd";
|
import { Spin , Menu } from "antd";
|
||||||
import FocusButton from "../UsersList/focus_button";
|
import FocusButton from "../UsersList/focus_button";
|
||||||
|
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { getImageUrl } from "educoder";
|
import { getImageUrl } from "educoder";
|
||||||
import { Route, Switch } from "react-router-dom";
|
import { Route, Switch } from "react-router-dom";
|
||||||
|
import Avatar from './Avatar/Index';
|
||||||
|
|
||||||
import "./new_user.css";
|
import "./new_user.css";
|
||||||
import "../css/index.scss";
|
import "../css/index.scss";
|
||||||
|
@ -14,10 +15,10 @@ import './Index.scss';
|
||||||
import Loadable from "react-loadable";
|
import Loadable from "react-loadable";
|
||||||
import Loading from "../../Loading";
|
import Loading from "../../Loading";
|
||||||
|
|
||||||
const UpdateInfo = Loadable({
|
// const UpdateInfo = Loadable({
|
||||||
loader: () => import("./Material/Index"),
|
// loader: () => import("./Material/Index"),
|
||||||
loading: Loading,
|
// loading: Loading,
|
||||||
});
|
// });
|
||||||
const InfosDevOps = Loadable({
|
const InfosDevOps = Loadable({
|
||||||
loader: () => import("./devOpsCI"),
|
loader: () => import("./devOpsCI"),
|
||||||
loading: Loading,
|
loading: Loading,
|
||||||
|
@ -66,7 +67,8 @@ class Infos extends Component {
|
||||||
project_type: undefined,
|
project_type: undefined,
|
||||||
route_type: undefined,
|
route_type: undefined,
|
||||||
undo_events:0,
|
undo_events:0,
|
||||||
menuKey:"0"
|
menuKey:"0",
|
||||||
|
avatarVisible:false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,29 +195,59 @@ class Infos extends Component {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onCancelAvatar=(reset)=>{
|
||||||
|
this.setState({
|
||||||
|
avatarVisible:false
|
||||||
|
})
|
||||||
|
if(reset){
|
||||||
|
const { menuKey } = this.state;
|
||||||
|
if(menuKey === "2" || menuKey === "3"){
|
||||||
|
window.location.reload();
|
||||||
|
}else{
|
||||||
|
this.fetchUser();
|
||||||
|
const { resetUserInfo } = this.props;
|
||||||
|
resetUserInfo && resetUserInfo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { current_user } = this.props;
|
const { current_user } = this.props;
|
||||||
const { username } = this.props.match.params;
|
const { username } = this.props.match.params;
|
||||||
const { user, isSpin, route_type , undo_events , menuKey } = this.state;
|
const { user, isSpin, route_type , undo_events , menuKey , avatarVisible } = this.state;
|
||||||
return (
|
return (
|
||||||
<div className="newMain clearfix">
|
<div className="newMain clearfix">
|
||||||
|
{
|
||||||
|
avatarVisible &&
|
||||||
|
<Avatar
|
||||||
|
onCancel={this.onCancelAvatar}
|
||||||
|
avatarImg={getImageUrl(`/${user && user.image_url}`)}
|
||||||
|
login={current_user && current_user.login}
|
||||||
|
/>
|
||||||
|
}
|
||||||
<Spin spinning={isSpin}>
|
<Spin spinning={isSpin}>
|
||||||
<div className="new-content-flex">
|
<div className="new-content-flex">
|
||||||
<div className="list-left" style={{border:"none"}}>
|
<div className="list-left" style={{border:"none"}}>
|
||||||
<div className="bgcF">
|
<div className="bgcF">
|
||||||
<div className="list-l-Menu text-center" style={{padding:"20px 25px"}}>
|
<div className="list-l-Menu text-center" style={{padding:"20px 25px"}}>
|
||||||
<span className="headimg">
|
<div className="headimg-div">
|
||||||
<img src={getImageUrl(`/${user && user.image_url}`)} alt=""/>
|
<span className="headimg">
|
||||||
<span>
|
<img src={getImageUrl(`/${user && user.image_url}`)} alt=""/>
|
||||||
{
|
<span>
|
||||||
user && user.gender===1?
|
{
|
||||||
<i className="iconfont icon-nan1"></i>
|
user && user.gender===1?
|
||||||
:
|
<i className="iconfont icon-nan1"></i>
|
||||||
<i className="iconfont icon-nv1"></i>
|
:
|
||||||
}
|
<i className="iconfont icon-nv1"></i>
|
||||||
|
}
|
||||||
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
{
|
||||||
|
current_user && current_user.login && current_user.login === username ?
|
||||||
|
<span className="updateAvatar" onClick={()=>{this.setState({avatarVisible:true})}}>修改头像</span>
|
||||||
|
:""
|
||||||
|
}
|
||||||
|
</div>
|
||||||
<div className="text-center mt15 font-24 task-hide" title={user && user.username}>
|
<div className="text-center mt15 font-24 task-hide" title={user && user.username}>
|
||||||
{user && user.username}
|
{user && user.username}
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue