forgeplus-react/src/forge/Issues/Pages/details.jsx

538 lines
19 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React , { useEffect , useState , forwardRef , useRef } from 'react';
import { Spin , Form , InputNumber, message } from 'antd';
import { getImageUrl } from 'educoder';
import { Link } from 'react-router-dom';
import { Box , LongWidth } from '../../Component/layout';
import RenderHtml from "../../../components/render-html";
import DropMenu from '../Component/dropMenu';
import NewPanel from '../Component/newPanel';
import Attachments from "../../Upload/attachment";
import DelBox from '../Component/delBox';
import Date from '../Component/date';
import moment from 'moment';
import Copy from '../Component/copy';
import axios from 'axios';
import CommentList from '../Component/comments/list';
import Claims from '../../claims/claims';
import ChooseMenu from '../Component/chooseMenu';
function Details(props){
const owner = props.match.params.owner;
const projectsId = props.match.params.projectsId;
const index = props.match.params.index;
const [ details , setDetails ] = useState(undefined);
const [ statusList , setStatusList ] = useState([]);
const [ prioritiesList , setPrioritiesList ] = useState([]);
const [ chargeList , setChargeList ] = useState([]);
const [ charge , setCharge ] = useState(undefined);
const [ millstoneList , setMillstoneList ] = useState([]);
const [ millstone , setMillstone ] = useState(undefined);
const [ tagList , setTagList ] = useState(undefined);
const [ tag , setTag ] = useState(undefined);
const [ branchList , setBranchList ] = useState(undefined);
const [ branch , setBranch ] = useState(undefined);
const [ desc , setDesc ] = useState(undefined);
const [ orderId , setOrderId ] = useState(undefined);
const [ delVisible , setDelVisible] = useState(false);
const [ edit , setEdit] = useState(false);
const [ copy , setCopy] = useState(false);
const [ start_date, setStartDate ] = useState("");
const [ due_date, setDueDate ] = useState("");
const [ commentReload, setCommentReload] = useState(undefined);
const [ editFlag , setEditFlag ] = useState(false);
const [ amountEditFlag , setAmountEditFlag ] = useState(false);
const [ assigner_choose , setAssigner_choose ] = useState([]);
const [ prioritie_choose , setPrioritie_choose ] = useState([]);
const [ status_choose , setStatus_choose ] = useState([]);
const [ tag_choose , setTag_choose ] = useState([]);
const [ millstone_choose , setMillstone_choose ] = useState([]);
const [ branch_choose , setBranch_choose ] = useState([]);
const [ rewardAmount , setRewardAmount ] = useState(undefined);
const [ rewardFlag , setRewardFlag ] = useState(false);
const pathname = props.history.location.pathname;
const permission = props && props.projectDetail && props.projectDetail.permission;
let colors = ["#1abcb1","#28be6c","#e67e22","#db3d1d"];
const {projectDetail , open_blockchain ,current_user, showNpsModal } = props;
useEffect(()=>{
if(pathname === `/${owner}/${projectsId}/issues/${index}/copy`){
setEdit(true);
setCopy(true);
}else{
setEdit(false);
setCopy(false);
}
},[pathname])
useEffect(()=>{
if(projectDetail && details){
const { author, name} = projectDetail;
document.title = `${details.subject}-任务-${author.name}/${name}`;
}
},[details,projectDetail])
useEffect(()=>{
if(index){
Init();
}
},[index])
function Init(){
const url = `/v1/${owner}/${projectsId}/issues/${index}`;
axios.get(url).then(result=>{
if(result && result.data){
let data = result.data;
setDetails(data);
let per = data && !data.user_permission;
setEditFlag(per);
setDesc(data && data.description);
const aut = current_user && data.author && (data.author.login === current_user.login);
const con = data.pull_fixed === false && aut;
setAmountEditFlag(con);
setAssigner_choose(data.assigners);
if(data.priority && data.priority.id){
setPrioritie_choose([{...data.priority,color:colors[data.priority.id-1]}]);
}else{
setPrioritie_choose([]);
}
setStatus_choose(data.status && data.status.id ? [data.status]:[]);
setTag_choose(data.tags);
setMillstone_choose(data.milestone && data.milestone.id ? [data.milestone]:[]);
setBranch_choose(data.branch_name ? [{name:data.branch_name}] : []);
setRewardAmount(data.blockchain_token_num);
data.start_date && setStartDate(moment(data.start_date).format('YYYY-MM-DD'));
data.due_date && setDueDate(moment(data.due_date).format('YYYY-MM-DD'));
setOrderId(data.id);
}
}).catch(error=>{
console.log(error);
})
}
function statusTag(name){
switch (name) {
case "低":
return "status low";
case "正常":
return "status normals";
case "高":
return "status hight";
default:
return "status urgent";
}
}
// 获取状态列表
useEffect(()=>{
getStatus();
},[])
function getStatus(){
const url = `/v1/${owner}/${projectsId}/issue_statues`;
axios.get(url).then(result=>{
if(result && result.data){
setStatusList(result.data.statues);
}
})
}
// 获取优先级列表
useEffect(()=>{
getPriorities();
},[])
function getPriorities(){
const url = `/v1/${owner}/${projectsId}/issue_priorities`;
axios.get(url).then(result=>{
if(result && result.data){
let priorities = result.data.priorities;
let array = addColorForPriorities(priorities);
setPrioritiesList(array);
}
})
}
function addColorForPriorities(list){
let array =[];
if(list && list.length>0){
array = list.map((i,k)=>{
let arr = {...i,color:colors[k]}
return arr;
})
}
return array;
}
// 获取负责人列表
useEffect(()=>{
getCharge();
},[charge])
function getCharge(){
const url = `/v1/${owner}/${projectsId}/collaborators`;
axios.get(url,{params:{keyword:charge,only_name:true}}).then(result=>{
if(result && result.data){
setChargeList(result.data.collaborators);
}
})
}
// 获取里程碑列表
useEffect(()=>{
getMillstone();
},[millstone])
function getMillstone(){
const url = `/v1/${owner}/${projectsId}/milestones`;
axios.get(url,{params:{keyword:millstone,only_name:true}}).then(result=>{
if(result && result.data){
setMillstoneList(result.data.milestones);
}
})
}
// 获取标记列表
useEffect(()=>{
getSign();
},[tag])
function getSign(){
const url = `/v1/${owner}/${projectsId}/issue_tags`;
axios.get(url,{params:{keyword:tag,only_name:true}}).then(result=>{
if(result && result.data){
setTagList(result.data.issue_tags);
}
})
}
// 获取标记列表
useEffect(()=>{
getBranch(branch);
},[branch])
function getBranch(branch){
if(branch){
let b = [...branchList];
let l = b.filter(i=>i.name.indexOf(branch)>-1);
setBranchList(l);
return ;
}
const url = `/${owner}/${projectsId}/branches.json`;
axios.get(url,{params:{keyword:tag}}).then(result=>{
if(result && result.data){
setBranchList(result.data);
}
})
}
// 可单个编辑保存右侧的项(!copy:非复制状态下)
function saveForeach(c,s,p,t,m,b,sDate,eDate,rewardAmount){
if(sDate && due_date){
if(sDate > due_date){
setStartDate(start_date);
return props.showNotification("开始日期不能晚于结束日期!");
}
}
if(eDate && start_date){
if(eDate < start_date){
setDueDate(due_date);
return props.showNotification("结束日期不能早于开始日期!");
}
}
if(!copy){
const url = `/v1/${owner}/${projectsId}/issues/${index}`;
axios.patch(url,{
branch_name: b ? b.join(",") :undefined,
status_id: s ? s.join(",") : undefined,
priority_id: p ? p.join(",") :undefined,
milestone_id: m ? m.join(",") :undefined,
issue_tag_ids: t?t:undefined,
assigner_ids: c?c:undefined,
start_date:sDate,
due_date:eDate,
blockchain_token_num:rewardAmount
}).then(result=>{
if(result){
Init();
// 更新操作日志
setCommentReload(Math.random());
}
}).catch(error=>{})
}
}
function deleteFunc(){
const url = `/v1/${owner}/${projectsId}/issues/${index}`;
axios.delete(url).then(result=>{
if(result){
props.showNotification("任务删除成功!");
props.history.push(`/${owner}/${projectsId}/issues`);
}
}).catch(error=>{})
}
// 编辑保存
function createFunc(values,fileList,receivers_login,description){
let params ={
subject: values.subject,
attachment_ids: fileList,
receivers_login: receivers_login,
description: description
}
if(!copy){
// 调用编辑保存接口
const url = `/v1/${owner}/${projectsId}/issues/${index}`;
axios.patch(url,{
...params
}).then(result=>{
if(result){
window.scrollTo(0,0);
props.showNotification("任务更新成功!");
Init();
setEdit(false);
// 刷新操作记录
setCommentReload(Math.random());
showNpsModal("submitIssue", 1);
}
}).catch(error=>{})
}else{
// 调用新建保存接口
const url = `/v1/${owner}/${projectsId}/issues`;
let b = branch_choose && branch_choose.length>0 ? branch_choose.map(i=>{return i.name}) :undefined;
let t = tag_choose && tag_choose.length>0 ? tag_choose.map(i=>{return i.id}) :undefined;
let a = assigner_choose && assigner_choose.length>0 ? assigner_choose.map(i=>{return i.id}) :undefined;
let m = millstone_choose && millstone_choose.length>0 ? millstone_choose.map(i=>{return i.id}) :undefined;
let p = prioritie_choose && prioritie_choose.length>0 ? prioritie_choose.map(i=>{return i.id}) :undefined;
let s = status_choose && status_choose.length>0 ? status_choose.map(i=>{return i.id}) :undefined;
axios.post(url,{
...params,
branch_name: b && b.join(","),
status_id: s && s.join(","),
priority_id: p && p.join(","),
milestone_id: m && m.join(","),
issue_tag_ids: t,
assigner_ids: a,
start_date,
due_date
}).then(result=>{
if(result && result.data && result.data.project_issues_index){
window.scrollTo(0,0);
props.showNotification("任务复制成功!");
props.history.push(`/${owner}/${projectsId}/issues/${result.data.project_issues_index}`);
showNpsModal("createIssue", 1);
}
}).catch(error=>{})
}
}
// 取消编辑或复制
function onCancel(){
if(copy){
props.history.push(`/${owner}/${projectsId}/issues/${index}`);
}else{
setEdit(false);
window.scrollTo(0,0);
}
}
function refreshFunc(){
// 更新操作日志
setCommentReload(Math.random());
}
// 悬赏金额 失去焦点保存数据
function amountBlur(e){
if(!editFlag){
setRewardFlag(false);
const value = e.target.value;
if(value<0){
message.info("请输入大于0的正整数");
setRewardAmount(rewardAmount);
return;
}
setRewardAmount(e.target.value);
if((value && value >= 0) || !value){
saveForeach(undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,value);
}
}
}
function changeAmount(value){
if(amountEditFlag){
setRewardAmount(value);
}else{
setRewardAmount(rewardAmount);
}
}
return(
details ?
<Box>
<LongWidth>
<DelBox
visible={delVisible}
onCancel={()=>setDelVisible(false)}
onSuccess={deleteFunc}
content={<div style={{paddingTop:"3px"}}><p className="font-15 mb20">您确定要删除当前任务</p></div>}
/>
{
edit ?
<div style={{paddingTop:"25px"}} >
<NewPanel
{...props}
onCancel={onCancel}
title={details.subject}
desc={edit ? desc : undefined}
files={copy ? undefined : details.attachments}
createFunc={createFunc}
owner = {owner} projectsId = {projectsId}
/>
</div>
:
<div>
<div className="editpanel">
<div className="detailbanner">
<div className="detailtitle">
<div className="mb12">
{details.priority && <span className={statusTag(details.priority.name)}>{ details.priority.name }</span> }
<p className="name">{details.subject}</p>
</div>
<div>
<div className="ilog mt5">
<Copy value={`/${owner}/${projectsId}/issues/${index}`}><span className="number">#{details.project_issues_index}</span></Copy>
</div>
{
details.author &&
<div>
{ details.author.login ?
<Link to={`/${details.author.login}`} className="author"><img src={details.author.image_url} alt="" />{details.author.name}</Link>
:
<span className="author color-grey-6"><img src={details.author.image_url} alt="" />{details.author.name}</span>
}
<span className="ml10" style={{color:"#898d9d"}}>添加于{details.created_at}</span>
</div>
}
</div>
</div>
{
details.user_permission &&
<ul className="detailoperate">
<li><a className="color-blue" onClick={()=>setEdit(true)}><i className="iconfont icon-a-bianji12 font-12 mr5"></i></a></li>
<li><Link to={`/${owner}/${projectsId}/issues/${index}/copy`} className="color-blue ml20"><i className="iconfont icon-a-fuzhi2 font-12 mr5"></i></Link></li>
<li><a className="color-red ml20" onClick={()=>setDelVisible(true)}><i className="iconfont icon-fuzhi-shanchu font-12 mr5"></i></a></li>
</ul>
}
</div>
<div class="descPanel">
{desc ?
<RenderHtml owner={owner} projectsId={projectsId} className="break_word_comments imageLayerParent" value={desc} url={props.history.location} />
:
<span className="color-grey-9 ml3 mr3">暂无描述</span>
}
{details.attachments && details.attachments.length > 0 ?
<Attachments
attachments={details.attachments}
showNotification={props.showNotification}
/>
: ""
}
</div>
</div>
<div id="commentList">
<CommentList {...props} issueInfo={details} reload = {commentReload} reloadComment = {()=>{setCommentReload(Math.random())}}/>
</div>
</div>
}
</LongWidth>
<div className="shortwidth mt25">
{orderId && <div className="claimpart"><Claims issue_id={orderId} {...props} refreshFunc={refreshFunc}/></div>}
<ChooseMenu
placeholder="负责人"
menus={chargeList}
searchFunc={(value)=>{setCharge(value)}}
headImg
selectValueList={assigner_choose}
editFlag={editFlag}
chooseFunc={(list)=>{setAssigner_choose(list);let l = list && list.length>0 ?list.map(i=>{return i.id || i.name}):[];saveForeach(l);}}
double={5}
removeFlag={!editFlag}
/>
<DropMenu
placeholder="状态"
menus={statusList}
selectValueList={status_choose}
mustFlag
editFlag={editFlag}
chooseFunc={(list)=>{setStatus_choose(list);let l = list && list.length>0 ?list.map(i=>{return i.id || i.name}):[];saveForeach(undefined,l);}}
/>
<DropMenu
placeholder="优先级"
menus={prioritiesList}
selectValueList={prioritie_choose}
colorFlag="1"
mustFlag
editFlag={editFlag}
chooseFunc={(list)=>{setPrioritie_choose(list);let l = list && list.length>0 ?list.map(i=>{return i.id || i.name}):[];saveForeach(undefined,undefined,l);}}
/>
<ChooseMenu
placeholder="标记"
menus={tagList}
searchFunc={(value)=>{setTag(value)}}
selectValueList={tag_choose}
chooseFunc={(list)=>{setTag_choose(list);let l = list && list.length>0 ?list.map(i=>{return i.id || i.name}):[];saveForeach(undefined,undefined,undefined,l);}}
double={3}
colorFlag="2"
removeFlag={!editFlag}
editFlag={editFlag}
onAdd={permission && permission !== "Reporter" ? ()=>{getSign();} :false}
owner={owner}
projectsId={projectsId}
/>
{/* <ChooseMenu
placeholder="里程碑"
menus={millstoneList}
searchFunc={(value)=>{setMillstone(value)}}
selectValueList={millstone_choose}
editFlag={editFlag}
auto
chooseFunc={(list)=>{setMillstone_choose(list);let l = list && list.length>0 ?list.map(i=>{return i.id || i.name}):[];saveForeach(undefined,undefined,undefined,undefined,l);}}
/> */}
<ChooseMenu
placeholder="关联分支"
menus={branchList}
auto
searchFunc={(value)=>{setBranch(value)}}
selectValueList={branch_choose}
editFlag={editFlag}
chooseFunc={(list)=>{setBranch_choose(list);let l = list && list.length>0 ?list.map(i=>{return i.id || i.name}):[];saveForeach(undefined,undefined,undefined,undefined,undefined,l);}}
/>
{
open_blockchain &&
<li style={{paddingBottom:"0px"}}>
<span>
悬赏金额
{/* {!editFlag && <a onClick={editReward}><i className="iconfont icon-a-bianji12 font-13" style={{color:"#898d9d"}}></i></a> } */}
</span>
<InputNumber
onBlur={amountBlur}
placeholder="请输入悬赏金额"
style={{width:"100%",color:rewardAmount?"#333":"#acb0bf"}}
value={rewardAmount}
onChange={changeAmount}
className="borderNo mt5"
disabled={!amountEditFlag}
/>
</li>
}
<Date name="开始日期" today={start_date} setDate={(date)=>{saveForeach(undefined,undefined,undefined,undefined,undefined,undefined,date)}} editFlag={editFlag}/>
<Date name="结束日期" today={due_date} setDate={(date)=>{saveForeach(undefined,undefined,undefined,undefined,undefined,undefined,undefined,date)}} editFlag={editFlag}/>
</div>
</Box>
:
<div style={{width:"100%",display:"flex",alignItems:"center",justifyContent:'center',height:"400px"}}><Spin /></div>
)
}
export default Form.create()(forwardRef(Details));