dev_forge
Jasder 5 years ago
commit c250aac0dd

@ -166,6 +166,7 @@ class IssuesController < ApplicationController
author_id: current_user.id,
project_id: @project.id
}
@issue = Issue.new(issue_params)
if @issue.save!
if params[:attachment_ids].present?
@ -174,6 +175,7 @@ class IssuesController < ApplicationController
unless attachment.blank?
attachment.container = @issue
attachment.author_id = current_user.id
attachment.description = ""
attachment.save
end
end
@ -243,6 +245,7 @@ class IssuesController < ApplicationController
unless attachment.blank?
attachment.container = @issue
attachment.author_id = current_user.id
attachment.description = ""
attachment.save
end
end
@ -400,4 +403,4 @@ class IssuesController < ApplicationController
end
tracker_array
end
end
end

@ -24,6 +24,7 @@ json.be_depended_issues @be_depended_issues_array
json.depended_issues @depended_issues_array
json.issue_classify @issue.issue_classify
json.branch_name @issue.branch_name
json.journals_count @issue.get_journals_size
json.attachments do
json.array! @issue_attachments do |attachment|
json.partial! "attachments/attachment_simple", locals: {attachment: attachment}

@ -1,4 +1,32 @@
defaults: &defaults
default: &default
# 用户登入的时候设置/登出的时候清空
autologin_cookie_name: 'autologin_trustie'
#附件上传路径
attachment_folder: '/tmp'
# webssh相关
tomcat_webssh: 'https://testwebssh.educoder.net'
webssh_username: 'root'
webssh_password: '123123'
# git服务地址
git_address_ip: 'http://10.9.73.116:8891'
#新版git服务地址
git_address_domain: 'http://testbdgit2.educoder.net'
# git管理员用户名问题, 适用于git客户端的操作
git_username: 'edugit'
git_password: 'xinedugit#'
ucloud:
public_key: 'z7AAP5vtgm8UsbLIfbHodzb+iqH2vPz0sqK+jS4Kx7Nt9D6SgpLkKA=='
private_key: 'f3cb7907a54957953aebb32508b853934a9d3e91'
public_bucket: 'educoer'
public_bucket_host: 'http://educoer.cn-bj.ufileos.com'
public_cdn_host: 'http://educoer.ufile.ucloud.com.cn'
oauth:
qq:
appid: 'test'
@ -8,25 +36,50 @@ defaults: &defaults
secret: 'test'
scope: 'snsapi_login'
base_url: 'https://api.weixin.qq.com'
aliyun_vod:
access_key_id: 'test'
access_key_secret: 'test'
base_url: 'http://vod.cn-shanghai.aliyuncs.com'
cate_id: '-1'
callback_url: 'http://47.96.87.25:48080/api/callbacks/aliyun_vod.json'
signature_key: 'test12345678'
wechat:
appid: 'test'
secret: 'test'
weapp:
appid: 'test'
secret: 'test'
aliyun_vod:
access_key_id: 'test'
access_key_secret: 'test'
base_url: 'http://vod.cn-shanghai.aliyuncs.com'
cate_id: '-1'
callback_url: 'http://47.96.87.25:48080/api/callbacks/aliyun_vod.json'
signature_key: 'test12345678'
gitea:
access_key_id: 'root'
access_key_secret: '_Trustie_10010'
domain: 'https://testgitea.trustie.net'
base_url: '/api/v1'
production:
<<: *default
# 中间层地址
#同步到trustie的token和url
sync_token: "34c82f51e0b699d9d16d70fd6497c9b1e4821d6ea3e872558a6537a091076b8e"
sync_url: "https://www.trustie.net"
cloud_bridge: 'http://10.9.63.225:8890'
cloud_tomcat_php: 'http://10.9.63.225'
bridge_secret_key: 'priEn3UwXfJs3PmyXnSG'
cookie_domain: '.educoder.net'
attachment_folder: '/home/pdl/eduplus2/files'
host_name: 'https://testeduplus2.educoder.net'
old_edu_host: 'http://testbdweb.educoder.net'
development:
<<: *defaults
<<: *default
#同步到trustie的token和url
sync_token: "34c82f51e0b699d9d16d70fd6497c9b1e4821d6ea3e872558a6537a091076b8e"
sync_url: "http://127.0.0.1:3000"
cloud_bridge: 'http://10.9.63.225:8890'
cloud_tomcat_php: 'http://10.9.63.225'
host_name: 'https://testeduplus2.educoder.net'
old_edu_host: 'http://testbdweb.educoder.net'
test:
<<: *defaults
<<: *default
cloud_tomcat_php: 'http://10.9.63.225'
host_name: 'https://testeduplus2.educoder.net'
old_edu_host: 'http://testbdweb.educoder.net'
production:
<<: *defaults

@ -1,6 +1,6 @@
import React , { Component } from 'react';
import { Menu } from 'antd';
import { getImageUrl } from 'educoder';
import { getImageUrl , markdownToHTML } from 'educoder';
import { Router , Route , Link } from 'react-router-dom';
@ -17,6 +17,7 @@ import axios from 'axios';
* branch:当前分支
* filePath:点击目录时当前目录的路径
* subfileType:保存当前点击目录的文件类型显示目录列表时才显示新建文件如果点击的是文件就不显示新建文件按钮
* readMeContent:根目录下面的readme文件内容
*/
class CoderRootDirectory extends Component{
constructor(props){
@ -27,6 +28,7 @@ class CoderRootDirectory extends Component{
filePath:[],
http_url:undefined,
subFileType:"",
readMeContent:undefined,
branchList:undefined,
fileDetail:undefined,
@ -133,17 +135,43 @@ class CoderRootDirectory extends Component{
renderData=(data)=>{
const rootList = [];
const readMeContent = [];
data && data.map((item,key)=>{
rootList.push({
key,
...item
})
if(item.name === 'README.md'){
readMeContent.push({...item})
}
})
this.setState({
rootList:rootList
rootList:rootList,
readMeContent
})
}
// readme文件内容
renderReadMeContent=(readMeContent)=>{
const { fileDetail } = this.state;
if(fileDetail){return;}
if(readMeContent && readMeContent.length > 0){
return(
<div className="commonBox">
<div className="commonBox-title">{readMeContent[0].name}</div>
<div className="commonBox-info">
{
readMeContent[0].content ?
<div className={"markdown-body"} dangerouslySetInnerHTML={{__html: markdownToHTML(readMeContent[0].content).replace(/▁/g, "▁▁▁")}}></div>
:
<span>暂无~</span>
}
</div>
</div>
)
}
}
// 选择分支
changeBranch=(value)=>{
const { branchList } = this.props;
@ -158,7 +186,7 @@ class CoderRootDirectory extends Component{
})
}
render(){
const { rootList , branch ,filePath , fileDetail , subFileType } = this.state;
const { rootList , branch ,filePath , fileDetail , subFileType , readMeContent } = this.state;
const { branchLastCommit , http_url , isManager , isDeveloper } = this.props;
const { projectsId } = this.props.match.params;
@ -256,8 +284,11 @@ class CoderRootDirectory extends Component{
{
fileDetail &&
<CoderRootFileDetail detail = {fileDetail}></CoderRootFileDetail>
<CoderRootFileDetail detail = {fileDetail} {...this.props} {...this.state}></CoderRootFileDetail>
}
{/* readme.txt */}
{ this.renderReadMeContent(readMeContent) }
</div>
)

@ -1,9 +1,11 @@
import React , { Component } from "react";
import Editor from "react-monaco-editor";
import { Popconfirm } from 'antd';
import { Popconfirm, Result } from 'antd';
import './list.css';
import axios from 'axios';
function bytesToSize(bytes) {
if (bytes === 0) return '0 B';
let k = 1024,
@ -15,31 +17,101 @@ class CoderRootFileDetail extends Component{
constructor(props){
super(props);
this.state={
readOnly:true
readOnly:true,
value:undefined
}
}
componentDidMount=()=>{
const { detail } = this.props;
this.setState({
value:detail.content
})
}
EditFile=()=>{
this.setState({
readOnly:false
})
}
CancelEdit=()=>{
this.setState({
readOnly:true
})
}
detail=()=>{
// 编辑文件
changeContent=(e)=>{
this.setState({
value:e
})
}
deleteFile=()=>{
const { current_user , branch , detail }= this.props;
const { projectsId } = this.props.match.params;
const url = `/${current_user.login}/${projectsId}/contents/files/delete.json`;
axios.delete(url,{
params:{
filepath:detail.path,
branch
}
}).then(result=>{
if(result){
this.props.showNotification("删除成功!");
this.props.history.push(`/projects/${projectsId}`);
}
}).catch(error=>{
console.log(error);
})
}
// 确认修改文件
UpdateFile=()=>{
const { current_user , branch , detail}= this.props;
const { projectsId } = this.props.match.params;
const { value } = this.state;
const url =`/${current_user.login}/${projectsId}/contents/files/update.json`;
axios.put(url,{
filepath:detail.path,
branch,
content:value,
sha:detail.sha,
}).then(result=>{
if(result){
this.props.showNotification("修改成功!");
this.setState({
readOnly:true
})
}
}).catch(error=>{
console.log(error);
})
}
render(){
const { detail } = this.props;
const { readOnly } = this.state;
const { readOnly ,value } = this.state;
return(
<div className="branchTable">
<p className="branchTitle f-wrap-alignCenter f-wrap-between">
<span>{bytesToSize(detail && detail.size)}</span>
<span>
<a onClick={this.EditFile} className="ml20"><i className="iconfont icon-bianji font-15 color-grey-6"></i></a>
<Popconfirm title="确认删除这个文件?" className="ml20" okText="确定" cancelText="取消" onConfirm={this.detail}>
{
readOnly ?
<a onClick={this.EditFile} className="ml20"><i className="iconfont icon-bianji font-15 color-grey-6"></i></a>
:
<React.Fragment>
<button type="button" class="ant-btn ant-btn-sm mr10" onClick={this.CancelEdit}><span> </span></button>
<button type="button" class="ant-btn ant-btn-primary ant-btn-sm" onClick={this.UpdateFile}><span> </span></button>
</React.Fragment>
}
<Popconfirm title="确认删除这个文件?" className="ml20" okText="确定" cancelText="取消" onConfirm={this.deleteFile}>
<a><i className="iconfont icon-shanchu font-15 color-grey-6"></i></a>
</Popconfirm>
</span>
@ -47,7 +119,8 @@ class CoderRootFileDetail extends Component{
<Editor
height="300px"
theme={"vs-dark"}
value={detail && detail.content}
value={value}
onChange={this.changeContent}
readOnly={readOnly}
/>
</div>

@ -12,10 +12,18 @@ const FileNew = Loadable({
loader: () => import('../Newfile/Index'),
loading: Loading,
})
const TagList = Loadable({
loader: () => import('../Order/Tags'),
loading: Loading,
})
const OrderNew = Loadable({
loader: () => import('../Order/New'),
loading: Loading,
})
const OrderDetail = Loadable({
loader: () => import('../Order/Detail'),
loading: Loading,
})
const OrderIndex = Loadable({
loader: () => import('../Order/order'),
loading: Loading,
@ -196,6 +204,19 @@ class Detail extends Component{
}
></Route>
{/* 标签列表 */}
<Route path="/projects/:projectsId/orders/tags"
render={
(props) => (<TagList {...this.props} {...props} {...this.state}/>)
}
></Route>
{/* 工单详情 */}
<Route path="/projects/:projectsId/orders/:orderId/detail"
render={
(props) => (<OrderDetail {...this.props} {...props} {...this.state}/>)
}
></Route>
{/* 新建工单 */}
<Route path="/projects/:projectsId/orders/new"

@ -413,6 +413,20 @@ body,#root{
max-width: 100%;
}
}
.commonBox{
border:1px solid #f4f4f4;
border-radius: 4px;
margin-top: 25px;
}
.commonBox .commonBox-title{
padding:10px 15px;
box-sizing: border-box;
font-size: 18px;
background: #f0f0f0;
}
.commonBox .commonBox-info{
padding:20px 15px;
}
@media screen and (max-width: 370px){
.p-r-tags,.p-r-btn{

@ -0,0 +1,84 @@
import React , {Component} from 'react';
import {Link} from 'react-router-dom';
import axios from 'axios';
import Nav from './Nav';
class Detail extends Component{
constructor(props){
super(props);
this.state={
data:undefined
}
}
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
})
}
}).catch((error)=>{
console.log(error);
})
}
render(){
const { projectsId } = this.props.match.params;
const { data } = this.state;
return(
<div className="main">
<div className="topWrapper">
<Nav {...this.props} {...this.state}/>
<Link to={`/projects/${projectsId}/orders/new`} className="topWrapper_btn">创建工单</Link>
</div>
<div>
<div className="detailContent">
<p>
<span className="font-16">{ data && data.subject }</span>
<a onClick={this.editOrder} className="color-blue fr">编辑</a>
</p>
<p className="mt15">{ data && data.description }</p>
<p className="mt10 color-grey-c">
{ data && data.author_name} { data && data.created_at }创建{ data && data.journals_count && data.journals_count > 0 ?` · ${data.journals_count} 条评论`:""}
</p>
</div>
<div className="f-wrap-between mt20" style={{alignItems:"flex-start"}}>
<div className="list-right df"></div>
<div className="list-left DetailRight">
<p>
<span className="span_title">当前状态</span>
<span>已解决</span>
</p>
<p>
<span className="span_title">优先级</span>
<span></span>
</p>
<p>
<span className="span_title">指派给</span>
<span>蔡世</span>
</p>
<p>
<span className="span_title">里程碑</span>
<span>20200131前上线</span>
</p>
<p>
<span className="span_title">里程碑</span>
<span>20200131前上线</span>
</p>
</div>
</div>
</div>
</div>
)
}
}
export default Detail;

@ -3,10 +3,11 @@ import { Link } from 'react-router-dom';
import './order.css'
class Nav extends Component{
render(){
const { projectsId } = this.props.match.params;
return(
<p className="topWrapper_nav">
<Link to={``} >标签</Link>
<Link to={``}>里程</Link>
<Link to={`/projects/${projectsId}/orders/tags`} >标签</Link>
<Link to={``}>里程</Link>
</p>
)
}

@ -44,7 +44,6 @@ class New extends Component{
getSelectList=()=>{
const { projectsId } = this.props.match.params;
const url = `/projects/${projectsId}/issues/new.json`;
axios.get(url).then((result)=>{
if(result){
@ -82,7 +81,8 @@ class New extends Component{
attachment_ids:fileList
}).then(result=>{
if(result){
this.props.showNotification("工单创建成功!");
this.props.history.push(`/projects/${projectsId}/orders`);
}
}).catch(error=>{
console.log(error);
@ -107,7 +107,7 @@ class New extends Component{
return(
<div className="main">
<div className="topWrapper">
<Nav />
<Nav {...this.props} {...this.state} />
</div>
<Form>
<div className="f-wrap-between mt20" style={{alignItems:"flex-start"}}>
@ -182,7 +182,9 @@ class New extends Component{
label="状态"
>
{getFieldDecorator('status_id', {
rules: [],
rules: [{
required: true, message: '请选择完成状态'
}],
})(
<Select value={status_id}>
<Option value={""}>未选择完成状态</Option>
@ -194,7 +196,9 @@ class New extends Component{
label="类型"
>
{getFieldDecorator('issue_type', {
rules: [],
rules: [{
required: true, message: '请选择类型'
}],
})(
<Select value={issue_type}>
<Option value={""}>未选择类型</Option>
@ -206,7 +210,9 @@ class New extends Component{
label="分类"
>
{getFieldDecorator('tracker_id', {
rules: [],
rules: [{
required: true, message: '请选择分类'
}],
})(
<Select value={tracker_id}>
<Option value={""}>未选择分类</Option>
@ -230,7 +236,9 @@ class New extends Component{
label="优先度"
>
{getFieldDecorator('priority_id', {
rules: [],
rules: [{
required: true, message: '请选择优先度'
}],
})(
<Select value={priority_id}>
<Option value={""}>未选择优先度</Option>
@ -242,7 +250,9 @@ class New extends Component{
label="完成度"
>
{getFieldDecorator('done_ratio', {
rules: [],
rules: [{
required: true, message: '请选择完成度'
}],
})(
<Select value={done_ratio}>
<Option value={""}>未选择完成度</Option>

@ -0,0 +1,47 @@
import React , { Component } from 'react';
import { Link } from 'react-router-dom';
class OrderItem extends Component{
render(){
const { issues , search_count , page , limit } = this.props;
const { projectsId } = this.props.match.params;
const renderList =()=>{
if(issues && issues.length > 0){
return(
issues.map((item,key)=>{
return(
<div className="issueItem">
<div className="flex-1">
<p className="mb15 df">
<span className="issueNo"># {search_count - (key + (page-1) * limit)}</span>
<Link to={`/projects/${projectsId}/orders/${item.id}/detail`} className="flex-1 hide-1 font-16 color-grey-3 lineh-30">{item.name}</Link>
</p>
<p className="color-grey-6">
<span>{item.created_at}</span>
{ item.journals_count ? <span className="ml20"><i className="iconfont icon-pinglun1 mr3 font-16"></i>{item.journals_count}</span> : "" }
</p>
</div>
<ul className="topWrapper_select">
<li>{item.issue_tags || "--"}</li>
<li>{item.issue_type || "--"}</li>
<li>{item.tracker || "--"}</li>
<li>{item.author_name || "--"}</li>
<li>{item.assign_user_name || "--"}</li>
<li>{item.priority || "--"}</li>
<li>{item.done_ratio || "--"}</li>
</ul>
</div>
)
})
)
}
}
return(
<div>
{renderList()}
</div>
)
}
}
export default OrderItem;

@ -0,0 +1,134 @@
import React , {Component} from 'react';
import { Dropdown , Icon , Menu , Pagination } from 'antd';
import { Link } from 'react-router-dom';
import Nav from './Nav';
import NoneData from '../../modules/courses/coursesPublic/NoneData';
import axios from 'axios';
class Tags extends Component{
constructor(props){
super(props);
this.state={
data:undefined,
limit:15,
page:1,
order_name:undefined,
order_type:undefined
}
}
componentDidMount=()=>{
this.getList();
}
getList=(page,order_name,order_type)=>{
const { projectsId } = this.props.match.params;
const { limit } = this.state;
const url = `/projects/${projectsId}/issue_tags.json`;
axios.get(url,{
params:{
page,limit,order_name,order_type
}
}).then((result)=>{
if(result){
this.setState({
data:result.data
})
}
}).catch((error)=>{
console.log(error);
})
}
ChangePage=(page)=>{
this.setState({
page
})
this.getList(page);
}
// 排序
arrayList=(e)=>{
this.setState({
order_name:e.key,
order_type:e.item.props.value
})
this.getList(1,e.key,e.item.props.value);
}
render(){
const { data , limit , page } = this.state;
const { projectsId } = this.props.match.params;
const menu = (
<Menu onClick={this.arrayList}>
<Menu.Item key={'created_at'} value="desc">按创建时间降序排序</Menu.Item>
<Menu.Item key={'created_at'} value="asc">按创建时间升序排序</Menu.Item>
<Menu.Item key={'issues_count'} value="desc">按issue个数降序排序</Menu.Item>
<Menu.Item key={'issues_count'} value="asc">按issue个数升序排序</Menu.Item>
</Menu>
)
const Paginations = (
<React.Fragment>
{
data && data.issue_tags_count > limit ?
<div className="mt30 mb50 edu-txt-center">
<Pagination simple defaultCurrent={page} total={data && data.issue_tags_count} pageSize={limit} onChange={this.ChangePage}></Pagination>
</div>:""
}
</React.Fragment>
)
const renderList =()=>{
if(data && data.issue_tags && data.issue_tags.length>0 ){
return(
<div className="tagList">
{
data.issue_tags.map((item,key)=>{
return(
<div>
<span className="f-wrap-alignCenter">
<span style={{backgroundColor:`${item.color}`}} className="tagColor"></span>
{item.name}
</span>
<span className="hide-1">{item.description}</span>
<span>{item.issues_count}个开启的工单</span>
</div>
)
})
}
</div>
)
}else{
return(
<NoneData />
)
}
}
return(
<div className="main">
<div>
<div className="topWrapper">
<Nav {...this.props} {...this.state} />
<Link to={`/projects/${projectsId}/orders/new`} className="topWrapper_btn">新建标签</Link>
</div>
<div className="topWrapper">
<span>{ data && data.issue_tags_count }个标签</span>
<ul className="topWrapper_select">
<li>
<Dropdown className="topWrapperSelect" overlay={menu} trigger={['click']} placement="bottomCenter">
<span>标签<Icon type="caret-down" className="ml5" /></span>
</Dropdown>
</li>
</ul>
</div>
{ renderList() }
{ Paginations }
</div>
</div>
)
}
}
export default Tags;

@ -150,6 +150,49 @@
margin-bottom: 0px;
}
/* 工单标签列表 */
.tagList > div{
border-bottom: 1px dashed #f4f4f4;
display: flex;
justify-content: space-around;
padding:15px 0px;
}
.tagList > div:last-child{
border-bottom: none;
}
.tagList > div > span{
display: block
}
.tagList > div > span:nth-child(2){
width: 450px;
}
.tagColor{
display: inline-block;
width:20px;
height: 15px;
border-radius: 4px;
margin-right: 5px;
}
/* 工单详情 */
.detailContent{
padding:15px 0px;
border-bottom: 1px solid #f4f4f4;
}
.DetailRight{
padding: 10px 15px;
border:1px solid #f4f4f4;
border-radius: 4px;
}
.DetailRight > p{
height: 30px;
line-height:30px;
}
.DetailRight > p >span:nth-child(1){
min-width: 90px;
margin-right: 15px;
text-align: right;
}
@media screen and (max-width: 700px){
.topWrapper_select li{
width:auto;

@ -1,19 +1,44 @@
import React , { Component } from "react";
import {Link} from 'react-router-dom';
import { Input ,Dropdown , Menu , Icon } from 'antd';
import { Input ,Dropdown , Menu , Icon , Pagination , Spin } from 'antd';
import './order.css';
import NoneData from '../../modules/courses/coursesPublic/NoneData';
import Nav from './Nav';
import OrderItem from './OrderItem';
import axios from 'axios';
const Search = Input.Search;
/**
* issue_chosen:下拉的筛选列表,
* data:列表接口返回的所有数据,
* issues:列表数组,
* isSpin:加载中,
* search:搜索关键字,
* author_id:发布者id,
* assigned_to_id:指派给的id
* limit:每页条数,
* page:当前页,
* search_count:列表总条数
* issue_type:搜索条件
*/
class order extends Component{
constructor(props){
super(props);
this.state={
issue_chosen:undefined
issue_chosen:undefined,
data:undefined,
issues:undefined,
isSpin:false,
search:undefined,
author_id:undefined,
assigned_to_id:undefined,
limit:15,
page:1,
search_count:undefined,
issue_type:undefined
}
}
@ -37,131 +62,196 @@ class order extends Component{
})
}
getIssueList=()=>{
// 获取列表数据
getIssueList=(page,limit,search,author_id,assigned_to_id,id,value)=>{
const { projectsId } = this.props.match.params;
const url = `/projects/${projectsId}/issues.json`;
axios.get(url,{
params:{}
params:{
page,limit,search,author_id,assigned_to_id,
[id]:value
}
}).then((result)=>{
if(result){
this.setState({
data:result.data,
issues:result.data.issues,
search_count:result.data.search_count,
isSpin:false
})
}
}).catch((error)=>{
console.log(error);
})
}
getOption=(e)=>{
console.log(e);
getOption=(e,id)=>{
this.setState({
[id]:e.key
})
const { page,limit,search,author_id,assigned_to_id } = this.state;
this.getIssueList(page,limit,search,author_id,assigned_to_id,id,e.key);
}
renderMenu =(array,name)=>{
renderMenu =(array,name,id)=>{
return(
<Menu>
<Menu.Item key="0" onClick={this.getOption}>{name}</Menu.Item>
<Menu.Item key={undefined} onClick={(e)=>this.getOption(e,id)}>{name}</Menu.Item>
{
array && array.length > 0 && array.map((item,key)=>{
return(
<Menu.Item key={item.id} onClick={this.getOption}>{item.name}</Menu.Item>
<Menu.Item key={item.id} onClick={(e)=>this.getOption(e,id)}>{item.name}</Menu.Item>
)
})
}
</Menu>
)
}
// 翻页
ChangePage=(page)=>{
this.setState({
page,
isSpin:true
})
const {limit,search} = this.state;
this.getIssueList(page,limit,search);
}
// 搜索
searchFunc=(value)=>{
this.setState({
search:value,
isSpin:true
})
const {page,limit} = this.state;
this.getIssueList(page,limit,value);
}
// 筛选:全部、指派给我、由我创建
ChangeAssign=(type)=>{
const { limit, search} = this.state;
this.setState({
isSpin:true
})
if(type){
const { current_user } = this.props;
if(type===1){
this.setState({
page:1,
author_id:current_user.user_id,
assigned_to_id:undefined
})
this.getIssueList(1,limit,search,current_user.user_id,undefined);
}else{
this.setState({
page:1,
author_id:undefined,
assigned_to_id:current_user.user_id
})
this.getIssueList(1,limit,search,undefined,current_user.user_id);
}
}else{
this.setState({
page:1,
author_id:undefined,
assigned_to_id:undefined
})
this.getIssueList(1,limit,search,undefined,undefined);
}
}
render(){
const { issue_chosen } = this.state;
const { issue_chosen , issues , limit , page , search_count , data , assigned_to_id , author_id , isSpin } = this.state;
const { projectsId } = this.props.match.params;
const Paginations = (
<React.Fragment>
{
search_count > limit ?
<div className="mt30 mb50 edu-txt-center">
<Pagination simple defaultCurrent={page} total={search_count} pageSize={limit} onChange={this.ChangePage}></Pagination>
</div>:""
}
</React.Fragment>
)
return(
<div className="main">
<div className="topWrapper">
<Nav />
<Nav {...this.props} {...this.state}/>
<Link to={`/projects/${projectsId}/orders/new`} className="topWrapper_btn">创建工单</Link>
</div>
<div className="topWrapper" style={{borderBottom:"none"}}>
<p className="topWrapper_nav">
<span>2个开启中</span>
<span>100个已关闭</span>
<span>{data && data.open_count}个开启中</span>
<span>{data && data.close_count}个已关闭</span>
</p>
<div>
<Search
placeholder="搜索"
enterButton
onSearch={value => console.log(value)}
onSearch={this.searchFunc}
style={{ width: 300 }}
/>
</div>
</div>
<div className="f-wrap-between mb20">
<ul className="topWrapper_type">
<li className="active">全部</li>
<li>指派给我</li>
<li>由我创建</li>
<li>@我的</li>
</ul>
<ul className="topWrapper_select">
<li>
<Dropdown className="topWrapperSelect" overlay={this.renderMenu(issue_chosen && issue_chosen.issue_tag,'标签')} trigger={['click']} placement="bottomCenter">
<span>标签<Icon type="caret-down" className="ml5" /></span>
</Dropdown>
</li>
<li>
<Dropdown className="topWrapperSelect" overlay={this.renderMenu(issue_chosen && issue_chosen.issue_type,'所有类型')} trigger={['click']} placement="bottomCenter">
<span>类型<Icon type="caret-down" className="ml5" /></span>
</Dropdown>
</li>
<li>
<Dropdown className="topWrapperSelect" overlay={this.renderMenu(issue_chosen && issue_chosen.tracker,'所有分类')} trigger={['click']} placement="bottomCenter">
<span>分类<Icon type="caret-down" className="ml5" /></span>
</Dropdown>
</li>
<li>
<Dropdown className="topWrapperSelect" overlay={this.renderMenu(issue_chosen && issue_chosen.assign_user,'发布人')} trigger={['click']} placement="bottomCenter">
<span>发布人<Icon type="caret-down" className="ml5" /></span>
</Dropdown>
</li>
<li>
<Dropdown className="topWrapperSelect" overlay={this.renderMenu(issue_chosen && issue_chosen.assign_user,'指派人')} trigger={['click']} placement="bottomCenter">
<span>指派人<Icon type="caret-down" className="ml5" /></span>
</Dropdown>
</li>
<li>
<Dropdown className="topWrapperSelect" overlay={this.renderMenu(issue_chosen && issue_chosen.priority,'优先度')} trigger={['click']} placement="bottomCenter">
<span>优先度<Icon type="caret-down" className="ml5"/></span>
</Dropdown>
</li>
<li>
<Dropdown className="topWrapperSelect" overlay={this.renderMenu(issue_chosen && issue_chosen.done_ratio,'完成度')} trigger={['click']} placement="bottomCenter">
<span>完成度<Icon type="caret-down" className="ml5" /></span>
</Dropdown>
</li>
</ul>
</div>
<div>
<div className="issueItem">
<div className="flex-1">
<p className="mb15 df">
<span className="issueNo">#10</span>
<span className="flex-1 hide-1 font-16 color-grey-3 lineh-30">forge重构issue列表issue列表issue列表issue列表</span>
</p>
<p className="color-grey-6">
<span>1小时前创建</span>
<span className="ml20"><i className="iconfont icon-pinglun1 mr3 font-16"></i>3</span>
</p>
</div>
<Spin spinning={isSpin}>
<div className="f-wrap-between mb20">
<ul className="topWrapper_type">
<li className={!author_id && !assigned_to_id ? "active":""} onClick={()=>this.ChangeAssign()}>全部</li>
<li className={author_id ? "active":""} onClick={()=>this.ChangeAssign(1)}>指派给我</li>
<li className={assigned_to_id ? "active":""} onClick={()=>this.ChangeAssign(2)}>由我创建</li>
{/* <li>@我的</li> */}
</ul>
<ul className="topWrapper_select">
<li>release</li>
<li>普通</li>
<li>缺陷</li>
<li>猜猜</li>
<li>猜猜猜</li>
<li></li>
<li>0%</li>
<li>
<Dropdown className="topWrapperSelect" overlay={this.renderMenu(issue_chosen && issue_chosen.issue_tag,'标签','issue_tag_id')} trigger={['click']} placement="bottomCenter">
<span>标签<Icon type="caret-down" className="ml5" /></span>
</Dropdown>
</li>
<li>
<Dropdown className="topWrapperSelect" overlay={this.renderMenu(issue_chosen && issue_chosen.issue_type,'所有类型','issue_type')} trigger={['click']} placement="bottomCenter">
<span>类型<Icon type="caret-down" className="ml5" /></span>
</Dropdown>
</li>
<li>
<Dropdown className="topWrapperSelect" overlay={this.renderMenu(issue_chosen && issue_chosen.tracker,'所有分类','tracker_id')} trigger={['click']} placement="bottomCenter">
<span>分类<Icon type="caret-down" className="ml5" /></span>
</Dropdown>
</li>
<li>
<Dropdown className="topWrapperSelect" overlay={this.renderMenu(issue_chosen && issue_chosen.assign_user,'发布人','author_id')} trigger={['click']} placement="bottomCenter">
<span>发布人<Icon type="caret-down" className="ml5" /></span>
</Dropdown>
</li>
<li>
<Dropdown className="topWrapperSelect" overlay={this.renderMenu(issue_chosen && issue_chosen.assign_user,'指派人','assigned_to_id')} trigger={['click']} placement="bottomCenter">
<span>指派人<Icon type="caret-down" className="ml5" /></span>
</Dropdown>
</li>
<li>
<Dropdown className="topWrapperSelect" overlay={this.renderMenu(issue_chosen && issue_chosen.priority,'优先度','priority_id')} trigger={['click']} placement="bottomCenter">
<span>优先度<Icon type="caret-down" className="ml5"/></span>
</Dropdown>
</li>
<li>
<Dropdown className="topWrapperSelect" overlay={this.renderMenu(issue_chosen && issue_chosen.done_ratio,'完成度','done_ratio')} trigger={['click']} placement="bottomCenter">
<span>完成度<Icon type="caret-down" className="ml5" /></span>
</Dropdown>
</li>
</ul>
</div>
</div>
{
search_count === 0 ?
<NoneData></NoneData>
:
<OrderItem issues={issues} search_count={search_count} page={page} limit={limit} {...this.props} {...this.state}></OrderItem>
}
{ Paginations }
</Spin>
</div>
)
}

@ -1,10 +1,9 @@
import React, { Component } from 'react';
import { getImageUrl , getUrl } from 'educoder';
import { getUrl } from 'educoder';
class NoneData extends Component{
constructor(props) {
super(props)
}
render(){
const { style } = this.props;
return(

Loading…
Cancel
Save