Merge branch 'newVersion_forge' of http://gitea.trustie.net/jasder/forgeplus-react into newVersion_forge

This commit is contained in:
caishi 2020-06-03 09:56:18 +08:00
commit 4920fed97f
28 changed files with 3267 additions and 1813 deletions

View File

@ -68,12 +68,15 @@ const http500 = Loadable({
loading: Loading,
})
// 个人主页
// const InfosIndex = Loadable({
// loader: () => import('./modules/user/usersInfo/InfosIndex'),
// loading: Loading,
// })
const InfosIndex = Loadable({
loader: () => import('./modules/user/usersInfo/InfosIndex'),
loader: () => import('./forge/users/Infos'),
loading: Loading,
})
class App extends Component {
constructor(props) {
super(props)
@ -257,8 +260,6 @@ class App extends Component {
return (<InfosIndex {...this.props} {...props} {...this.state} />)
}
}></Route>
<Route exact path="/"
render={
(props) => (<Projects {...this.props} {...props} {...this.state}></Projects>)

View File

@ -98,9 +98,9 @@ export function initAxiosInterceptors(props) {
// TODO 避免重复的请求 https://github.com/axios/axios#cancellation
// TODO 读取到package.json中的配置
// var proxy = "http://localhost:3000"
var proxy = "http://localhost:3000"
// proxy = "https://pre-newweb.educoder.net"
var proxy = "https://testforgeplus.trustie.net/"
// var proxy = "https://testforgeplus.trustie.net/"
// 在这里使用requestMap控制避免用户通过双击等操作发出重复的请求
// 如果需要支持重复的请求考虑config里面自定义一个allowRepeat参考来控制

View File

@ -1,62 +1,76 @@
import React, { Component } from 'react';
import React, { Component } from "react";
import { Route, Switch } from 'react-router-dom';
import { withRouter } from 'react-router'
import { Route, Switch } from "react-router-dom";
import { withRouter } from "react-router";
import { SnackbarHOC } from "educoder";
import { CNotificationHOC } from "../modules/courses/common/CNotificationHOC";
import { TPMIndexHOC } from "../modules/tpm/TPMIndexHOC";
import { SnackbarHOC } from 'educoder';
import { CNotificationHOC } from '../modules/courses/common/CNotificationHOC';
import { TPMIndexHOC } from '../modules/tpm/TPMIndexHOC';
import "./css/index.css";
import './css/index.css';
import Loadable from 'react-loadable';
import Loading from '../Loading';
import { ImageLayerOfCommentHOC } from '../modules/page/layers/ImageLayerOfCommentHOC';
import Loadable from "react-loadable";
import Loading from "../Loading";
import { ImageLayerOfCommentHOC } from "../modules/page/layers/ImageLayerOfCommentHOC";
const ProjectNew = Loadable({
loader: () => import('./New/Index'),
loader: () => import("./New/Index"),
loading: Loading,
})
});
const ProjectIndex = Loadable({
loader: () => import('./Main/Index'),
loader: () => import("./Main/Index"),
loading: Loading,
})
});
const ProjectDetail = Loadable({
loader: () => import('./Main/Detail'),
loader: () => import("./Main/Detail"),
loading: Loading,
})
});
class Index extends Component {
render() {
return (
<div className="newMain clearfix">
<Switch {...this.props}>
<Route path="/projects/:projectsType/new"
render={
(props) => (<ProjectNew {...this.props} {...props} {...this.state} />)
}
<Route
path="/projects/:projectsType/new"
render={(props) => (
<ProjectNew {...this.props} {...props} {...this.state} />
)}
></Route>
<Route path="/projects/:projectsId"
render={
(props) => (<ProjectDetail {...this.props} {...props} {...this.state} />)
}
<Route
path="/projects/:projectsId"
render={(props) => (
<ProjectDetail {...this.props} {...props} {...this.state} />
)}
></Route>
<Route exact path="/projects"
render={
(props) => (<ProjectIndex {...this.props} {...props} {...this.state} />)
}
<Route
exact
path="/projects"
render={(props) => (
<ProjectIndex {...this.props} {...props} {...this.state} />
)}
></Route>
<Route exact path="/"
render={
(props) => (<ProjectIndex {...this.props} {...props} {...this.state}></ProjectIndex>)
}
<Route
exact
path="/"
render={(props) => (
<ProjectIndex
{...this.props}
{...props}
{...this.state}
></ProjectIndex>
)}
/>
</Switch>
</div>
)
);
}
}
export default withRouter(ImageLayerOfCommentHOC({ imgSelector: '.imageLayerParent img, .imageLayerParent .imageTarget', parentSelector: '.newMain' })(CNotificationHOC()(SnackbarHOC()(TPMIndexHOC(Index)))));
export default withRouter(
ImageLayerOfCommentHOC({
imgSelector: ".imageLayerParent img, .imageLayerParent .imageTarget",
parentSelector: ".newMain",
})(CNotificationHOC()(SnackbarHOC()(TPMIndexHOC(Index))))
);

View File

@ -112,6 +112,7 @@ const TrendsIndex = Loadable({
loader: () => import('../Activity/Activity'),
loading: Loading,
})
/**
* permissionManager:管理员Reporter报告人员(只有读取权限)Developer开发人员除不能设置仓库信息外
*/
@ -239,11 +240,10 @@ class Detail extends Component {
// fork项目
forkFunc = () => {
const { checkIfLogin } = this.props;
if (!checkIfLogin) {
this.props.showLoginDialog();
return;
}
// if (!checkIfLogin) {
// this.props.showLoginDialog();
// return;
// }
this.setState({
isSpin: true
})

View File

@ -121,7 +121,7 @@ class UserSubmitComponent extends Component {
};
return (
<div>
<span className="df mt20" style={{ alignItems: "center" }}>
<span className="df mt30" style={{ alignItems: "center" }}>
<Link
to={`/users/${current_user && current_user.login}/projects`}
className="show-user-link"
@ -185,7 +185,7 @@ class UserSubmitComponent extends Component {
</Form>
</div>
</div>
<div className="mt50 text-center">
<div className="mt20 text-center">
<Button
type="primary"
onClick={editor_type === "new" ? this.subMitFrom : this.UpdateFile}

View File

@ -45,7 +45,7 @@ class m_editor extends Component {
<div>
<div className="branchTable">
<Editor
height="320px"
height="600px"
language={language ? language : "plaintext"}
theme={"vs-grey"}
defaultValue="请输入内容"

View File

@ -1,375 +1,16 @@
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import axios from 'axios';
import Nav from './Nav';
import UploadComponent from '../Upload/Index';
import { getImageUrl } from 'educoder';
import { Modal, Form, Input, Select } from 'antd';
import MDEditor from '../../modules/tpm/challengesnew/tpm-md-editor';
import Attachments from '../Upload/attachment'
const Option = Select.Option;
import React, { Component } from "react";
import OrderItem from './order_form'
class CopyDetail extends Component {
constructor(props) {
super(props);
this.state = {
data: undefined,
isShow: false,
imgsrc: '',
journalsdata: undefined,
//图片区域是否显示 none 隐藏 block 显示
display: 'none',
titledisplay: 'none',
subject: '',
branch_name: "",
issue_tag_ids: "",
fixed_version_id: "",
tracker_id: 0,
issue_type: 0,
status_id: 0,
assigned_to_id: "",
priority_id: 0,
done_ratio: 0,
textcount: "",
fileList: undefined,
get_attachments: undefined,
}
}
componentDidMount = () => {
this.getDetail();
}
getDetail = () => {
const { projectsId, orderId } = this.props.match.params;
const url = `/projects/${projectsId}/issues/${orderId}/edit.json`;
axios.get(url).then((result) => {
if (result) {
this.setState({
data: result.data,
subject: result.data.subject,
issue_chosen: result.data.issue_chosen,
branches: result.data.branches,
tracker_id: result.data.tracker_id,
issue_type: result.data.issue_type,
status_id: result.data.status_id,
priority_id: result.data.priority_id,
done_ratio: result.data.done_ratio,
textcount: result.data.description,
branch_name: result.data.branch_name,
get_attachments: result.data.attachments,
fileList: undefined,
issue_tag_ids: result.data.issue_tags && result.data.issue_tags[0].id,
fixed_version_id: result.data.fixed_version_id,
assigned_to_id: result.data.assigned_to_id
})
this.getjournalslist();
}
}).catch((error) => {
console.log(error);
})
}
handleok = () => {
this.setState({
isShow: false
});
};
handleCancel = () => {
this.setState({
isShow: false
});
}
imgshow = () => {
this.setState({
isShow: true
});
};
stringJson = (value) => {
let _value = null;
try {
_value = JSON.parse(value);
} catch (e) {
_value = value;
}
return _value
}
//删除任务
deleteorder = (id) => {
const { projectsId, orderId } = this.props.match.params;
const url = `/projects/${projectsId}/issues/${orderId}.json`;
axios.delete(url, {
data: {
project_id: projectsId,
id: id
}
}).then((result) => {
if (result) {
this.props.history.push(`/projects/${projectsId}/orders`);
}
}).catch((error) => {
console.log(error);
})
}
onContentChange = (value) => {
this.setState({
textcount: value
})
}
changmodelname = (e) => {
this.setState({
subject: e.target.value
})
}
changmodelcount = (e) => {
this.setState({
textcount: e.target.value
})
}
renderSelect = (list) => {
if (list && list.length > 0) {
return (
list.map((item, key) => {
return (
<Option key={key + 1} value={item.id}>{item.name}</Option>
)
})
)
}
}
handleSubmit = () => {
const { fileList } = this.state;
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
const { projectsId, orderId } = this.props.match.params;
const { subject } = this.state;
const url = `/projects/${projectsId}/issues/${orderId}.json`;
if (values.issue_tag_ids === 0) {
values.issue_tag_ids = ""
} else {
values.issue_tag_ids = [values.issue_tag_ids]
}
if (values.assigned_to_id === 0) {
values.assigned_to_id = ""
}
const { textcount } = this.state;
axios.put(url, {
project_id: projectsId,
subject: subject,
id: orderId,
description: textcount,
attachment_ids: fileList,
...values
}).then(result => {
if (result) {
this.props.history.push(`/projects/${projectsId}/orders`);
}
}).catch(error => {
console.log(error);
})
}
})
}
render() {
const { projectsId, orderId } = this.props.match.params;
const { getFieldDecorator } = this.props.form;
const { current_user } = this.props;
const { issue_tag_ids, fixed_version_id, branch_name, status_id, tracker_id, issue_type, assigned_to_id, priority_id, done_ratio,
issue_chosen, branches, subject, textcount, get_attachments } = this.state;
return (
<div className="main">
<div className="topWrapper">
<Nav {...this.props} {...this.state} />
</div>
<div>
<Form>
<div className="f-wrap-between mt20" style={{ alignItems: "flex-start" }}>
<div className="list-right df">
<Link to={``}><img className="user_img"
src={getImageUrl(`images/${current_user && current_user.image_url}`)} alt="" /></Link>
<div className="new_context">
<Form.Item>
{getFieldDecorator('subject', {
rules: [{
required: true, message: '请填写任务标题'
}],
initialValue: subject
})(
<Input placeholder="标题" onChange={this.changmodelname} />
)}
</Form.Item>
<div className="quillContent" style={{ marginBottom: "20px" }}>
</div>
<MDEditor placeholder={'请输入任务的描述...'} height={200}
mdID={'order-copy-description'} initValue={textcount} onChange={this.onContentChange} ></MDEditor>
<UploadComponent load={this.UploadFunc}
showNotification={this.props.showNotification} isComplete={true} ></UploadComponent>
{
get_attachments ?
<Attachments attachments={get_attachments} showNotification={this.props.showNotification}
canDelete={true} />
:
""
}
<p className="clearfix mt15 text-right">
<a className="topWrapper_btn fr" type="submit" style={{ marginLeft: 5 }}
onClick={this.handleSubmit}>保存</a>
<Link to={`/projects/${projectsId}/orders/${orderId}/detail`}
className="a_btn cancel_btn fr">取消</Link>
</p>
</div>
</div>
<div className="list-left" style={{ paddingRight: "0px", paddingLeft: "15px", paddingTop: "10px" }}>
<div className="list-l-panel">
<Form.Item
label="分支"
>
{getFieldDecorator('branch_name', {
initialValue: branch_name,
rules: [],
})(
<Select>
<Option value={''}>分支未指定</Option>
{
branches && branches.length > 0 && branches.map((item, key) => {
return (
<Option value={item}>{item}</Option>
)
})
}
</Select>
)}
</Form.Item>
<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('status_id', {
initialValue: status_id,
rules: [{
required: true, message: '请选择完成状态'
}],
})(
<Select>
{this.renderSelect(issue_chosen && issue_chosen.issue_status)}
</Select>
)}
</Form.Item>
<Form.Item
label="分类"
>
{getFieldDecorator('tracker_id', {
initialValue: tracker_id,
rules: [{
required: true, message: '请选择分类'
}],
})(
<Select>
{this.renderSelect(issue_chosen && issue_chosen.tracker)}
</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>
<Form.Item
label="优先度"
>
{getFieldDecorator('priority_id', {
initialValue: priority_id,
rules: [{
required: true, message: '请选择优先度'
}],
})(
<Select>
{this.renderSelect(issue_chosen && issue_chosen.priority)}
</Select>
)}
</Form.Item>
<Form.Item
label="完成度"
>
{getFieldDecorator('done_ratio', {
initialValue: done_ratio,
rules: [{
required: true, message: '请选择完成度'
}],
})(
<Select value={done_ratio}>
{this.renderSelect(issue_chosen && issue_chosen.done_ratio)}
</Select>
)}
</Form.Item>
</div>
</div>
</div>
</Form>
</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>
<OrderItem form_type="copy" {...this.props}></OrderItem>
)
}
}
const CopyDetailForm = Form.create({ name: 'CopyDetailForm' })(CopyDetail);
export default CopyDetailForm;
}
export default CopyDetail;

View File

@ -1,15 +1,15 @@
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import axios from 'axios';
import UploadComponent from '../Upload/Index';
import { getImageUrl } from 'educoder';
import { Modal, Form, Tooltip, Popconfirm, Pagination, Spin } from 'antd'
import Attachments from '../Upload/attachment';
import MDEditor from '../../modules/tpm/challengesnew/tpm-md-editor';
import RenderHtml from '../../components/render-html';
import AmplifyImg from './AmplifyImg';
import React, { Component } from "react";
import { Link } from "react-router-dom";
import axios from "axios";
import { getImageUrl } from "educoder";
import { Modal, Form, Tooltip, Popconfirm, Pagination, Spin, Tag } from "antd";
import Attachments from "../Upload/attachment";
// import MDEditor from "../../modules/tpm/challengesnew/tpm-md-editor";
import RenderHtml from "../../components/render-html";
import Comments from "../comments/comments"
import "./order.css";
// import AmplifyImg from "./AmplifyImg";
class Detail extends Component {
constructor(props) {
@ -17,12 +17,12 @@ class Detail extends Component {
this.state = {
data: undefined,
isShow: false,
imgsrc: '',
imgsrc: "",
journalsdata: undefined,
//图片区域是否显示 none 隐藏 block 显示
display: 'none',
titledisplay: 'none',
countvalue: '',
display: "none",
titledisplay: "none",
countvalue: "",
//是否需要编辑
isedit: undefined,
fileList: undefined,
@ -31,314 +31,184 @@ class Detail extends Component {
search_count: undefined,
isSpin: false,
showFiles: true,
quillValue: '',
quillValue: "",
quillFlag: false,
// 点击放大的图片路径
imageUrl: undefined,
visible: false,
journal_spin: false,
edit_spin: false
}
edit_spin: false,
};
}
componentDidMount = () => {
this.getDetail();
}
};
getDetail = () => {
const { projectsId, orderId } = this.props.match.params;
const url = `/projects/${projectsId}/issues/${orderId}.json`;
axios.get(url).then((result) => {
if (result) {
this.setState({
data: result.data
})
this.getjournalslist();
}
}).catch((error) => {
console.log(error);
})
}
axios
.get(url)
.then((result) => {
if (result) {
this.setState({
data: result.data,
});
// this.getjournalslist();
}
})
.catch((error) => {
console.log(error);
});
};
handleok = () => {
this.setState({
isShow: false
isShow: false,
});
};
handleCancel = () => {
this.setState({
isShow: false
});
}
imgshow = () => {
this.setState({
isShow: true
isShow: false,
});
};
//添加评论
addjournals = () => {
const { quillValue } = this.state;
this.setState({
journal_spin: true
})
if (!quillValue) {
this.setState({
quillFlag: true,
journal_spin: false
})
return;
}
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
const { data, page, limit, fileList } = this.state;
const url = `/issues/${data.id}/journals.json`;
axios.post(url, {
...values,
content: quillValue,
issue_id: data.id,
attachment_ids: fileList
}).then(result => {
if (result) {
this.props.showNotification("评论成功!");
this.props.form.setFieldsValue({
content: ""
});
this.setState({
showFiles: false,
quillValue: '',
quillFlag: false,
journal_spin: false
})
this.getjournalslist(page, limit);
}
}).catch(error => {
this.setState({
journal_spin: false
})
console.log(error);
})
}else{
this.setState({
journal_spin: false
})
}
})
}
//获取评论信息
getjournalslist = (page, limit) => {
const { data } = this.state;
const url = `/issues/${data.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,
})
}
}).catch(error => {
console.log(error);
})
}
//删除任务信息
deletedetail = (id) => {
const { projectsId, orderId } = this.props.match.params;
const url = `/projects/${projectsId}/issues/${orderId}.json`;
axios.delete(url, {
data: {
project_id: projectsId,
id: id
}
}).then((result) => {
if (result) {
this.props.history.push(`/projects/${projectsId}/orders`);
}
}).catch((error) => {
console.log(error);
})
}
axios
.delete(url, {
data: {
project_id: projectsId,
id: id,
},
})
.then((result) => {
if (result) {
this.props.history.push(`/projects/${projectsId}/orders`);
}
})
.catch((error) => {
console.log(error);
});
};
//关闭任务
closedetail = (id) => {
const { projectsId, orderId } = this.props.match.params;
const url = `/projects/${projectsId}/issues/${orderId}/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);
})
}
//修改评论
updatedetail = (id) => {
const { page, limit, countvalue } = this.state;
const { orderId } = this.props.match.params;
this.setState({
edit_spin: true
})
const url = `/issues/${orderId}/journals/${id}.json`;
axios.put(url, {
issue_id: orderId,
id: id,
content: countvalue
}).then(result => {
if (result) {
this.setState({
isedit: undefined,
edit_spin: false
})
this.getjournalslist(page, limit);
}
}).catch(error => {
this.setState({
edit_spin: false
axios
.post(url, {
project_id: projectsId,
id: orderId,
status_id: id,
})
console.log(error);
})
}
// 获取上传后的文件id数组
UploadFunc = (fileList) => {
this.setState({
fileList
})
}
//删除评论
deleteorder = (id) => {
const { orderId } = this.props.match.params;
const { page, limit } = this.state;
const url = `/issues/${orderId}/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);
})
}
.then((result) => {
if (result) {
this.getDetail();
}
})
.catch((error) => {
console.log(error);
});
};
editdetail = (count, status) => {
this.setState({
countvalue: this.stringJson(count),
isedit: status
})
}
isedit: status,
});
};
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>
)
}
}
// 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>
// );
// }
// };
//复制
copydetail = () => {
const { projectsId, orderId } = this.props.match.params;
const url = `/projects/${projectsId}/issues/${orderId}/copy.json`;
axios.post(url, {
project_id: projectsId,
id: orderId,
}).then(result => {
if (result) {
this.props.history.push(`/projects/${projectsId}/orders/${result.data.issue_id}/copyetail`);
}
}).catch(error => {
console.log(error);
})
}
axios
.post(url, {
project_id: projectsId,
id: orderId,
})
.then((result) => {
if (result) {
this.props.history.push(
`/projects/${projectsId}/orders/${result.data.issue_id}/copyetail`
);
}
})
.catch((error) => {
console.log(error);
});
};
// 翻页
ChangePage = (page) => {
this.setState({
page,
isSpin: true
})
isSpin: true,
});
const { limit } = this.state;
this.getjournalslist(page, limit);
}
};
// 判断是否重新上传文件
changeIsComplete = (flag) => {
this.setState({
showFiles: flag
})
}
// 新建评论
onContentChange = (value) => {
if (value) {
this.setState({
quillValue: value,
quillFlag: false
})
}
}
// 编辑评论
onEditContentChange = (value) => {
if (value) {
this.setState({
countvalue: value
})
}
}
showFiles: flag,
});
};
handleShowImage = (value) => {
this.setState({
imageUrl: value,
visible: true
})
}
visible: true,
});
};
setVisible = (flag) => {
this.setState({
visible: flag
})
}
visible: flag,
});
};
stringJson = (value) => {
let _value = null;
@ -348,269 +218,202 @@ class Detail extends Component {
} catch (e) {
_value = value;
}
return _value
}
return _value;
};
commentCtx = (v) => {
return (
<RenderHtml className="break_word_comments" value={v} />
)
return <RenderHtml className="break_word_comments" value={v} />;
};
render() {
const { projectsId, orderId } = this.props.match.params;
const { data, journalsdata, page, limit, search_count, isSpin, isedit, showFiles, quillValue, quillFlag, countvalue, imageUrl, visible, journal_spin, edit_spin } = this.state;
const { current_user } = this.props;
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}>
{
key > 0 &&
<div className="order_line" style={{ marginLeft: 80 }}></div>
}
<div className="df">
<Link to={`/users/${item && item.user_login}/projects`} className="show-user-link">
<img className="user_img" src={getImageUrl(`images/${item && 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 && isedit === undefined && (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 && 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" }}>
<div className="quillContent mt20">
<MDEditor placeholder={'添加评论...'} height={200}
mdID={`orderdetail-add-description${item.id}`} startInit={isedit && isedit === item.id} initValue={countvalue} onChange={this.onEditContentChange} ></MDEditor>
<p className="quillFlag">
{quillFlag && <span className="">请输入评论内容</span>}
</p>
</div>
<p className="clearfix mt15">
<Spin spinning={edit_spin}>
<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>
</Spin>
</p>
</div>
</div>
<div style={{ display: this.state.display }}>
<div className="div_line" ></div>
</div>
</div>
</div>
</li>
)
})
}
</div>
)
const {
data,
} = this.state;
const get_color = (type) => {
if (type === "高") {
return "#e67e22";
} else if (type === "正常") {
return "#28be6c";
} else if (type === "低") {
return "#1abc9c";
} else {
return "#e74c3c";
}
}
};
return (
<div className="main">
{visible && <AmplifyImg url={imageUrl} visible={visible} setVisible={this.setVisible} />}
<div>
<div className="detailContent">
<p>
{
data ?
<span className="font-20">{data.issue_classify === "issue" ? (data.tracker ? data.tracker : "缺陷") : "合并请求"}</span>
:
""
}
<span className="font-20" > {data && data.subject}</span>
<div className="ProjectListIndex">
<div className="list-right">
<div className="grid-item pd20 border-1f">
<Link
to={`/users/${data && data.author_login}/projects`}
className="show-user-link"
>
<img
className="user_img"
src={getImageUrl(`images/${data && data.author_picture}`)}
alt=""
width="50"
height="50"
/>
</Link>
<div className="ml10">
<div className="ver-middle">
<span className="mr10 ver-middle">
<span className="font-16">
{data && data.issue_classify === "issue"
? data.tracker
? data.tracker
: "缺陷"
: "合并请求"}
</span>
<span className="font-16 fwb">{data && data.subject}</span>
</span>
</p>
<p className="mt15 color-grey-c">
<span className={data && data.issue_status === "关闭" ? "closedetail" : "opendetail"}>{data && data.issue_status === "关闭" ? "关闭中" : "开启中"} </span>
<span className="ml10 lineH32">
{data && data.author_name} {data && data.created_at}创建{data && data.journals_count && data.journals_count > 0 ? ` · ${data.journals_count} 条评论` : ""}
</span>
{
data && data.user_permission ?
<span className="pull-right lineH32">
<a className="color-blue fr" onClick={this.copydetail}>复制</a>
<Popconfirm placement="bottom" title={'您确定要删除吗'} okText="是" cancelText="否" onConfirm={() => this.deletedetail(orderId)}>
<a className="color-blue fr" style={{ marginLeft: 20, marginRight: 20 }}>删除</a>
{data && data.priority && (
<Tag color={get_color(data.priority)}>{data.priority}</Tag>
)}
</div>
<div className="mt10">
<span className="color-grey-9 mr5"></span>
<Link
to={`/users/${data && data.author_login}/projects`}
className="show-user-link color-blue"
>
{data && data.author_name}
</Link>
<span className="color-grey-9 ml5">
添加于 {data && data.created_at}
</span>
{data && data.user_permission ? (
<span className="pull-right">
<a className="color-blue fr" onClick={this.copydetail}>
复制
</a>
<Popconfirm
placement="bottom"
title={"您确定要删除吗"}
okText="是"
cancelText="否"
onConfirm={() => this.deletedetail(orderId)}
>
<a
className="color-blue fr"
style={{ marginLeft: 20, marginRight: 20 }}
>
删除
</a>
</Popconfirm>
<Link to={`/projects/${projectsId}/orders/${orderId}/updatedetail`} className="color-blue fr">编辑</Link>
<Link
to={`/projects/${projectsId}/orders/${orderId}/updatedetail`}
className="color-blue fr"
>
编辑
</Link>
</span>
:
) : (
""
}
)}
</div>
</div>
</div>
<div className="pd20">
<div className="detail_p">
{data && data.description && data.description.length > 0 ? (
this.commentCtx(data.description)
) : (
<span className="color-grey-9 ml3 mr3">没有描述</span>
)}
</div>
{data && data.attachments && data.attachments.length > 0 ? (
<Attachments
attachments={data.attachments}
showNotification={this.props.showNotification}
/>
) : (
""
)}
</div>
<Comments order_id={orderId} showNotification={this.props.showNotification} {...this.props} />
</div>
<div className="list-left list-left-padding">
<div className="pd20 background-f">
<p className="grid-item pb15">
<span className="issue_detail_info">分支:</span>
<span>{data && data.branch_name ? data.branch_name : "--"}</span>
</p>
<p className="grid-item pb15">
<span className="issue_detail_info">是否上链:</span>
<span>{data && data.issue_type==="2" ? '是' : "--"}</span>
</p>
{
data && data.issue_type==="2" &&
<p className="grid-item pb15">
<span className="issue_detail_info">token值:</span>
<span>{data && data.token ? data.token : "--"}</span>
</p>
}
<p className="grid-item pb15">
<span className="issue_detail_info">标签:</span>
<span>
{data && data.issue_tags ? (
<span
className="issue-tag-show"
style={{ background: data.issue_tags[0].color }}
>
{data.issue_tags[0].name}
</span>
) : (
"--"
)}
</span>
</p>
<p className="grid-item pb15">
<span className="issue_detail_info">里程碑:</span>
<span className="title_overflow">
{data && data.version ? data.version : "--"}
</span>
</p>
<p className="grid-item pb15">
<span className="issue_detail_info">状态:</span>
<span>
{data && data.issue_status ? data.issue_status : "--"}
</span>
</p>
<p className="grid-item pb15">
<span className="issue_detail_info">分类:</span>
<span>{data && data.tracker ? data.tracker : "--"}</span>
</p>
<p className="grid-item pb15">
<span className="issue_detail_info">负责人:</span>
<span>
{data && data.assign_user_name ? data.assign_user_name : "--"}
</span>
</p>
<p className="grid-item pb15">
<span className="issue_detail_info">开始日期:</span>
<span>{data && data.start_date ? data.start_date : "--"}</span>
</p>
<p className="grid-item pb15">
<span className="issue_detail_info">结束日期:</span>
<span>{data && data.due_date ? data.due_date : "--"}</span>
</p>
</div>
<div className="f-wrap-between mt20" style={{ alignItems: "flex-start" }}>
<div className="item-list-right" >
<div className="df ">
<Link to={``}><img className="user_img" src={getImageUrl(`images/${data && data.author_picture}`)} alt="" /></Link>
<div className="detail_context">
<div className="detail_p">
{data && data.description && (data.description.length > 0) ? this.commentCtx(data.description) : <span className="color-grey-9 ml3 mr3">没有描述</span>}
</div>
{
data && data.attachments && data.attachments.length > 0 ?
<Attachments attachments={data.attachments} showNotification={this.props.showNotification} />
:
""
}
</div>
</div>
<div className="order_line" style={{ marginLeft: 80 }}></div>
<Spin spinning={isSpin}>
<ul className="ul_width">
{renderList()}
</ul>
</Spin>
{Paginations}
{
current_user && current_user.login ?
<React.Fragment>
<div className="order_line" style={{ marginLeft: 80 }}></div>
<div className="df">
<img className="user_img" src={getImageUrl(`images/${current_user && current_user.image_url}`)} alt="" />
<div className="new_context">
<div className="quillContent" style={{ marginBottom: "20px" }}>
<MDEditor placeholder={'添加评论...'} height={200}
mdID={'orderdetail-add-descriptions'} initValue={quillValue} onChange={this.onContentChange} ></MDEditor>
<p className="quillFlag">
{quillFlag && <span className="">请输入评论内容</span>}
</p>
</div>
<UploadComponent load={this.UploadFunc} isComplete={showFiles} changeIsComplete={this.changeIsComplete}></UploadComponent>
<p className="clearfix mt15">
<Spin spinning={journal_spin}>
<a className="topWrapper_btn fr" type="submit" onClick={this.addjournals}>评论</a>
{
data && data.user_permission ?
<a className="Closeor_btn fr" type="submit"
onClick={() => this.closedetail(data && data.issue_status === "关闭" ? 2 : 5)}>{data && data.issue_status === "关闭" ? "重新开启" : "关闭"}</a>
:
""
}
</Spin>
</p>
</div>
</div>
</React.Fragment>
:
<div className="loginDiv"><Link to={`/login`}>登录</Link></div>
}
</div>
<div className="list-left DetailRight" style={{ backgroundColor: "#fff" }}>
<p>
<span className="span_title">分支</span>
<span>{
data && data.branch_name ? data.branch_name : "--"
}</span>
</p>
<p>
<span className="span_title">标签</span>
<span>{
data && data.issue_tags ? <span className="issue-tag-show" style={{ background: data.issue_tags[0].color }}>{data.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.version ? data.version : "--"
}</span>
</p>
<p>
<span className="span_title">当前状态</span>
<span>{
data && data.issue_status ? data.issue_status : "--"
}</span>
</p>
<p>
<span className="span_title">分类</span>
<span>{
data && data.tracker ? data.tracker : "--"
}</span>
</p>
<p>
<span className="span_title">指派给</span>
<span>{data && data.assign_user_name ? data.assign_user_name : "--"}</span>
</p>
<p>
<span className="span_title">优先级</span>
<span>{data && data.priority ? data.priority : "--"}</span>
</p>
<p>
<span className="span_title">完成度</span>
<span>{data && data.done_ratio ? data.done_ratio : "--"}</span>
</p>
</div>
<p className="grid-item pb15">
<span className="issue_detail_info">完成度:</span>
<span>{data && data.done_ratio ? data.done_ratio : "--"}</span>
</p>
</div>
</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 WrappedDetailForm = Form.create({ name: 'DetailOrderForm' })(Detail);
export default WrappedDetailForm;
const WrappedDetailForm = Form.create({ name: "DetailOrderForm" })(Detail);
export default WrappedDetailForm;

View File

@ -1,311 +1,17 @@
import React, { Component } from "react";
import { Form, Input, Select, Spin } from 'antd';
import { getImageUrl } from 'educoder';
import UploadComponent from '../Upload/Index';
import MDEditor from '../../modules/tpm/challengesnew/tpm-md-editor';
import './order.css';
import axios from 'axios';
import { Link } from "react-router-dom";
const Option = Select.Option;
import OrderItem from './order_form'
class New extends Component {
constructor(props) {
super(props);
this.state = {
branch_name: "",
issue_tag_ids: "",
fixed_version_id: "",
tracker_id: "缺陷",
issue_type: "普通",
status_id: '新增',
assigned_to_id: "",
priority_id: "正常",
done_ratio: "0%",
issue_chosen: undefined,
branches: undefined,
fileList: undefined,
description: undefined,
isSpin: false
}
}
componentDidMount = () => {
if (!this.props.checkIfLogin()) {
this.props.showLoginDialog();
return;
}
this.InitData();
this.getSelectList();
}
InitData = () => {
this.props.form.setFieldsValue({
...this.state
});
}
getSelectList = () => {
let projectsId = ""
if (this.props.match.params.milepostId) {
projectsId = this.props.match.params.projectsId;
this.props.form.setFieldsValue({
fixed_version_id: this.props.match.params.milepostId
});
} else {
projectsId = this.props.match.params.projectsId;
}
const url = `/projects/${projectsId}/issues/new.json`;
axios.get(url).then((result) => {
if (result) {
this.setState({
issue_chosen: result.data.issue_chosen,
branches: result.data.branches
})
}
}).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>
)
})
)
}
}
// 创建
handleSubmit = () => {
this.setState({
isSpin: true
})
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
const { projectsId } = this.props.match.params;
const { fileList } = this.state;
const url = `/projects/${projectsId}/issues.json`;
if (values.status_id === "新增") {
values.status_id = "1"
}
// if(values.issue_type==="普通"){
// values.issue_type="1"
// }
if (values.tracker_id === "缺陷") {
values.tracker_id = "1"
}
if (values.priority_id === "正常") {
values.priority_id = "2"
}
if (values.done_ratio === "0%") {
values.done_ratio = "0"
}
if (values.issue_tag_ids.length > 0) {
values.issue_tag_ids = [values.issue_tag_ids]
}
const { description } = this.state;
axios.post(url, {
...values,
description: description,
attachment_ids: fileList
}).then(result => {
if (result) {
this.props.showNotification("任务创建成功!");
this.props.history.push(`/projects/${projectsId}/orders`);
this.setState({
description: '',
isSpin: false
})
const { getDetail } = this.props;
getDetail && getDetail();
}
}).catch(error => {
this.setState({
isSpin: false
})
console.log(error);
})
}else{
this.setState({
isSpin: false
})
}
})
}
// 获取上传后的文件id数组
UploadFunc = (fileList) => {
this.setState({
fileList
})
}
onContentChange = (value) => {
this.setState({
description: value
})
}
render() {
const { getFieldDecorator } = this.props.form;
const { current_user } = this.props;
const { description, issue_chosen, branches, isSpin } = this.state;
return (
<div className="main">
<Form>
<div className="f-wrap-between mt20" style={{ alignItems: "flex-start" }}>
<div className="list-right df">
<Link to={`/users/${current_user && current_user.login}/projects`} className="show-user-link">
<img className="user_img" src={getImageUrl(`images/${current_user && current_user.image_url}`)} alt="" />
</Link>
<div className="new_context">
<Form.Item>
{getFieldDecorator('subject', {
rules: [{
required: true, message: '请填写任务标题'
}],
})(
<Input placeholder="标题" />
)}
</Form.Item>
<div className="quillContent" style={{ marginBottom: "20px" }}>
<MDEditor placeholder={'请输入描述信息'} height={350}
mdID={'order-new-description'} initValue={description} onChange={this.onContentChange} ></MDEditor>
</div>
<UploadComponent load={this.UploadFunc} showNotification={this.props.showNotification} isComplete={true}></UploadComponent>
<p className="clearfix mt15">
<Spin spinning={isSpin}>
<a className="topWrapper_btn fr" type="submit" onClick={this.handleSubmit}>创建任务</a>
</Spin>
</p>
</div>
</div>
<div className="list-left mt10" style={{ paddingRight: "0px", paddingLeft: "0px", width: "25%", backgroundColor: "#fff" }}>
<div className="list-l-panel">
<Form.Item>
{getFieldDecorator('branch_name', {
rules: [],
})(
<Select>
<Option value={''}>分支未指定</Option>
{
branches && branches.length > 0 && branches.map((item, key) => {
return (
<Option value={item}>{item}</Option>
)
})
}
</Select>
)}
</Form.Item>
<Form.Item
label="标签"
>
{getFieldDecorator('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', {
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('status_id', {
rules: [{
required: true, message: '请选择完成状态'
}],
})(
<Select>
{this.renderSelect(issue_chosen && issue_chosen.issue_status)}
</Select>
)}
</Form.Item>
<Form.Item
label="分类"
>
{getFieldDecorator('tracker_id', {
rules: [{
required: true, message: '请选择分类'
}],
})(
<Select>
{this.renderSelect(issue_chosen && issue_chosen.tracker)}
</Select>
)}
</Form.Item>
<Form.Item
label="指派成员"
>
{getFieldDecorator('assigned_to_id', {
rules: [{
}],
})(
<Select>
<Option value={""}>未指派成员</Option>
{this.renderSelect(issue_chosen && issue_chosen.assign_user)}
</Select>
)}
</Form.Item>
<Form.Item
label="优先度"
>
{getFieldDecorator('priority_id', {
rules: [{
required: true, message: '请选择优先度'
}],
})(
<Select>
{this.renderSelect(issue_chosen && issue_chosen.priority)}
</Select>
)}
</Form.Item>
<Form.Item
label="完成度"
>
{getFieldDecorator('done_ratio', {
rules: [{
required: true, message: '请选择完成度'
}],
})(
<Select>
{this.renderSelect(issue_chosen && issue_chosen.done_ratio)}
</Select>
)}
</Form.Item>
</div>
</div>
</div>
</Form>
</div>
<OrderItem form_type="new" {...this.props}></OrderItem>
)
}
}
const WrappedNewForm = Form.create({ name: 'NewOrderForm' })(New);
export default WrappedNewForm;
export default New;

View File

@ -1,6 +1,6 @@
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { Popconfirm } from 'antd'
import { Popconfirm, Tag } from 'antd'
import { TagInfo } from '../Utils/TagColor';
@ -18,7 +18,7 @@ class OrderItem extends Component {
return (
issue_tags.map((item, key) => {
return (
<span>{item.name}</span>
<Tag color={item.color} className="mlr10" key={key}>{item.name}</Tag>
)
})
)

View File

@ -1,403 +1,17 @@
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import axios from 'axios';
import UploadComponent from '../Upload/Index';
import { getImageUrl } from 'educoder';
import { Modal, Form, Input, Select, Spin } from 'antd'
import Attachments from '../Upload/attachment';
import MDEditor from '../../modules/tpm/challengesnew/tpm-md-editor';
const Option = Select.Option;
import React, { Component } from "react";
import OrderItem from './order_form'
class UpdateDetail extends Component {
constructor(props) {
super(props);
this.state = {
data: undefined,
isShow: false,
imgsrc: '',
journalsdata: undefined,
//图片区域是否显示 none 隐藏 block 显示
display: 'none',
titledisplay: 'none',
subject: '',
branch_name: "",
issue_tag_ids: "",
fixed_version_id: "",
tracker_id: 0,
issue_type: 0,
status_id: 0,
assigned_to_id: "",
priority_id: 0,
done_ratio: 0,
textcount: "",
fileList: undefined,
get_attachments: undefined,
isSpin: false
}
}
componentDidMount = () => {
this.getDetail();
}
getDetail = () => {
const { projectsId, orderId } = this.props.match.params;
const url = `/projects/${projectsId}/issues/${orderId}/edit.json`;
axios.get(url).then((result) => {
if (result) {
this.setState({
data: result.data,
subject: result.data.subject,
issue_chosen: result.data.issue_chosen,
branches: result.data.branches,
tracker_id: result.data.tracker_id,
issue_type: result.data.issue_type,
status_id: result.data.status_id,
priority_id: result.data.priority_id,
done_ratio: result.data.done_ratio,
textcount: result.data.description,
branch_name: result.data.branch_name,
get_attachments: result.data.attachments,
fileList: undefined,
issue_tag_ids: result.data.issue_tags && result.data.issue_tags[0].id,
fixed_version_id: result.data.fixed_version_id,
assigned_to_id: result.data.assigned_to_id
})
}
}).catch((error) => {
console.log(error);
})
}
handleok = () => {
this.setState({
isShow: false
});
};
handleCancel = () => {
this.setState({
isShow: false
});
}
imgshow = () => {
this.setState({
isShow: true
});
};
onContentChange = (value) => {
this.setState({
textcount: value
})
}
changmodelname = (e) => {
this.setState({
subject: e.target.value
})
}
changmodelcount = (e) => {
this.setState({
textcount: e.target.value
})
}
renderSelect = (list) => {
if (list && list.length > 0) {
return (
list.map((item, key) => {
return (
<Option key={key + 1} value={item.id}>{item.name}</Option>
)
})
)
}
}
// 切换完成度
changeRatio = (e) => {
if (e === 0) {
this.props.form.setFieldsValue({
status_id: 1
})
this.setState({
status_id: 1
})
} else if (e === 100) {
this.props.form.setFieldsValue({
status_id: 3
})
this.setState({
status_id: 3
})
} else {
this.props.form.setFieldsValue({
status_id: 2
})
this.setState({
status_id: 2
})
}
}
// 切换状态
changeStatus = (e) => {
// console.log(e);
if (e === 1) {
this.props.form.setFieldsValue({
done_ratio: 0
})
this.setState({
done_ratio: 0
})
} else if (e === 3) {
this.props.form.setFieldsValue({
done_ratio: 100
})
this.setState({
done_ratio: 100
})
}
}
// 获取上传后的文件id数组
UploadFunc = (fileList) => {
this.setState({
fileList
})
}
handleSubmit = () => {
this.setState({
isSpin: true
})
const { fileList } = this.state;
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
const { projectsId, orderId } = this.props.match.params;
const { subject } = this.state;
const url = `/projects/${projectsId}/issues/${orderId}.json`;
if (values.issue_tag_ids === 0) {
values.issue_tag_ids = ""
} else {
values.issue_tag_ids = [values.issue_tag_ids]
}
if (values.assigned_to_id === 0) {
values.assigned_to_id = ""
}
const { textcount } = this.state;
axios.put(url, {
project_id: projectsId,
subject: subject,
id: orderId,
description: textcount,
attachment_ids: fileList,
...values
}).then(result => {
if (result) {
this.props.history.push(`/projects/${projectsId}/orders/${orderId}/detail`);
}
}).catch(error => {
this.setState({
isSpin: false
})
console.log(error);
})
}else{
this.setState({
isSpin: false
})
}
})
}
render() {
const { projectsId, orderId } = this.props.match.params;
const { getFieldDecorator } = this.props.form;
const { current_user } = this.props;
const { issue_tag_ids, fixed_version_id, branch_name, status_id, tracker_id, issue_type, assigned_to_id, priority_id, done_ratio,
issue_chosen, branches, subject, textcount, get_attachments, isSpin } = this.state;
return (
<div className="main">
<div>
<Form>
<div className="f-wrap-between mt20" style={{ alignItems: "flex-start" }}>
<div className="list-right df" >
<Link to={`/users/${current_user && current_user.login}/projects`} className="show-user-link">
<img className="user_img" src={getImageUrl(`images/${current_user && current_user.image_url}`)} alt="" />
</Link>
<div className="new_context">
<Form.Item>
{getFieldDecorator('subject', {
rules: [{
required: true, message: '请填写任务标题'
}],
initialValue: subject
})(
<Input placeholder="标题" onChange={this.changmodelname} />
)}
</Form.Item>
<MDEditor placeholder={'请输入任务的描述...'} height={350}
mdID={'order-update-description'} initValue={textcount} onChange={this.onContentChange} ></MDEditor>
<UploadComponent load={this.UploadFunc} showNotification={this.props.showNotification} isComplete={true}></UploadComponent>
{
get_attachments ?
<Attachments attachments={get_attachments} showNotification={this.props.showNotification} canDelete={true} />
:
""
}
<p className="clearfix mt15 text-right">
<Spin spinning={isSpin}>
<a className="topWrapper_btn fr" type="submit" style={{ marginLeft: 5 }} onClick={this.handleSubmit}>保存</a>
<Link to={`/projects/${projectsId}/orders/${orderId}/detail`} className="a_btn cancel_btn fr">取消</Link>
</Spin>
</p>
</div>
</div>
<div className="list-left mt10" style={{ paddingRight: "0px", paddingLeft: "0px", width: "25%", backgroundColor: "#fff" }}>
<div className="list-l-panel">
<Form.Item
label="分支"
>
{getFieldDecorator('branch_name', {
initialValue: branch_name,
rules: [],
})(
<Select>
<Option value={''}>分支未指定</Option>
{
branches && branches.length > 0 && branches.map((item, key) => {
return (
<Option value={item}>{item}</Option>
)
})
}
</Select>
)}
</Form.Item>
<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('status_id', {
initialValue: status_id,
rules: [{
required: true, message: '请选择完成状态'
}],
})(
<Select onChange={this.changeStatus}>
{this.renderSelect(issue_chosen && issue_chosen.issue_status)}
</Select>
)}
</Form.Item>
<Form.Item
label="分类"
>
{getFieldDecorator('tracker_id', {
initialValue: tracker_id,
rules: [{
required: true, message: '请选择分类'
}],
})(
<Select>
{this.renderSelect(issue_chosen && issue_chosen.tracker)}
</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>
<Form.Item
label="优先度"
>
{getFieldDecorator('priority_id', {
initialValue: priority_id,
rules: [{
required: true, message: '请选择优先度'
}],
})(
<Select>
{this.renderSelect(issue_chosen && issue_chosen.priority)}
</Select>
)}
</Form.Item>
<Form.Item
label="完成度"
>
{getFieldDecorator('done_ratio', {
initialValue: done_ratio,
rules: [{
required: true, message: '请选择完成度'
}],
})(
<Select value={done_ratio} onChange={this.changeRatio}>
{this.renderSelect(issue_chosen && issue_chosen.done_ratio)}
</Select>
)}
</Form.Item>
</div>
</div>
</div>
</Form>
</div>
<Modal
onCancel={this.handleCancel}
visible={this.state.isShow}
width="400px"
footer={
[]
}
bodyStyle={{ textAlign: 'center' }}
>
<img class="list_img" src="https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=1608431072,669449145&fm=27&gp=0.jpg" alt="" />
</Modal>
</div>
<OrderItem form_type="edit" {...this.props}></OrderItem>
)
}
}
const UpdateDetailForm = Form.create({ name: 'UpdateDetailForm' })(UpdateDetail);
export default UpdateDetailForm;
}
export default UpdateDetail;

View File

@ -1,24 +1,24 @@
.topWrapper {
padding-bottom:20px;
padding-bottom: 20px;
box-sizing: border-box;
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.quillContent{
.quillContent {
position: relative;
margin-bottom: 4px;
}
.quillFlag{
.quillFlag {
position: absolute;
bottom:0px;
left:6px;
bottom: 0px;
left: 6px;
height: 20px;
line-height: 18px;
color: red;
}
.topmilepost{
.topmilepost {
padding: 20px 0;
box-sizing: border-box;
display: flex;
@ -26,18 +26,17 @@
flex-wrap: wrap;
}
.miledetail{
.miledetail {
padding: 20px 0;
box-sizing: border-box;
justify-content: space-between;
border-bottom: 1px solid #EEEEEE;
border-bottom: 1px solid #eeeeee;
flex-wrap: wrap;
}
.topWrapper_nav{
.topWrapper_nav {
display: flex;
}
.detail_p{
.detail_p {
display: flex;
/*padding:10px;*/
/*width: 80%;*/
@ -45,7 +44,7 @@
/*margin: auto;*/
}
.detail_right{
.detail_right {
/*display: flex;*/
flex-grow: 1;
text-align: right;
@ -53,99 +52,102 @@
/*padding-left: 15px;*/
/*margin: auto; */
}
.commit_p{
.commit_p {
font-size: 12px;
padding-top: 10px;
padding-left: 5px;
}
.ul_width{
.ul_width {
width: 100%;
}
.a_btn{
border-radius:4px;
padding:0 12px;
.a_btn {
border-radius: 4px;
padding: 0 12px;
margin-right: 15px;
line-height: 30px;
}
.cancel_btn{
border:1px solid #e6e6e6;
.cancel_btn {
border: 1px solid #e6e6e6;
color: #333 !important;
}
.delete_btn{
border:1px solid red;
.delete_btn {
border: 1px solid red;
color: red !important;
}
.cancel_btn:hover{background: #e6e6e6}
.Closeor_btn{
border:1px solid red;
.cancel_btn:hover {
background: #e6e6e6;
}
.Closeor_btn {
border: 1px solid red;
color: red;
height: 32px;
text-align: center;
border-radius:4px;
padding:0px 12px;
border-radius: 4px;
padding: 0px 12px;
margin-right: 15px;
line-height: 32px;
}
.rectangle {
width: 8px;
height: 8px;
border-radius: 100%;
margin-top: 15px;
margin-left: -4px;
margin-bottom: 10px;
background: green;
}
.order_line{
display: flex;
height: 32px;
margin: auto;
border-left:1px solid #eee;
}
.comment_img{
height: 25px;
width: 25px;
margin-top: 5px;
border-radius: 100%;
}
width: 8px;
height: 8px;
border-radius: 100%;
margin-top: 15px;
margin-left: -4px;
margin-bottom: 10px;
background: green;
}
.order_line {
display: flex;
height: 32px;
margin: auto;
border-left: 1px solid #eee;
}
.comment_img {
height: 25px;
width: 25px;
margin-top: 5px;
border-radius: 100%;
}
.topWrapper_nav a,.topWrapper_nav span{
border:1px solid #f4f4f4;
.topWrapper_nav a,
.topWrapper_nav span {
border: 1px solid #f4f4f4;
border-radius: 5px 0px 0px 5px;
height: 34px;
line-height: 34px;
text-align: center;
padding:0px 10px;
padding: 0px 10px;
display: block;
cursor: pointer;
}
.topWrapper_nav a:hover{
.topWrapper_nav a:hover {
background: #f4f4f4;
}
.topWrapper_nav a:last-child,.topWrapper_nav span:last-child{
.topWrapper_nav a:last-child,
.topWrapper_nav span:last-child {
border-left: none;
border-radius: 0px 5px 5px 0px;
}
.topWrapper_btn {
background: #fff;
border:1px solid #5091FF;
color: #5091FF!important;
padding:0px 12px;
border: 1px solid #5091ff;
color: #5091ff !important;
padding: 0px 12px;
text-align: center;
height: 32px;
line-height: 32px;
border-radius: 4px;
}
.topWrapper_type{
.topWrapper_type {
display: flex;
}
.topWrapper_type li{
.topWrapper_type li {
display: flex;
align-items: center;
margin-right: 30px;
}
.topWrapper_type li >span{
.topWrapper_type li > span {
display: block;
height: 30px;
line-height: 30px;
@ -154,23 +156,23 @@
min-width: 60px;
box-sizing: border-box;
text-align: center;
background:rgba(250,250,250,1);
border:1px solid rgba(221,221,221,1);
background: rgba(250, 250, 250, 1);
border: 1px solid rgba(221, 221, 221, 1);
cursor: pointer;
}
.topWrapper_type li > span.active{
color: #4CACFF;
border:1px solid rgba(80,145,255,1);
.topWrapper_type li > span.active {
color: #4cacff;
border: 1px solid rgba(80, 145, 255, 1);
}
.topWrapper_select{
.topWrapper_select {
display: flex;
flex-wrap: wrap;
align-items: center;
}
.topWrapper .ant-btn.ant-input-search-button{
.topWrapper .ant-btn.ant-input-search-button {
height: 30px;
}
.title_overflow{
.title_overflow {
max-width: 220px;
white-space: nowrap;
overflow: hidden;
@ -179,11 +181,11 @@
-o-text-overflow: ellipsis;
text-overflow: ellipsis;
}
.topWrapper_select li{
.topWrapper_select li {
text-align: center;
cursor: pointer;
color: #666;
width:90px;
width: 90px;
text-align: center;
display: inline-block;
overflow: hidden;
@ -191,39 +193,41 @@
-o-text-overflow: ellipsis;
text-overflow: ellipsis;
}
.topWrapper_select li:active{
.topWrapper_select li:active {
background: #f4f4f4;
border-radius: 4px;
}
.no-cursor li{cursor: default !important;}
.ant-dropdown-menu .ant-dropdown-menu-item{
.no-cursor li {
cursor: default !important;
}
.ant-dropdown-menu .ant-dropdown-menu-item {
text-align: center;
padding:6px 30px;
padding: 6px 30px;
cursor: pointer;
}
.issueItem{
.issueItem {
display: flex;
flex-wrap: wrap;
align-content: center;
border-bottom:1px dashed #cecdcd;
padding:16px 0px 16px 20px;
border-bottom: 1px dashed #cecdcd;
padding: 16px 0px 16px 20px;
}
.issueNo{
padding:0px 5px;
.issueNo {
padding: 0px 5px;
border-radius: 4px;
background: #f4f4f4;
display: block;
margin-right: 8px;
color:#666;
color: #666;
height: 30px;
line-height: 30px;
}
.issueOpen{
.issueOpen {
background: #21ba45 !important;
color: #fff !important;
}
.margin_detail{
.margin_detail {
margin-left: 15px;
margin-right: 15px;
}
@ -241,7 +245,7 @@
margin-left: 15px;
padding: 15px;
position: relative;
background: #FFFFFF;
background: #ffffff;
}
.new_context:before {
position: absolute;
@ -265,41 +269,41 @@
top: 14px;
right: 100%;
}
.list-l-panel{
border:1px solid #f4f4f4;
.list-l-panel {
border: 1px solid #f4f4f4;
border-radius: 4px;
padding:10px 15px;
padding: 10px 15px;
}
.list-l-panel .ant-row{
.list-l-panel .ant-row {
margin-bottom: 0px;
}
/*编辑任务*/
.editingsheet{
/*编辑任务*/
.editingsheet {
background: #ffffff;
color: #21ba45!important;
padding:0px 12px;
color: #21ba45 !important;
padding: 0px 12px;
text-align: center;
height: 32px;
line-height: 32px;
}
/*开启中 关闭中*/
.opendetail{
.opendetail {
display: inline-block;
background: #21ba45;
color: #ffffff!important;
padding:0px 12px;
color: #ffffff !important;
padding: 0px 12px;
text-align: center;
height: 32px;
/*width: 110px;*/
border-radius: 4px;
line-height: 32px;
}
.closedetail{
.closedetail {
display: inline-block;
background: #e60b0b;
color: #ffffff!important;
padding:0px 12px;
color: #ffffff !important;
padding: 0px 12px;
text-align: center;
height: 32px;
/*width: 110px;*/
@ -307,30 +311,29 @@
line-height: 32px;
}
.commenttitle{
color: #21ba45!important;
.commenttitle {
color: #21ba45 !important;
}
.topWrapper_detali{
.topWrapper_detali {
display: flex;
/*height: 35px;*/
background-color: #eee;
align-items: center;
margin-bottom: 10px;
}
.towwrapper_img_detali{
.towwrapper_img_detali {
display: flex;
padding-left: 80px;
margin-left: 80px;
margin-right: 20px;
border: 1px solid #4CACFF;
border: 1px solid #4cacff;
}
.div_line{
.div_line {
width: 100%;
border: 10px solid #4CACFF;
border: 10px solid #4cacff;
}
.list_img{
.list_img {
height: 145px;
padding: 15px;
width: 145px;
@ -345,7 +348,7 @@
/*padding-left: 0px;*/
/*margin-right: 15px;*/
position: relative;
background: #FFFFFF;
background: #ffffff;
border-radius: 4px;
width: 0;
}
@ -372,34 +375,38 @@
right: 100%;
}
/* 任务标签列表 */
.tagList > div{
.tagList > div {
border-bottom: 1px dashed #f4f4f4;
display: flex;
justify-content: space-around;
padding:15px 0px;
padding: 15px 0px;
}
.divwidth{
.divwidth {
width: 74%;
}
.listTowItems{
.listTowItems {
width: 80%;
padding-left: 80px;
}
.tagList > div:last-child{
.tagList > div:last-child {
border-bottom: none;
}
.mr10{margin-right: 10px;}
.text-right{text-align: right;}
.mr10 {
margin-right: 10px;
}
.text-right {
text-align: right;
}
/*.tagList > div > span{*/
/*display: block*/
/*display: block*/
/*}*/
/*.tagList > div > span:nth-child(2){*/
/*width: 450px;*/
/*width: 450px;*/
/*}*/
.tagColor{
.tagColor {
display: inline-block;
width:28px;
width: 28px;
height: 14px;
border-radius: 4px;
margin-right: 5px;
@ -407,87 +414,87 @@
}
/*里程碑*/
.milepostdiv{
.milepostdiv {
display: flex;
}
.milepostwidth{
.milepostwidth {
display: flex;
width: 60%;
}
.mileposwidth{
.mileposwidth {
background: #21ba45;
border-radius: 4px;
width: 40%;
}
.milepostrighe{
.milepostrighe {
display: flex;
width: 80%;
}
.milepostleft{
.milepostleft {
display: flex;
justify-content: center;
}
.textwidth{
.textwidth {
display: flex;
width: 100%;
}
.newmilepostleft{
.newmilepostleft {
padding: 15px;
margin-right: 50px;
width: 60%;
}
.newmilepostrighe{
.newmilepostrighe {
margin-left: 50px;
padding: 15px;
width: 30%;
}
/* 任务详情 */
.detailContent{
padding:15px 0px;
.detailContent {
padding: 15px 0px;
border-bottom: 1px solid #f4f4f4;
}
.DetailRight{
padding: 10px 15px;
border:1px solid #f4f4f4;
.DetailRight {
padding: 10px 15px;
border: 1px solid #f4f4f4;
border-radius: 4px;
}
.DetailRight > p{
.DetailRight > p {
height: 30px;
line-height:30px;
line-height: 30px;
}
.inptwidth{
.inptwidth {
width: 20%;
}
.inputcount{
.inputcount {
width: 40%;
}
.loginDiv{
.loginDiv {
border: 1px solid #f7c977;
background: rgb(255, 204, 113,0.3);
background: rgb(255, 204, 113, 0.3);
text-align: center;
padding:8px 0px;
padding: 8px 0px;
border-radius: 4px;
width: 100%;
color: #999;
margin-top: 15px;
}
.loginDiv a{
.loginDiv a {
text-decoration: underline;
color: #4CACFF;
color: #4cacff;
margin-right: 3px;
}
.tagdiv{
.tagdiv {
padding: 15px;
height: 75px;
box-sizing: border-box;
display: flex;
justify-content: space-between;
border: 1px solid #EEEEEE;
border: 1px solid #eeeeee;
flex-wrap: wrap;
}
.dialogdiv{
.dialogdiv {
padding: 5px;
height: 45px;
box-sizing: border-box;
@ -495,64 +502,183 @@
justify-content: space-between;
flex-wrap: wrap;
}
.issue-tag-show{padding: 3px 8px; color: #fff; border-radius: 6px;}
.journal-list-item{padding: 12px 15px}
.issue-tag-show {
padding: 3px 8px;
color: #fff;
border-radius: 6px;
}
.journal-list-item {
padding: 10px;
}
/*.DetailRight > p >span:nth-child(1){*/
/*min-width: 90px;*/
/*margin-right: 15px;*/
/*text-align: right;*/
/*min-width: 90px;*/
/*margin-right: 15px;*/
/*text-align: right;*/
/*}*/
.span_title{
min-width: 90px;
.span_title {
min-width: 40px;
margin-right: 15px;
text-align: right;
color: rgba(0, 0, 0, 0.65);
}
.target-detail-search .ant-input-group-addon{border: none !important;}
.target-detail-search .ant-input-search-button{height: 32px !important;}
a.issue-type-button.active{background: #4CACFF; color: #fff;}
a.issue-type-button.active:hover{background: #f4f4f4; color: #4CACFF;}
@media screen and (max-width: 700px){
.topWrapper_select li{
width:auto;
.target-detail-search .ant-input-group-addon {
border: none !important;
}
.target-detail-search .ant-input-search-button {
height: 32px !important;
}
a.issue-type-button.active {
background: #4cacff;
color: #fff;
}
a.issue-type-button.active:hover {
background: #f4f4f4;
color: #4cacff;
}
@media screen and (max-width: 700px) {
.topWrapper_select li {
width: auto;
}
}
.ml10{margin-left: 10px;}
.lineH32{line-height: 32px;}
.lineH40{line-height: 40px;}
.item-list-right{width: 74%; padding: 0px 15px 10px 0}
.detail_edit_action{padding:10px; color: #999; cursor: pointer; line-height: 40px;}
.attachmentsList{
margin-left:4px;
.ml10 {
margin-left: 10px;
}
.lineH32 {
line-height: 32px;
}
.lineH40 {
line-height: 40px;
}
.item-list-right {
width: 74%;
padding: 0px 15px 10px 0;
}
.detail_edit_action {
padding: 10px;
color: #999;
cursor: pointer;
line-height: 40px;
}
.attachmentsList {
margin-left: 4px;
}
.paper-clip-color {
color: #29bd8b !important;
}
.attachment-list-delete {
display: none;
}
.attachment-list-div:hover {
background-color: #e6f7ff;
}
.attachment-list-div:hover .attachment-list-delete {
display: block !important;
}
.attachment-list-a {
color: rgba(0, 0, 0, 0.65) !important;
}
.btp1 {
border-top: 1px solid #f4f4f4;
}
.grid-item {
display: grid;
align-items: center;
grid-template-columns: max-content 1fr;
}
.grid-item-left {
display: grid;
align-items: center;
grid-template-columns: 1fr max-content;
}
.fwb {
font-weight: bold;
}
.paper-clip-color{color:#29bd8b !important}
.attachment-list-delete{display: none;}
.attachment-list-div:hover{background-color: #e6f7ff;}
.attachment-list-div:hover .attachment-list-delete{display: block !important;}
.attachment-list-a{color: rgba(0, 0, 0, 0.65) !important;}
.btp1{border-top: 1px solid #f4f4f4;}
.fwb{font-weight: bold;}
/* 发布人、指派人数量过多时要出现滚动条 */
.ant-dropdown-menu{
.ant-dropdown-menu {
max-height: 350px;
overflow-y:auto;
overflow-y: auto;
}
.ql-bubble .ql-editor img{
min-width:100px!important;
.ql-bubble .ql-editor img {
min-width: 100px !important;
}
.AmplifyImg .ant-modal{
padding:0px;
.AmplifyImg .ant-modal {
padding: 0px;
}
.AmplifyImg img{
.AmplifyImg img {
max-width: 100%;
margin: 0px auto;
}
.AmplifyImg .ant-modal-body{
padding:25px;
.AmplifyImg .ant-modal-body {
padding: 25px;
}
.amplifyContent{
.amplifyContent {
text-align: center;
}
.mb-0{margin-bottom: 0 !important;}
.mb-0 {
margin-bottom: 0 !important;
}
.text-yellow {
color: #ff6e21;
}
.border-1f {
border-bottom: 1px solid #f4f4f4;
}
.background-f {
background: #fff;
}
.issue_detail_info {
width: 65px;
margin-right: 15px;
text-align: right;
color: #888888;
}
.list-left-padding {
padding: 0 0 0 20px !important;
}
.comment-background {
background: rgba(250, 250, 250, 1);
/* padding: 15px; */
border: 1px solid #f4f4f4;
}
.border-bottom-comment {
border-bottom: 1px solid #eee;
}
.comment-background .ant-list-header {
padding: 20px;
}
.comment-background .ant-list-item {
padding: 16px;
}
/* .comment-background .ant-list-split .ant-list-item:last-child{border-bottom: 1px solid #e8e8e8;} */
.border-top-e {
border-top: 1px solid #e8e8e8;
}
.commentStyle {
background-color: #fff !important;
}
.reply-comment-input .add_reply_button {
background-color: #fff !important;
color: #bbb;
width: 100%;
text-align: left;
border: 1px solid rgba(238, 238, 238, 1);
box-shadow: none;
}
.children-comment-bg {
background: rgba(241, 248, 255, 1);
border: 1px solid rgba(238, 238, 238, 1);
}
.display-in{
display: inherit;
}
.issue-form-right .ant-form-item{
margin-bottom: 8px !important;
}
.issue-form-right .ant-row label{font-size: 14px !important; font-weight: 500;}
.issue-edit-form-right{margin-bottom: 0 !important;}
.plr10{padding: 0 10px;}
.issue-form-index .editormd-toolbar{position: absolute !important;}

View File

@ -37,7 +37,7 @@ class order extends Component {
assigned_to_id: undefined,
search_count: undefined,
issue_type: undefined,
status_type: undefined,
status_type: "1", // 默认显示开启中的
issue_tag_ids: "标签",
tracker_ids: "类型",
author_ids: "发布人",
@ -55,7 +55,7 @@ class order extends Component {
allValue: [],
all: false,
select_params: {
status_type: undefined, //开启中和关闭中,全部,默认为全部
status_type: "1", //开启中和关闭中,全部,默认为全部
assigned_to_id: undefined, // 负责人
author_id: undefined, // 发布人
issue_tag_id: undefined, // 标签

View File

@ -0,0 +1,604 @@
import React, { Component } from "react";
import { Form, Input, Select, Button, DatePicker, Switch } from "antd";
import Upload from "../Upload/Index";
import UploadImg from "../Images/upload.png";
import MDEditor from "../../modules/tpm/challengesnew/tpm-md-editor";
import moment from "moment";
import "./order.css";
import Attachments from "../Upload/attachment";
import axios from "axios";
const Option = Select.Option;
class order_form extends Component {
constructor(props) {
super(props);
this.state = {
branch_name: "",
issue_tag_ids: "",
fixed_version_id: "",
tracker_id: "缺陷",
issue_type: "1",
status_id: "新增",
assigned_to_id: "",
priority_id: "正常",
done_ratio: "0%",
issue_chosen: undefined,
branches: undefined,
fileList: undefined,
description: undefined,
isSpin: false,
token: undefined,
start_date: "",
due_date: "",
subject: "",
get_attachments: undefined,
show_token: false,
};
}
componentDidMount = () => {
this.getSelectList();
this.get_detail();
};
get_detail = () => {
const { form_type } = this.props;
if (form_type === "new") {
this.InitData();
this.getSelectList();
} else {
this.state.isSpin = true;
const { projectsId, orderId } = this.props.match.params;
const url = `/projects/${projectsId}/issues/${orderId}/edit.json`;
axios
.get(url)
.then((result) => {
if (result) {
this.setState(
{
branch_name: result.data.branch_name,
issue_tag_ids: [
result.data.issue_tags && result.data.issue_tags[0].id
? String(
result.data.issue_tags && result.data.issue_tags[0].id
)
: "",
],
fixed_version_id: result.data.fixed_version_id
? String(result.data.fixed_version_id)
: "",
tracker_id: result.data.tracker_id
? String(result.data.tracker_id)
: "",
issue_type: result.data.issue_type,
status_id: result.data.status_id
? String(result.data.status_id)
: "",
assigned_to_id: result.data.assigned_to_id
? String(result.data.assigned_to_id)
: "",
priority_id: result.data.priority_id
? String(result.data.priority_id)
: "",
done_ratio: result.data.done_ratio,
fileList: undefined,
description: result.data.description,
isSpin: false,
token: result.data.token,
get_attachments: result.data.attachments,
start_date: result.data.start_date,
due_date: result.data.due_date,
subject: result.data.subject,
},
() => this.InitData()
);
}
})
.catch((error) => {
this.state.isSpin = false;
console.log(error);
});
}
};
InitData = () => {
// this.props.form.setFieldsValue({
// ...this.state,
// });
};
getSelectList = () => {
let projectsId = "";
if (this.props.match.params.milepostId) {
projectsId = this.props.match.params.projectsId;
this.props.form.setFieldsValue({
fixed_version_id: this.props.match.params.milepostId,
});
} else {
projectsId = this.props.match.params.projectsId;
}
const url = `/projects/${projectsId}/issues/new.json`;
axios
.get(url)
.then((result) => {
if (result) {
this.setState({
issue_chosen: result.data.issue_chosen,
branches: result.data.branches,
});
}
})
.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>
);
});
}
};
// 创建
handleSubmit = () => {
this.setState({
isSpin: true,
});
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
const { form_type } = this.props;
const { projectsId, orderId } = this.props.match.params;
// const { projectsId } = this.props.match.params;
const { fileList } = this.state;
if (values.status_id === "新增") {
values.status_id = "1";
}
if (values.tracker_id === "缺陷") {
values.tracker_id = "1";
}
if (values.priority_id === "正常") {
values.priority_id = "2";
}
if (values.done_ratio === "0%") {
values.done_ratio = "0";
}
if (values.issue_tag_ids.length > 0) {
values.issue_tag_ids = [values.issue_tag_ids];
}
const { description, start_date, due_date, issue_type } = this.state;
if (form_type === "new") {
const url = `/projects/${projectsId}/issues.json`;
axios
.post(url, {
...values,
description: description,
attachment_ids: fileList,
start_date: start_date,
due_date: due_date,
issue_type: issue_type,
})
.then((result) => {
if (result) {
this.props.showNotification("任务创建成功!");
this.props.history.push(`/projects/${projectsId}/orders`);
this.setState({
description: "",
isSpin: false,
});
const { getDetail } = this.props;
getDetail && getDetail();
}
})
.catch((error) => {
this.setState({
isSpin: false,
});
console.log(error);
});
} else {
const url = `/projects/${projectsId}/issues/${orderId}.json`;
axios
.put(url, {
description: description,
attachment_ids: fileList,
start_date: start_date,
due_date: due_date,
issue_type: issue_type,
...values,
})
.then((result) => {
if (result) {
this.props.history.push(
`/projects/${projectsId}/orders/${orderId}/detail`
);
this.props.showNotification("任务更新成功!");
}
})
.catch((error) => {
this.setState({
isSpin: false,
});
console.log(error);
});
}
}
this.setState({
isSpin: false,
});
});
};
// 获取上传后的文件id数组
UploadFunc = (fileList) => {
this.setState({
fileList,
});
};
onContentChange = (value) => {
this.setState({
description: value,
});
};
// 修改开始时间
changeBeginTime = (start_date, value) => {
this.setState({
start_date: value,
});
};
changeEndTime = (due_date, value) => {
this.setState({
due_date: value,
});
};
// 切换完成度
changeRatio = (e) => {
if (e === "0") {
this.props.form.setFieldsValue({
status_id: "1",
});
this.setState({
status_id: "1",
});
} else if (e === "100") {
this.props.form.setFieldsValue({
status_id: "3",
});
this.setState({
status_id: "3",
});
} else {
this.props.form.setFieldsValue({
status_id: "2",
});
this.setState({
status_id: "2",
});
}
};
//切换状态
changeStatus = (e) => {
if (e === "1") {
this.props.form.setFieldsValue({
done_ratio: "0",
});
this.setState({
done_ratio: "0",
});
} else if (e === "3") {
this.props.form.setFieldsValue({
done_ratio: "100",
});
this.setState({
done_ratio: "100",
});
}
};
//切换是否上链操作
change_issue_type = (e) => {
if (e) {
this.setState({
issue_type: "2",
show_token: true,
});
} else {
this.setState({
issue_type: "1",
show_token: false,
});
}
};
render() {
const { getFieldDecorator } = this.props.form;
const projectsId = this.props.match.params.projectsId;
const { orderId } = this.props.match.params;
const { form_type } = this.props;
const {
issue_tag_ids,
fixed_version_id,
branch_name,
status_id,
tracker_id,
issue_type,
assigned_to_id,
priority_id,
done_ratio,
issue_chosen,
branches,
subject,
description,
get_attachments,
isSpin,
start_date,
due_date,
token,
show_token,
} = this.state;
return (
<div className="ProjectListIndex issue-form-index">
<Form className="width100 display-in" size="small">
<div className="list-right">
<div className="pd20">
<h3 className="mb15">
{form_type === "new" ? "新建" :( form_type === "copy" ? "复制" : "编辑")}任务
</h3>
<Form.Item>
{getFieldDecorator("subject", {
rules: [
{
required: true,
message: "请填写任务标题",
},
],
initialValue: subject,
})(<Input placeholder="标题" size="large" />)}
</Form.Item>
<div className="quillContent">
<MDEditor
placeholder={"请输入描述信息"}
height={500}
mdID={"order-new-description"}
initValue={description}
onChange={this.onContentChange}
></MDEditor>
</div>
{get_attachments && get_attachments.length > 0 ? (
<div className="mt20">
<Attachments
attachments={get_attachments}
showNotification={this.props.showNotification}
canDelete={true}
/>
</div>
) : (
""
)}
<Upload
className="commentStyle mt30"
isComplete={true}
load={this.UploadFunc}
icon={
<img
src={UploadImg}
width="58"
alt=""
style={{ marginBottom: 15 }}
/>
}
size={100}
showNotification={this.props.showNotification}
/>
<p className="clearfix mt20 text-right">
<Button
type="primary"
loading={isSpin}
onClick={this.handleSubmit}
size="large"
>
<span className="plr10">
{form_type === "new" ? "创建" : "提交"}
</span>
</Button>
<Button
type="default"
className="ml30"
href={
form_type === "new"
? `/projects/${projectsId && orderId}/orders` : `/projects/${projectsId}/orders/${orderId && orderId}/detail`
}
size="large"
>
<span className="plr10">取消</span>
</Button>
</p>
</div>
</div>
<div className="list-left list-left-padding issue-edit-form-right">
<div className="pd20 background-f issue-form-right">
<Form.Item>
{getFieldDecorator("branch_name", {
rules: [],
initialValue: branch_name,
})(
<Select>
<Option value={""}>分支未指定</Option>
{branches &&
branches.length > 0 &&
branches.map((item, key) => {
return (
<Option value={item} key={key}>
{item}
</Option>
);
})}
</Select>
)}
</Form.Item>
<Form.Item label="状态">
{getFieldDecorator("status_id", {
rules: [
{
required: true,
message: "请选择完成状态",
},
],
initialValue: status_id,
})(
<Select onChange={this.changeStatus}>
{this.renderSelect(
issue_chosen && issue_chosen.issue_status
)}
</Select>
)}
</Form.Item>
<Form.Item label="类型">
{getFieldDecorator("tracker_id", {
rules: [
{
required: true,
message: "请选择类型",
},
],
initialValue: tracker_id,
})(
<Select>
{this.renderSelect(issue_chosen && issue_chosen.tracker)}
</Select>
)}
</Form.Item>
<Form.Item label="优先度">
{getFieldDecorator("priority_id", {
rules: [
{
required: true,
message: "请选择优先度",
},
],
initialValue: priority_id,
})(
<Select>
{this.renderSelect(issue_chosen && issue_chosen.priority)}
</Select>
)}
</Form.Item>
<Form.Item label="完成度">
{getFieldDecorator("done_ratio", {
rules: [
{
required: true,
message: "请选择完成度",
},
],
initialValue: done_ratio,
})(
<Select onChange={this.changeRatio}>
{this.renderSelect(issue_chosen && issue_chosen.done_ratio)}
</Select>
)}
</Form.Item>
<Form.Item label="里程碑">
{getFieldDecorator("fixed_version_id", {
rules: [],
initialValue: fixed_version_id,
})(
<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("issue_tag_ids", {
rules: [],
initialValue: issue_tag_ids,
})(
<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("assigned_to_id", {
rules: [{}],
initialValue: assigned_to_id,
})(
<Select>
<Option value={""}>未指派成员</Option>
{this.renderSelect(
issue_chosen && issue_chosen.assign_user
)}
</Select>
)}
</Form.Item>
<Form.Item label="开始日期">
<DatePicker
value={start_date ? moment(start_date, "YYYY-MM-DD") : null}
style={{ width: "100%" }}
placeholder="请选择开始日期"
onChange={this.changeBeginTime}
/>
</Form.Item>
<Form.Item label="结束日期">
<DatePicker
value={due_date ? moment(due_date, "YYYY-MM-DD") : null}
style={{ width: "100%" }}
placeholder="请选择结束日期"
onChange={this.changeEndTime}
/>
</Form.Item>
<Form.Item label="是否上链">
<Switch
checkedChildren="是"
unCheckedChildren="否"
defaultChecked={false}
checked={issue_type && issue_type === "2"}
onChange={this.change_issue_type}
/>
</Form.Item>
{(show_token || (issue_type && issue_type === "2")) && (
<Form.Item label="token">
{getFieldDecorator("token", {
rules: [
{
required: true,
message: "请填写token值",
},
],
initialValue: token,
})(<Input placeholder="请填写token值" />)}
</Form.Item>
)}
</div>
</div>
</Form>
</div>
);
}
}
const WrappedNewForm = Form.create({ name: "NewOrderForm" })(order_form);
export default WrappedNewForm;

View File

@ -47,11 +47,11 @@ class Attachment extends Component{
<div>
{
attachments ?
<div className="attachmentsList">
<div className="attachmentsList mt20">
{
attachments.map((item,key)=>{
return(
<div key= {key} style={{display: (Deleted.length > 0 && Deleted.indexOf(item.id) !== -1) ? "none" : "block"}} className="mt10 attachment-list-div" >
<div key= {key} style={{display: (Deleted.length > 0 && Deleted.indexOf(item.id) !== -1) ? "none" : "block"}} className="pd510 attachment-list-div" >
<Link to={`${item.url}`} target="_blank" className="attachment-list-a">
<i className="iconfont icon-fujian mr8 paper-clip-color font-12"></i>
<span>{item.title}</span>

View File

@ -1,6 +1,6 @@
import React, { Component } from "react";
import axios from "axios";
import { Spin, Button } from "antd";
import { Button } from "antd";
import "./list.css";
class FocusButton extends Component {
@ -10,6 +10,9 @@ class FocusButton extends Component {
is_watch: false,
id: "",
isSpin: false,
fontClass: "font-12",
starText: "关注",
is_block: false
};
}
@ -22,6 +25,9 @@ class FocusButton extends Component {
is_watch: this.props.is_watch,
id: this.props.id,
isSpin: false,
fontClass: this.props.fontClass ? this.props.fontClass : "font-12",
starText: this.props.starText ? this.props.starText : "关注",
is_block: this.props.is_block === undefined ? false : this.props.is_block
});
};
@ -46,23 +52,24 @@ class FocusButton extends Component {
}
})
.catch((error) => {
this.setState({isSpin: false})
console.log(error);
});
};
render() {
const { is_watch, isSpin } = this.state;
const { is_watch, isSpin,fontClass,starText,is_block } = this.state;
return (
<Button loading={isSpin} onClick={() => this.focusFunc(is_watch)}>
<Button block={is_block} loading={isSpin} onClick={() => this.focusFunc(is_watch)}>
{is_watch ? (
<span className="">
<i className="iconfont icon-shixing font-15 text-yellow mr-4"></i>
<span className="font-12">已关注</span>
<span className={fontClass}>已关注</span>
</span>
) : (
<span className="">
<i className="iconfont icon-kongxing font-15"></i>
<span className="font-12">关注</span>
<span className={fontClass}>{starText}</span>
</span>
)}
</Button>

View File

@ -0,0 +1,206 @@
import React, { Component } from "react";
import { Link } from "react-router-dom";
import axios from "axios";
import { getImageUrl } from "educoder";
import { List, Popconfirm, Pagination, Button } from "antd";
import Attachments from "../Upload/attachment";
import RenderHtml from "../../components/render-html";
import "../Order/order.css";
class children_comments extends Component {
constructor(props) {
super(props);
this.state = {
journalsdata: undefined,
limit: 10,
page: 1,
journal_spin: false,
search_count: 0,
};
}
componentDidMount() {
this.getChildrenJournals();
}
componentDidUpdate(prevProps, prevState) {
if (this.props.children_comment_id) {
if (prevProps.children_comment_id !== this.props.children_comment_id)
this.getChildrenJournals();
}
}
//获取评论信息
getChildrenJournals = (i_order_id, i_parentId) => {
const { order_id, parent_id } = this.props;
const { page, limit } = this.state;
let new_order_id = i_order_id ? i_order_id : order_id;
let new_parent_id = i_parentId ? i_parentId : parent_id;
const url = `/issues/${new_order_id}/journals/${new_parent_id}/get_children_journals.json`;
axios
.get(url, {
params: {
page,
limit,
},
})
.then((result) => {
if (result) {
this.setState({
journalsdata: result.data,
search_count: result.data.journals_count,
isSpin: false,
});
}
})
.catch((error) => {
console.log(error);
});
};
//删除评论
deleteorder = (id) => {
const { order_id } = this.props;
const url = `/issues/${order_id}/journals/${id}.json`;
axios
.delete(url, {
data: {
issue_id: order_id,
id: id,
},
})
.then((result) => {
if (result) {
this.getChildrenJournals();
}
})
.catch((error) => {
console.log(error);
});
};
// 翻页
ChangePage = (page) => {
this.state.page = page;
this.state.isSpin = true;
this.getChildrenJournals();
};
commentCtx = (v) => {
return <RenderHtml className="break_word_comments" value={v} />;
};
render() {
const {
journalsdata,
page,
limit,
search_count,
isSpin,
parent_id,
} = this.state;
const { current_user } = this.props;
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 = (item) => {
return (
<div className="width100">
<div className="grid-item pb10">
<Link
to={`/users/${item && item.user_login}/projects`}
className="show-user-link"
>
<img
className="radius"
src={getImageUrl(`images/${item && item.user_picture}`)}
alt=""
width="30"
height="30"
/>
</Link>
<span className="grid-item">
<span>
<Link
to={`/users/${item && item.user_login}/projects`}
className="show-user-link color-blue ml10"
>
{item && item.user_name}
</Link>
<span className="color-grey-8 ml20">{item.created_at}</span>
</span>
<span className="text-right">
{current_user &&
(current_user.admin ||
current_user.login === item.user_login) ? (
<Popconfirm
placement="bottom"
title={"确定要删除当前评论吗?"}
okText="是"
cancelText="否"
onConfirm={() => this.deleteorder(item.id)}
>
<Button type="link">
<i className="iconfont icon-shanchu font-15 color-grey-6"></i>
</Button>
</Popconfirm>
) : (
""
)}
</span>
</span>
</div>
<div className="ml30">
{this.commentCtx(item.content)}
{item && item.attachments && 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>
);
};
return (
<div>
{search_count > 0 && (
<div className="children-comment-bg">
<List
size="large"
loading={isSpin}
dataSource={journalsdata.issue_journals}
renderItem={(item) => <List.Item>{renderList(item)}</List.Item>}
/>
{Paginations}
</div>
)}
</div>
);
}
}
export default children_comments;

View File

@ -0,0 +1,175 @@
import React, { Component } from "react";
import { Link } from "react-router-dom";
import axios from "axios";
import { getImageUrl } from "educoder";
import { List, Popconfirm, Pagination, Button } from "antd";
import Attachments from "../Upload/attachment";
// import MDEditor from "../../modules/tpm/challengesnew/tpm-md-editor";
import RenderHtml from "../../components/render-html";
import "../Order/order.css";
class children_journals extends Component {
constructor(props) {
super(props);
this.state = {
journalsdata: this.props.comments,
limit: 10,
page: 1,
journal_spin: false,
search_count: this.props.comments && this.props.comments.journals_count,
orderId: this.props.order_id,
parent_id: this.props.parent_id
};
}
//删除评论
deleteorder = (id) => {
const { orderId, parent_id, page, limit } = this.state;
const url = `/issues/${orderId}/journals/${id}.json`;
axios
.delete(url, {
data: {
issue_id: orderId,
id: id,
},
})
.then((result) => {
if (result) {
this.props.getChildrenJournals(orderId,parent_id,1,limit);
// this.getChildrenJournals();
}
})
.catch((error) => {
console.log(error);
});
};
// 翻页
ChangePage = (page) => {
const { orderId, parent_id, limit } = this.state;
this.state.page = page
this.state.isSpin = true
this.props.getChildrenJournals(orderId,parent_id,page,limit);
// this.getChildrenJournals();
};
commentCtx = (v) => {
return <RenderHtml className="break_word_comments" value={v} />;
};
render() {
const {
journalsdata,
page,
limit,
search_count,
isSpin
} = this.state;
const { current_user } = this.props;
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 = (item) => {
return (
<div className="width100">
<div className="grid-item pb10">
<Link
to={`/users/${item && item.user_login}/projects`}
className="show-user-link"
>
<img
className="radius"
src={getImageUrl(`images/${item && item.user_picture}`)}
alt=""
width="30"
height="30"
/>
</Link>
<span className="grid-item">
<span>
<Link
to={`/users/${item && item.user_login}/projects`}
className="show-user-link color-blue ml10"
>
{item && item.user_name}
</Link>
<span className="color-grey-8 ml20">{item.created_at}</span>
</span>
<span className="text-right">
{current_user &&
(current_user.admin ||
current_user.login === item.user_login) ? (
<Popconfirm
placement="bottom"
title={"确定要删除当前评论吗?"}
okText="是"
cancelText="否"
onConfirm={() => this.deleteorder(item.id)}
>
<Button type="link">
<i className="iconfont icon-shanchu font-15 color-grey-6"></i>
</Button>
</Popconfirm>
) : (
""
)}
</span>
</span>
</div>
<div className="ml30">
{this.commentCtx(item.content)}
{item && item.attachments && 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>
);
};
return (
<div>
{
search_count > 0 &&
<div className="children-comment-bg">
<List
size="large"
loading={isSpin}
dataSource={journalsdata.issue_journals}
renderItem={(item) => <List.Item>{renderList(item)}</List.Item>}
/>
{Paginations}
</div>
}
</div>
);
}
}
export default children_journals;

View File

@ -0,0 +1,518 @@
import React, { Component } from "react";
import { Link } from "react-router-dom";
import axios from "axios";
import Upload from "../Upload/Index";
import UploadImg from "../Images/upload.png";
import { getImageUrl } from "educoder";
import { List, Popconfirm, Pagination, Button } from "antd";
import Attachments from "../Upload/attachment";
import MDEditor from "../../modules/tpm/challengesnew/tpm-md-editor";
import RenderHtml from "../../components/render-html";
import ChildrenComments from "./children_comments";
import "../Order/order.css";
class comments extends Component {
constructor(props) {
super(props);
this.state = {
content: undefined,
journalsdata: undefined,
isedit: undefined,
fileList: undefined,
limit: 10,
page: 1,
journal_spin: false,
edit_spin: false,
attachment_clean: true,
orderId: this.props.order_id,
is_reply: false,
reply_id: undefined,
reply_content: undefined,
new_journal_id: undefined,
};
}
componentDidMount = () => {
this.getjournalslist();
};
//添加评论
addjournals = () => {
const { content, reply_content } = this.state;
this.setState({
journal_spin: true,
});
if (!content && !reply_content) {
this.setState({
journal_spin: false,
});
return;
}
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
const {
page,
limit,
fileList,
orderId,
reply_id,
is_reply,
} = this.state;
const url = `/issues/${orderId}/journals.json`;
axios
.post(url, {
...values,
content: is_reply ? reply_content : content,
issue_id: orderId,
attachment_ids: fileList,
parent_id: reply_id,
})
.then((result) => {
if (result && result.data.status === 0) {
this.props.form.setFieldsValue({
content: "",
reply_content: undefined,
});
this.setState({
showFiles: false,
content: "",
is_reply: false,
reply_id: undefined,
reply_content: undefined,
quillFlag: false,
journal_spin: false,
attachment_clean: false,
});
this.state.new_journal_id = result.data.id;
this.getjournalslist(page, limit);
}
this.props.showNotification(result.data.message);
})
.catch((error) => {
this.setState({
journal_spin: false,
});
console.log(error);
});
} else {
this.setState({
journal_spin: false,
});
}
});
};
add_reply = (id) => {
this.setState({
is_reply: true,
success_journal: false,
reply_id: id,
});
};
cancel_reply = () => {
this.setState({
is_reply: false,
reply_id: undefined,
success_journal: false,
reply_content: undefined,
});
};
//获取评论信息
getjournalslist = (page, limit) => {
const { orderId } = this.state;
const url = `/issues/${orderId}/journals.json`;
let id = orderId;
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,
});
}
})
.catch((error) => {
console.log(error);
});
};
// 获取上传后的文件id数组
UploadFunc = (fileList) => {
this.setState({
fileList,
attachment_clean: true,
});
};
//删除评论
deleteorder = (id) => {
const { page, limit, orderId } = this.state;
const url = `/issues/${orderId}/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);
});
};
renderJournalList = (list) => {
if (list && list.length > 0) {
return list.map((item, key) => {
return (
<div key={key + 1} className="journal-list-item">
<span className="fwb 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>
);
}
};
// 翻页
ChangePage = (page) => {
this.setState({
page,
isSpin: true,
});
const { limit } = this.state;
this.getjournalslist(page, limit);
};
// 判断是否重新上传文件
changeIsComplete = (flag) => {
this.setState({
showFiles: flag,
});
};
// 新建评论
onContentChange = (value) => {
if (value) {
this.setState({
content: value,
quillFlag: false,
});
}
};
replyContentChange = (value) => {
if (value) {
this.setState({
reply_content: value,
quillFlag: false,
});
}
};
onRef = (ref) => {
this.child = ref;
};
commentCtx = (v) => {
return <RenderHtml className="break_word_comments" value={v} />;
};
render() {
const {
journalsdata,
page,
limit,
search_count,
isSpin,
content,
quillFlag,
journal_spin,
attachment_clean,
is_reply,
reply_id,
reply_content,
orderId,
new_journal_id,
} = this.state;
const { current_user } = this.props;
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 new_comment = (is_reply, item_id) => {
return (
<div>
{current_user && current_user.login ? (
<div>
<div className="grid-item pb10">
<Link
to={`/users/${current_user && current_user.login}/projects`}
className="show-user-link"
>
<img
className="radius"
src={getImageUrl(
`images/${current_user && current_user.image_url}`
)}
alt=""
width="30"
height="30"
/>
</Link>
<Link
to={`/users/${current_user && current_user.login}/projects`}
className="show-user-link color-blue ml10"
>
{current_user && current_user.real_name}
</Link>
</div>
<MDEditor
placeholder={"添加评论..."}
height={200}
mdID={
item_id
? "orderdetail-add-descriptions" + item_id
: "orderdetail-add-descriptions"
}
initValue={is_reply ? reply_content : content}
onChange={
is_reply ? this.replyContentChange : this.onContentChange
}
></MDEditor>
<p className="quillFlag">
{quillFlag && <span className="">请输入评论内容</span>}
</p>
<Upload
className="commentStyle"
isComplete={attachment_clean}
load={this.UploadFunc}
icon={
<img
src={UploadImg}
width="58"
alt=""
style={{ marginBottom: 15 }}
/>
}
size={100}
showNotification={this.props.showNotification}
/>
<p className="clearfix mt20 text-right">
{is_reply && (
<Button
onClick={this.cancel_reply}
size="large"
className="mr15"
>
取消
</Button>
)}
<Button
type="primary"
onClick={this.addjournals}
loading={journal_spin}
size="large"
>
评论
</Button>
</p>
</div>
) : (
<div className="loginDiv">
<Link to={`/login`}>登录</Link>
</div>
)}
</div>
);
};
const renderList = (item) => {
return (
<div className="width100">
<div className="grid-item pb10">
<Link
to={`/users/${item && item.user_login}/projects`}
className="show-user-link"
>
<img
className="radius"
src={getImageUrl(`images/${item && item.user_picture}`)}
alt=""
width="30"
height="30"
/>
</Link>
<span className="grid-item">
<span>
<Link
to={`/users/${item && item.user_login}/projects`}
className="show-user-link color-blue ml10"
>
{item && item.user_name}
</Link>
<span className="color-grey-8 ml20">{item.created_at}</span>
</span>
<span className="text-right">
{current_user &&
(current_user.admin ||
current_user.login === item.user_login) ? (
<Popconfirm
placement="bottom"
title={"确定要删除当前评论吗?"}
okText="是"
cancelText="否"
onConfirm={() => this.deleteorder(item.id)}
>
<Button type="link">
<i className="iconfont icon-shanchu font-15 color-grey-6"></i>
</Button>
</Popconfirm>
) : (
""
)}
</span>
</span>
</div>
<div className="ml30">
{item.content ? (
this.commentCtx(item.content)
) : (
<div>{this.renderJournalList(item.journal_details)}</div>
)}
{item && item.attachments && item.attachments.length > 0 ? (
<Attachments
attachments={item.attachments}
showNotification={this.props.showNotification}
canDelete={
current_user &&
(current_user.admin || current_user.login === item.user_login)
}
/>
) : (
""
)}
<ChildrenComments
order_id={orderId}
parent_id={item.id}
onRef={this.onRef}
children_comment_id={new_journal_id}
{...this.props}
></ChildrenComments>
</div>
{current_user && (
<div>
{is_reply && reply_id && reply_id === item.id ? (
<div className="pd20">{new_comment(is_reply, item.id)}</div>
) : (
<div className="grid-item mt15">
<Link
to={`/users/${current_user && current_user.login}/projects`}
className="show-user-link mr10"
>
<img
className="radius"
src={getImageUrl(
`images/${current_user && current_user.image_url}`
)}
alt=""
width="30"
height="30"
/>
</Link>
<span className="reply-comment-input">
<Button
className="add_reply_button"
onClick={() => this.add_reply(item.id)}
>
<span>我要回复</span>
</Button>
</span>
</div>
)}
</div>
)}
</div>
);
};
return (
<div className="pd20">
<div className="comment-background">
{journalsdata && journalsdata.journals_total_count > 0 ? (
<List
size="large"
loading={isSpin}
header={<div>回复({journalsdata.journals_total_count})</div>}
dataSource={journalsdata.issue_journals}
renderItem={(item) => <List.Item>{renderList(item)}</List.Item>}
/>
) : (
<div className="ant-list-header border-bottom-comment">
<div>回复({search_count})</div>
</div>
)}
{Paginations}
<div className="pd20 border-top-e">{new_comment()}</div>
</div>
</div>
);
}
}
export default comments;

636
src/forge/comments/new.js Normal file
View File

@ -0,0 +1,636 @@
import React, { Component } from "react";
import { Link } from "react-router-dom";
import axios from "axios";
import Upload from "../Upload/Index";
import UploadImg from "../Images/upload.png";
import { getImageUrl } from "educoder";
import { List } from "antd";
import Attachments from "../Upload/attachment";
import MDEditor from "../../modules/tpm/challengesnew/tpm-md-editor";
import RenderHtml from "../../components/render-html";
import new_comment from "./new"
import "./order.css";
class comments extends Component {
constructor(props) {
super(props);
this.state = {
};
}
componentDidMount = () => {
this.getjournalslist();
};
handleok = () => {
this.setState({
isShow: false,
});
};
handleCancel = () => {
this.setState({
isShow: false,
});
};
imgshow = () => {
this.setState({
isShow: true,
});
};
//添加评论
addjournals = () => {
const { quillValue } = this.state;
this.setState({
journal_spin: true,
});
if (!quillValue) {
this.setState({
quillFlag: true,
journal_spin: false,
});
return;
}
this.props.form.validateFieldsAndScroll((err, values) => {
if (!err) {
const { data, page, limit, fileList } = this.state;
const url = `/issues/${data.id}/journals.json`;
axios
.post(url, {
...values,
content: quillValue,
issue_id: data.id,
attachment_ids: fileList,
})
.then((result) => {
if (result) {
this.props.showNotification("评论成功!");
this.props.form.setFieldsValue({
content: "",
});
this.setState({
showFiles: false,
quillValue: "",
quillFlag: false,
journal_spin: false,
});
this.getjournalslist(page, limit);
}
})
.catch((error) => {
this.setState({
journal_spin: false,
});
console.log(error);
});
} else {
this.setState({
journal_spin: false,
});
}
});
};
//获取评论信息
getjournalslist = (page, limit) => {
const { data } = this.state;
const url = `/issues/${data.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,
});
}
})
.catch((error) => {
console.log(error);
});
};
//修改评论
updatedetail = (id) => {
const { page, limit, countvalue } = this.state;
const { orderId } = this.props.match.params;
this.setState({
edit_spin: true,
});
const url = `/issues/${orderId}/journals/${id}.json`;
axios
.put(url, {
issue_id: orderId,
id: id,
content: countvalue,
})
.then((result) => {
if (result) {
this.setState({
isedit: undefined,
edit_spin: false,
});
this.getjournalslist(page, limit);
}
})
.catch((error) => {
this.setState({
edit_spin: false,
});
console.log(error);
});
};
// 获取上传后的文件id数组
UploadFunc = (fileList) => {
this.setState({
fileList,
});
};
//删除评论
deleteorder = (id) => {
const { orderId } = this.props.match.params;
const { page, limit } = this.state;
const url = `/issues/${orderId}/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);
});
};
editdetail = (count, status) => {
this.setState({
countvalue: this.stringJson(count),
isedit: status,
});
};
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>
);
}
};
// 翻页
ChangePage = (page) => {
this.setState({
page,
isSpin: true,
});
const { limit } = this.state;
this.getjournalslist(page, limit);
};
// 判断是否重新上传文件
changeIsComplete = (flag) => {
this.setState({
showFiles: flag,
});
};
// 新建评论
onContentChange = (value) => {
if (value) {
this.setState({
quillValue: value,
quillFlag: false,
});
}
};
// 编辑评论
onEditContentChange = (value) => {
if (value) {
this.setState({
countvalue: value,
});
}
};
handleShowImage = (value) => {
this.setState({
imageUrl: value,
visible: true,
});
};
setVisible = (flag) => {
this.setState({
visible: flag,
});
};
stringJson = (value) => {
let _value = null;
try {
_value = JSON.parse(value);
} catch (e) {
_value = value;
}
return _value;
};
commentCtx = (v) => {
return <RenderHtml className="break_word_comments" value={v} />;
};
render() {
const { projectsId, orderId } = this.props.match.params;
const {
data,
journalsdata,
page,
limit,
search_count,
isSpin,
isedit,
quillFlag,
countvalue,
edit_spin,
} = this.state;
const { current_user } = this.props;
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}>
{key > 0 && (
<div
className="order_line"
style={{ marginLeft: 80 }}
></div>
)}
<div className="df">
<Link
to={`/users/${item && item.user_login}/projects`}
className="show-user-link"
>
<img
className="user_img"
src={getImageUrl(`images/${item && 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 &&
isedit === undefined &&
(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 &&
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",
}}
>
<div className="quillContent mt20">
<MDEditor
placeholder={"添加评论..."}
autoFocus={true}
height={200}
mdID={`orderdetail-add-description${item.id}`}
startInit={isedit && isedit === item.id}
initValue={countvalue}
onChange={this.onEditContentChange}
></MDEditor>
<p className="quillFlag">
{quillFlag && (
<span className="">请输入评论内容</span>
)}
</p>
</div>
<p className="clearfix mt15">
<Spin spinning={edit_spin}>
<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>
</Spin>
</p>
</div>
</div>
<div style={{ display: this.state.display }}>
<div className="div_line"></div>
</div>
</div>
</div>
</li>
);
})}
</div>
);
}
};
return (
<div className="ProjectListIndex">
</div>
// <div className="main">
// {visible && <AmplifyImg url={imageUrl} visible={visible} setVisible={this.setVisible} />}
// <div>
// <div className="detailContent">
// <p>
// {
// data ?
// <span className="font-20">【{data.issue_classify === "issue" ? (data.tracker ? data.tracker : "缺陷") : "合并请求"}】</span>
// :
// ""
// }
// <span className="font-20" > {data && data.subject}</span>
// </p>
// <p className="mt15 color-grey-c">
// <span className={data && data.issue_status === "关闭" ? "closedetail" : "opendetail"}>{data && data.issue_status === "关闭" ? "关闭中" : "开启中"} </span>
// <span className="ml10 lineH32">
// 由 {data && data.author_name} 于 {data && data.created_at}创建{data && data.journals_count && data.journals_count > 0 ? ` · ${data.journals_count} 条评论` : ""}
// </span>
// {
// data && data.user_permission ?
// <span className="pull-right lineH32">
// <a className="color-blue fr" onClick={this.copydetail}>复制</a>
// <Popconfirm placement="bottom" title={'您确定要删除吗'} okText="是" cancelText="否" onConfirm={() => this.deletedetail(orderId)}>
// <a className="color-blue fr" style={{ marginLeft: 20, marginRight: 20 }}>删除</a>
// </Popconfirm>
// <Link to={`/projects/${projectsId}/orders/${orderId}/updatedetail`} className="color-blue fr">编辑</Link>
// </span>
// :
// ""
// }
// </p>
// </div>
// <div className="f-wrap-between mt20" style={{ alignItems: "flex-start" }}>
// <div className="item-list-right" >
// <div className="df ">
// <Link to={``}><img className="user_img" src={getImageUrl(`images/${data && data.author_picture}`)} alt="" /></Link>
// <div className="detail_context">
// <div className="detail_p">
// {data && data.description && (data.description.length > 0) ? this.commentCtx(data.description) : <span className="color-grey-9 ml3 mr3">没有描述</span>}
// </div>
// {
// data && data.attachments && data.attachments.length > 0 ?
// <Attachments attachments={data.attachments} showNotification={this.props.showNotification} />
// :
// ""
// }
// </div>
// </div>
// <div className="order_line" style={{ marginLeft: 80 }}></div>
// <Spin spinning={isSpin}>
// <ul className="ul_width">
// {renderList()}
// </ul>
// </Spin>
// {Paginations}
// {
// current_user && current_user.login ?
// <React.Fragment>
// <div className="order_line" style={{ marginLeft: 80 }}></div>
// <div className="df">
// <img className="user_img" src={getImageUrl(`images/${current_user && current_user.image_url}`)} alt="" />
// <div className="new_context">
// <div className="quillContent" style={{ marginBottom: "20px" }}>
// <MDEditor placeholder={'添加评论...'} height={200}
// mdID={'orderdetail-add-descriptions'} initValue={quillValue} onChange={this.onContentChange} ></MDEditor>
// <p className="quillFlag">
// {quillFlag && <span className="">请输入评论内容</span>}
// </p>
// </div>
// <UploadComponent load={this.UploadFunc} isComplete={showFiles} changeIsComplete={this.changeIsComplete}></UploadComponent>
// <p className="clearfix mt15">
// <Spin spinning={journal_spin}>
// <a className="topWrapper_btn fr" type="submit" onClick={this.addjournals}>评论</a>
// {
// data && data.user_permission ?
// <a className="Closeor_btn fr" type="submit"
// onClick={() => this.closedetail(data && data.issue_status === "关闭" ? 2 : 5)}>{data && data.issue_status === "关闭" ? "重新开启" : "关闭"}</a>
// :
// ""
// }
// </Spin>
// </p>
// </div>
// </div>
// </React.Fragment>
// :
// <div className="loginDiv"><Link to={`/login`}>登录</Link>并参与到对话中</div>
// }
// </div>
// <div className="list-left DetailRight" style={{ backgroundColor: "#fff" }}>
// <p>
// <span className="span_title">分支</span>
// <span>{
// data && data.branch_name ? data.branch_name : "--"
// }</span>
// </p>
// <p>
// <span className="span_title">标签</span>
// <span>{
// data && data.issue_tags ? <span className="issue-tag-show" style={{ background: data.issue_tags[0].color }}>{data.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.version ? data.version : "--"
// }</span>
// </p>
// <p>
// <span className="span_title">当前状态</span>
// <span>{
// data && data.issue_status ? data.issue_status : "--"
// }</span>
// </p>
// <p>
// <span className="span_title">分类</span>
// <span>{
// data && data.tracker ? data.tracker : "--"
// }</span>
// </p>
// <p>
// <span className="span_title">指派给</span>
// <span>{data && data.assign_user_name ? data.assign_user_name : "--"}</span>
// </p>
// <p>
// <span className="span_title">优先级</span>
// <span>{data && data.priority ? data.priority : "--"}</span>
// </p>
// <p>
// <span className="span_title">完成度</span>
// <span>{data && data.done_ratio ? data.done_ratio : "--"}</span>
// </p>
// </div>
// </div>
// </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>
);
}
}
export default comments;

View File

@ -115,4 +115,5 @@ ul,ol,dl{
}
.ver-middle{
vertical-align: middle;
}
}
.pd510{padding: 5px 10px;}

191
src/forge/users/Infos.js Normal file
View File

@ -0,0 +1,191 @@
import React, { Component } from "react";
import { Link } from "react-router-dom";
import { Avatar, Tag, Button, Pagination, Spin, Dropdown, Menu } from "antd";
import FocusButton from "../UsersList/focus_button";
import axios from "axios";
import { getImageUrl } from "educoder";
import { Route, Switch } from "react-router-dom";
import { withRouter } from "react-router";
import { SnackbarHOC } from "educoder";
import { CNotificationHOC } from "../../modules/courses/common/CNotificationHOC";
import { TPMIndexHOC } from "../../modules/tpm/TPMIndexHOC";
import "./new_user.css";
import "../css/index.css";
import Loadable from "react-loadable";
import Loading from "../../Loading";
import { ImageLayerOfCommentHOC } from "../../modules/page/layers/ImageLayerOfCommentHOC";
const InfosIndex = Loadable({
loader: () => import("./InfosUser"),
loading: Loading,
});
class Infos extends Component {
constructor(props) {
super(props);
this.state = {
isSpin: false,
user: undefined,
};
}
componentDidMount = () => {
this.fetchUser();
};
fetchUser = () => {
let url = `/users/${this.props.match.params.username}.json`;
axios
.get(url)
.then((result) => {
this.setState({
user: result.data,
});
})
.catch((error) => {
console.log(error);
this.setState({
isSpin: false,
});
});
};
render() {
const { current_user, mygetHelmetapi } = this.props;
const { user } = this.state;
return (
<div className="newMain clearfix">
<div className="new-content-flex">
<div className="list-left">
<div className="bgcF">
<div className="list-l-Menu text-center pd20 ">
<Avatar
size={110}
src={getImageUrl(`images/${user && user.image_url}`)}
/>
{user && user.user_identity && (
<div className="mt-n15 position-relative">
<Tag color="#FF6E21">{user && user.user_identity}</Tag>
</div>
)}
<div>
{user && current_user && user.login === current_user.login && (
<div className="user-info-star-button ">
<Button
block
className="text-button-grey"
href={`${
mygetHelmetapi && mygetHelmetapi.new_course.edit_account
}`}
target="_blank"
>
{" "}
<i className="iconfont icon-shezhi4 font-15 mr5"></i>
修改资料
</Button>
</div>
)}
{current_user && user && user.login !== current_user.login && (
<div className="user-info-star-button ">
<FocusButton
is_block={true}
is_watch={user.is_watch}
id={user.login}
fontClass={"font-14 ml5"}
starText={"关注TA"}
/>
</div>
)}
</div>
<div className="width100 inline-block mt20">
<Link
to={`/users/${user && user.login}/watchings`}
className="with50 text-center pull-left"
>
<div>我关注的</div>
<span>{user && user.watching_count}</span>
</Link>
<Link
to={`/users/${user && user.login}/watched`}
className="with50 text-center pull-left"
>
<div>关注我的</div>
<span>{user && user.watched_count}</span>
</Link>
</div>
</div>
</div>
{current_user && user && current_user.id === user.id && (
<div className="bgcF">
<div className="list-l-Menu">
<p className="list-l-p pd20">
<span className="font-16 fwb">
<i className="iconfont icon-dahuizhongzuo3x font-15 mr5"></i>
待办事项
</span>
<span className="text-yellow font-16">
{user.undo_events}
</span>
</p>
</div>
</div>
)}
<div className="bgcF">
<ul class="list-l-Menu">
<li class="MenuTitle fwb">
<i class="iconfont icon-xiangmuleixing font-15 mr5"></i>
项目类型
</li>
<li class="active">
<p>
<span class="font-16">托管项目</span>
<span class="color-blue">3773</span>
</p>
</li>
<li class="">
<p>
<span class="font-16">镜像项目</span>
<span class="color-blue">3</span>
</p>
</li>
</ul>
</div>
<div className="bgcF">
<div className="list-l-Menu">
<p className="list-l-p pd20">
<span className="font-16 fwb">
<i className="iconfont icon-itsm-liuchengguanli font-15 mr5"></i>
组织
</span>
<span className="color-blue font-16">
{user && user.undo_events}
</span>
</p>
</div>
</div>
</div>
<div className="list-right">
<Switch {...this.props}>
<Route
path="/users/:username/projects"
render={(props) => {
return <InfosIndex {...this.props} {...this.state} />;
}}
></Route>
</Switch>
</div>
</div>
</div>
);
}
}
export default withRouter(
ImageLayerOfCommentHOC({
imgSelector: ".imageLayerParent img, .imageLayerParent .imageTarget",
parentSelector: ".newMain",
})(CNotificationHOC()(SnackbarHOC()(TPMIndexHOC(Infos))))
);

View File

@ -0,0 +1,105 @@
import React, { Component } from "react";
// import { SnackbarHOC } from 'educoder';
import { Link } from "react-router-dom";
import { Avatar, Tag, Button, Pagination, Spin, Dropdown, Menu } from "antd";
import FocusButton from "../UsersList/focus_button";
import axios from "axios";
import { getImageUrl } from "educoder";
import NoneData from "../Nodata";
// import "./new_user.css";
import "../css/index.css";
class InfosUser extends Component {
constructor(props) {
super(props);
this.state = {
category: undefined,
status: undefined,
page: 1,
per_page: 16,
sort_by: "updated_on",
sort_direction: "desc",
totalCount: undefined,
data: undefined,
isSpin: false,
};
}
componentDidMount = () => {
};
//切换种类
changeCategory = (cate) => {
this.setState({
category: cate,
page: 1,
isSpin: true,
});
let { status, sort_by, sort_direction } = this.state;
this.getCourses(cate, status, 1, sort_by, sort_direction);
};
//切换状态
changeStatus = (status) => {
this.setState({
status: status,
page: 1,
isSpin: true,
});
let { category, sort_by, sort_direction } = this.state;
this.getCourses(category, status, 1, sort_by, sort_direction);
};
//切换页数
changePage = (page) => {
this.setState({
page,
isSpin: true,
});
let { category, status, sort_by, sort_direction } = this.state;
this.getCourses(category, status, page, sort_by, sort_direction);
};
//切换种类
updatedlist(sort_by) {
//按照什么样子排序
this.setState({
isSpin: true,
});
let { category, status, page, sort_direction } = this.state;
this.getCourses(category, status, 1, sort_by, "desc");
}
//排序
updatedlists(sort_directions) {
//是否是倒序
this.setState({
isSpin: true,
});
let { category, status, page, sort_by, sort_direction } = this.state;
let sort_directiony = sort_directions;
if (sort_directions === "asc") {
if (sort_directions === sort_direction) {
sort_directiony = "desc";
}
} else if (sort_directions === "desc") {
if (sort_directions === sort_direction) {
sort_directiony = "asc";
}
}
this.getCourses(category, status, page, sort_by, sort_directiony);
}
render() {
return (
<div>
ddddd
</div>
);
}
}
export default InfosUser;

View File

@ -0,0 +1,101 @@
.new-content-flex{
width: 1200px;
margin: 20px auto;
display: -ms-flexbox;
display: flex;
-ms-flex-align: start;
align-items: flex-start;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
}
.list-left{
width: 26%;
padding-right: 20px;
box-sizing: border-box;
margin-bottom: 20px;
}
.list-right{
width:74%;
background: #fff;
padding:10px;
}
.list-l-Menu{
margin-bottom: 12px;
border-radius:2px;
background-color: #fff;
}
.list-l-Menu>li{
font-size: 1rem;
padding:0px 0px 0px 20px;
box-sizing: border-box;
position: relative;
}
.list-l-Menu>li > p{
height: 62px;
line-height: 62px;
width: 100%;
border-bottom: 1px solid #eee;
display: flex;
justify-content: space-between;
cursor: pointer;
padding-right: 20px;
}
.list-l-Menu>li:last-child > p{
border-bottom: none;
}
.list-l-Menu li p span:last-child{
color: #999;
}
.list-l-Menu .MenuTitle{
font-size: 16px;
background-size: 100% 100%;
height: 62px;
line-height: 62px;
border-bottom: 1px solid #E0E0E0;
}
.list-l-Menu > li:not(.MenuTitle):hover{
background-color: #fafafa;
}
/* 左侧menu */
.list-l-Menu .ant-menu-inline{
border:none;
}
.list-l-Menu .ant-menu-inline .ant-menu-item{
width:100%!important;
}
.list-l-Menu .ant-menu-item-group-title{
padding:0px;
}
.list-l-Menu li.active{
background-color: #fafafa;
}
.list-l-Menu li.active::before{
position: absolute;
left: 0px;
top: 10px;
width: 6px;
content: '';
height: 33px;
background: #4CACFF;
}
.text-center{text-align: center;}
.mt-n15{margin-top: -15px;}
.position-relative{position: relative;}
.mr-5{margin-right: 5px;}
a.text-button-grey{
color: rgba(0, 0, 0, 0.65)
}
.user-info-star-button{margin: 20px 50px 0 50px}
.list-l-p{
width: 100%;
display: -ms-flexbox;
display: flex;
-ms-flex-pack: justify;
justify-content: space-between;
cursor: pointer;
padding-right: 20px;
}
.fwb {
font-weight: bold;
}

View File

@ -922,12 +922,13 @@ class NewHeader extends Component {
</a>
<ul className="edu-menu-list" style={{ top: '46px', 'textAlign': 'center' }}>
<li className="bor-bottom-greyE">
<a href="javascript:void(0)" className="fs12 hide-1 task-hide edu-txt-w80">{user.username}</a>
<a href={`/users/${this.props.current_user.login}`}>个人中心</a>
{/* <a href="javascript:void(0)" className="fs12 hide-1 task-hide edu-txt-w80">{user.username}</a> */}
</li>
{
{/* {
mygetHelmetapi2 && mygetHelmetapi2.new_course && mygetHelmetapi2.new_course.edit_account &&
<li><a href={`${mygetHelmetapi2.new_course.edit_account}`} target="_blank">修改资料</a></li>
}
} */}
{
mygetHelmetapi2 && mygetHelmetapi2.new_course && mygetHelmetapi2.new_course.my_courses &&
<li><a href={`${mygetHelmetapi2.new_course.my_courses}`} target="_blank">我的课程</a></li>

View File

@ -96,7 +96,7 @@ body>.-task-title {
}
.newContainer {
background: #fafafa !important;
background: #EAEBEC !important;
}
.ant-modal-title {

View File

@ -581,7 +581,7 @@ export function TPMIndexHOC(WrappedComponent) {
}
render() {
let { Headertop, Footerdown, isRender, AccountProfiletype, AccountPhoneemailtype } = this.state;
let { Headertop, Footerdown, isRender, AccountProfiletype, AccountPhoneemailtype, current_user } = this.state;
const common = {
isSuperAdmin: this.isSuperAdmin,
isAdminOrCreator: this.isAdminOrCreator,

View File

@ -75,14 +75,14 @@ function md_elocalStorage(editor, mdu, id) {
}
export default ({ mdID, onChange, onCMBeforeChange, onCMBlur, error = false, className = '', noStorage = false, imageExpand = true, placeholder = '', width = '100%', height = 400, initValue = '', emoji, watch, showNullButton = false, showResizeBar = false, startInit = true }) => {
export default ({ mdID,onChange,autoFocus,onCMBeforeChange, onCMBlur, error = false, className = '', noStorage = false, imageExpand = true, placeholder = '', width = '100%', height = 400, initValue = '', emoji, watch, showNullButton = false, showResizeBar = false, startInit = true }) => {
const editorEl = useRef()
const resizeBarEl = useRef()
const [editorInstance, setEditorInstance] = useState()
const containerId = `mdEditor_${mdID}`
const editorBodyId = `mdEditors_${mdID}`
const tipId = `e_tips_mdEditor_${mdID}`
const tipId = `e_tips_mdEditor_${mdID}`
function onLayout() {
let ro
@ -92,7 +92,10 @@ export default ({ mdID, onChange, onCMBeforeChange, onCMBlur, error = false, cla
if (entry.target.offsetHeight > 0 || entry.target.offsetWidth > 0) {
editorInstance.resize()
editorInstance.cm.refresh()
editorInstance.cm.focus()
// if(autofocus){
// editorInstance.cm.focus()
// }
}
}
})
@ -102,6 +105,7 @@ export default ({ mdID, onChange, onCMBeforeChange, onCMBlur, error = false, cla
}
useEffect(() => {
if (editorInstance) {
return
}
@ -120,7 +124,7 @@ export default ({ mdID, onChange, onCMBeforeChange, onCMBlur, error = false, cla
searchReplace: true,
htmlDecode: "style,script,iframe",
sequenceDiagram: true,
autoFocus: false,
autoFocus: autoFocus === undefined ? false : autoFocus,
watch: watch === undefined ? true : watch,
saveHTMLToTextarea: true,