forgeplus-react/src/forge/Merge/MessageCount.js

848 lines
29 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 , {Component} from 'react';
import {Link} from 'react-router-dom';
import axios from 'axios';
import Nav from '../Order/Nav';
import UploadComponent from '../Upload/Index';
import { getImageUrl } from 'educoder';
import {Modal, Form, Input, Tooltip, Popconfirm, Pagination, Spin, Dropdown, Icon, Menu, Select} from 'antd'
import Attachments from '../Upload/attachment'
import './merge.css';
import QuillForEditor from '../quillForEditor';
import MergeSubmit from './MergeSubmit';
const Option = Select.Option;
const TextArea = Input.TextArea;
const options = [
['bold', 'italic', 'underline'],
[{header: [1,2,3,false]}],
['blockquote', 'code-block'],
['link', 'image'],
['formula']
];
class MessageCount extends Component{
constructor(props){
super(props);
this.state={
data:undefined,
isShow:false,
imgsrc:'',
journalsdata:undefined,
//图片区域是否显示 none 隐藏 block 显示
display:'none',
titledisplay:'none',
countvalue:'',
//是否需要编辑
isedit:undefined,
fileList:undefined,
limit:10,
page:1,
search_count:undefined,
isSpin:false,
showFiles: true,
ismesrge:'none',
buttonshow:'none',
mergename:'合并请求',
mergekey:'merge',
title:'',
body:'',
commentsContent:undefined,
quillFlag:false,
SpinFlag:true,
editMerge: false,
issue_tag_ids: undefined,
issue_chosen: undefined,
fixed_version_id: undefined,
assigned_to_id: undefined
}
}
componentDidMount=()=>{
this.setState({
SpinFlag:true
})
this.getDetail();
}
getDetail=()=>{
const { projectsId , mergeId} = this.props.match.params;
const url = `/projects/${projectsId}/pull_requests/${mergeId}.json`;
axios.get(url).then((result)=>{
if(result){
this.setState({
data:result.data
})
this.getjournalslist();
}
}).catch((error)=>{
console.log(error);
})
}
handleok=() => {
this.setState({
isShow:false
});
};
handleCancel=()=>{
this.setState({
isShow:false
});
}
imgshow=()=>{
this.setState({
isShow:true
});
};
//添加评论
addjournals=()=>{
const { data, page, limit, fileList , commentsContent } = this.state;
if(!commentsContent){
this.setState({
quillFlag:true
})
return;
}
this.props.form.validateFieldsAndScroll((err, values) => {
if(!err){
const url = `/issues/${data.issue.id}/journals.json`;
axios.post(url,{
...values,
content:JSON.stringify(commentsContent),
issue_id:data.id,
attachment_ids:fileList
}).then(result=>{
if(result){
this.props.form.setFieldsValue({
content: "",
attachments_ids: undefined
});
this.setState({
showFiles: false,
quillFlag:false,
commentsContent:undefined
})
this.getjournalslist(page, limit);
this.props.showNotification("评论成功!");
// this.UploadFunc(undefined)
}
}).catch(error=>{
console.log(error);
})
}
})
}
//获取评论信息
getjournalslist=(page, limit)=>{
const { data} = this.state;
const url = `/issues/${data.issue.id}/journals.json`;
let id=data.id;
axios.get(url,{
params:{
id,page,limit
}
}).then(result=>{
if(result){
this.setState({
journalsdata:result.data,
search_count:result.data.journals_count,
isSpin:false,
fileList:undefined,
showFiles: true,
SpinFlag:false
})
}
}).catch(error=>{
console.log(error);
})
}
//关闭任务
closedetail=(id)=>{
const {projectsId,orderId} = this.props.match.params;
const {data } = this.state;
const url = `/projects/${projectsId}/issues/${data.issue.id}/close_issue.json`;
axios.post(url,{
project_id:projectsId,
id:orderId,
status_id:id,
}).then(result=>{
if(result){
this.getDetail();
}
}).catch(error=>{
console.log(error);
})
}
//合并请求
prmerge=()=>{
const {projectsId} = this.props.match.params;
const {data,title,body,mergekey} = this.state;
const url = `/projects/${projectsId}/pull_requests/${data.pull_request.id}/pr_merge.json`;
axios.post(url,{
project_id:projectsId,
id:data.pull_request.id,
do:mergekey,
body:body,
title:title,
}).then(result=>{
if(result){
this.getDetail();
}
}).catch(error=>{
console.log(error);
})
}
//修改评论
updatedetail=(id)=>{
// console.log("updtedetail", this.state)
const {page, limit,data } = this.state;
const {orderId} = this.props.match.params;
const url = `/issues/${data.issue.id}/journals/${id}.json`;
axios.put(url,{
issue_id:orderId,
id:id,
content:JSON.stringify(this.state.countvalue)
}).then(result=>{
if(result){
this.setState({
isedit: undefined
})
this.getjournalslist(page, limit);
}
}).catch(error=>{
console.log(error);
})
}
// 获取上传后的文件id数组
UploadFunc=(fileList)=>{
this.setState({
fileList
})
}
//删除评论
deleteorder=(id)=>{
const { orderId} = this.props.match.params;
const { page, limit,data } = this.state;
const url = `/issues/${data.issue.id}/journals/${id}.json`;
axios.delete(url,{ data: {
issue_id: orderId,
id:id
}
}).then((result)=>{
if(result){
this.getjournalslist(page,limit)
}
}).catch((error)=>{
console.log(error);
})
}
changmodelname=(value)=>{
this.setState({
countvalue:value
})
}
changtitlepr=(e)=>{
this.setState({
title:e.target.value
})
}
changbodypr=(e)=>{
this.setState({
body:e.target.value
})
}
editdetail=(count,status)=>{
this.setState({
countvalue:count,
isedit:status
})
}
submitmerge=()=>{
if(this.state.mergekey==="rebase"){
this.setState({
buttonshow:'block',
ismesrge:'none'
})
}else{
this.setState({
ismesrge:'block',
buttonshow:'block'
})
}
}
nonemerge=()=>{
this.setState({
ismesrge:'none',
buttonshow:'none'
})
}
renderJournalList=(list)=>{
if(list && list.length >0){
return(
list.map((item,key)=>{
return(
<div key={key+1} className="journal-list-item">
<span className="font-weight-bold mr3">
{item.detail}
</span>
<span className="mr5 color-grey-9">
{item.old_value &&item.old_value.length > 0 ? "更新为" : "新增"}
</span>
<span>
{item.value && item.value.length > 0 ?
item.detail === "标签" ? <span className="issue-tag-show" style={{background: item.value[0].color}}>{item.value[0].name}</span> : item.value
:
"无"
}
</span>
</div>
)
})
)
}else{
return(
<div>
<span>没有评论~</span>
</div>
)
}
}
handleSubmit=()=>{
const { fileList } = this.state;
this.props.form.validateFieldsAndScroll((err, values) => {
if(!err){
const { projectsId , mergeId } = this.props.match.params;
const url = `/projects/${projectsId}/pull_requests/${mergeId}/simple_update.json`;
if(values.issue_tag_ids===''){
values.issue_tag_ids = []
}else{
values.issue_tag_ids = [parseInt(values.issue_tag_ids)]
}
if(values.assigned_to_id===0){
values.assigned_to_id = ""
}
axios.post(url,{
...values
}).then(result=>{
if(result.data.status === 0){
this.setState({
editMerge:false
})
this.getDetail()
this.props.showNotification(result.data.message);
}
}).catch(error=>{
console.log(error);
})
}
})
}
renderSelect=(list)=>{
if(list && list.length >0){
return(
list.map((item,key)=>{
return(
<Option key={key+1} value={item.id}>{item.name}</Option>
)
})
)
}
}
// 翻页
ChangePage=(page)=>{
this.setState({
page,
isSpin:true
})
const {limit} = this.state;
this.getjournalslist(page,limit);
}
getOption=(e)=>{
if(e.key === "rebase"){
this.setState({
mergename:e.item.props.value,
mergekey:e.key,
title:'',
body:'',
buttonshow:'block'
})
}else{
this.setState({
mergename:e.item.props.value,
mergekey:e.key,
title:'',
body:'',
ismesrge:'block',
buttonshow:'block'
})
}
}
changeComments=(value)=>{
this.setState({
commentsContent:value
})
if(value){
this.setState({
quillFlag:false
})
}
}
cancelSubmit=()=>{
this.setState({
editMerge: false
})
}
change_to_edit=()=>{
const { projectsId , mergeId} = this.props.match.params;
const url = `/projects/${projectsId}/pull_requests/${mergeId}/edit.json`;
axios.get(url).then((result)=>{
if(result){
this.setState({
issue_chosen:result.data.issue.issue_chosen,
issue_tag_ids: result.data.issue.issue_tags && result.data.issue.issue_tags[0].id,
fixed_version_id: result.data.issue.fixed_version_id,
assigned_to_id: result.data.issue.assigned_to_id,
editMerge: true
})
}
}).catch((error)=>{
console.log(error);
})
}
stringJson=(value) =>{
let _value = null;
try {
_value = JSON.parse(value);
} catch (e) {
_value = value;
}
return _value
}
commentCtx = (ctx) => {
let _ctx = null;
try {
_ctx = JSON.parse(ctx);
} catch (e) {
_ctx = ctx;
}
return (
<QuillForEditor
readOnly={true}
value={_ctx}
showUploadImage={this.handleShowImage}
/>
)
};
render(){
const { projectsId,mergeId } = this.props.match.params;
const { data,journalsdata, page, limit, search_count, isSpin, isedit, showFiles , commentsContent , quillFlag, editMerge, issue_tag_ids, issue_chosen,fixed_version_id,assigned_to_id } = this.state;
const { getFieldDecorator } = this.props.form;
const { current_user } = this.props;
const url = this.props.history.location.pathname;
const editMergeForm =()=>{
return(
<div>
<Form>
<Form.Item
label="标签"
>
{getFieldDecorator('issue_tag_ids', {
initialValue: issue_tag_ids ? [issue_tag_ids] : '',
rules: [],
})(
<Select>
<Option value={''}>{issue_chosen && issue_chosen.issue_tag.length > 0 ? '未选择标签':'请在仓库设置里添加标签'}</Option>
{this.renderSelect(issue_chosen && issue_chosen.issue_tag)}
</Select>
)}
</Form.Item>
<Form.Item
label="里程碑"
>
{getFieldDecorator('fixed_version_id', {
initialValue: fixed_version_id ? fixed_version_id : "",
rules: [],
})(
<Select>
<Option value={''}>{issue_chosen && issue_chosen.issue_version.length > 0 ? '未选择里程碑': '请添加里程碑'}</Option>
{this.renderSelect(issue_chosen && issue_chosen.issue_version)}
</Select>
)}
</Form.Item>
<Form.Item
label="指派成员"
>
{getFieldDecorator('assigned_to_id', {
initialValue: assigned_to_id ? assigned_to_id : "",
})(
<Select>
<Option value={''}>未指派成员</Option>
{this.renderSelect(issue_chosen && issue_chosen.assign_user)}
</Select>
)}
</Form.Item>
<p className="clearfix mt15 text-right">
<a className="topWrapper_btn fr" type="submit" style={{marginLeft: 5}} onClick={this.handleSubmit}>保存</a>
<a className="a_btn cancel_btn fr" onClick={this.cancelSubmit}>取消</a>
</p>
</Form>
</div>
)
}
const menu = (
<Menu onClick={(e)=>this.getOption(e)}>
<Menu.Item key={'merge'} value="合并请求">合并请求</Menu.Item>
<Menu.Item key={'rebase'} value="变基并合并">变基并合并</Menu.Item>
<Menu.Item key={'rebase-merge'} value="变基合并 --no-ff">变基合并 --no-ff</Menu.Item>
<Menu.Item key={'squash'} value="压缩提交并合并">压缩提交并合并</Menu.Item>
</Menu>
)
const Paginations = (
<React.Fragment>
{
search_count > limit ?
<div className="pt30 mb50 edu-txt-center btp1">
<Pagination simple defaultCurrent={page} total={search_count} pageSize={limit} onChange={this.ChangePage}></Pagination>
</div>:""
}
</React.Fragment>
)
const renderList =()=>{
if(journalsdata && journalsdata.issue_journals && journalsdata.issue_journals.length>0 ){
return(
<div className="tagList">{
journalsdata.issue_journals.map((item,key)=>{
return(
<li key={key}>
<div className="df">
<Link to={``}><img className="user_img" src={getImageUrl(`images/${item.user_picture && item.user_picture}`)} alt=""/></Link>
<div className="detail_context" >
<div className="topWrapper_detali">
<p className="ml6 detail_p lineH40">
{item.user_name}
<span className="color-grey-9 ml3 mr3">评论于</span>
<Tooltip title={item.format_time} placement="bottom">
<span>{item.created_at}</span>
</Tooltip>
</p>
<div className="detail_right" style={{display: current_user && (current_user.admin || current_user.login === item.user_login) ? "block" : "none"}}>
<span onClick={()=>this.editdetail(item.content,item.id)} className="detail_edit_action">编辑</span>
<Popconfirm placement="bottom" title={'确定要删除当前评论吗'} okText="是" cancelText="否" onConfirm={()=>this.deleteorder(item.id)}>
<span className="detail_edit_action">删除</span>
</Popconfirm>
</div>
</div>
<div className="detail_ptitlecount">
<div style={{display: (isedit && isedit === item.id) ? "none" : "block"}} >
{
item.content ?
this.commentCtx(item.content)
:
<div>
{this.renderJournalList(item.journal_details)}
</div>
}
{
item && item.attachments.length > 0 ?
<Attachments attachments={item.attachments} showNotification={this.props.showNotification} canDelete={current_user && (current_user.admin || current_user.login === item.user_login)}/>
:
""
}
</div>
<div style={{display: (isedit && isedit === item.id) ? "block" : "none"}}>
<QuillForEditor
value = {this.stringJson(this.state.countvalue)}
wrapStyle={{
height: '220px',
opacity:1,
marginTop:"20px"
}}
// autoFocus={true}
style={{ height: '170px' }}
placeholder="评论内容"
options={options}
onContentChange={this.changmodelname}
/>
{/* <TextArea style={{height:"200px"}} value={this.state.countvalue} onChange={this.changmodelname}/> */}
<p className="clearfix mt15">
<a className="topWrapper_btn fr" type="submit" onClick={()=>this.updatedetail(item.id)}>保存</a>
<a className="a_btn cancel_btn fr" type="submit" onClick={()=>this.editdetail(item.content,undefined)}>取消</a>
</p>
</div>
</div>
<div style={{display: this.state.display}}>
<div className="div_line" ></div>
</div>
</div>
</div>
<div className="order_line" style={{marginLeft:80}}></div>
</li>
)
})
}
</div>
)
}
}
return(
<div className="main">
{/*<div className="topWrapper">*/}
{/*<Nav {...this.props} {...this.state}/>*/}
{/*{*/}
{/*data && data.issue.user_permission ?*/}
{/*<Link to={`/projects/${projectsId}/merge/new`} className="topWrapper_btn">创建合并请求</Link>*/}
{/*: ''*/}
{/*}*/}
{/*</div>*/}
<div>
<div className="detailContent">
{
data &&
<p>
<span className="font-20">{ data.issue && (data.issue.issue_classify==='issue' ? data.issue.tracker : "合并")}</span>
<span className="font-20" > { data.issue && data.issue.subject }</span>
</p>
}
<p className="mt10 color-grey-c">
<span className={data&&data.issue.issue_status==="关闭"?"closedetail":data&&data.pull_request.status===0?"opendetail":"prdetail"}>{data&&data.issue.issue_status==="关闭"?"关闭中":data&&data.pull_request.status===0?"开启中":"已合并"} </span>
<span className="color-grey-c ml10">
{ data && data.issue.author_name} { data && data.issue.created_at }创建{ data && data.issue.journals_count && data.issue.journals_count > 0 ?` · ${data.issue.journals_count} 条评论`:""}
</span>
<span className="span_title ml10">
请求从<strong> {data && data.pull_request.head} </strong><strong> {data && data.pull_request.base} </strong>
</span>
<span className="pull-right lineH32">
{/*{*/}
{/*data && data.issue.user_permission ?*/}
{/*<Link to={`/projects/${projectsId}/merge/${mergeId}/UpdateMerge`} className="color-blue fr">编辑</Link>*/}
{/*: ''*/}
{/*}*/}
{
data && data.issue.user_permission ?
<a onClick={this.change_to_edit} className="color-blue fr">编辑</a>
: ''
}
</span>
</p>
{
data && data.attachments.length > 0 ?
<div className="df mt20">
<Attachments attachments={data.attachments} showNotification={this.props.showNotification}/>
</div>
:
""
}
<div className="">
<div className="normal f-wrap-between">
<ul className="headerMenu-wrapper" style={{paddingTop:15,paddingLeft:15}}>
<li className={url.indexOf("Messagecount")>0? "active" : ""}><Link to={`/projects/${projectsId}/merge/${mergeId}/Messagecount`} className="color-grey">对话内容</Link></li>
<li className={url.indexOf("MergeSubmit")>0 ? "active" : ""}><Link to={`/projects/${projectsId}/merge/${mergeId}/MergeSubmit`} className="color-grey">代码提交</Link></li>
</ul>
</div>
</div>
</div>
{
url.indexOf("Messagecount")>0 ?
<Spin spinning={this.state.SpinFlag}>
<div className="f-wrap-between mt5" style={{alignItems:"flex-start"}}>
<div className="item-list-right" >
{
data && data.issue.user_permission ?
<div>
<div className="df" style={{display:this.state.data&&this.state.data.pull_request.status===1?'none':'flex'}}>
<img className="user_img" src={getImageUrl(`images/${current_user && current_user.image_url}`)} alt=""/>
<div className="new_context" >
<p>该合并请求可以进行自动合并操作</p>
<p style={{marginTop:15,display:this.state.mergekey==='rebase'?this.state.buttonshow==='none'?"block":"none":this.state.ismesrge==='none'?"block":"none"}}>
{/* <button className="topmerge_btn" onClick={this.submitmerge} >{this.state.mergename}</button> */}
{/* <Dropdown style={{marginBottom:5}} overlay={menu} trigger={['click']} > */}
<Dropdown.Button overlay={menu} type="primary" onClick={this.submitmerge} icon={<Icon type="caret-down"/>}>
{this.state.mergename}
</Dropdown.Button>
{
data&&data.pull_request.status===0 ?
<div className="pull-right">
<a className="Closeor_btn fr" type="submit"
onClick={() => this.closedetail(data && data.issue.issue_status === "关闭" ? 2 : 5)}>{data && data.issue.issue_status === "关闭" ? "点击开启" : "关闭"}</a>
{/*<a className="cancel_btn fr" type="submit"*/}
{/*onClick={() => this.closedetail(data && data.issue.issue_status === "关闭" ? 2 : 5)}>{data && data.issue.issue_status === "关闭" ? "开启" : "关闭"}</a>*/}
</div>
: ""
}
{/* </Dropdown> */}
</p>
<div style={{display:this.state.ismesrge,marginTop:15}}>
<Input placeholder="标题" value={this.state.title} onChange={this.changtitlepr}/>
{/*<div className="quillContent" style={{marginTop:"20px"}}>*/}
{/*<QuillForEditor*/}
{/*value = {this.state.body}*/}
{/*wrapStyle={{*/}
{/*height: '220px',*/}
{/*opacity:1,*/}
{/*}}*/}
{/*// autoFocus={true}*/}
{/*style={{ height: '170px' }}*/}
{/*placeholder="请输入合并请求描述..."*/}
{/*options={options}*/}
{/*onContentChange={this.changbodypr}*/}
{/*/>*/}
{/*</div>*/}
<TextArea placeholder="请输入合并描述..." style={{height:"170px",marginTop:20}} value={this.state.body} onChange={this.changbodypr} />
</div>
<p className="clearfix mt15" style={{display:this.state.buttonshow}}>
<a className="topWrapper_btn " type="submit" onClick={()=>this.prmerge()}>合并请求</a>
<a className="a_btn cancel_btn " type="submit" style={{marginLeft:15}} onClick={this.nonemerge}>取消</a>
</p>
</div>
</div>
<div className="order_line" style={{marginLeft:80}}></div>
</div>
: ''
}
<Spin spinning={isSpin}>
<ul className="ul_width">
{renderList()}
</ul>
</Spin>
{ Paginations }
<div className="df">
<img className="user_img" src={getImageUrl(`images/${current_user && current_user.image_url}`)} alt=""/>
<div className="new_context">
{/* <Form.Item>
{getFieldDecorator('content', {
rules: [{
required: true, message: '请输入内容'
}],
})(
<TextArea placeholder="添加评论..." style={{height: "200px"}}/>
)}
</Form.Item> */}
<div className="quillContent">
<QuillForEditor
value = {commentsContent}
wrapStyle={{
height: '240px',
opacity:1,
}}
// autoFocus={true}
style={{ height: '170px' }}
placeholder="请输入评论内容..."
options={options}
onContentChange={this.changeComments}
/>
<p className="quillFlag">
{ quillFlag && <span className="">请输入评论内容</span>}
</p>
</div>
<UploadComponent load={this.UploadFunc} isComplete={showFiles}></UploadComponent>
<p className="clearfix mt15">
<a className="topWrapper_btn fr" type="submit" onClick={this.addjournals}>评论</a>
{/*<a className="Closeor_btn fr" type="submit" style={{display:data&&data.pull_request.status===0?'block':'none'}}*/}
{/*onClick={() => this.closedetail(data && data.issue.issue_status === "关闭" ? 2 : 5)}>{data && data.issue.issue_status === "关闭" ? "开启" : "关闭"}</a>*/}
</p>
</div>
</div>
</div>
{
editMerge ?
<div className="list-left DetailRight mt10">
{ editMergeForm() }
</div>
:
<div className="list-left DetailRight mt30">
<p>
<span className="span_title">标签</span>
<span>{
data && data.issue.issue_tags ? <span className="issue-tag-show" style={{background: data.issue.issue_tags[0].color}}>{data.issue.issue_tags[0].name}</span> : "--"
}</span>
</p>
<p style={{display: "inline-block",'white-space': "nowrap" }}>
<span className="span_title">里程碑</span>
<span className="title_overflow">{
data && data.issue.version ? data.issue.version : "--"
}</span>
</p>
<p>
<span className="span_title">指派给</span>
<span>{data && data.issue.assign_user_name ? data.issue.assign_user_name : "--"}</span>
</p>
</div>
}
</div>
</Spin>
:
<MergeSubmit {...this.props} {...this.state} data={data} />
}
</div>
<Modal
onCancel={this.handleCancel}
visible={this.state.isShow}
width="400px"
footer={[]}
bodyStyle={{textAlign:'center'}}
>
<img className="list_img" src="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1608431072,669449145&fm=27&gp=0.jpg" alt=""/>
</Modal>
</div>
)
}
}
const MessageCountForm = Form.create({ name: 'MessageCountForm' })(MessageCount);
export default MessageCountForm;