Merge remote-tracking branch 'fork/dev_edu_local' into dev_edu_local
This commit is contained in:
commit
55e5abf48c
|
|
@ -32,7 +32,8 @@ export function initAxiosInterceptors(props) {
|
|||
// 判断网络是否连接
|
||||
initOnlineOfflineListener();
|
||||
|
||||
var proxy = "http://172.16.100.220:81";
|
||||
// var proxy = "http://172.16.100.220:81";
|
||||
var proxy = 'http://172.16.100.130:81'
|
||||
//响应前的设置
|
||||
axios.interceptors.request.use(
|
||||
config => {
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ function EducoderAccount({form , visible , onOk , email}){
|
|||
return(
|
||||
<Modal
|
||||
visible={visible}
|
||||
// visible={false}
|
||||
title="提示"
|
||||
width="500px"
|
||||
closable={false}
|
||||
|
|
|
|||
|
|
@ -1,84 +1,270 @@
|
|||
import React, { useState , forwardRef, useEffect } from 'react';
|
||||
import { Form , Modal , Input , Radio } from 'antd';
|
||||
import React, { useState, forwardRef, useEffect } from 'react';
|
||||
import { Form, Modal, Input, Radio, Upload, Button, Icon, message } from 'antd';
|
||||
import Axios from 'axios';
|
||||
import { getUploadActionUrl, appendFileSizeToUploadFileAll } from 'educoder';
|
||||
|
||||
export default Form.create()(
|
||||
forwardRef((props)=>{
|
||||
const { getFieldDecorator, validateFields , setFieldsValue } = props && props.form;
|
||||
const [ visible , setVisible ] = useState(false);
|
||||
const JoinProjectForm = Form.create({
|
||||
name: 'join_project_form',
|
||||
})(
|
||||
forwardRef((props) => {
|
||||
const { getFieldDecorator, validateFields } = props.form;
|
||||
const { onOk, onCancel } = props;
|
||||
|
||||
useEffect(()=>{
|
||||
if(!visible){
|
||||
setFieldsValue({
|
||||
code:undefined,
|
||||
role:"developer"
|
||||
})
|
||||
useEffect(() => {
|
||||
if (props.visible) {
|
||||
props.form.setFieldsValue({
|
||||
code: '',
|
||||
role: 'developer',
|
||||
});
|
||||
}
|
||||
},[visible])
|
||||
}, [props.visible])
|
||||
|
||||
function onOk() {
|
||||
validateFields((error,values)=>{
|
||||
if(!error){
|
||||
const url = `/applied_projects.json`;
|
||||
Axios.post(url,{
|
||||
applied_project:{
|
||||
...values
|
||||
}
|
||||
}).then(result=>{
|
||||
if(result && result.data){
|
||||
setVisible(false);
|
||||
props.showNotification("申请加入项目成功,等待审核!");
|
||||
}
|
||||
}).catch(error=>{})
|
||||
}
|
||||
})
|
||||
}
|
||||
function checkValue(rule, value, callback){
|
||||
if(!value){
|
||||
function checkValue(rule, value, callback) {
|
||||
if (!value) {
|
||||
callback();
|
||||
}
|
||||
if(value.length < 6 || value.length > 6){
|
||||
callback("请输入6位数的邀请码");
|
||||
if (value.length < 6 || value.length > 6) {
|
||||
callback('请输入6位数的邀请码');
|
||||
}
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
return(
|
||||
<React.Fragment>
|
||||
<Modal
|
||||
title="加入项目"
|
||||
width="480px"
|
||||
visible={visible}
|
||||
centered={true}
|
||||
onOk={onOk}
|
||||
onCancel={()=>setVisible(false)}
|
||||
>
|
||||
<Form layout={'inline'} className="inviteForm">
|
||||
<Form.Item label="项目邀请码">
|
||||
{getFieldDecorator("code",{
|
||||
rules:[
|
||||
{required:true,message:"请输入6位项目邀请码"},
|
||||
{validator:checkValue}
|
||||
]
|
||||
})(
|
||||
<Input placeholder="请输入6位项目邀请码" autoComplete={"off"} maxLength="6" style={{width:"300px"}}/>
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item label="选择角色">
|
||||
{getFieldDecorator("role",{
|
||||
rules:[{required:true,message:"请选择角色"}]
|
||||
})(
|
||||
<Radio.Group defaultValue={"developer"}>
|
||||
<Radio value="manager">管理员</Radio>
|
||||
<Radio value="developer">开发者</Radio>
|
||||
<Radio value="reporter">报告者</Radio>
|
||||
</Radio.Group>
|
||||
)}
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
<a onClick={()=>setVisible(true)}>加入项目</a>
|
||||
</React.Fragment>
|
||||
)
|
||||
const handleOk = () => {
|
||||
validateFields((error, values) => {
|
||||
if (!error) {
|
||||
onOk(values);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title="加入项目"
|
||||
width="480px"
|
||||
visible={props.visible}
|
||||
centered={true}
|
||||
onOk={handleOk}
|
||||
onCancel={onCancel}
|
||||
>
|
||||
<Form layout="inline" className="inviteForm">
|
||||
<Form.Item label="项目邀请码">
|
||||
{getFieldDecorator('code', {
|
||||
rules: [
|
||||
{ required: true, message: '请输入6位项目邀请码' },
|
||||
{ validator: checkValue },
|
||||
],
|
||||
})(
|
||||
<Input
|
||||
placeholder="请输入6位项目邀请码"
|
||||
autoComplete="off"
|
||||
maxLength="6"
|
||||
style={{ width: '300px' }}
|
||||
/>
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item label="选择角色">
|
||||
{getFieldDecorator('role', {
|
||||
rules: [{ required: true, message: '请选择角色' }],
|
||||
})(
|
||||
<Radio.Group>
|
||||
<Radio value="manager">管理员</Radio>
|
||||
<Radio value="developer">开发者</Radio>
|
||||
<Radio value="reporter">报告者</Radio>
|
||||
</Radio.Group>
|
||||
)}
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
);
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
const PersonalInfoForm = Form.create({
|
||||
name: 'personal_info_form',
|
||||
})(
|
||||
forwardRef((props) => {
|
||||
const { getFieldDecorator, validateFields } = props.form;
|
||||
const { onOk, onCancel, contentFileList, uploadProps } = props;
|
||||
|
||||
useEffect(() => {
|
||||
if (props.visible) {
|
||||
props.form.setFieldsValue({
|
||||
remarks: '',
|
||||
attachment_id: '',
|
||||
});
|
||||
}
|
||||
}, [props.visible])
|
||||
|
||||
const handleOk = () => {
|
||||
validateFields((error, values) => {
|
||||
if (!error) {
|
||||
const attachmentId = contentFileList.map((item) => {
|
||||
return item.response ? item.response.id : item.id;
|
||||
});
|
||||
onOk({ ...values, attachment_id: attachmentId.join(',') });
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title="填写个人信息"
|
||||
width="480px"
|
||||
visible={props.visible}
|
||||
centered={true}
|
||||
onOk={handleOk}
|
||||
onCancel={onCancel}
|
||||
>
|
||||
<Form layout="inline" className="inviteForm2">
|
||||
<Form.Item label="个人情况">
|
||||
{getFieldDecorator('remarks', {
|
||||
rules: [{ required: true, message: '请输入个人情况' }],
|
||||
})(
|
||||
<Input
|
||||
placeholder="请输入个人情况"
|
||||
// autoComplete="off"
|
||||
maxLength={200}
|
||||
style={{ width: '300px', pointerEvents: 'auto' }} // 确保 pointer-events 为 auto
|
||||
/>
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item label="个人资料" style={{ flexWrap: 'nowrap' }}>
|
||||
{getFieldDecorator('attachment_id', {
|
||||
rules: [],
|
||||
})(
|
||||
<Upload {...uploadProps}>
|
||||
<Button type="default" className='mr5'>
|
||||
<Icon type="upload" /> 上传附件
|
||||
</Button>
|
||||
(单个文件最大20MB)
|
||||
</Upload>
|
||||
)}
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
);
|
||||
})
|
||||
);
|
||||
|
||||
export default forwardRef((props) => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [infoVis, setInfoVis] = useState(false);
|
||||
const [contentFileList, setContentFileList] = useState([]);
|
||||
// 新增状态用于保存加入项目表单的数据
|
||||
const [joinProjectValues, setJoinProjectValues] = useState({});
|
||||
|
||||
const uploadProps = {
|
||||
fileList: contentFileList,
|
||||
multiple: false,
|
||||
action: `${getUploadActionUrl()}`,
|
||||
onChange: (info) => {
|
||||
let content = info.fileList;
|
||||
setContentFileList(appendFileSizeToUploadFileAll(content));
|
||||
},
|
||||
onRemove: (file) => {
|
||||
if (file.response != undefined) {
|
||||
Modal.confirm({
|
||||
content: '是否确认删除?',
|
||||
onOk: () => {
|
||||
deleteAttachment(file);
|
||||
},
|
||||
onCancel() {
|
||||
console.log('Cancel');
|
||||
},
|
||||
});
|
||||
return false;
|
||||
}
|
||||
},
|
||||
beforeUpload: (file) => {
|
||||
console.log('beforeUpload', file.name);
|
||||
const isLt150M = file.size / 1024 / 1024 <= 20;
|
||||
if (!isLt150M) {
|
||||
message.error('文件大小必须不超过20MB!');
|
||||
}
|
||||
return isLt150M;
|
||||
},
|
||||
};
|
||||
|
||||
const deleteAttachment = (file) => {
|
||||
const url = `/attachments/${file.response ? file.response.id : file.uid}.json`;
|
||||
Axios.delete(url, {})
|
||||
.then((response) => {
|
||||
if (response.data) {
|
||||
const { status } = response.data;
|
||||
if (status === 0) {
|
||||
setContentFileList([]);
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
};
|
||||
|
||||
const handleJoinProjectOk = (values) => {
|
||||
const url = `/applied_projects.json`;
|
||||
setJoinProjectValues({ ...values })
|
||||
Axios.post(url, {
|
||||
applied_project: {
|
||||
alert_remarks: false,
|
||||
...values,
|
||||
},
|
||||
})
|
||||
.then((result) => {
|
||||
if (result) {
|
||||
setVisible(false);
|
||||
if (result.data.data.need_verify) {
|
||||
setInfoVis(true);
|
||||
} else {
|
||||
props.showNotification('申请已提交,请等待项目管理者审核!');
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
};
|
||||
|
||||
const handlePersonalInfoOk = (values) => {
|
||||
const url = `/applied_projects.json`;
|
||||
let attachmentId = contentFileList.map(item => {
|
||||
return item.response ? item.response.id : item.id
|
||||
})
|
||||
Axios.post(url, {
|
||||
applied_project: {
|
||||
...joinProjectValues,
|
||||
alert_remarks: true,
|
||||
...values,
|
||||
attachment_id: attachmentId.join(','),
|
||||
},
|
||||
})
|
||||
.then((result) => {
|
||||
if (result && result.data) {
|
||||
setInfoVis(false);
|
||||
setContentFileList([]);
|
||||
props.showNotification('申请已提交,请等待项目管理者审核!');
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<JoinProjectForm
|
||||
visible={visible}
|
||||
onOk={handleJoinProjectOk}
|
||||
onCancel={() => setVisible(false)}
|
||||
/>
|
||||
<PersonalInfoForm
|
||||
visible={infoVis}
|
||||
onOk={handlePersonalInfoOk}
|
||||
onCancel={() => setInfoVis(false)}
|
||||
contentFileList={contentFileList}
|
||||
uploadProps={uploadProps}
|
||||
/>
|
||||
<a onClick={() => setVisible(true)}>加入项目</a>
|
||||
</React.Fragment>
|
||||
);
|
||||
});
|
||||
|
|
@ -152,4 +152,17 @@
|
|||
width: 110px;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
.inviteForm2{
|
||||
.ant-form-item{
|
||||
margin-right: 0px;
|
||||
display:flex;
|
||||
flex-wrap: nowrap;
|
||||
|
||||
}
|
||||
.ant-form-item-label{
|
||||
width: 92px;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
|
@ -35,6 +35,7 @@ class Index extends Component {
|
|||
})
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="newMain clearfix">
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React, { Component } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Menu, Input , Spin, Pagination , Popover , Select , Button } from 'antd';
|
||||
import { Menu, Input , Spin, Pagination , Popover , Select , Button,Tabs } from 'antd';
|
||||
import { getImageUrl } from 'educoder';
|
||||
import '../css/index.scss'
|
||||
import './list.css';
|
||||
|
|
@ -32,14 +32,15 @@ class Index extends Component {
|
|||
recommendList:undefined,
|
||||
|
||||
languageList:undefined,
|
||||
languageId:undefined
|
||||
languageId:undefined,
|
||||
filter:undefined,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
componentDidMount = () => {
|
||||
const { page, limit, search, sort, project_type, category_id , languageId } = this.state;
|
||||
this.getListData(page, limit, search, sort, project_type, category_id , languageId);
|
||||
const { page, limit, search, sort, project_type, category_id , languageId,filter } = this.state;
|
||||
this.getListData(page, limit, search, sort, project_type, category_id , languageId,filter);
|
||||
|
||||
this.getType();
|
||||
|
||||
|
|
@ -74,7 +75,7 @@ class Index extends Component {
|
|||
}
|
||||
|
||||
// 获取列表
|
||||
getListData = (page, limit, search, sort, project_type, category_id,languageId) => {
|
||||
getListData = (page, limit, search, sort, project_type, category_id,languageId,filter) => {
|
||||
const { current_user } = this.props;
|
||||
const url = `/projects.json`;
|
||||
axios.get(url, {
|
||||
|
|
@ -86,7 +87,8 @@ class Index extends Component {
|
|||
sort_by: sort,
|
||||
project_type,
|
||||
category_id,
|
||||
language_id:languageId
|
||||
language_id:languageId,
|
||||
filter
|
||||
}
|
||||
}).then((result) => {
|
||||
if (result) {
|
||||
|
|
@ -132,8 +134,8 @@ class Index extends Component {
|
|||
search: undefined
|
||||
})
|
||||
this.setTypeList(list, type)
|
||||
const { page, limit, sort, category_id , languageId } = this.state;
|
||||
this.getListData(page, limit, undefined, sort, type, category_id , languageId);
|
||||
const { page, limit, sort, category_id , languageId,filter } = this.state;
|
||||
this.getListData(page, limit, undefined, sort, type, category_id , languageId,filter);
|
||||
}
|
||||
|
||||
// 获取类型
|
||||
|
|
@ -168,8 +170,8 @@ class Index extends Component {
|
|||
page: 1
|
||||
});
|
||||
this.setCategoryList(list, id)
|
||||
const { limit, sort, project_type , languageId } = this.state;
|
||||
this.getListData(1, limit, undefined, sort, project_type, id , languageId);
|
||||
const { limit, sort, project_type , languageId,filter } = this.state;
|
||||
this.getListData(1, limit, undefined, sort, project_type, id , languageId,filter);
|
||||
}
|
||||
|
||||
// 排序
|
||||
|
|
@ -180,8 +182,8 @@ class Index extends Component {
|
|||
search: undefined,
|
||||
isSpin: true
|
||||
})
|
||||
const { limit, project_type, category_id , languageId } = this.state;
|
||||
this.getListData(1, limit, undefined, e.key, project_type, category_id , languageId);
|
||||
const { limit, project_type, category_id , languageId,filter } = this.state;
|
||||
this.getListData(1, limit, undefined, e.key, project_type, category_id , languageId,filter);
|
||||
}
|
||||
|
||||
// 搜索
|
||||
|
|
@ -193,8 +195,8 @@ class Index extends Component {
|
|||
project_type: undefined,
|
||||
sort: "updated_on"
|
||||
})
|
||||
const { limit, sort, category_id , languageId } = this.state;
|
||||
this.getListData(1, limit, value, sort, undefined, category_id , languageId);
|
||||
const { limit, sort, category_id , languageId ,filter} = this.state;
|
||||
this.getListData(1, limit, value, sort, undefined, category_id , languageId,filter);
|
||||
}
|
||||
changeSearchValue = (e) => {
|
||||
this.setState({
|
||||
|
|
@ -206,8 +208,8 @@ class Index extends Component {
|
|||
this.setState({
|
||||
page
|
||||
})
|
||||
const { limit, search, sort, project_type, category_id , languageId } = this.state;
|
||||
this.getListData(page, limit, search, sort, project_type, category_id , languageId);
|
||||
const { limit, search, sort, project_type, category_id , languageId,filter } = this.state;
|
||||
this.getListData(page, limit, search, sort, project_type, category_id , languageId,filter);
|
||||
}
|
||||
|
||||
getoDetail=(login,identifier)=>{
|
||||
|
|
@ -220,8 +222,17 @@ class Index extends Component {
|
|||
isSpin:true,
|
||||
languageId:e === 0 ?undefined:e
|
||||
})
|
||||
const { page, limit, sort , project_type , category_id } = this.state;
|
||||
this.getListData(page, limit, undefined, sort, project_type, category_id ,e === 0 ?undefined:e);
|
||||
const { page, limit, sort , project_type , category_id,filter } = this.state;
|
||||
this.getListData(page, limit, undefined, sort, project_type, category_id ,e === 0 ?undefined:e,filter);
|
||||
}
|
||||
|
||||
changeFilter=(e)=>{
|
||||
this.setState({
|
||||
isSpin:true,
|
||||
filter:e
|
||||
})
|
||||
const { page,limit, search, sort, project_type, category_id , languageId } = this.state;
|
||||
this.getListData(page, limit, search, sort, project_type, category_id , languageId,e);
|
||||
}
|
||||
|
||||
menu =()=> {
|
||||
|
|
@ -282,7 +293,7 @@ class Index extends Component {
|
|||
{
|
||||
recommendList && recommendList.length>0 &&
|
||||
<div className="recommandProjects">
|
||||
{
|
||||
{/* {
|
||||
recommendList.map((item,key)=>{
|
||||
return(
|
||||
<div onClick={()=>this.getoDetail(item.author && item.author.login,item.identifier)}>
|
||||
|
|
@ -298,7 +309,7 @@ class Index extends Component {
|
|||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
} */}
|
||||
</div>
|
||||
}
|
||||
|
||||
|
|
@ -315,7 +326,19 @@ class Index extends Component {
|
|||
</div>
|
||||
<div className="list-right boxShandow radius-2" style={{padding:0}}>
|
||||
<Spin spinning={isSpin}>
|
||||
<div className="list-r-operation">
|
||||
<div style={{padding:'20px 30px 0px 30px'}}>
|
||||
<Tabs size='large' type="card" onChange={(key)=>{
|
||||
this.changeFilter(key)
|
||||
}}>
|
||||
<Tabs.TabPane tab="全部" key="undefined" />
|
||||
<Tabs.TabPane tab="我管理的" key="manage" />
|
||||
<Tabs.TabPane tab="我学习的" key="study" />
|
||||
</Tabs>
|
||||
{/* <Button size='large' onClick={()=>{this.changeFilter(undefined)}} type={this.state.filter == undefined ? 'primary':'default'}>全部</Button>
|
||||
<Button size='large' onClick={()=>{this.changeFilter('manage')}} type={this.state.filter == 'manage' ? 'primary':'default'} className='ml10 mr10'>我管理的</Button>
|
||||
<Button size='large' onClick={()=>{this.changeFilter('study')}} type={this.state.filter == 'study' ? 'primary':'default'}>我学习的</Button> */}
|
||||
</div>
|
||||
<div className="list-r-operation" style={{padding:'5px 30px 20px 30px'}}>
|
||||
<div>
|
||||
<Select
|
||||
showSearch
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { Component } from 'react';
|
||||
import { Tooltip } from 'antd';
|
||||
import { Tooltip, Badge, Modal, Form, Input, Upload, Button, Icon, Radio, message } from 'antd';
|
||||
import { getImageUrl } from 'educoder';
|
||||
import { AlignCenter } from '../Component/layout';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
|
@ -7,87 +7,279 @@ import '../css/index.scss';
|
|||
import Nodata from '../Nodata';
|
||||
import './list.css';
|
||||
import img_parise from '../Images/parise.png';
|
||||
import Axios from 'axios'; // 引入 Axios
|
||||
import { getUploadActionUrl,appendFileSizeToUploadFileAll } from 'educoder';
|
||||
|
||||
class PrivateAccessModal extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
contentFileList: []
|
||||
};
|
||||
}
|
||||
|
||||
handleOk = () => {
|
||||
this.props.form.validateFields((err, values) => {
|
||||
if (!err) {
|
||||
const url = `/applied_projects.json`;
|
||||
let attachmentId = this.state.contentFileList.map(item => {
|
||||
return item.response ? item.response.id : item.id
|
||||
})
|
||||
Axios.post(url, {
|
||||
applied_project: {
|
||||
alert_remarks: true,
|
||||
...values,
|
||||
attachment_id: attachmentId.join(','),
|
||||
code: this.props.projectInfo.invite_code
|
||||
},
|
||||
})
|
||||
.then((result) => {
|
||||
if (result && result.data) {
|
||||
this.setState({
|
||||
contentFileList: []
|
||||
});
|
||||
message.info('申请已提交,请等待项目管理者审核!');
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
this.props.onClose();
|
||||
this.props.form.resetFields();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
handleCancel = () => {
|
||||
this.props.onClose();
|
||||
this.props.form.resetFields();
|
||||
}
|
||||
|
||||
uploadProps = ()=>{
|
||||
return {
|
||||
fileList: this.state.contentFileList,
|
||||
multiple: false,
|
||||
action: `${getUploadActionUrl()}`,
|
||||
onChange: (info) => {
|
||||
let content = info.fileList;
|
||||
this.setState({
|
||||
contentFileList: appendFileSizeToUploadFileAll(content)
|
||||
});
|
||||
},
|
||||
onRemove: (file) => {
|
||||
if (file.response != undefined) {
|
||||
Modal.confirm({
|
||||
content: '是否确认删除?',
|
||||
onOk: () => {
|
||||
this.deleteAttachment(file);
|
||||
},
|
||||
onCancel() {
|
||||
console.log('Cancel');
|
||||
},
|
||||
});
|
||||
return false;
|
||||
}
|
||||
},
|
||||
beforeUpload: (file) => {
|
||||
console.log('beforeUpload', file.name);
|
||||
const isLt150M = file.size / 1024 / 1024 <= 20;
|
||||
if (!isLt150M) {
|
||||
message.error('文件大小必须不超过20MB!');
|
||||
}
|
||||
return isLt150M;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
deleteAttachment = (file) => {
|
||||
const url = `/attachments/${file.response ? file.response.id : file.uid}.json`;
|
||||
Axios.delete(url, {})
|
||||
.then((response) => {
|
||||
if (response.data) {
|
||||
const { status } = response.data;
|
||||
if (status === 0) {
|
||||
this.setState({
|
||||
contentFileList: []
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
return (
|
||||
<Modal
|
||||
title="加入项目"
|
||||
visible={this.props.visible}
|
||||
onOk={this.handleOk}
|
||||
onCancel={this.handleCancel}
|
||||
centered={true}
|
||||
width={500}
|
||||
>
|
||||
<Form layout="inline" className="inviteForm2">
|
||||
<Form.Item label="选择角色">
|
||||
{getFieldDecorator('role', {
|
||||
rules: [{ required: true, message: '请选择角色' }],
|
||||
initialValue: 'developer',
|
||||
})(
|
||||
<Radio.Group defaultValue={'developer'}>
|
||||
<Radio value="manager">管理员</Radio>
|
||||
<Radio value="developer">开发者</Radio>
|
||||
<Radio value="reporter">报告者</Radio>
|
||||
</Radio.Group>
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item label="个人情况">
|
||||
{getFieldDecorator('remarks', {
|
||||
rules: [{ required: true, message: '请输入个人情况' }],
|
||||
})(
|
||||
<Input
|
||||
placeholder="请输入个人情况"
|
||||
// autoComplete="off"
|
||||
maxLength={200}
|
||||
style={{ width: '300px', pointerEvents: 'auto' }} // 确保 pointer-events 为 auto
|
||||
/>
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item label="个人资料" style={{ flexWrap: 'nowrap' }}>
|
||||
{getFieldDecorator('attachment_id', {
|
||||
rules: [],
|
||||
})(
|
||||
<Upload {...this.uploadProps()}>
|
||||
<Button type="default" className='mr5'>
|
||||
<Icon type="upload" /> 上传附件
|
||||
</Button>
|
||||
(单个文件最大20MB)
|
||||
</Upload>
|
||||
)}
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const WrappedPrivateAccessModal = Form.create()(PrivateAccessModal);
|
||||
|
||||
class IndexItem extends Component {
|
||||
TurnToDetail = (login, url) => {
|
||||
this.props.history.push({
|
||||
pathname: url,
|
||||
state: login
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
state = {
|
||||
showModal: false,
|
||||
projectInfo: null
|
||||
};
|
||||
|
||||
openModal = (projectInfo) => {
|
||||
this.setState({ showModal: true, projectInfo });
|
||||
};
|
||||
|
||||
closeModal = () => {
|
||||
this.setState({ showModal: false, projectInfo: null });
|
||||
};
|
||||
|
||||
render() {
|
||||
const { projects } = this.props;
|
||||
return (
|
||||
<div className="project-list minH-670" style={{padding:"0px 20px"}}>
|
||||
{ projects && projects.length > 0 ? projects.map((item, key) => {
|
||||
<div className="project-list minH-670" style={{ padding: "0px 20px" }}>
|
||||
{projects && projects.length > 0 ? projects.map((item, key) => {
|
||||
return (
|
||||
<div className="p-r-Item" key={key}>
|
||||
{
|
||||
item.platform === "educoder" ?
|
||||
<a href="javascript:void(0)" style={{cursor:"default"}} className="show-user-link">
|
||||
<img className="p-r-photo" alt="" src={item.author && item.author.image_url} ></img>
|
||||
</a>
|
||||
:
|
||||
<Link to={item.author && (item.author.type === "Organization" ? `/organize/${item.author.login}`:`/users/${item.author.login}`)} className="show-user-link">
|
||||
<img className="p-r-photo" alt="" src={getImageUrl(`/${item.author && item.author.image_url}`)} ></img>
|
||||
</Link>
|
||||
item.platform === "educoder" ? (
|
||||
<a href="javascript:void(0)" style={{ cursor: "default" }} className="show-user-link">
|
||||
<img className="p-r-photo" alt="" src={item.author && item.author.image_url} />
|
||||
</a>
|
||||
) : (
|
||||
<Link to={item.author && (item.author.type === "Organization" ? `/organize/${item.author.login}` : `/users/${item.author.login}`)} className="show-user-link">
|
||||
<img className="p-r-photo" alt="" src={getImageUrl(`/${item.author && item.author.image_url}`)} />
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
<div className="p-r-Infos">
|
||||
<div className="p-r-name">
|
||||
<AlignCenter>
|
||||
<Link to={`/projects/${item.author.login}/${item.identifier}`} title={`${item.author.name}/${item.name}`} className="color-grey-3 font-18 task-hide " style={{maxWidth: 470 }}>
|
||||
<Link onClick={(e) => {
|
||||
if (item.is_member || item.is_manager || !item.join_project_need_verify) {
|
||||
return true;
|
||||
} else {
|
||||
e.preventDefault();
|
||||
this.openModal(item);
|
||||
return false;
|
||||
}
|
||||
}} to={`/projects/${item.author.login}/${item.identifier}`} title={`${item.author.name}/${item.name}`} className="color-grey-3 font-18 task-hide " style={{ maxWidth: 470 }}>
|
||||
{item.author.name}/{item.name}
|
||||
</Link>
|
||||
{ !item.is_public && <span className="privateTag">私有</span> }
|
||||
{!item.is_public && <span className="privateTag">私有</span>}
|
||||
{
|
||||
item.forked_from_project_id ?
|
||||
item.forked_from_project_id ? (
|
||||
<span className="ml5">
|
||||
<i className="iconfont icon-fork font-18 color-orange" />
|
||||
</span>
|
||||
: ""
|
||||
) : null
|
||||
}
|
||||
{
|
||||
item.type && item.type !== 0 ?
|
||||
item.type === 2 ?
|
||||
<Tooltip title="该项目是一个镜像" className="ml5">
|
||||
<i className="iconfont icon-banbenku font-18 color-green" />
|
||||
</Tooltip>:
|
||||
<span className="ml5">
|
||||
<i className="iconfont icon-jingxiang font-18 color-green" />
|
||||
</span>:""
|
||||
item.type && item.type !== 0 ?
|
||||
item.type === 2 ?
|
||||
<Tooltip title="该项目是一个镜像" className="ml5">
|
||||
<i className="iconfont icon-banbenku font-18 color-green" />
|
||||
</Tooltip> :
|
||||
<span className="ml5">
|
||||
<i className="iconfont icon-jingxiang font-18 color-green" />
|
||||
</span> : null
|
||||
}
|
||||
</AlignCenter>
|
||||
<AlignCenter>
|
||||
{
|
||||
(item.is_manager && item.join_project_need_verify && !!item.pending_verify_count) && <span style={{position:'relative',display:'inline-block',width:'120px',textAlign:'center',background:'rgba(250,100,0,0.1)',borderRadius:'2px',border:'1px solid #FFDCC5'}}>
|
||||
<Badge dot offset={[-90,7]} style={{ backgroundColor: '#FA6400' }}><span style={{fontSize:'12px',color:'#FA6400'}}>待审核申请:{item.pending_verify_count}</span></Badge>
|
||||
</span>}
|
||||
<span className="p-r-tags">
|
||||
{
|
||||
item.praises_count && item.praises_count>0 ?
|
||||
<span className="pariseTag">
|
||||
<img src={img_parise} alt="" className="pariseImg" />赞 {item.praises_count}
|
||||
</span>:""
|
||||
item.praises_count && item.praises_count > 0 ?
|
||||
<span className="pariseTag">
|
||||
<img src={img_parise} alt="" className="pariseImg" />赞 {item.praises_count}
|
||||
</span> : null
|
||||
}
|
||||
{
|
||||
item.forked_count && item.forked_count>0 ?
|
||||
<span>
|
||||
<i className="iconfont icon-fork mr3 font-16" style={{ color: "#1B8FFF" }} />fork {item.forked_count}
|
||||
</span>:""
|
||||
item.forked_count && item.forked_count > 0 ?
|
||||
<span>
|
||||
<i className="iconfont icon-fork mr3 font-16" style={{ color: "#1B8FFF" }} />fork {item.forked_count}
|
||||
</span> : null
|
||||
}
|
||||
</span>
|
||||
</AlignCenter>
|
||||
</div>
|
||||
<p className="break_word task-hide-2 mt10" style={{ maxHeight: "44px",lineHeight:"22px" }}>{item.description}</p>
|
||||
<p className="break_word task-hide-2 mt10" style={{ maxHeight: "44px", lineHeight: "22px" }}>{item.description}</p>
|
||||
|
||||
<div className="p-r-about">
|
||||
<span className="p-r-detail">
|
||||
{/* <span><label>浏览量:</label>{item.visits}</span> */}
|
||||
{/* {item.category && item.category.id && <span>{item.category.name}</span>} */}
|
||||
{item.last_update_time ? <span><label>更新于</label>{item.time_ago}</span> : ""}
|
||||
{item.language && item.language.id ? <span className="color-grey-3">{item.language.name}</span> : ""}
|
||||
{item.last_update_time ? <span><label>更新于</label>{item.time_ago}</span> : null}
|
||||
{item.language && item.language.id ? <span className="color-grey-3">{item.language.name}</span> : null}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}) : <Nodata _html="暂无数据~"></Nodata>}
|
||||
);
|
||||
}) : <Nodata _html="暂无数据~" />}
|
||||
<WrappedPrivateAccessModal
|
||||
visible={this.state.showModal}
|
||||
onClose={this.closeModal}
|
||||
projectInfo={this.state.projectInfo}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default IndexItem;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { Skeleton , Tooltip } from 'antd';
|
||||
import { Skeleton , Tooltip,Badge } from 'antd';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
function DetailBanner({ history,list , owner , projectsId , isManager , url , pathname , state , urlFlag , projectDetail , platform ,open_devops }){
|
||||
|
|
@ -109,7 +109,7 @@ function DetailBanner({ history,list , owner , projectsId , isManager , url , pa
|
|||
<li className={pathname === "setting" ? "active" : ""}>
|
||||
<Link to={`/projects/${owner}/${projectsId}/setting`}>
|
||||
<i className={url && url.indexOf("/setting") > 0 ? "iconfont icon-cangku color-grey-3 mr5 font-14":"iconfont icon-cangku color-grey-6 font-14 mr5"}></i>
|
||||
<span>设置</span>
|
||||
{projectDetail && projectDetail.pending_verify_count ? <Badge dot offset={[6,-2]}><span>设置</span></Badge> :'设置'}
|
||||
</Link>
|
||||
</li>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,8 @@ class Index extends Component {
|
|||
project_category_name: undefined,
|
||||
license_name: undefined,
|
||||
ignore_name: undefined,
|
||||
descNum:0
|
||||
descNum:0,
|
||||
join_project_need_verify:true
|
||||
}
|
||||
}
|
||||
componentDidMount = () => {
|
||||
|
|
@ -169,7 +170,7 @@ class Index extends Component {
|
|||
isSpin: true
|
||||
})
|
||||
const { projectsType } = this.props.match.params;
|
||||
const { project_language_id, project_category_id, license_id, ignore_id , owners_id , owners_name } = this.state;
|
||||
const { project_language_id, project_category_id, license_id, ignore_id , owners_id , owners_name,join_project_need_verify } = this.state;
|
||||
const decoderPass = Base64.encode(values.password);
|
||||
const url = (projectsType && projectsType === "mirror") ? "/projects/migrate.json" : "/projects.json";
|
||||
axios.post(url, {
|
||||
|
|
@ -179,7 +180,8 @@ class Index extends Component {
|
|||
project_category_id,
|
||||
license_id,
|
||||
ignore_id,
|
||||
user_id:owners_id
|
||||
user_id:owners_id,
|
||||
join_project_need_verify
|
||||
}).then((result) => {
|
||||
if (result) {
|
||||
if (result.data.id) {
|
||||
|
|
@ -288,6 +290,7 @@ class Index extends Component {
|
|||
ignore_list,
|
||||
|
||||
mirrorCheck,
|
||||
join_project_need_verify,
|
||||
|
||||
descNum
|
||||
} = this.state;
|
||||
|
|
@ -511,6 +514,14 @@ class Index extends Component {
|
|||
)}
|
||||
</Form.Item >
|
||||
}
|
||||
<Form.Item
|
||||
label="加入项目设置"
|
||||
colon={false}
|
||||
>
|
||||
{getFieldDecorator('join_project_need_verify')(
|
||||
<Checkbox checked={join_project_need_verify} onChange={(e)=>this.setState({join_project_need_verify:e.target.checked})}>用户加入项目时需要审核<span className="font-13 color-grey-9">(使用邀请码加入也需要审核,由项目所有人或管理员审核)</span></Checkbox>
|
||||
)}
|
||||
</Form.Item >
|
||||
<div>
|
||||
注:<span className="ant-form-item-required"></span> 为必填项,否则为选填
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,248 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { WhiteBack, FlexAJ } from '../Component/layout';
|
||||
import { Table, Pagination, Popconfirm, Button, Modal, message, Input } from 'antd';
|
||||
import Title from '../Component/Title';
|
||||
import Search from '../Component/Search';
|
||||
import styled from 'styled-components';
|
||||
import { getImageUrl } from 'educoder';
|
||||
import axios from 'axios';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
const Img = styled.img`{
|
||||
width:30px;
|
||||
height:30px;
|
||||
border-radius:50%;
|
||||
}`
|
||||
|
||||
|
||||
export default ((props) => {
|
||||
const [page, setPage] = useState(1);
|
||||
const [limit, setLimit] = useState(15);
|
||||
const [total, setTotal] = useState(0);
|
||||
const [search, setSearch] = useState(undefined);
|
||||
const [data, setData] = useState([]);
|
||||
const [status, setStatus] = useState(1);
|
||||
|
||||
useEffect(() => {
|
||||
getData();
|
||||
}, [])
|
||||
|
||||
function getData(status, search, page) {
|
||||
const url = `/applied_projects.json`;
|
||||
axios.get(url, {
|
||||
params: {
|
||||
page, limit,
|
||||
keyword: search,
|
||||
status,
|
||||
project_id: (props.projectDetail) ? props.projectDetail.project_id :''
|
||||
}
|
||||
}).then(result => {
|
||||
if (result && result.data) {
|
||||
setData(result.data.data.list);
|
||||
setTotal(result.data.data.count);
|
||||
}
|
||||
}).catch(error => { })
|
||||
}
|
||||
|
||||
// 切换分页
|
||||
function ChangePage(page) {
|
||||
setPage(page);
|
||||
getData(status, search, page);
|
||||
}
|
||||
|
||||
function verify(id, verifyStatus, reason) {
|
||||
const url = `/applied_projects/${id}/verify.json?status=${status}`;
|
||||
axios.post(url, {
|
||||
verify_status: verifyStatus,
|
||||
status,
|
||||
reason
|
||||
}).then(result => {
|
||||
if (result && result.data) {
|
||||
message.success("操作成功!");
|
||||
getData(status, search, page);
|
||||
}
|
||||
}).catch(error => { })
|
||||
}
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: '用户名',
|
||||
dataIndex: 'user_name',
|
||||
ellipsis: true,
|
||||
width: "12%",
|
||||
align:'left',
|
||||
render: (item, record) => <span>{item || '--'}</span>
|
||||
},
|
||||
{
|
||||
title: '申请角色',
|
||||
dataIndex: 'applied_project',
|
||||
ellipsis: true,
|
||||
width: "10%",
|
||||
align:'left',
|
||||
render: (value, item) => {
|
||||
return value || "--"
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '学号',
|
||||
dataIndex: 'student_id',
|
||||
ellipsis: true,
|
||||
width: "10%",
|
||||
align: "left",
|
||||
render: (value) => {
|
||||
return value || "--"
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '邮箱',
|
||||
dataIndex: 'mail',
|
||||
ellipsis: true,
|
||||
width: "10%",
|
||||
align:'left',
|
||||
render: (value) => value || "--"
|
||||
},
|
||||
{
|
||||
title: '个人情况',
|
||||
dataIndex: 'remarks',
|
||||
ellipsis: true,
|
||||
width: "15%",
|
||||
align:'left',
|
||||
render: (value) => value || "--"
|
||||
},
|
||||
{
|
||||
title: '上传附件',
|
||||
dataIndex: 'attachment_info',
|
||||
width: "10%",
|
||||
align:'left',
|
||||
render: (value, record) => {
|
||||
if (JSON.stringify(record.attachment_info)!="{}") {
|
||||
return <Button type='link' style={{padding:'0'}} onClick={() => {
|
||||
// 构建下载链接
|
||||
const downloadUrl = `${record.attachment_info.url}`;
|
||||
// 创建一个 a 元素
|
||||
const a = document.createElement('a');
|
||||
// 设置 a 元素的 href 属性为下载链接
|
||||
a.href = downloadUrl;
|
||||
// 设置 a 元素的 download 属性,可根据实际情况设置文件名
|
||||
a.download = record.attachment_info.title || 'attachment';
|
||||
// 模拟点击 a 元素
|
||||
document.body.appendChild(a)
|
||||
a.click();
|
||||
// 移除 a 元素
|
||||
document.body.removeChild(a);
|
||||
}}>下载</Button>
|
||||
} else {
|
||||
return '--'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '拒绝原因',
|
||||
dataIndex: 'reason',
|
||||
ellipsis: true,
|
||||
width: "15%",
|
||||
align:'left',
|
||||
render: (value) => value || "--"
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'operation1',
|
||||
width: "15%",
|
||||
align:'right',
|
||||
flex:'right',
|
||||
render: (value, item) => {
|
||||
return (
|
||||
<div>
|
||||
<Button type='link' style={{padding:'0 5px'}} onClick={() => {
|
||||
Modal.confirm({
|
||||
title: '是否确认同意TA的加入?',
|
||||
okText: '确认',
|
||||
cancelText: '取消',
|
||||
centered: true,
|
||||
onOk: () => {
|
||||
verify(item.id, 'agree', '')
|
||||
},
|
||||
});
|
||||
}}>同意</Button>
|
||||
<Button type='link' style={{padding:'0 5px',color:'#FF0000'}} onClick={() => {
|
||||
let rejectReason = '';
|
||||
Modal.confirm({
|
||||
title: '拒绝申请',
|
||||
icon: null,
|
||||
okText: '确认',
|
||||
centered: true,
|
||||
width: 500,
|
||||
content: <div>
|
||||
<div className='mb10 mt15'><span style={{ color: "#ff4d4f" }}>*</span><span>拒绝原因:</span></div>
|
||||
<div><Input.TextArea placeholder='请输入拒绝原因' rows={3} maxLength={200} onChange={(event) => {
|
||||
rejectReason = event.target.value;
|
||||
}} /></div>
|
||||
</div>,
|
||||
cancelText: '取消',
|
||||
onOk: () => {
|
||||
verify(item.id, 'reject', rejectReason)
|
||||
},
|
||||
})
|
||||
}}>拒绝</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'operation2',
|
||||
width: "15%",
|
||||
align:'right',
|
||||
flex:'right',
|
||||
render: (value, record) => <span style={{color:'#1991FF'}}>{record.status == 'accepted'? '已同意':'已拒绝'}</span>
|
||||
}
|
||||
].filter(item => {
|
||||
if (status == 1) {
|
||||
return item.dataIndex != 'operation2' && item.dataIndex!= 'reason'
|
||||
}else{
|
||||
return item.dataIndex != 'operation1'
|
||||
}
|
||||
})
|
||||
|
||||
return (
|
||||
<WhiteBack>
|
||||
<Title>
|
||||
<span>审核管理</span>
|
||||
</Title>
|
||||
<FlexAJ className="padding20-30">
|
||||
<div>
|
||||
<Button size='default' type={status == 1 ? 'primary' : 'default'} onClick={() => {
|
||||
setStatus(1);
|
||||
getData(1, search)
|
||||
}}>待审核</Button>
|
||||
<Button size='default' type={status == 2 ? 'primary' : 'default'} className='ml10' onClick={() => {
|
||||
setStatus(2);
|
||||
getData(2, search)
|
||||
}}>已审核</Button>
|
||||
</div>
|
||||
<div style={{ width: "300px" }}>
|
||||
<Search placeholder="搜索用户信息" onSearch={(value) => {
|
||||
setSearch(value)
|
||||
getData(status, value)
|
||||
}} />
|
||||
</div>
|
||||
</FlexAJ>
|
||||
<div className="pl30 pr30 pb30" style={{ minHeight: "400px" }}>
|
||||
<Table
|
||||
size="small"
|
||||
columns={columns}
|
||||
dataSource={data}
|
||||
pagination={false}
|
||||
className="teamMemberTable"
|
||||
></Table>
|
||||
{
|
||||
total > limit ?
|
||||
<div className="edu-txt-center mt30 mb20">
|
||||
<Pagination simple current={page} total={total} pageSize={limit} onChange={ChangePage}></Pagination>
|
||||
</div>
|
||||
: ""
|
||||
}
|
||||
</div>
|
||||
</WhiteBack>
|
||||
)
|
||||
})
|
||||
|
|
@ -7,6 +7,7 @@ import "./setting.scss";
|
|||
import Loadable from "react-loadable";
|
||||
import Loading from "../../Loading";
|
||||
import { Box, Long, Short, Gap } from '../Component/layout';
|
||||
import {Badge} from 'antd'
|
||||
|
||||
const BranchNew = Loadable({
|
||||
loader: () => import("./BranchRule"),
|
||||
|
|
@ -16,6 +17,10 @@ const Branch = Loadable({
|
|||
loader: () => import("./Branch"),
|
||||
loading: Loading,
|
||||
});
|
||||
const Audit = Loadable({
|
||||
loader: () => import("./Audit"),
|
||||
loading: Loading,
|
||||
});
|
||||
const Setting = Loadable({
|
||||
loader: () => import("./Setting"),
|
||||
loading: Loading,
|
||||
|
|
@ -65,6 +70,18 @@ class Index extends Component {
|
|||
</Link>
|
||||
</p>
|
||||
</li>
|
||||
<li
|
||||
className={
|
||||
pathname.indexOf("setting/audit") > -1 ? "active" : ""
|
||||
}
|
||||
>
|
||||
<p>
|
||||
<Link to={`/projects/${owner}/${projectsId}/setting/audit`} className="w-100">
|
||||
<i className="iconfont icon-zhongqingdianxinicon10 font-18 mr10"></i>
|
||||
{(this.props.projectDetail && this.props.projectDetail.pending_verify_count) ? <Badge dot offset={[6,-2]}><span style={{color:'#05101a',fontSize:'16px'}}>审核管理</span></Badge> : '审核管理'}
|
||||
</Link>
|
||||
</p>
|
||||
</li>
|
||||
<li
|
||||
className={
|
||||
pathname.indexOf("setting/branch") > -1 ? "active" : ""
|
||||
|
|
@ -125,6 +142,12 @@ class Index extends Component {
|
|||
<BranchNew {...this.props} {...props} {...this.state} />
|
||||
)}
|
||||
></Route>
|
||||
<Route
|
||||
path="/projects/:owner/:projectsId/setting/audit"
|
||||
render={(props) => (
|
||||
<Audit {...this.props} {...props} {...this.state} />
|
||||
)}
|
||||
></Route>
|
||||
<Route
|
||||
path="/projects/:owner/:projectsId/setting/branch"
|
||||
render={(props) => (
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@ class Setting extends Component {
|
|||
project_units:['home',"activity","code"],
|
||||
divertVisible:false,
|
||||
is_transfering:undefined,
|
||||
projectName:undefined
|
||||
projectName:undefined,
|
||||
join_project_need_verify:false
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -77,6 +78,7 @@ class Setting extends Component {
|
|||
this.setState({
|
||||
projectName:result.data.project_name,
|
||||
private_check: result.data.private,
|
||||
join_project_need_verify:result.data.join_project_need_verify,
|
||||
loading:false,
|
||||
project_units:units
|
||||
});
|
||||
|
|
@ -142,12 +144,13 @@ class Setting extends Component {
|
|||
|
||||
update=(values)=>{
|
||||
const { projectsId , owner } = this.props.match.params;
|
||||
const { private_check } = this.state;
|
||||
const { private_check ,join_project_need_verify} = this.state;
|
||||
const url = `/${owner}/${projectsId}.json`;
|
||||
axios.put(url, {
|
||||
name: values.project_name,
|
||||
description: values.project_description,
|
||||
private: private_check,
|
||||
join_project_need_verify:join_project_need_verify,
|
||||
...values,
|
||||
}).then((result) => {
|
||||
if (result) {
|
||||
|
|
@ -196,7 +199,7 @@ class Setting extends Component {
|
|||
const { getFieldDecorator } = this.props.form;
|
||||
const { projectDetail } = this.props;
|
||||
|
||||
const { CategoryList, LanguageList, private_check ,loading } = this.state;
|
||||
const { CategoryList, LanguageList, private_check ,loading,join_project_need_verify } = this.state;
|
||||
let mirror = projectDetail && projectDetail.mirror;
|
||||
let type = projectDetail && projectDetail.type;
|
||||
const forked_from_project_id = this.props && this.props.projectDetail && this.props.projectDetail.forked_from_project_id;
|
||||
|
|
@ -216,8 +219,8 @@ class Setting extends Component {
|
|||
],
|
||||
})(<Input placeholder="请输入项目名称" />)}
|
||||
</Form.Item>
|
||||
<div className="df" style={{ alignItems: "center" }}>
|
||||
<span className="mr20 mb15 font-16">可见性</span>
|
||||
<div className="df">
|
||||
<span className="mr20 mb15 font-14" style={{marginTop:'8px'}}>可见性</span>
|
||||
<Form.Item label="">
|
||||
{getFieldDecorator("private", {
|
||||
rules: [],
|
||||
|
|
@ -227,8 +230,8 @@ class Setting extends Component {
|
|||
onChange={this.changePrivate}
|
||||
disabled={forked_from_project_id}
|
||||
>
|
||||
<span className="color-grey-9">将仓库设为私有</span>
|
||||
<span className="color-grey-6">
|
||||
<span className="color-grey-6">将仓库设为私有</span>
|
||||
<span className="color-grey-9">
|
||||
{ forked_from_project_id ?`(Fork仓库的可见性实时同步自源仓库,不支持直接修改)`:`(修改仓库的可见性,将会影响到该仓库下所有Fork仓库的可见性)`}
|
||||
</span>
|
||||
</Checkbox>
|
||||
|
|
@ -284,6 +287,24 @@ class Setting extends Component {
|
|||
</Checkbox.Group>
|
||||
)}
|
||||
</Form.Item>
|
||||
<div className="df">
|
||||
<span className="mr20 mb15 font-14" style={{marginTop:'8px'}}>加入项目设置</span>
|
||||
<Form.Item label="">
|
||||
{getFieldDecorator("join_project_need_verify", {
|
||||
rules: [],
|
||||
})(
|
||||
<Checkbox
|
||||
checked={join_project_need_verify}
|
||||
onChange={(e)=>this.setState({join_project_need_verify:e.target.checked})}
|
||||
>
|
||||
<span className="color-grey-6">用户加入项目时需要审核</span>
|
||||
<span className="color-grey-9">
|
||||
(使用邀请码加入也需要审核,由项目所有人或管理员审核)
|
||||
</span>
|
||||
</Checkbox>
|
||||
)}
|
||||
</Form.Item>
|
||||
</div>
|
||||
<p className="clearfix">
|
||||
<a className="submitBtn" onClick={this.resetSetting}>
|
||||
更新仓库设置
|
||||
|
|
|
|||
Loading…
Reference in New Issue