项目转移--整体数据绑定

This commit is contained in:
caishi 2021-04-26 14:59:19 +08:00
parent 09065383c1
commit 4e48b0b363
7 changed files with 241 additions and 103 deletions

View File

@ -25,7 +25,7 @@ if (isDev) {
} }
debugType = window.location.search.indexOf('debug=t') !== -1 ? 'teacher' : debugType = window.location.search.indexOf('debug=t') !== -1 ? 'teacher' :
window.location.search.indexOf('debug=s') !== -1 ? 'student' : window.location.search.indexOf('debug=s') !== -1 ? 'student' :
window.location.search.indexOf('debug=a') !== -1 ? 'admin' : parsed.debug || 'admin' window.location.search.indexOf('debug=a') !== -1 ? 'admin' : parsed.debug || 'student'
} }
window._debugType = debugType; window._debugType = debugType;
export function initAxiosInterceptors(props) { export function initAxiosInterceptors(props) {

View File

@ -1,27 +1,66 @@
import React ,{ forwardRef, useEffect, useState } from 'react'; import React ,{ forwardRef, useEffect, useState } from 'react';
import { Modal , Form , Input , Radio , Select } from 'antd'; import { Modal , Form , Input , Radio , Select } from 'antd';
import './Index.scss'; import './Index.scss';
import Axios from 'axios';
const { Option } = Select; const { Option } = Select;
function DivertModal({form , visible , onSuccess , onCancel}){ function DivertModal({form , visible , onSuccess , onCancel,owner,repo}){
const { getFieldDecorator, validateFields , setFieldsValue } = form; const { getFieldDecorator, validateFields , setFieldsValue } = form;
const [ cate , setCate ] = useState(0); const [ cate , setCate ] = useState(0);
const [ organizations , setOrganizations ] = useState(undefined);
useEffect(()=>{ useEffect(()=>{
setFieldsValue({goal:cate}) setFieldsValue({goal:cate})
},[]) },[])
useEffect(()=>{
if(owner && repo && visible===true){
getTeam();
}
},[repo,owner,visible])
function getTeam(){
const url = `/${owner}/${repo}/applied_transfer_projects/organizations.json`;
Axios.get(url).then(result=>{
if(result){
setOrganizations(result.data.organizations);
}
}).catch(error=>{})
}
//
function onOk(){ function onOk(){
validateFields((error,values)=>{ validateFields((error,values)=>{
if(!error){ if(!error){
onSuccess(); const url = `/${owner}/${repo}/applied_transfer_projects.json`;
Axios.post(url,{
...values
}).then(result=>{
if(result){
onSuccess();
}
}).catch(error=>{})
} }
}) })
} }
function changeType(e){ function changeType(e){
setCate(e.target.value); setCate(e.target.value);
setFieldsValue({
owner_name:undefined
})
} }
function checkIdentifier(rule, value, callback){
if(!value){
callback();
}
if (repo && value !== repo) {
callback("请输入当前项目的标识!");
}
callback();
}
const layout = { const layout = {
labelCol: { span: 5 }, labelCol: { span: 5 },
wrapperCol: { span: 18 }, wrapperCol: { span: 18 },
@ -33,7 +72,7 @@ function DivertModal({form , visible , onSuccess , onCancel}){
title="转移仓库" title="转移仓库"
onCancel={onCancel} onCancel={onCancel}
onOk={onOk} onOk={onOk}
okText="转移" okText="确认转移"
cancelText={"取消"} cancelText={"取消"}
centered centered
> >
@ -63,27 +102,47 @@ function DivertModal({form , visible , onSuccess , onCancel}){
</Radio.Group> </Radio.Group>
)} )}
</Form.Item> </Form.Item>
<Form.Item label=" " style={{display:cate === 0 ? "block":"none"}}> {
{getFieldDecorator("username",{ cate === 0 &&
rules:[{required:true,message:"请输入目标用户名"}] <Form.Item label=" ">
})( {getFieldDecorator("owner_name",{
<Input placeholder="请输入要转移的目标用户名" autoComplete={"off"}/> rules:[{required:true,message:"请输入目标用户名"}]
)} })(
</Form.Item> <Input placeholder="请输入目标用户" autoComplete={"off"}/>
<Form.Item label=" " style={{display:cate ===1 ? "block" : "none"}}> )}
{getFieldDecorator("identitfy", </Form.Item>
{rules:[{required:true,message:"请输入目标组织"}]} }
)( {
<Select placeholder="请选择要转移的目标组织" > cate === 1 &&
<Option value="组织kkk">组织kkk</Option> <Form.Item label=" ">
<Option value="组织kkk1">组织kkk1</Option> {getFieldDecorator("owner_name",
<Option value="组织kkk2">组织kkk2</Option> {rules:[{required:true,message:"请选择目标组织"}]}
</Select> )(
)} <Select placeholder="请选择目标组织" >
</Form.Item> {
organizations && organizations.length > 0 ?
organizations.map((i,k)=>{
return(
<Option value={i.name}>{i.nickname}</Option>
)
})
:""
}
</Select>
)}
</Form.Item>
}
<Form.Item label="仓库标识:"> <Form.Item label="仓库标识:">
{getFieldDecorator("username", {getFieldDecorator("identifier",
{rules:[{required:true,message:"请输入仓库标识"}]} {
rules:[
{required:true,message:"请输入仓库标识"},
{
validator:checkIdentifier
}
]
}
)( )(
<Input placeholder="请输入仓库标识" autoComplete={"off"}/> <Input placeholder="请输入仓库标识" autoComplete={"off"}/>
)} )}

View File

@ -1,4 +1,5 @@
.noticeMenu{ .noticeMenu{
padding:0px 20px;
.ant-menu-item{ .ant-menu-item{
font-size: 16px; font-size: 16px;
padding:0px; padding:0px;

View File

@ -1,28 +1,36 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import Nodata from '../Nodata'; import Nodata from '../Nodata';
import { Skeleton , Pagination } from 'antd'; import {Pagination } from 'antd';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { getImageUrl } from 'educoder'; import { getImageUrl } from 'educoder';
import Axios from "axios";
let l= [
{
name:"创新使者",image_url:"system/lets/letter_avatars/2/D/169_162_140/120.png",
type:"moving",time:"几分钟前",login:"innov"
},
{
name:"创新使者",image_url:"system/lets/letter_avatars/2/D/169_162_140/120.png",
type:"moving",time:"几分钟前",login:"innov"
}
]
const limit = 15; const limit = 15;
function Notify(props){ function Notify(props){
const username = props.match.params.username;
const [ list , setList ] = useState(undefined); const [ list , setList ] = useState(undefined);
const [ page , setPage ] = useState(1); const [ page , setPage ] = useState(1);
const [ total , setTotal ] = useState(0); const [ total , setTotal ] = useState(0);
useEffect(()=>{ useEffect(()=>{
setList(l); if(username){
},[]) getList();
}
},[username,page])
function getList(){
const url = `/users/${username}/applied_messages.json`;
Axios.get(url,{
params:{
page,per_page:limit
}
}).then(result=>{
if(result){
setList(result.data.applied_messages);
setTotal(result.data.total_count);
}
}).catch(error=>{})
}
return( return(
<div> <div>
@ -34,13 +42,13 @@ function Notify(props){
list.map((i,k)=>{ list.map((i,k)=>{
return( return(
<li> <li>
<Link to={`/users/${i.login}`}><img src={getImageUrl(i.image_url)} alt="" className="notifyImg"/></Link> <Link to={`/users/${i.login}`}><img src={getImageUrl(i.applied_user && i.applied_user.image_url)} alt="" className="notifyImg"/></Link>
<div className="notifyFlex"> <div className="notifyFlex">
<p className="notifyInfos"> <p className="notifyInfos">
<Link to={`/users/${i.login}`} className="font-15 mr20">{i.name}</Link> <Link to={`/users/${i.applied_user && i.applied_user.login}`} className="font-15 mr20">{i.applied_user && i.applied_user.name}</Link>
<span className="color-grey-9">{i.time}</span> <span className="color-grey-9">{i.time_ago}</span>
</p> </p>
<p>正在将仓库转移给某某某</p> <p>{i.name}</p>
</div> </div>
</li> </li>
) )
@ -49,9 +57,9 @@ function Notify(props){
</ul> </ul>
</div> </div>
: :
<Skeleton /> ""
} }
{list && list.length === 0 && <Nodata _html="暂无数组" /> } {list && list.length === 0 && <Nodata _html="暂无数组" />}
{ {
total > limit && total > limit &&
<div className="edu-txt-center pt20 pb20"> <div className="edu-txt-center pt20 pb20">

View File

@ -1,38 +1,57 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import Nodata from '../Nodata'; import Nodata from '../Nodata';
import { FlexAJ } from '../Component/layout'; import { FlexAJ } from '../Component/layout';
import { Skeleton , Pagination } from 'antd'; import { Pagination , Popconfirm } from 'antd';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { getImageUrl } from 'educoder'; import { getImageUrl } from 'educoder';
import Axios from 'axios';
let l= [
{
name:"创新使者",image_url:"system/lets/letter_avatars/2/D/169_162_140/120.png",
type:"moving",time:"几分钟前",login:"innov"
},
{
name:"创新使者",image_url:"system/lets/letter_avatars/2/D/169_162_140/120.png",
type:"moving",time:"几分钟前",login:"innov"
}
]
const limit = 15; const limit = 15;
function UndoEvent(props){ function UndoEvent(props){
const username = props.match.params.username;
const [ list , setList ] = useState(undefined); const [ list , setList ] = useState(undefined);
const [ page , setPage ] = useState(1); const [ page , setPage ] = useState(1);
const [ total , setTotal ] = useState(0); const [ total , setTotal ] = useState(0);
useEffect(()=>{ useEffect(()=>{
setList(l); if(username){
},[]) getList();
}
},[username,page])
function getList(){
const url = `/users/${username}/applied_transfer_projects.json`;
Axios.get(url,{
params:{
page,per_page:limit
}
}).then(result=>{
if(result){
setList(result.data.applied_transfer_projects);
setTotal(result.data.total_count);
}
}).catch(error=>{})
}
// //
function acceptDivert(){ function acceptDivert(id){
const url = `/users/${username}/applied_transfer_projects/${id}/accept.json`;
Axios.post(url).then(result=>{
if(result && result.data){
getList();
}
}).catch(error=>{})
} }
// //
function revertDivert(){ function revertDivert(id){
const url = `/users/${username}/applied_transfer_projects/${id}/refuse.json`;
Axios.post(url).then(result=>{
if(result && result.data){
getList();
}
}).catch(error=>{})
} }
return( return(
@ -45,18 +64,34 @@ function UndoEvent(props){
list.map((i,k)=>{ list.map((i,k)=>{
return( return(
<li> <li>
<Link to={`/users/${i.login}`}><img src={getImageUrl(i.image_url)} alt="" className="notifyImg"/></Link> <Link to={`/users/${i.user && i.user.login}`}><img src={getImageUrl(i.user && i.user.image_url)} alt="" className="notifyImg"/></Link>
<div className="notifyFlex"> <div className="notifyFlex">
<p className="notifyInfos"> <p className="notifyInfos">
<Link to={`/users/${i.login}`} className="font-15 mr20">{i.name}</Link> <Link to={`/users/${i.login}`} className="font-15 mr20">{i.user && i.user.name}</Link>
<span className="color-grey-9">{i.time}</span> <span className="color-grey-9">{i.time_ago}</span>
</p> </p>
<FlexAJ> <FlexAJ>
<p>请求将仓库转移给用户名,是否接受</p> <p>请求将仓库转移给{i.owner && i.owner.name},是否接受</p>
<span> {
<a className="color-grey-3" onClick={acceptDivert}>接受</a> i.status === "common" &&
<a className="color-red ml20" onClick={revertDivert}>拒绝</a> <span>
</span> <Popconfirm title={`确定接受仓库${i.project && i.project.name}`} okText="确定" cancelText="取消" onConfirm={()=>acceptDivert(i.id)}>
<a className="color-blue">接受</a>
</Popconfirm>
<Popconfirm title={`确定拒绝接受仓库${i.project && i.project.name}`} okText="确定" cancelText="取消" onConfirm={()=>revertDivert(i.id)}>
<a className="color-red ml20">拒绝</a>
</Popconfirm>
</span>
}
{
i.status === "canceled" && <span className="color-grey-9">对方已取消转移</span>
}
{
i.status === "accept" && <span className="color-grey-9">已接受</span>
}
{
i.status === "refused" && <span className="color-grey-9">已拒绝</span>
}
</FlexAJ> </FlexAJ>
</div> </div>
</li> </li>
@ -66,9 +101,9 @@ function UndoEvent(props){
</ul> </ul>
</div> </div>
: :
<Skeleton /> ""
} }
{list && list.length === 0 && <Nodata _html="暂无数组" /> } {list && list.length === 0 && <Nodata _html="暂无数组" />}
{ {
total > limit && total > limit &&
<div className="edu-txt-center pt20 pb20"> <div className="edu-txt-center pt20 pb20">

View File

@ -27,7 +27,9 @@ class Setting extends Component {
private_check: undefined, private_check: undefined,
loading:true, loading:true,
project_units:['home',"activity","code"], project_units:['home',"activity","code"],
divertVisible:false divertVisible:false,
is_transfering:undefined,
permission:undefined
}; };
} }
@ -75,7 +77,9 @@ class Setting extends Component {
this.setState({ this.setState({
private_check: result.data.private, private_check: result.data.private,
loading:false, loading:false,
project_units:units project_units:units,
is_transfering:result.data.is_transfering,
permission:result.data.permission
}); });
} }
}) })
@ -196,20 +200,44 @@ class Setting extends Component {
} }
// 取消仓库转移 // 取消仓库转移
CancelDivertProject=()=>{ CancelDivertProject=()=>{
this.props.confirm({
content: "是否确认取消将此项目转移给他人?",
onOk: () => {
const { projectsId , owner } = this.props.match.params;
const url = `/${owner}/${projectsId}/applied_transfer_projects/cancel.json`;
axios.post(url).then(result=>{
if(result && result.data){
this.setState({
is_transfering:false
})
}
}).catch(error=>{})
},
});
} }
// 确定转移仓库 // 确定转移仓库
onSuccess=()=>{ onSuccess=()=>{
this.setState({
is_transfering:true,
divertVisible:false
})
} }
render() { render() {
const { getFieldDecorator } = this.props.form; const { getFieldDecorator } = this.props.form;
const { projectsId , owner } = this.props.match.params;
const { CategoryList, LanguageList, private_check ,loading , divertVisible } = this.state; const { CategoryList, LanguageList, private_check ,loading , divertVisible , permission , is_transfering } = this.state;
return ( return (
<div> <div>
<DivertModal visible={divertVisible} onSuccess={this.onSuccess} onCancel={()=>{this.setState({divertVisible:false})}}/> <DivertModal
owner={owner}
repo={projectsId}
visible={divertVisible}
onSuccess={this.onSuccess}
onCancel={()=>{this.setState({divertVisible:false})}}
/>
<Spin spinning={loading}> <Spin spinning={loading}>
<WhiteBack> <WhiteBack>
<Title>基本设置</Title> <Title>基本设置</Title>
@ -297,32 +325,41 @@ class Setting extends Component {
{/* 镜像设置部分,暂无接口,先不显示 */} {/* 镜像设置部分,暂无接口,先不显示 */}
{/* <Mirror /> */} {/* <Mirror /> */}
</WhiteBack> </WhiteBack>
<WhiteBack className="dangerousBox mb20"> {
<div> permission && (permission === "Admin" || permission === "Owner")?
<div className="dangerousTitle">危险操作区</div> <WhiteBack className="dangerousBox mb20">
<div className="flex-a-center padding15-10" style={{borderBottom:"1px solid #f9edbe"}}>
<div> <div>
<p className="font-bd font-16">转移仓库</p> <div className="dangerousTitle">危险操作区</div>
<p className="mt10"> <div className="flex-a-center padding15-10" style={{borderBottom:"1px solid #f9edbe"}}>
将此仓库转移给其他用户或组织 <div>
</p> <p className="font-bd font-16">转移仓库</p>
<p className="mt10">
将此仓库转移给其他用户或组织
</p>
</div>
{
is_transfering ?
<a onClick={this.CancelDivertProject} className="red_deleteBtn">取消转移</a>
:
<a onClick={this.DivertProject} className="red_deleteBtn">转移</a>
}
</div>
<div className="flex-a-center padding15-10">
<div>
<p className="font-bd font-16">删除本仓库</p>
<p className="mt10">
删除仓库是永久性的,
无法撤消且删除后与仓库关联的项目/任务/合并请求/版本发布等均会被删除
</p>
</div>
<a onClick={this.deleteProject} className="red_deleteBtn">
删除本仓库
</a>
</div>
</div> </div>
<a onClick={this.DivertProject} className="red_deleteBtn">转移</a> </WhiteBack>
</div> :""
<div className="flex-a-center padding15-10"> }
<div>
<p className="font-bd font-16">删除本仓库</p>
<p className="mt10">
删除仓库是永久性的,
无法撤消且删除后与仓库关联的项目/任务/合并请求/版本发布等均会被删除
</p>
</div>
<a onClick={this.deleteProject} className="red_deleteBtn">
删除本仓库
</a>
</div>
</div>
</WhiteBack>
</Spin> </Spin>
</div> </div>
); );

View File

@ -213,7 +213,7 @@ class Infos extends Component {
</div> </div>
</div> </div>
</div> </div>
{current_user && user && current_user.id === user.id && ( {current_user && user && user.login === current_user.login ? (
<div className="bgcF"> <div className="bgcF">
<div className="list-l-Menu"> <div className="list-l-Menu">
<li className={project_type && project_type === "notice" ? "active" : ""}> <li className={project_type && project_type === "notice" ? "active" : ""}>
@ -229,7 +229,7 @@ class Infos extends Component {
</li> </li>
</div> </div>
</div> </div>
)} ):""}
<div className="bgcF"> <div className="bgcF">
<ul className="list-l-Menu"> <ul className="list-l-Menu">
@ -289,8 +289,6 @@ class Infos extends Component {
</ul> </ul>
</div> </div>
} }
<div className="bgcF"> <div className="bgcF">
<div className="list-l-Menu"> <div className="list-l-Menu">
<li className={project_type && project_type === "organizes" ? "active" : ""}> <li className={project_type && project_type === "organizes" ? "active" : ""}>