diff --git a/src/forge/Issues/Component/addTagsBox.jsx b/src/forge/Issues/Component/addTagsBox.jsx index 257f81977..65ca4e763 100644 --- a/src/forge/Issues/Component/addTagsBox.jsx +++ b/src/forge/Issues/Component/addTagsBox.jsx @@ -1,13 +1,20 @@ import React , { useState } from 'react'; import { Form , Modal , Input, Button } from 'antd'; import ColorCard from './colorCard'; +import axios from 'axios'; -function AddTagsBox({visible,onCancel,onSuccess , form}){ +function AddTagsBox({visible,onCancel, onSuccess , form ,owner , projectsId}){ const { getFieldDecorator , getFieldsValue } = form; const [ colors , setColors ] = useState(undefined); function saveFunc(){ - + const { desc , name } = getFieldsValue(); + const url = `/v1/${owner}/${projectsId}/issue_tags`; + axios.post(url,{ + name,description:desc,color:colors ? colors.hex:"#F17013" + }).then(result=>{ + result && onSuccess(); + }).catch(error=>{}) } function getColor(colors){ diff --git a/src/forge/Issues/Component/allMenus.jsx b/src/forge/Issues/Component/allMenus.jsx new file mode 100644 index 000000000..fc55ad011 --- /dev/null +++ b/src/forge/Issues/Component/allMenus.jsx @@ -0,0 +1,176 @@ +import React,{ useState , useEffect , forwardRef ,useImperativeHandle , useRef } from 'react'; +import Menus from './menus'; +import axios from 'axios'; + +const array =[ + {id:1,name:"最新创建"}, + {id:2,name:"最早创建"}, + {id:3,name:"最新更新"}, + {id:4,name:"最早更新"} +] + +function AllMenus({owner,projectsId,chooseFunc,update},ref){ + // 列表右侧所有筛选项的值 + const [ authorList , setAuthorList ] = useState(undefined); + const [ author , setAuthor ] = useState(undefined); + const [ tagList , setTagList ] = useState(undefined); + const [ tag , setTag ] = useState(undefined); + const [ millstoneList , setMillstoneList ] = useState(undefined); + const [ millstone , setMillstone ] = useState(undefined); + const [ chargeList , setChargeList ] = useState(undefined); + const [ charge , setCharge ] = useState(undefined); + const [ statusList , setStatusList ] = useState(undefined); + const [ prioritiesList , setPrioritiesList ] = useState(undefined); + const [ ids , setIds ] = useState({author_id:undefined,issue_priorities_id:undefined,issue_tag_ids:undefined,milestone_id:undefined,sort_by:undefined,status_id:undefined,assigner_id:undefined}); + const [ names , setNames ] = useState({author_name:undefined,issue_priorities_name:undefined,issue_tag_name:undefined,milestone_name:undefined,sortby_name:undefined,status_name:undefined,assigner_name:undefined}); + + useImperativeHandle(ref, () => ({ + clearChoose: () => { + // 父组件按钮:清除筛选条件,将Ids\names里的字段全部改为undefined + setIds({author_id:undefined,issue_tag_ids:undefined,issue_priorities_id:undefined,milestone_id:undefined,sort_by:undefined,status_id:undefined,assigner_id:undefined}); + setNames({author_name:undefined,issue_tag_name:undefined,issue_priorities_name:undefined,milestone_name:undefined,sortby_name:undefined,status_name:undefined,assigner_name:undefined}); + } + })) + // 获取发布人列表 + useEffect(()=>{ + getSendPerson(); + },[author]) + + function getSendPerson(){ + const url = `/v1/${owner}/${projectsId}/issue_authors`; + axios.get(url,{params:{keyword:author,only_name:true}}).then(result=>{ + if(result && result.data){ + setAuthorList(result.data.authors); + } + }) + } + // 获取标记列表 + useEffect(()=>{ + getSign(); + },[tag]) + function getSign(){ + const url = `/v1/${owner}/${projectsId}/issue_tags`; + axios.get(url,{params:{keyword:tag,only_name:true}}).then(result=>{ + if(result && result.data){ + setTagList(result.data.issue_tags); + } + }) + } + // 获取里程碑列表 + useEffect(()=>{ + getMillstone(); + },[millstone]) + + function getMillstone(){ + const url = `/v1/${owner}/${projectsId}/milestones`; + axios.get(url,{params:{keyword:millstone,only_name:true}}).then(result=>{ + if(result && result.data){ + setMillstoneList(result.data.milestones); + } + }) + } + + // 获取负责人列表 + useEffect(()=>{ + getCharge(); + },[charge]) + + function getCharge(){ + const url = `/v1/${owner}/${projectsId}/issue_assigners`; + axios.get(url,{params:{keyword:charge,only_name:true}}).then(result=>{ + if(result && result.data){ + setChargeList(result.data.assigners); + } + }) + } + // 获取优先级列表 + useEffect(()=>{ + getPriorities(); + },[]) + + function getPriorities(){ + const url = `/v1/${owner}/${projectsId}/issue_priorities`; + axios.get(url).then(result=>{ + if(result && result.data){ + setPrioritiesList(result.data.priorities); + } + }) + } + // 获取状态列表 + useEffect(()=>{ + getStatus(); + },[]) + + function getStatus(){ + const url = `/v1/${owner}/${projectsId}/issue_statues`; + axios.get(url).then(result=>{ + if(result && result.data){ + setStatusList(result.data.statues); + } + }) + } + + function choose(id,name){ + let copy = {...ids,author_id:id}; + let copyname = { ...names,author_name:name} + setIds(copy);setNames(copyname); + chooseFunc(copy); + } + + return( + + ) +} +export default forwardRef(AllMenus); \ No newline at end of file diff --git a/src/forge/Issues/Component/datas.jsx b/src/forge/Issues/Component/datas.jsx index 2eb685ca7..514f08dda 100644 --- a/src/forge/Issues/Component/datas.jsx +++ b/src/forge/Issues/Component/datas.jsx @@ -6,39 +6,67 @@ import { Link } from "react-router-dom"; // issue列表显示 function Datas({checkbox ,item , projectsId,owner}){ + + function statusTag(name){ + switch (name) { + case "低": + return "status low"; + case "正常": + return "status normal"; + case "高": + return "status hight"; + default: + return "status urgent"; + } + } + return(
{checkbox}
- {item.priority_name} + {item.priority_name} {item.project_issues_index && #{item.project_issues_index}}
{item.subject} - invalid + { + item.tags && item.tags.length>0? + item.tags.map((i,k)=>{ + return( + {i.name} + ) + }) + :"" + }
- - {item.author && item.author.name} + + {item.author && item.author.name} {item.created_at} 发布 {item.updated_at}更新 - {item.milestone_name && {item.milestone_name} } + {item.milestone_name && {item.milestone_name} }
-
- - - - - - ... -
+ { + item.assigners && item.assigners.length > 0 ? +
+ { + item.assigners.map((i,k)=>{ + return( + k<5 && + ) + }) + } + {/* ... */} +
+ :"" + }
{item.status_name}
{item.comment_journals_count}
diff --git a/src/forge/Issues/Component/date.jsx b/src/forge/Issues/Component/date.jsx new file mode 100644 index 000000000..326bdad47 --- /dev/null +++ b/src/forge/Issues/Component/date.jsx @@ -0,0 +1,140 @@ +import React,{useRef,useEffect, useState , forwardRef } from 'react'; +import { Dropdown , Calendar , Select, Radio, Col, Row } from 'antd'; +import { findDOMNode } from 'react-dom'; +import moment from 'moment'; +const { Group , Button } = Radio; + +function Date({name , today , setDate},ref){ + const [ visible , setVisible ] = useState(false); + const [ time , setTime ] = useState(); + + useEffect(()=>{ + if(today){ + setTime(today); + } + },[today]) + + const refFa = useRef(null); + const refBox = useRef(null); + + + useEffect(() => { + document.addEventListener('click', clickMe , false); + }, []) + + const clickMe = ({ target }) => { + // 查找父组件 + const faComponent = findDOMNode(refFa.current); + const boxComponent = findDOMNode(refBox.current); + if (faComponent && boxComponent) { + const isChild = faComponent.contains(target); + const isBox = boxComponent.contains(target); + if(!isChild && !isBox){ + setVisible(false); + } + } + } + function onSelect(t){ + setTime(moment(t).format('YYYY-MM-DD')); + setDate(moment(t).format('YYYY-MM-DD')); + setVisible(false); + } + const overlay=( +
+ { + const start = 0; + const end = 12; + const monthOptions = []; + const current = value.clone(); + const localeData = value.localeData(); + const months = []; + for (let i = 0; i < 12; i++) { + current.month(i); + months.push(localeData.monthsShort(current)); + } + + for (let index = start; index < end; index++) { + monthOptions.push( + + {months[index]} + , + ); + } + const month = value.month(); + + const year = value.year(); + const options = []; + for (let i = year - 10; i < year + 10; i += 1) { + options.push( + + {i} + , + ); + } + return ( +
+ + + + onTypeChange(e.target.value)} value={type}> + + + + + + + + + + + +
+ ); + }} + onSelect={onSelect} + /> +
+ ) + return( + +
  • + + {name} + setVisible(visible ? false : true)}> + +

    {time || "未设置"}

    +
  • +
    + ) +} +export default forwardRef(Date); \ No newline at end of file diff --git a/src/forge/Issues/Component/drop.jsx b/src/forge/Issues/Component/drop.jsx index 9a4fe474a..272d96489 100644 --- a/src/forge/Issues/Component/drop.jsx +++ b/src/forge/Issues/Component/drop.jsx @@ -1,16 +1,16 @@ import React,{useState, useEffect, useRef, useImperativeHandle,forwardRef} from 'react'; -import { Dropdown ,Icon } from 'antd'; +import { Dropdown } from 'antd'; import { findDOMNode } from 'react-dom'; -function Drop({overlay,value},ref){ +function Drop({overlay , children , placement, overlayClassName},ref){ const [ visible , setVisible ] = useState(false); const refFa = useRef(null); const refBox = useRef(null); useImperativeHandle(ref, () => ({ - clearVisible: (value) => { + clearVisible: (v) => { // 父组件按钮:清除筛选条件,将dropmenu里的choose字段全部改为0 - setVisible(value); + setVisible(v); } })) @@ -32,14 +32,14 @@ function Drop({overlay,value},ref){ } return( {overlay}
    } trigger={['click']} + overlayClassName={overlayClassName} >
  • setVisible(visible ? false : true)}> - {value} - + {children}
  • ) diff --git a/src/forge/Issues/Component/editMenus.jsx b/src/forge/Issues/Component/editMenus.jsx index 0191ef354..926b98a0b 100644 --- a/src/forge/Issues/Component/editMenus.jsx +++ b/src/forge/Issues/Component/editMenus.jsx @@ -1,13 +1,23 @@ import React ,{ useState , useEffect , useRef } from 'react'; -import { Dropdown , Menu , Input } from 'antd'; +import { Dropdown , Menu , Input, message } from 'antd'; import { findDOMNode } from 'react-dom'; +import { getImageUrl } from 'educoder'; const { Search } = Input; -function EditMenus({name,list,value , onAdd , searchFlag}){ +// name:显示的标题 +// list[]:选项 +// value[]:显示的值 +// onAdd:标记管理、只针对标记 +// searchFlag:是否显示搜索输入框 +// editFlag:是否有编辑按钮 +// double:可多选 +// onChange:选择项后返回id数组 +function EditMenus({ name , emptyName='未设置',list,value , onAdd , searchFlag , editFlag , searchFunc ,double , onChange , imgFlag}){ const [ menus , setMenus ] = useState([]); const [ searchValue , setSearchValue ]= useState(undefined); const [ showValue , setShowValue ] = useState(undefined); + const [ valueId , setValueId ] = useState([]); const [ visible , setVisible ] = useState(false); const refFa = useRef(null); @@ -15,7 +25,14 @@ function EditMenus({name,list,value , onAdd , searchFlag}){ useEffect(()=>{ setMenus(list); - setShowValue(value); + if(value && value.length>0 && list && list.length>0){ + let n = value.map(item=>{ + let n = list.filter(j=>j.id.toString() === item); + return n.length>0 && n[0].name; + }); + setValueId(value); + setShowValue(n.join(",")); + } },[list,value]) useEffect(() => { @@ -35,48 +52,106 @@ function EditMenus({name,list,value , onAdd , searchFlag}){ } } - function chooseMenu(e){ + function chooseMenu(i){ setVisible(false); - setShowValue(e.item.props.children) + let l = valueId; + let idStr = i && i.id ? i.id.toString() :i.name; + // 分支列表没有id,只能根据name判断 + if(double){ + if(l.indexOf(idStr)>=0){ + l = l.filter(k=>k.toString() !== idStr); + }else{ + if(valueId.length > double){ + message.info(`最多只能添加${double}个${name}`); + return; + } + l.push(idStr); + } + setValueId(l); + console.log(l); + let nameList = i && i.id ? getByid(l) : getByName(l); + setShowValue(nameList.length >0 ? nameList.join(",") : undefined); + onChange(l); + }else{ + if(l.indexOf(idStr)>=0){ + setValueId([]); + onChange([]); + setShowValue(undefined); + }else{ + setValueId([`${i.id || i.name}`]); + onChange([`${i.id || i.name}`]); + setShowValue(i.name); + } + } + } + + function getByid(l){ + return l.length>0 ? l.map(item=>{ + let n = list.filter(j=>j.id.toString() === item); + return n.length>0 && n[0].name; + }) :""; + } + function getByName(l){ + return l.length>0 ? l.map(item=>{ + let n = list.filter(j=>j.name === item); + return n.length>0 && n[0].name; + }) :""; } // 搜索 function changeSearchvalue(e){ setSearchValue(e.target.value); + searchFunc(e.target.value); } return(
  • - {name} - + {name} + {!editFlag && setVisible(visible ? false : true)}>} + + { searchFlag &&
    - +
    } { menus && menus.length >0? - + { menus.map((i,k)=>{ return( - {i.name} + chooseMenu(i)}> + { imgFlag && } + {i.color && } + {i.name} + ) }) } :
    -

    {searchValue ? 创建新{showValue}“{searchValue}”: `暂无${name}`}

    +

    {searchValue ? 暂无{name}“{searchValue}”: `暂无${name}`}

    { name === "标记" && {setVisible(false);onAdd()}}>标记管理}
    }
  • }> -

    setVisible(visible ? false : true)} className={showValue?"operatevalue color-grey-3":"operatevalue"}>{showValue || "未设置"}

    +

    {showValue || emptyName}

    ) diff --git a/src/forge/Issues/Component/menus.jsx b/src/forge/Issues/Component/menus.jsx index 17f25b175..9aab7e5ba 100644 --- a/src/forge/Issues/Component/menus.jsx +++ b/src/forge/Issues/Component/menus.jsx @@ -1,178 +1,54 @@ -import React ,{ useImperativeHandle ,forwardRef , useState , useEffect , useRef } from 'react'; -import { Input , Menu } from 'antd'; +import React ,{ useState , useRef } from 'react'; +import { Input , Menu , Icon } from 'antd'; import { getImageUrl } from 'educoder'; import Drop from './drop'; -import axios from 'axios'; const { Search } = Input; -// id:固定位置顺序的唯一 // name:未选择时显示的内容 -// updateName:勾选列表后默认显示的内容 -// choose:选择的项的id -// menu:下拉列表,从接口获取,需一一填充 +// lists:下拉列表,从接口获取,需一一填充 // imgControl:控制是否显示头像 // size:下拉框宽度,small:120px,large:260px; -const menus=[ - { - id:1, - name:"发布人", - choose:0, - imgControl:true, - size:"large", - menu:[{id:1,name:"111",image_url:'https://testforgeplus.trustie.net/images/avatars/User/36480?t=1672730523'},{id:2,name:"222",image_url:''},{id:3,name:"333",image_url:''},{id:4,name:"4444",image_url:''}] - }, - { - id:7, - updateName:"更换优先级", - choose:0, - menu:[{id:1,name:"紧急"},{id:2,name:"正常"},{id:3,name:"低"},{id:4,name:"高"}] - }, - { - id:2, - name:"标记", - updateName:"更换标记", - choose:0, - size:"large", - menu:[{id:1,name:"red"},{id:2,name:"blue"},{id:3,name:"orange"},{id:4,name:"yellow"}] - }, - { - id:3, - name:"里程碑", - updateName:"更换里程碑", - choose:0, - size:"large", - menu:[{id:1,name:"11-11"},{id:2,name:"22-22"},{id:3,name:"33-33"},{id:4,name:"44-44"}] - }, - { - id:4, - name:"负责人", - updateName:"更换负责人", - choose:0, - size:"large", - menu:[{id:1,name:"you",img:''},{id:2,name:"she",img:''},{id:3,name:"he",img:''},{id:4,name:"they",img:''}] - }, - { - id:5, - name:"状态", - updateName:"更换状态", - choose:0, - size:"small", - menu:[{id:1,name:"新增"},{id:2,name:"正在解决"},{id:3,name:"已解决"},{id:4,name:"反馈"},{id:5,name:"关闭"},{id:6,name:"拒绝"}] - }, - { - id:6, - name:"排序", - choose:0, - size:"small", - menu:[{id:1,name:"最新创建"},{id:2,name:"最早创建"},{id:3,name:"最近更新"},{id:4,name:"最早更新"},{id:5,name:"高优先级"},{id:6,name:"低优先级"}] - } -] -function Menus({update,owner,projectsId},ref){ - const [ dropmenu , setDropMenu ] = useState(menus); - - +// chooseValue: 默认选择的项的id +// search: 搜索方法 +// chooseFunc: 选择项后需调用列表的查询方法 +// update: 编辑状态 +function Menus({name, id , lists , size , imgControl , searchFunc , chooseFunc , update },ref){ const dropRef = useRef(null); - - useEffect(()=>{ - getSendPerson(); - getSign(); - },[]) - - // 获取发布人 - function getSendPerson(){ - const url = `/v1/${owner}/${projectsId}/issue_authors`; - axios.get(url).then(result=>{ - if(result && result.data){ - MenusControl(1,result.data.authors); - } - }) - } - // 获取标记 - function getSign(){ - const url = `/v1/${owner}/${projectsId}/issue_tags`; - axios.get(url).then(result=>{ - if(result && result.data){ - MenusControl(2,result.data.issue_tags); - } - }) - } - - function MenusControl(num,data){ - let list = [...dropmenu]; - let todolist = []; - todolist = list.map((i,k)=>i.id === num ? {...i,menu:data} : i); - setDropMenu(todolist); - } - - - useImperativeHandle(ref, () => ({ - clearChoose: () => { - // 父组件按钮:清除筛选条件,将dropmenu里的choose字段全部改为0 - changeMenusValue(0); - } - })) - - useEffect(()=>{ - if(update){ - - } - },[update]) + // 修改menus数组里的字段值 function changeMenusValue(value,id){ - let todoList = [...dropmenu]; - let list = []; - if(id){ - list = todoList.map((i,k)=>id===i.id ? {...i,choose:value} : i); - }else{ - list = todoList.map((i,k)=>id ? i : {...i,choose:value}); - } - setDropMenu(list); + chooseFunc(id,value); dropRef.current && dropRef.current.clearVisible(false); - // 修改后调用父组件方法重新查询数据 - } - function menu(item){ - if(item.menu && item.menu.length>0){ - return
    - { item.size !== "small" && -
    - } - - { - item.menu.map((i,j)=>{ - return - {item.imgControl && } - changeMenusValue(i.id,item.id)}>{i.name} - - }) - } - -
    + function menu(data){ + return
    + { size !== "small" && +
    searchFunc(e.target.value)}/>
    } - else{ - return ""; - } + { + data && data.length>0 ? + + { + data.map((i,j)=>{ + return + {imgControl && } + changeMenusValue(i.name,i.id)}>{i.name} + + }) + } + + : +
    暂无{id ? '{name}': name}
    + } +
    } return( - dropmenu && dropmenu.length >0 ? - - :
    + + {(update && !id) ? `更换${name}` : name } + + ) } -export default forwardRef(Menus); \ No newline at end of file +export default Menus; \ No newline at end of file diff --git a/src/forge/Issues/Pages/list.jsx b/src/forge/Issues/Pages/list.jsx index 63e5ea473..455c2ae99 100644 --- a/src/forge/Issues/Pages/list.jsx +++ b/src/forge/Issues/Pages/list.jsx @@ -4,7 +4,7 @@ import bj from '../Img/biaoji.png'; import issueEmp from '../Img/issue-big.png'; import create from '../Img/create.png'; import { Link } from "react-router-dom"; -import Menus from '../Component/menus'; +import AllMenus from '../Component/allMenus'; import Datas from '../Component/datas'; import DelBox from '../Component/delBox'; import axios from 'axios'; @@ -27,8 +27,11 @@ function List(props){ const [ allIds , setAllIds ] = useState([]); const [ checkAll , setCheckAll ] = useState(false); + const [ updateIds , setUpdateIds ] = useState([]); + const [ page , setPage ] = useState(1); const [ total , setTotal ] = useState(undefined); + const menuRef = useRef(null); const owner = props.match.params.owner; const projectsId = props.match.params.projectsId; @@ -38,13 +41,16 @@ function List(props){ Init(); },[aboutMe,keyword,category]) // 获取issue列表数据 - function Init(){ + function Init(params){ setTotal(undefined); const url = `/v1/${owner}/${projectsId}/issues`; axios.get(url,{ params:{ participant_category:aboutMe, - keyword,category + keyword,category, + ...params, + sort_direction:(params && params.sort_by) ? ((params.sort_by === 1 || params.sort_by === 3) ? "desc" : "asc") :undefined, + sort_by:(params && params.sort_by) ? ((params.sort_by === 1 || params.sort_by === 2) ? "created_on" : "updated_on") : undefined } }).then(result=>{ if(result){ @@ -77,8 +83,10 @@ function List(props){ function clearCondition(){ setKeyword(undefined); setAboutMe("aboutme"); + Init(); // 清除下拉选项 menuRef.current && menuRef.current.clearChoose(); + } // 全选所有issue @@ -105,6 +113,25 @@ function List(props){ function cancelUpdate(){ setAllValue([]); setCheckAll(false); + // 清除下拉选项 + menuRef.current && menuRef.current.clearChoose(); + } + // 确认修改 allValue updateIds + function sureUpdate(){ + const url = `/v1/${owner}/${projectsId}/issues/batch_update`; + axios.patch(url,{ + assigner_ids: [updateIds && updateIds.assigner_id], + ids: allValue, + issue_tag_ids: [updateIds && updateIds.issue_tag_ids], + milestone_id: updateIds && updateIds.milestone_id, + priority_id: updateIds && updateIds.issue_priorities_id, + status_id: updateIds && updateIds.status_id + }).then(result=>{ + if(result){ + Init(); + cancelUpdate(); + } + }).catch(error=>{}) } // 切换页码 @@ -114,7 +141,25 @@ function List(props){ // 删除issue相关 func function onSuccess(){ - + const url = `/v1/${owner}/${projectsId}/issues/batch_destroy`; + axios.delete(url,{ + params:{ids:allValue} + }).then(result=>{ + if(result){ + setVisible(false); + props.showNotification("疑修删除成功!"); + Init(); + } + }).catch(error=>{}) + } + + function chooseFunc(ids){ + if(allValue && allValue.length>0){ + // 将ids保存下来以便修改 + setUpdateIds(ids); + }else{ + Init(ids); + } } return( @@ -158,16 +203,17 @@ function List(props){ }
    - 0} owner={owner} projectsId={projectsId} - update={allValue && allValue.length>0} + chooseFunc={chooseFunc} /> { allValue && allValue.length>0 ?
    - +
    @@ -191,7 +237,7 @@ function List(props){ issueList.map((item,key)=>{ return( } + checkbox={ } item={item} owner={owner} projectsId={projectsId} diff --git a/src/forge/Issues/Pages/new.jsx b/src/forge/Issues/Pages/new.jsx index 111b73c28..ec017a2b4 100644 --- a/src/forge/Issues/Pages/new.jsx +++ b/src/forge/Issues/Pages/new.jsx @@ -1,5 +1,5 @@ -import React , { useEffect , useState } from 'react'; -import { Button, Input , Dropdown , Menu } from 'antd'; +import React , { useEffect , useState , forwardRef } from 'react'; +import { Button, Input , Form } from 'antd'; import { Box , LongWidth } from '../../Component/layout'; import MDEditor from "../../../modules/tpm/challengesnew/tpm-md-editor"; import Upload from "../../Upload/Index"; @@ -7,18 +7,131 @@ import Attachments from "../../Upload/attachment"; import UploadImg from '../Img/UploadImg.png'; import EditMenus from '../Component/editMenus'; import AddTagsBox from '../Component/addTagsBox'; +import Date from '../Component/date'; +import axios from 'axios'; +import moment from 'moment'; -const menus = { - milestones:[{id:1,name:"里程碑1"},{id:2,name:"里程碑22"}], - issue_tags:[{id:1,name:"标记1"},{id:2,name:"标记22"}] -} function New(props){ - const [ content , setContent ] = useState(""); + const [ description , setDescription ] = useState(""); const [ visible , setVisible ] = useState(false); const [ fileList , setFileList] = useState(undefined); const [ attachments , setAttachments ] = useState([]); + + + const [ statusList , setStatusList ] = useState([]); + const [ prioritiesList , setPrioritiesList ] = useState([]); + const [ chargeList , setChargeList ] = useState([]); + const [ charge , setCharge ] = useState(undefined); + const [ millstoneList , setMillstoneList ] = useState([]); + const [ millstone , setMillstone ] = useState(undefined); + const [ tagList , setTagList ] = useState(undefined); + const [ tag , setTag ] = useState(undefined); + const [ branchList , setBranchList ] = useState(undefined); + const [ branch , setBranch ] = useState(undefined); + + const [ charegeId , setCharegeId ] = useState([]); + const [ statusId , setStatusId ] = useState([`1`]); + const [ prioritiesId , setPrioritiesId ] = useState([`2`]); + const [ tagId , setTagId ] = useState([]); + const [ millstoneId , setMillstoneId ] = useState([]); + const [ branchId , setBranchId ] = useState([]); + + const [ start_date, setStartDate ] = useState(moment().format('YYYY-MM-DD')); + const [ due_date, setDueDate ] = useState(""); + + const [ receivers_login , setReceiversLogin ] = useState(undefined); + + const owner = props.match.params.owner; + const projectsId = props.match.params.projectsId; + + const { form: { getFieldDecorator, validateFields , setFieldsValue } } = props; + + // 获取状态列表 + useEffect(()=>{ + getStatus(); + },[]) + + function getStatus(){ + const url = `/v1/${owner}/${projectsId}/issue_statues`; + axios.get(url).then(result=>{ + if(result && result.data){ + setStatusList(result.data.statues); + } + }) + } + // 获取优先级列表 + useEffect(()=>{ + getPriorities(); + },[]) + + function getPriorities(){ + const url = `/v1/${owner}/${projectsId}/issue_priorities`; + axios.get(url).then(result=>{ + if(result && result.data){ + setPrioritiesList(result.data.priorities); + } + }) + } + + // 获取负责人列表 + useEffect(()=>{ + getCharge(); + },[charge]) + + function getCharge(){ + const url = `/v1/${owner}/${projectsId}/collaborators`; + axios.get(url,{params:{keyword:charge,only_name:true}}).then(result=>{ + if(result && result.data){ + setChargeList(result.data.collaborators); + } + }) + } + // 获取里程碑列表 + useEffect(()=>{ + getMillstone(); + },[millstone]) + + function getMillstone(){ + const url = `/v1/${owner}/${projectsId}/milestones`; + axios.get(url,{params:{keyword:millstone,only_name:true}}).then(result=>{ + if(result && result.data){ + setMillstoneList(result.data.milestones); + } + }) + } + // 获取标记列表 + useEffect(()=>{ + getSign(); + },[tag]) + function getSign(){ + const url = `/v1/${owner}/${projectsId}/issue_tags`; + axios.get(url,{params:{keyword:tag,only_name:true}}).then(result=>{ + if(result && result.data){ + setTagList(result.data.issue_tags); + } + }) + } + // 获取标记列表 + useEffect(()=>{ + getBranch(branch); + },[branch]) + function getBranch(branch){ + if(branch){ + let b = [...branchList]; + let l = b.filter(i=>i.name.indexOf(branch)>-1); + setBranchList(l); + return ; + } + const url = `/${owner}/${projectsId}/branches.json`; + axios.get(url,{params:{keyword:tag}}).then(result=>{ + if(result && result.data){ + setBranchList(result.data); + } + }) + } + function onContentChange(value){ - setContent(value); + setDescription(value); } function UploadFunc(fileList){ setFileList(fileList); @@ -26,26 +139,72 @@ function New(props){ // 标记管理弹框 function onSuccess(){ - // 添加标记成功后需更新标记的数据数组 - + getSign(); + setVisible(false); } + // 创建 + function createFunc(){ + validateFields((error,values)=>{ + if (!error) { + const { subject } = values; + const url = `/v1/${owner}/${projectsId}/issues`; + axios.post(url,{ + description,subject, + branch_name:branchId.join(","), + status_id:statusId.join(","), + priority_id:prioritiesId.join(","), + milestone_id:millstoneId.join(","), + issue_tag_ids:tagId, + assigner_ids:charegeId, + attachment_ids:fileList, + start_date,due_date,receivers_login + }).then(result=>{ + if(result && result.data && result.data.project_issues_index){ + props.showNotification("任务创建成功!"); + props.history.push(`/${owner}/${projectsId}/issues/${result.data.project_issues_index}`); + } + }).catch(error=>{}) + } + }) + } + + function changeAtWhoLoginList(loginList){ + let list = new Set(receivers_login); + loginList.map(item => list.add(item)); + setReceiversLogin(Array.from(list)); + }; + return(
    - setVisible(false)} onSuccess={onSuccess} /> + setVisible(false)} onSuccess={onSuccess} + />

    新建疑修

    - +
    + + {getFieldDecorator("subject",{ + rules:[{required:true,message:"请输入疑修标题"}] + })( + + )} + +
    - +
    - - - - setVisible(true)} searchFlag/> - + setCharegeId(ids)} list={chargeList} searchFlag searchFunc={(value)=>setCharge(value)} double={5}/> + setStatusId(ids)} list={statusList} editFlag value={statusId}/> + setPrioritiesId(ids)} list={prioritiesList} value={prioritiesId}/> + setTagId(ids)} list={tagList} onAdd={()=>setVisible(true)} searchFlag double={3} searchFunc={(value)=>setTag(value)}/> + setMillstoneId(ids)} list={millstoneList} searchFlag searchFunc={(value)=>setMillstone(value)}/> + setBranchId(ids)} list={branchList} searchFlag searchFunc={(value)=>setBranch(value)}/> + setStartDate(date)}/> + setDueDate(date)}/>
    ) } -export default New; \ No newline at end of file +export default Form.create()(forwardRef(New)); \ No newline at end of file diff --git a/src/forge/Issues/index.scss b/src/forge/Issues/index.scss index 0be735da4..1be819fcb 100644 --- a/src/forge/Issues/index.scss +++ b/src/forge/Issues/index.scss @@ -201,7 +201,7 @@ align-items: center; color: #898d9d; margin-top: 12px; - &>img{ + img{ height: 22px; width: 22px; margin-right: 4px; @@ -214,14 +214,22 @@ color: #40424a; .principal{ position: relative; - height: 30px; + height: 20px; + &:hover{ + a{ + position:initial; + } + } + a{ + position: absolute; + right: 0px; + bottom: 0px; + transition: 0.6s; + } img,span{ width: 20px; height: 20px; border-radius: 50%; - position: absolute; - right: 0px; - bottom: 4px; } span{ background-color:#ced5ef; @@ -395,7 +403,6 @@ line-height: 20px; color: #acb0bf; margin-top: 10px; - cursor: pointer; } } } @@ -445,15 +452,28 @@ border-top: 1px solid rgba(172, 176, 191, 0.17); } } +.piecemenu{ + li{ + display: flex; + align-items: center; + } +} +.colorpiece{ + display: block; + width: 22px; + height: 15px; + margin-right: 9px; + border-radius:2px; +} .overlayStyle{ background-color:#ffffff; border-radius:6px; box-shadow:0px 0px 10px rgba(24, 54, 181, 0.17); .searchbox{ - padding:18px 20px 0px 16px; + padding:12px 20px 0px 16px; } .ant-menu{ - padding:0px 20px 10px 16px; + padding:12px 16px 10px 16px; max-height: 338px; overflow-y: auto; li{ @@ -513,6 +533,12 @@ align-items: center; } } +// 新建页面 +.explain{ + .ant-form-explain{ + position: absolute; + } +} // 评论相关 .addcomments{ diff --git a/src/forge/Upload/Index.js b/src/forge/Upload/Index.js index e9881393c..ea8ab180e 100644 --- a/src/forge/Upload/Index.js +++ b/src/forge/Upload/Index.js @@ -70,10 +70,12 @@ class Index extends Component { fileIdList = (fileList) => { let array = []; - fileList && fileList.length > 0 && fileList.map((item) => { - return array.push(item.response && (item.response.id || (item.response.data && item.response.data.id))); - }) - array && this.props.load && this.props.load(array); + if(fileList && fileList.length > 0){ + fileList.map((item) => { + return item.response && item.status==="done" && array.push((item.response.id || (item.response.data && item.response.data.id))); + }) + array && array.length>0 && this.props.load(array); + } } checkFile=(str)=>{