forked from Gitlink/forgeplus-react
Merge branch 'gitlink_server' of http://106.75.45.236:3000/Gitlink/forgeplus-react into feature_bot
This commit is contained in:
commit
ed32e55706
|
@ -89,8 +89,13 @@ export function initAxiosInterceptors(props) {
|
|||
|
||||
if (response.data.status === 404) {
|
||||
let responseURL = response.request ? response.request.responseURL:'';
|
||||
// 组织和个人的拥有情况,404不跳转
|
||||
if (responseURL.indexOf('/api/users/') === -1 && responseURL.indexOf('/api/organizations/') === -1 ) {
|
||||
locationurl('/nopage');
|
||||
// 邀请页面不进行404跳转
|
||||
if( window.location.pathname.includes('/invite') && (responseURL.includes('/simple.json')||responseURL.includes('/detail.json')||responseURL.includes('/menu_list.json'))){
|
||||
}else{
|
||||
locationurl('/nopage');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ export function getImageUrl(path) {
|
|||
// https://www.educoder.net
|
||||
// https://testbdweb.trustie.net
|
||||
// const local = 'http://localhost:3000'
|
||||
path && !path.startsWith('/') && !path.startsWith('http') && (path = '/'.concat(path));
|
||||
const local = 'https://testforgeplus.trustie.net';
|
||||
if (isDev) {
|
||||
return `${local}/${path}`
|
||||
|
|
|
@ -80,7 +80,7 @@ function AddMember({getID,login,showNotification}){
|
|||
<AutoComplete
|
||||
dataSource={source}
|
||||
value={searchKey}
|
||||
style={{ width: 300 }}
|
||||
style={{ width: 250 }}
|
||||
onChange={changeInputUser}
|
||||
onSelect={selectInputUser}
|
||||
placeholder="搜索需要添加的用户..."
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import { Modal, Button, } from 'antd';
|
||||
import { Base64 } from 'js-base64';
|
||||
import './index.scss';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { getImageUrl } from 'educoder'
|
||||
import axios from 'axios';
|
||||
|
||||
const identify = {
|
||||
manager: "管理员",
|
||||
developer: "开发者",
|
||||
reporter: "报告者",
|
||||
owner: "所有者",
|
||||
}
|
||||
function Invite({ history, current_user, match, projectDetail, showNotification }) {
|
||||
|
||||
if (!current_user.login) {
|
||||
let { pathname, search } = window.location;
|
||||
window.location.href = `/login?go_page=${pathname}${search}`;
|
||||
}
|
||||
let permission = projectDetail && projectDetail.permission;
|
||||
const { projectsId, owner } = match.params;
|
||||
let inviteString = window.location.search && window.location.search.split('?invite=')[1];
|
||||
let data = inviteString && JSON.parse(Base64.decode(inviteString));
|
||||
const [detail, setDetail] = useState({});
|
||||
const [visible, setVisible] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
if (permission && detail.role && detail.role == permission.toLocaleLowerCase() || permission == 'Owner') {
|
||||
showNotification(`您已经是${identify[detail.role]}了`)
|
||||
setTimeout(() => {
|
||||
history.push(`/${owner}/${projectsId}`);
|
||||
}, 2000)
|
||||
} else {
|
||||
setVisible(true)
|
||||
}
|
||||
}, [permission, detail.role]);
|
||||
|
||||
useEffect(() => {
|
||||
const url = `/${owner}/${projectsId}/project_invite_links/show_link.json?invite_sign=${data.sign}`;
|
||||
axios.get(url).then(res => {
|
||||
if (res && res.data) {
|
||||
setDetail(res.data);
|
||||
} else {
|
||||
showNotification('查询邀请链接失败');
|
||||
}
|
||||
})
|
||||
}, [])
|
||||
|
||||
function accept() {
|
||||
const url = `/${owner}/${projectsId}/project_invite_links/redirect_link.json?invite_sign=${data.sign}`;
|
||||
axios.post(url).then(res => {
|
||||
if (res && res.data.message == 'success') {
|
||||
if (detail.is_apply) {
|
||||
setVisible(false);
|
||||
Modal.success({ content: '提交申请成功,请等待该仓库管理员审核' });
|
||||
} else {
|
||||
history.push(`/${owner}/${projectsId}`);
|
||||
}
|
||||
}
|
||||
}).catch(error => { })
|
||||
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<div className="">
|
||||
{data && <Modal
|
||||
visible={visible}
|
||||
className="invite_development"
|
||||
title={<div className="ownerImage"><img src={detail.project && getImageUrl(detail.project.owner.image_url)} /></div>}
|
||||
width="548px"
|
||||
closable={true}
|
||||
onCancel={() => { setVisible(false); history.push(`/${current_user.login}`) }}
|
||||
centered
|
||||
okText={'接受'}
|
||||
cancelText={'拒绝'}
|
||||
onOk={accept}
|
||||
maskClosable={false}
|
||||
>
|
||||
<Link className="invite_project link" target="_blank" to={`/${data.ownerLogin}/${data.projectId}`}>{detail.project && detail.project.owner.name}/{detail.project && detail.project.name}</Link>
|
||||
<div className="invite_content">
|
||||
<Link className="link" to={`/${detail.user && detail.user.login}`}>{detail.user && detail.user.name}</Link> 邀请您以{identify[detail.role]}的身份加入此代码库
|
||||
是否接受邀请?
|
||||
</div>
|
||||
</Modal>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
export default Invite;
|
|
@ -0,0 +1,100 @@
|
|||
.invite_development {
|
||||
font-family: PingFang SC;
|
||||
height: 366px;
|
||||
background-image: linear-gradient(
|
||||
359.37deg,
|
||||
#ebf3ff 0%,
|
||||
#eff5ff 55.01%,
|
||||
#cfdeff 100%
|
||||
);
|
||||
border: 1.5px solid #ffffff;
|
||||
border-radius: 4px;
|
||||
|
||||
.ant-modal-close{
|
||||
top:0 !important;
|
||||
}
|
||||
.ant-modal-close-x{
|
||||
font-size: 30px;
|
||||
color: #666;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
line-height: 48px;
|
||||
transform: scaleX(1.05);
|
||||
}
|
||||
.ant-modal-content {
|
||||
background-color: inherit;
|
||||
}
|
||||
.ant-modal-header {
|
||||
background: inherit;
|
||||
border: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
.ownerImage {
|
||||
position: relative;
|
||||
top:-66px;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background-color: #e9f1ff;
|
||||
border: 1px solid #ffffff;
|
||||
border-radius: 50%;
|
||||
margin:0 auto;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
img{
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.invite_project {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
font-weight: 500;
|
||||
font-size: 20px;
|
||||
line-height: 22px;
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
.invite_content {
|
||||
width: 422px;
|
||||
padding: 24px 48px;
|
||||
background-color: rgba(225, 231, 255, 0.71);
|
||||
border-radius: 4px 4px 0px 0px;
|
||||
margin: 10px auto;
|
||||
font-weight: 500;
|
||||
font-size: 17px;
|
||||
line-height: 32px;
|
||||
text-align: center;
|
||||
color: #151d40;
|
||||
}
|
||||
.link {
|
||||
cursor: pointer;
|
||||
color: $primary-color;
|
||||
&:hover {
|
||||
color: $primary-color-hover;
|
||||
}
|
||||
}
|
||||
.ant-modal-footer {
|
||||
text-align: center;
|
||||
border: 0;
|
||||
padding-bottom: 55px;
|
||||
button {
|
||||
width: 150px;
|
||||
height: 42px;
|
||||
border-radius: 5px;
|
||||
font-size: 15px;
|
||||
&:first-child {
|
||||
background-color: rgba(196, 0, 14, 0.07);
|
||||
border: 1px solid;
|
||||
border-color: #f60011;
|
||||
color: #f60011;
|
||||
&:hover {
|
||||
opacity: 0.75;
|
||||
}
|
||||
}
|
||||
& + button {
|
||||
margin-left: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ import { Link, Route, Switch } from 'react-router-dom';
|
|||
import { Content, AlignTop } from '../Component/layout';
|
||||
import DetailBanner from './sub/DetailBanner';
|
||||
import cookie from 'react-cookies';
|
||||
import { Base64 } from 'js-base64';
|
||||
import '../css/index.scss'
|
||||
import './list.scss';
|
||||
|
||||
|
@ -145,6 +146,10 @@ const WikiEdit = Loadable({
|
|||
loader: () => import('../Wiki/EditWiki'),
|
||||
loading: Loading,
|
||||
});
|
||||
const Invite = Loadable({
|
||||
loader: () => import('../Invite/Index'),
|
||||
loading: Loading,
|
||||
});
|
||||
/**
|
||||
* permission:Manager:管理员,Reporter:报告人员(只有读取权限),Developer:开发人员(除不能设置仓库信息外)
|
||||
*/
|
||||
|
@ -227,12 +232,12 @@ class Detail extends Component {
|
|||
})
|
||||
}
|
||||
|
||||
clearIssueCookies=(history)=>{
|
||||
clearIssueCookies = (history) => {
|
||||
const { pathname } = history;
|
||||
const { projectsId , owner } = this.props.match.params;
|
||||
const { projectsId, owner } = this.props.match.params;
|
||||
let currentIssue = pathname.indexOf(`/${owner}/${projectsId}/issues`) === -1;
|
||||
if (currentIssue) {
|
||||
cookie.save('states', undefined,{ expires: 0,path:`/` });
|
||||
cookie.save('states', undefined, { expires: 0, path: `/` });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -304,15 +309,15 @@ class Detail extends Component {
|
|||
},
|
||||
disconnected: () => {
|
||||
console.log("###### cannot connected! ######");
|
||||
},
|
||||
},
|
||||
received: data => {
|
||||
console.log(`###### ---received data--- ######`);
|
||||
console.log(data);
|
||||
if (data) {
|
||||
if(deleteFlag){
|
||||
if (deleteFlag) {
|
||||
this.props.showNotification("镜像同步成功!");
|
||||
window.location.reload();
|
||||
}else{
|
||||
} else {
|
||||
if (data.project && data.project.mirror_status === 2) {
|
||||
this.deleteProjectBack();
|
||||
}
|
||||
|
@ -326,20 +331,20 @@ class Detail extends Component {
|
|||
cable.subscriptions.consumer.disconnect();
|
||||
}
|
||||
},
|
||||
onerror:()=>{
|
||||
onerror: () => {
|
||||
console.log("###### cannot connected! ######");
|
||||
}
|
||||
});
|
||||
|
||||
this.timerChannel = setTimeout(this.reloadDetail,5000);
|
||||
this.timerChannel = setTimeout(this.reloadDetail, 5000);
|
||||
}
|
||||
|
||||
reloadDetail=()=>{
|
||||
if(this.state.firstSync||this.state.secondSync){
|
||||
reloadDetail = () => {
|
||||
if (this.state.firstSync || this.state.secondSync) {
|
||||
window.location.reload();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
deleteProjectBack = () => {
|
||||
const { history } = this.props;
|
||||
|
@ -364,22 +369,33 @@ class Detail extends Component {
|
|||
axios.get(url).then((result) => {
|
||||
if (result && result.data) {
|
||||
if (result.data.status === 404) {
|
||||
this.props.history.push('/nopage');
|
||||
if (window.location.pathname.includes('/invite')) {
|
||||
let inviteString = window.location.search && window.location.search.split('?invite=')[1];
|
||||
let data = inviteString && JSON.parse(Base64.decode(inviteString));
|
||||
const { project = {}, projectDetail = {} } = this.state
|
||||
this.setState({
|
||||
project: Object.assign(project, { author: { name: data.ownerName } }),
|
||||
projectDetail: Object.assign(projectDetail, { name: data.projectName })
|
||||
});
|
||||
} else {
|
||||
this.props.history.push('/nopage');
|
||||
}
|
||||
} else {
|
||||
this.setState({
|
||||
projectDetail: result.data,
|
||||
project_id: result.data.project_id,
|
||||
isManager: result.data.permission && (result.data.permission === "Manager" || result.data.permission === "Admin" || result.data.permission === "Owner"),
|
||||
isReporter: result.data.permission && result.data.permission === "Reporter",
|
||||
isDeveloper: result.data.permission && result.data.permission === "Developer",
|
||||
http_url: result.data.clone_url,
|
||||
praised: result.data.praised,
|
||||
watched: result.data.watched,
|
||||
watchers_count: result.data.watchers_count,
|
||||
praises_count: result.data.praises_count,
|
||||
forked_count: result.data.forked_count,
|
||||
defaultBranch: result.data.default_branch
|
||||
})
|
||||
}
|
||||
this.setState({
|
||||
projectDetail: result.data,
|
||||
project_id: result.data.project_id,
|
||||
isManager: result.data.permission && (result.data.permission === "Manager" || result.data.permission === "Admin" || result.data.permission === "Owner"),
|
||||
isReporter: result.data.permission && result.data.permission === "Reporter",
|
||||
isDeveloper: result.data.permission && result.data.permission === "Developer",
|
||||
http_url: result.data.clone_url,
|
||||
praised: result.data.praised,
|
||||
watched: result.data.watched,
|
||||
watchers_count: result.data.watchers_count,
|
||||
praises_count: result.data.praises_count,
|
||||
forked_count: result.data.forked_count,
|
||||
defaultBranch: result.data.default_branch
|
||||
})
|
||||
}
|
||||
}).catch((error) => { })
|
||||
}
|
||||
|
@ -464,7 +480,7 @@ class Detail extends Component {
|
|||
const url = `/${owner}/${projectsId}/forks.json`;
|
||||
axios.post(url).then(result => {
|
||||
if (result && result.data.status === 0) {
|
||||
if(result.data.message === "fork失败,你已拥有了这个项目"){
|
||||
if (result.data.message === "fork失败,你已拥有了这个项目") {
|
||||
this.props.history.push(`/${current_user && current_user.login}/${projectsId}`);
|
||||
return;
|
||||
}
|
||||
|
@ -490,7 +506,7 @@ class Detail extends Component {
|
|||
axios.post(url).then(result => {
|
||||
if (result && result.data && result.data.status === 0) {
|
||||
this.setState({
|
||||
secondSync:true
|
||||
secondSync: true
|
||||
})
|
||||
this.canvasChannel(true);
|
||||
} else {
|
||||
|
@ -527,10 +543,9 @@ class Detail extends Component {
|
|||
let pathname = checkPathname(projectsId, owner, url);
|
||||
|
||||
const { state } = this.props.history.location;
|
||||
|
||||
const common = {
|
||||
getDetail: this.getDetail,
|
||||
getBanner:this.getBanner,
|
||||
getBanner: this.getBanner,
|
||||
changeOpenDevops: this.changeOpenDevops,
|
||||
defaultBranch
|
||||
}
|
||||
|
@ -549,7 +564,7 @@ class Detail extends Component {
|
|||
<Link to={`/${owner}/${projectsId}`} className="projectN mt6">{projectDetail && projectDetail.name}</Link>
|
||||
</div>
|
||||
{projectDetail && projectDetail.private && <span className="privateTag mt6">私有</span>}
|
||||
{ !platform && <span className="privateTag red mt6">只读</span> }
|
||||
{!platform && <span className="privateTag red mt6">只读</span>}
|
||||
</AlignTop>
|
||||
<div className="mt8">
|
||||
{
|
||||
|
@ -718,7 +733,7 @@ class Detail extends Component {
|
|||
(props) => (<Setting {...this.props} {...props} {...this.state} {...common} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
|
||||
{/*修改里程碑*/}
|
||||
<Route path="/:owner/:projectsId/milestones/:meilid/edit"
|
||||
render={
|
||||
|
@ -758,18 +773,18 @@ class Detail extends Component {
|
|||
{/* 修改详情 edit*/}
|
||||
<Route path="/:owner/:projectsId/issues/:orderId/edit"
|
||||
render={
|
||||
(props) => (<OrderupdateDetail {...this.props} {...props} {...this.state} {...common} form_type={"edit"}/>)
|
||||
(props) => (<OrderupdateDetail {...this.props} {...props} {...this.state} {...common} form_type={"edit"} />)
|
||||
}
|
||||
></Route>
|
||||
{/* 复制详情 copyetail*/}
|
||||
<Route path="/:owner/:projectsId/issues/:orderId/copyetail"
|
||||
render={
|
||||
(props) => (<OrderupdateDetail {...this.props} {...props} {...this.state} {...common} form_type={"copy"}/>)
|
||||
(props) => (<OrderupdateDetail {...this.props} {...props} {...this.state} {...common} form_type={"copy"} />)
|
||||
}
|
||||
></Route>
|
||||
|
||||
{/* 任务详情 */}
|
||||
<Route path="/:owner/:projectsId/issues/:orderId"
|
||||
|
||||
{/* 任务详情 */}
|
||||
<Route path="/:owner/:projectsId/issues/:orderId"
|
||||
render={
|
||||
(props) => (<OrderDetail {...this.props} {...this.state} {...props} {...common} />)
|
||||
}
|
||||
|
@ -861,6 +876,12 @@ class Detail extends Component {
|
|||
(props) => (<CoderDepot {...this.props} {...props} {...this.state} {...common} />)
|
||||
}
|
||||
></Route>
|
||||
{/* 邀请 */}
|
||||
<Route path="/:owner/:projectsId/invite"
|
||||
render={
|
||||
(props) => (<Invite {...this.props} {...props} {...this.state} {...common} />)
|
||||
}
|
||||
></Route>
|
||||
<Route path="/:owner/:projectsId/:subIndex"
|
||||
render={
|
||||
(props) => (<CoderRootIndex {...this.props} {...props} {...this.state} {...common} />)
|
||||
|
|
|
@ -4,6 +4,7 @@ import AddMember from '../Component/AddMember';
|
|||
import AddGroup from '../Component/AddGroup';
|
||||
import Member from './CollaboratorMember';
|
||||
import Group from './CollaboratorGroup';
|
||||
import MemberByLink from './CollaboratorMemberByLink';
|
||||
|
||||
function Collaborator(props){
|
||||
const [ nav , setNav] = useState("1");
|
||||
|
@ -23,11 +24,10 @@ function Collaborator(props){
|
|||
setNewGroupId(id);
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<WhiteBack>
|
||||
<div className="flex-a-center baseForm bbr">
|
||||
{
|
||||
{/* {
|
||||
author && author.type === "Organization" ?
|
||||
<span>
|
||||
<span style={{cursor:"pointer"}} className={nav === "1" ? "font-18 text-black color-blue":"font-18 text-black"} onClick={()=>{setNav("1");setNewId(undefined)}}>协作者管理</span>
|
||||
|
@ -35,22 +35,26 @@ function Collaborator(props){
|
|||
</span>
|
||||
:
|
||||
<span className="font-18 text-black">协作者管理</span>
|
||||
}
|
||||
} */}
|
||||
<span>
|
||||
<span style={{cursor:"pointer"}} className={nav === "1" ? "font-15 text-black color-blue":"font-15 text-black"} onClick={()=>{setNav("1");setNewId(undefined)}}>协作者管理</span>
|
||||
<span style={{cursor:"pointer"}} className={nav === "3" ? "font-15 text-black color-blue ml30":"font-15 text-black ml30"} onClick={()=>{setNav("3");}}>邀请成员</span>
|
||||
{author && author.type === "Organization" && <span style={{cursor:"pointer"}} className={nav === "2" ? "font-15 text-black ml30 color-blue":"font-15 text-black ml30"} onClick={()=>{setNav("2");setNewId(undefined);setNewGroupId(undefined)}}>团队管理</span>}
|
||||
</span>
|
||||
{
|
||||
nav === "1" &&
|
||||
<AddMember getID={getID} login showNotification={props.showNotification}/>
|
||||
}
|
||||
{
|
||||
(nav !== "1" && addOperation) &&
|
||||
(nav === "2" && addOperation) &&
|
||||
<AddGroup getGroupID={getGroupID} organizeId={owner}/>
|
||||
}
|
||||
</div>
|
||||
<div>
|
||||
{
|
||||
nav === "1" ?
|
||||
<Member newId={newId} flag={newIdFlag} projectsId={projectsId} owner={owner} project_id={props.project_id} author={props.projectDetail && props.projectDetail.author} showNotification={props.showNotification}/>
|
||||
:
|
||||
<Group setAddOperation={setAddOperation} owner={owner} projectsId={projectsId} newGroupId={newGroupId}/>
|
||||
nav === "1" ? <Member newId={newId} flag={newIdFlag} projectsId={projectsId} owner={owner} project_id={props.project_id} author={props.projectDetail && props.projectDetail.author} showNotification={props.showNotification}/>
|
||||
: nav === "2" ? <Group setAddOperation={setAddOperation} owner={owner} projectsId={projectsId} newGroupId={newGroupId}/>
|
||||
: <MemberByLink newId={newId} flag={newIdFlag} projectsId={projectsId} owner={owner} project_id={props.project_id} author={props.projectDetail && props.projectDetail.author} showNotification={props.showNotification}/>
|
||||
}
|
||||
</div>
|
||||
</WhiteBack>
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
import React, { useEffect, useState, useImperativeHandle, forwardRef } from 'react';
|
||||
import { Select, Checkbox, Button, Input, Spin, Table, Tooltip, Pagination, Popconfirm } from "antd";
|
||||
import axios from 'axios';
|
||||
import { Base64 } from 'js-base64';
|
||||
import NoneData from "../Nodata";
|
||||
import { Link } from "react-router-dom";
|
||||
import { getImageUrl } from "educoder";
|
||||
|
||||
const { Search } = Input;
|
||||
const LIMIT = 15;
|
||||
const optionList = [
|
||||
{ value: "manager", name: "管理员 - 拥有仓库设置功能、代码库读、写操作权限" },
|
||||
{ value: "developer", name: "开发人员 - 拥有代码库读、写操作权限" },
|
||||
{ value: "reporter", name: "报告者 - 拥有代码库读操作权限" }
|
||||
];
|
||||
function CollaboratorMemberByLink({ projectsId, owner, project_id, author, showNotification, newId, flag }) {
|
||||
|
||||
const [role, setRole] = useState('developer');
|
||||
const [is_apply, setIs_apply] = useState(true);
|
||||
const [inviteUrl, setinviteUrl] = useState('');
|
||||
const [copy, setCopy] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const url = `/${owner}/${projectsId}/project_invite_links/current_link.json`;
|
||||
axios.get(url, {
|
||||
params: {
|
||||
role,
|
||||
is_apply
|
||||
}
|
||||
}).then(res => {
|
||||
if (res && res.data) {
|
||||
let params = {
|
||||
projectName: res.data.project.name,
|
||||
projectId: res.data.project.identifier,
|
||||
// role: res.data.role,
|
||||
ownerLogin: res.data.project.owner.login,
|
||||
ownerName: res.data.project.owner.name,
|
||||
// userName: res.data.user.name,
|
||||
// userLogin: res.data.user.login,
|
||||
sign:res.data.sign,
|
||||
};
|
||||
let urlParams = JSON.stringify(params);
|
||||
let content = Base64.encode(urlParams);
|
||||
|
||||
setinviteUrl(`${window.location.origin}/${owner}/${projectsId}/invite?invite=${content}`);
|
||||
setCopy(false);
|
||||
}
|
||||
}).catch(error => { })
|
||||
}, [role, is_apply]);
|
||||
|
||||
function inviteClick() {
|
||||
const copyEle = document.querySelector('#inviteUrl'); // 获取要复制的节点
|
||||
if (!copyEle) {
|
||||
console.error("您的CopyTool未设置正确的inputId");
|
||||
return;
|
||||
}
|
||||
copyEle.select(); // 执行选中元素
|
||||
if (document.execCommand('copy')) {
|
||||
document.execCommand('copy');
|
||||
setCopy(true);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='addMemByLinkBox'>
|
||||
<div className='font-16 mt20 mb10'>请选择邀请用户权限</div>
|
||||
<Select className='selectBox' defaultValue="developer" onChange={(v) => { setRole(v) }}>
|
||||
{optionList.map(item => {
|
||||
return <Select.Option value={item.value} key={item.value}>{item.name}</Select.Option>
|
||||
})}
|
||||
</Select>
|
||||
|
||||
<Checkbox checked={is_apply} className='font-15 checkBox' onChange={e => { setIs_apply(e.target.checked) }}>需要管理员审核</Checkbox>
|
||||
|
||||
<div className='font-16 mt25 mb10'>邀请链接</div>
|
||||
<Input
|
||||
id="inviteUrl"
|
||||
value={inviteUrl}
|
||||
readOnly
|
||||
addonAfter={<Button type='primary' onClick={inviteClick}>{copy ? '复制成功' : '复制链接'}</Button>} className='linkBox'
|
||||
/>
|
||||
<div className='tipBox mt25'>
|
||||
<div>注: </div>
|
||||
<div className='ml5'>
|
||||
1、管理员可通过分享邀请链接的方式,邀请其他成员加入项目<br />
|
||||
2、若已勾选管理员审核选项,用户接收邀请后管理员可在个人主页中“待办事项”窗口审核成员审核信息,若不需要管理员审核,成员接收邀请后,将直接加入项目
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
export default forwardRef(CollaboratorMemberByLink);
|
|
@ -57,7 +57,7 @@ class Index extends Component {
|
|||
<li className={flag ? "active" : ""}>
|
||||
<p>
|
||||
<Link to={`/${owner}/${projectsId}/settings`} className="w-100">
|
||||
<i className="iconfont icon-huabanfuben font-18 mr10"></i>基本设置
|
||||
<i className="iconfont icon-huabanfuben font-15 mr10"></i>基本设置
|
||||
</Link>
|
||||
</p>
|
||||
</li>
|
||||
|
@ -68,7 +68,7 @@ class Index extends Component {
|
|||
>
|
||||
<p>
|
||||
<Link to={`/${owner}/${projectsId}/settings/collaborators`} className="w-100">
|
||||
<i className="iconfont icon-chengyuan font-18 mr10"></i>
|
||||
<i className="iconfont icon-chengyuan font-15 mr10"></i>
|
||||
协作者管理
|
||||
</Link>
|
||||
</p>
|
||||
|
@ -80,7 +80,7 @@ class Index extends Component {
|
|||
>
|
||||
<p>
|
||||
<Link to={`/${owner}/${projectsId}/settings/webhooks`} className="w-100">
|
||||
<i className="iconfont icon-a-xuanzhongwebhookicon font-18 mr10 color-grey-9"></i>
|
||||
<i className="iconfont icon-a-xuanzhongwebhookicon font-15 mr10 color-grey-9"></i>
|
||||
网络钩子
|
||||
</Link>
|
||||
</p>
|
||||
|
@ -92,7 +92,7 @@ class Index extends Component {
|
|||
>
|
||||
<p>
|
||||
<Link to={`/${owner}/${projectsId}/settings/branches`} className="w-100">
|
||||
<i className="iconfont icon-fenzhi font-20 mr10"></i>
|
||||
<i className="iconfont icon-fenzhi font-15 mr10"></i>
|
||||
分支设置
|
||||
</Link>
|
||||
</p>
|
||||
|
@ -102,7 +102,7 @@ class Index extends Component {
|
|||
>
|
||||
<p>
|
||||
<Link to={`/${owner}/${projectsId}/settings/labels`} className="w-100">
|
||||
<i className="iconfont icon-xiangmubiaoqian font-18 mr10 color-grey-6"></i>
|
||||
<i className="iconfont icon-xiangmubiaoqian font-15 mr10 color-grey-6"></i>
|
||||
项目标记
|
||||
</Link>
|
||||
</p>
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
content: '';
|
||||
}
|
||||
.baseForm{
|
||||
padding:15px 30px!important;
|
||||
padding:15px 0!important;
|
||||
}
|
||||
.collaboratorList{
|
||||
min-height: 400px;
|
||||
|
@ -243,4 +243,31 @@
|
|||
&>div:last-child{
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
.addMemByLinkBox{
|
||||
color:#202d40;
|
||||
.selectBox {
|
||||
width: 55%;
|
||||
display: block;
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
.checkBox{
|
||||
color:#151d40;
|
||||
}
|
||||
.tipBox{
|
||||
background-color:rgba(199, 209, 255, 0.17);
|
||||
color:#7e849e;
|
||||
padding: 20px 150px 20px 25px;
|
||||
display: flex;
|
||||
}
|
||||
.linkBox{
|
||||
width: 55%;
|
||||
.ant-input-group-addon{
|
||||
padding: 0;
|
||||
}
|
||||
.ant-btn{
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -225,24 +225,24 @@ form{
|
|||
margin-bottom: 12px;
|
||||
border-radius:2px;
|
||||
background-color: #fff;
|
||||
// box-shadow: 0px 0px 2px rgba(0,0,0,0.2);
|
||||
padding: 20px 0;
|
||||
border:1px solid rgba(79, 108, 188, 0.21);
|
||||
&>li{
|
||||
font-size: 1rem;
|
||||
padding:0px 0px 0px 20px;
|
||||
font-size: 15px;
|
||||
padding:0px 0px 0px 25px;
|
||||
box-sizing: border-box;
|
||||
color: #333;
|
||||
position: relative;
|
||||
& > p{
|
||||
height: 62px;
|
||||
line-height: 62px;
|
||||
height: 49px;
|
||||
width: 100%;
|
||||
border-bottom: 1px solid #eee;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
padding-right: 20px;
|
||||
margin:0px;
|
||||
border-bottom: 1px solid #eee;
|
||||
a{
|
||||
width:100%;
|
||||
color: #202d40;
|
||||
|
@ -264,10 +264,9 @@ form{
|
|||
& li.active::before{
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: 15px;
|
||||
width: 6px;
|
||||
content: '';
|
||||
height: 33px;
|
||||
height: 100%;
|
||||
// background: #4CACFF;
|
||||
background: $primary-color;
|
||||
}
|
||||
|
|
|
@ -180,7 +180,7 @@ class InfosUser extends Component {
|
|||
placeholder="输入项目名称关键字进行搜索"
|
||||
enterButton="搜索"
|
||||
size="large"
|
||||
onSearch={this.get_projects}
|
||||
onSearch={()=>{this.get_projects()}}
|
||||
className="list-r-Search"
|
||||
value={search}
|
||||
onChange={this.changeSearchValue}
|
||||
|
|
Loading…
Reference in New Issue