diff --git a/src/AppConfig.js b/src/AppConfig.js
index f897831f..2c34caa6 100644
--- a/src/AppConfig.js
+++ b/src/AppConfig.js
@@ -25,7 +25,7 @@ if (isDev) {
}
debugType = window.location.search.indexOf('debug=t') !== -1 ? 'teacher' :
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;
export function initAxiosInterceptors(props) {
diff --git a/src/forge/Head/AddProjectModal.jsx b/src/forge/Head/AddProjectModal.jsx
new file mode 100644
index 00000000..8e3073e3
--- /dev/null
+++ b/src/forge/Head/AddProjectModal.jsx
@@ -0,0 +1,84 @@
+import React, { useState , forwardRef, useEffect } from 'react';
+import { Form , Modal , Input , Radio } from 'antd';
+import Axios from 'axios';
+
+export default Form.create()(
+ forwardRef((props)=>{
+ const { getFieldDecorator, validateFields , setFieldsValue } = props && props.form;
+ const [ visible , setVisible ] = useState(false);
+
+ useEffect(()=>{
+ if(!visible){
+ setFieldsValue({
+ code:undefined,
+ role:"developer"
+ })
+ }
+ },[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){
+ callback();
+ }
+ if(value.length < 6 || value.length > 6){
+ callback("请输入6位数的邀请码");
+ }
+ callback();
+ }
+
+ return(
+
+ setVisible(false)}
+ >
+
+ {getFieldDecorator("code",{
+ rules:[
+ {required:true,message:"请输入6位项目邀请码"},
+ {validator:checkValue}
+ ]
+ })(
+
+ )}
+
+
+ {getFieldDecorator("role",{
+ rules:[{required:true,message:"请选择角色"}]
+ })(
+
+ 管理员
+ 开发者
+ 报告者
+
+ )}
+
+
+
+ setVisible(true)}>加入项目
+
+ )
+ })
+)
\ No newline at end of file
diff --git a/src/forge/Head/Header.js b/src/forge/Head/Header.js
index b2387cb6..f9071162 100644
--- a/src/forge/Head/Header.js
+++ b/src/forge/Head/Header.js
@@ -5,8 +5,7 @@ import axios from 'axios';
import { Input , notification , Dropdown , Menu } from 'antd';
import LoginDialog from '../../modules/login/LoginDialog';
-import GotoQQgroup from '../../modal/GotoQQgroup'
-
+import AddProjectModal from './AddProjectModal';
import '../../modules/tpm/TPMIndex.css';
import './header.scss';
@@ -268,11 +267,11 @@ class NewHeader extends Component {
)
})
}
+
)
}
-
renderMenu=(personal)=>{
const { current_user } = this.props;
return(
diff --git a/src/forge/Head/header.scss b/src/forge/Head/header.scss
index 507262e3..a2c11b7a 100644
--- a/src/forge/Head/header.scss
+++ b/src/forge/Head/header.scss
@@ -1,7 +1,6 @@
.dropdownFlex{
display:flex;
- padding:5px;
background:#fff;
border-radius: 3px;
.ant-menu-vertical > .ant-menu-item{
@@ -9,6 +8,13 @@
height: 35px;
line-height: 35px;
margin:0px;
+ &.ant-menu-item-selected{
+ background-color: #fff;
+ a{color: rgba(0, 0, 0, 0.65)!important;}
+ }
+ &.ant-menu-item-active{
+ a{color: #4cacff!important;}
+ }
}
.ant-menu-vertical{
border:none;
@@ -104,4 +110,13 @@
}
}
}
+}
+.inviteForm{
+ .ant-form-item{
+ margin-right: 0px;
+ }
+ .ant-form-item-label{
+ width: 110px;
+ text-align: right;
+ }
}
\ No newline at end of file
diff --git a/src/forge/Notice/Apply.jsx b/src/forge/Notice/Apply.jsx
new file mode 100644
index 00000000..3c77edfa
--- /dev/null
+++ b/src/forge/Notice/Apply.jsx
@@ -0,0 +1,114 @@
+import React, { useEffect , useState } from 'react';
+import Axios from 'axios';
+import { Pagination , Spin , Popconfirm }from 'antd';
+import { Link } from 'react-router-dom';
+import { getImageUrl } from 'educoder';
+import Nodata from '../Nodata';
+import { FlexAJ } from '../Component/layout';
+
+const limit = 15;
+function Apply(props) {
+ const username = props.match.params.username;
+ const [ list , setList ] = useState(undefined);
+ const [ page , setPage ] = useState(1);
+ const [ total , setTotal ] = useState(0);
+ const [ isSpin , setIsSpin ] = useState(true);
+
+ useEffect(()=>{
+ if(username){
+ setIsSpin(true);
+ getList();
+ }
+ },[username])
+
+ function getList() {
+ const url = `/users/${username}/applied_projects.json`;
+ Axios.get(url).then(result=>{
+ if(result){
+ setList(result.data.applied_projects);
+ setTotal(result.data.total_count);
+ setIsSpin(false);
+ }
+ }).catch(error=>{})
+ }
+
+ // 接受
+ function acceptDivert(id){
+ const url = `/users/${username}/applied_projects/${id}/accept.json`;
+ Axios.post(url).then(result=>{
+ if(result && result.data){
+ getList();
+ props && props.deleteEvent("apply",1);
+ }
+ }).catch(error=>{})
+ }
+
+ // 拒绝
+ function revertDivert(id){
+ const url = `/users/${username}/applied_projects/${id}/refuse.json`;
+ Axios.post(url).then(result=>{
+ if(result && result.data){
+ getList();
+ props && props.deleteEvent("apply",1);
+ }
+ }).catch(error=>{})
+ }
+ return(
+
+
+
+ {
+ list && list.length > 0 ?
+
+ {
+ list.map((i,k)=>{
+ return(
+ -
+
+
+
+ {i.user && i.user.name}
+ {i.time_ago}
+
+
+ 申请以【{i.role === "developer" ?"开发者":i.role === "manager" ? "管理者":"报告者"}】身份加入【{i.project && i.project.name}】项目。是否同意?
+ {
+ i.status === "common" &&
+
+ acceptDivert(i.id)}>
+ 同意
+
+ revertDivert(i.id)}>
+ 拒绝
+
+
+ }
+ {
+ i.status === "accepted" && 已接受
+ }
+ {
+ i.status === "refused" && 已拒绝
+ }
+
+
+
+ )
+ })
+ }
+
+ :
+ ""
+ }
+ {list && list.length === 0 &&
}
+ {
+ total > limit &&
+
+ }
+
+
+
+ )
+}
+export default Apply;
\ No newline at end of file
diff --git a/src/forge/Notice/Index.jsx b/src/forge/Notice/Index.jsx
new file mode 100644
index 00000000..94c63804
--- /dev/null
+++ b/src/forge/Notice/Index.jsx
@@ -0,0 +1,128 @@
+import React, { useEffect, useState } from "react";
+import { Link } from 'react-router-dom';
+import './Index.scss';
+
+import Loadable from "react-loadable";
+import Loading from "../../Loading";
+import { Route, Switch } from "react-router-dom";
+
+const Apply = Loadable({
+ loader: () => import("./Apply"),
+ loading: Loading,
+});
+const Notify = Loadable({
+ loader: () => import("./Notify"),
+ loading: Loading,
+});
+const UndoEvent = Loadable({
+ loader: () => import("./UndoEvent"),
+ loading: Loading,
+});
+function Index(props){
+ const username = props.match.params.username;
+ const pathname = props.history.location.pathname;
+ const user = props.user;
+
+ const [ menu , setMenu ] = useState("notify");
+ const [ messagesCount , setMessagesCount ] = useState(0);
+ const [ transferCount , setTransferCount ] = useState(0);
+ const [ applyCount , setApplyCount ] = useState(0);
+
+ const [ flag , setFlag ] = useState(true);
+ const { current_user } = props;
+
+ useEffect(()=>{
+ if((username && current_user && (current_user.login !== username))){
+ props.history.push(`/users/${username}`);
+ }
+ },[current_user,username])
+
+ useEffect(()=>{
+ if(user){
+ setTransferCount(user.undo_transfer_projects);
+ setApplyCount(user.undo_join_projects);
+ setMessagesCount(user.undo_messages);
+ }
+ },[user])
+
+ useEffect(()=>{
+ if(pathname && username){
+ if(pathname === `/users/${username}/notice`){
+ setMenu("notify");
+ changeNum(user.undo_messages);
+ }
+ if(pathname === `/users/${username}/notice/undo`){
+ setMenu("undo");
+ }
+ if(pathname === `/users/${username}/notice/apply`){
+ setMenu("apply");
+ }
+ }
+ },[pathname,user])
+
+ function changeNum(){
+ if(flag){
+ messagesCount && props.deleteUndoEvent(messagesCount);
+ setFlag(false);
+ }
+ }
+
+ function deleteEvent(type,count) {
+ let c = count;
+ if(type==="apply"){
+ setApplyCount(applyCount-count);
+ }else if(type==="undo"){
+ setTransferCount(applyCount-count);
+ }else{
+ setMessagesCount(0);
+ c = messagesCount;
+ }
+ (c || c===0) && props.deleteUndoEvent(c);
+ }
+
+ return (
+
+
+ -
+
+ 通知
+ {messagesCount ? {messagesCount}:""}
+
+
+ -
+
+ 接收仓库
+ {transferCount ? {transferCount}:""}
+
+
+ -
+
+ 成员申请
+ {applyCount ? {applyCount}:""}
+
+
+
+
+ {
+ return ;
+ }}
+ >
+ {
+ return ;
+ }}
+ >
+ {
+ return ;
+ }}
+ >
+
+
+ );
+}
+export default Index;
diff --git a/src/forge/Notice/Index.scss b/src/forge/Notice/Index.scss
index a50c3413..b00e18a5 100644
--- a/src/forge/Notice/Index.scss
+++ b/src/forge/Notice/Index.scss
@@ -26,7 +26,7 @@
min-width: 23px;
text-align: center;
background-color: #ffe4b3;
- margin-top: 19px;
+ margin-top: 27px;
margin-left: 10px;
display: block;
}
diff --git a/src/forge/Notice/Notify.jsx b/src/forge/Notice/Notify.jsx
index 3aad55ae..761366d3 100644
--- a/src/forge/Notice/Notify.jsx
+++ b/src/forge/Notice/Notify.jsx
@@ -13,6 +13,10 @@ function Notify(props){
const [ total , setTotal ] = useState(0);
const [ isSpin , setIsSpin ] = useState(true);
+ useEffect(()=>{
+ props && props.deleteEvent("notify",0);
+ },[])
+
useEffect(()=>{
if(username){
setIsSpin(true);
@@ -43,7 +47,7 @@ function Notify(props){
return 取消转移【{project && project.name}】仓库
case 'common':
return 正在将【{project && project.name}】仓库转移给【{owner && owner.name}】
- case 'successed':
+ case 'successed':
return 【{project && project.name}】仓库成功转移给【{owner && owner.name}】
default:
return 拒绝转移【{project && project.name}】仓库
@@ -53,6 +57,20 @@ function Notify(props){
}
}
+ function renderApplyStatus(status,applied) {
+ let { project } = applied;
+ if(status){
+ switch(status){
+ case 'successed':
+ return 已通过你加入【{project && project.name}】项目的申请
+ default:
+ return 已拒绝你加入【{project && project.name}】项目的申请
+ }
+ }else{
+ return ""
+ }
+ }
+
return(
@@ -70,7 +88,7 @@ function Notify(props){
{i.applied_user && i.applied_user.name}
{i.time_ago}
- {renderStatus(i.status,i.applied)}
+ { i.applied_type === "AppliedProject" ? renderApplyStatus(i.status,i.applied):renderStatus(i.status,i.applied)}
)
diff --git a/src/forge/Notice/UndoEvent.jsx b/src/forge/Notice/UndoEvent.jsx
index 68557a9e..c8c579dc 100644
--- a/src/forge/Notice/UndoEvent.jsx
+++ b/src/forge/Notice/UndoEvent.jsx
@@ -42,7 +42,7 @@ function UndoEvent(props){
Axios.post(url).then(result=>{
if(result && result.data){
getList();
- props && props.fetchUser();
+ props && props.deleteEvent("undo",1);
}
}).catch(error=>{})
}
@@ -53,7 +53,7 @@ function UndoEvent(props){
Axios.post(url).then(result=>{
if(result && result.data){
getList();
- props && props.fetchUser();
+ props && props.deleteEvent("undo",1);
}
}).catch(error=>{})
}
diff --git a/src/forge/users/Infos.js b/src/forge/users/Infos.js
index c19bce07..9b292d2e 100644
--- a/src/forge/users/Infos.js
+++ b/src/forge/users/Infos.js
@@ -66,7 +66,6 @@ class Infos extends Component {
project_type: undefined,
route_type: undefined,
undo_events:0,
- undo_messages:0,
menuKey:"0"
};
}
@@ -124,20 +123,14 @@ class Infos extends Component {
});
const { current_user } = this.props;
const { username } = this.props.match.params;
- const { pathname } = this.props.location;
- const { notice } = this.state;
let url = `/users/${username || (current_user && current_user.login)}.json`;
axios.get(url).then((result) => {
let e = result.data && result.data.undo_events;
- let p = result.data && result.data.undo_messages;
- let n = notice || pathname === `/users/${username}/notice` ;
this.setState({
user: result.data,
isSpin: false,
- undo_events:n ? (e-p) : e,
- undo_messages:0,
- notice:n
+ undo_events:e
});
})
.catch((error) => {
@@ -161,7 +154,6 @@ class Infos extends Component {
this.setState({
route_type: undefined,
project_type:"notice",
- notice:true
},()=>{
this.props.history.push(`/users/${user && user.login}/notice`);
this.fetchUser();
@@ -190,6 +182,15 @@ class Infos extends Component {
resetUserInfo && resetUserInfo();
}
+ // 修改待办事项右侧的数量
+ deleteUndoEvent=(count)=>{
+ let { undo_events } = this.state;
+ let undo = undo_events - count;
+ this.setState({
+ undo_events:undo
+ })
+ }
+
render() {
const { current_user } = this.props;
const { username } = this.props.match.params;
@@ -306,7 +307,7 @@ class Infos extends Component {
{
- return ;
+ return ;
}}
>