update issue

This commit is contained in:
caishi 2023-02-23 18:03:26 +08:00
parent a1a8308d00
commit d66f83d3ec
12 changed files with 217 additions and 74 deletions

View File

@ -11,7 +11,7 @@ const array =[
{id:6,name:"低优先级"}
]
function AllMenus({owner,projectsId,chooseFunc,update},ref){
function AllMenus({owner,projectsId,chooseFunc,update,defaultNames,defaultIds},ref){
//
const [ authorList , setAuthorList ] = useState(undefined);
const [ author , setAuthor ] = useState(undefined);
@ -26,6 +26,18 @@ function AllMenus({owner,projectsId,chooseFunc,update},ref){
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});
useEffect(()=>{
if(defaultNames){
setNames(defaultNames);
}
},[defaultNames])
useEffect(()=>{
if(defaultIds){
setIds(defaultIds);
}
},[defaultIds])
useImperativeHandle(ref, () => ({
clearChoose: () => {
// Ids\namesundefined
@ -122,10 +134,10 @@ function AllMenus({owner,projectsId,chooseFunc,update},ref){
}
function choose(id,name){
let copy = {...ids,author_id:id.join(",")};
let copyname = { ...names,author_name:name}
let copy = {...ids,author_id:id && id.length>0 ? id.join(","):undefined};
let copyname = { ...names,author_name:name};
setIds(copy);setNames(copyname);
chooseFunc(copy);
chooseFunc(copy,copyname);
}
return(
@ -145,7 +157,7 @@ function AllMenus({owner,projectsId,chooseFunc,update},ref){
name={"优先级" } size={"small"}
lists={prioritiesList}
names={names && names.issue_priorities_name}
chooseFunc={(id,name)=>{let copy = {...ids,issue_priorities_id:id.join(",")};let copyname = { ...names,issue_priorities_name:name};setNames(copyname);setIds(copy);chooseFunc(copy)}}
chooseFunc={(id,name)=>{let copy = {...ids,issue_priorities_id:id && id.length>0 ? id.join(","):undefined};let copyname = { ...names,issue_priorities_name:name};setNames(copyname);setIds(copy);chooseFunc(copy,copyname)}}
/>
}
<Menus
@ -155,7 +167,7 @@ function AllMenus({owner,projectsId,chooseFunc,update},ref){
double
names={names && names.issue_tag_name}
lists={tagList} searchFunc={(value)=>setTag(value)}
chooseFunc={(id,name)=>{let copy = {...ids,issue_tag_ids:id.join(",")};let copyname = { ...names,issue_tag_name:name};setNames(copyname);setIds(copy);chooseFunc(copy)}}
chooseFunc={(id,name)=>{let copy = {...ids,issue_tag_ids:id && id.length>0 ? id.join(","):undefined};let copyname = { ...names,issue_tag_name:name};setNames(copyname);setIds(copy);chooseFunc(copy,copyname)}}
/>
<Menus
update={update}
@ -163,7 +175,7 @@ function AllMenus({owner,projectsId,chooseFunc,update},ref){
name={"里程碑"} size={"large"}
names={names && names.milestone_name}
lists={millstoneList} searchFunc={(value)=>setMillstone(value)}
chooseFunc={(id,name)=>{let copy = {...ids,milestone_id:id.join(",")};let copyname = { ...names,milestone_name:name};setNames(copyname);setIds(copy);chooseFunc(copy)}}
chooseFunc={(id,name)=>{let copy = {...ids,milestone_id:id && id.length>0 ? id.join(","):undefined};let copyname = { ...names,milestone_name:name};setNames(copyname);setIds(copy);chooseFunc(copy,copyname)}}
/>
<Menus
update={update}
@ -171,7 +183,8 @@ function AllMenus({owner,projectsId,chooseFunc,update},ref){
name={"负责人"} size={"large"} imgControl
names={names && names.assigner_name}
lists={chargeList} searchFunc={(value)=>setCharge(value)}
chooseFunc={(id,name)=>{let copy = {...ids,assigner_id:id.join(",")};let copyname = { ...names,assigner_name:name};setNames(copyname);setIds(copy);chooseFunc(copy)}}
double={update ? true : false }
chooseFunc={(id,name)=>{let copy = {...ids,assigner_id:id && id.length>0 ? id.join(","):undefined};let copyname = { ...names,assigner_name:name};setNames(copyname);setIds(copy);chooseFunc(copy,copyname)}}
/>
<Menus
update={update}
@ -179,14 +192,14 @@ function AllMenus({owner,projectsId,chooseFunc,update},ref){
name={"状态"} size={"small"}
lists={statusList}
names={names && names.status_name}
chooseFunc={(id,name)=>{let copy = {...ids,status_id:id.join(",")};let copyname = { ...names,status_name:name};setNames(copyname);setIds(copy);chooseFunc(copy)}}
chooseFunc={(id,name)=>{let copy = {...ids,status_id:id && id.length>0 ? id.join(","):undefined};let copyname = { ...names,status_name:name};setNames(copyname);setIds(copy);chooseFunc(copy,copyname)}}
/>
{ !update && <Menus
ids={ids && ids.sort_by}
name={"排序"} size={"small"}
lists={array}
names={names && names.sortby_name}
chooseFunc={(id,name)=>{let copy = {...ids,sort_by:id.join(",")};let copyname = { ...names,sortby_name:name};setNames(copyname);setIds(copy);chooseFunc(copy)}}
chooseFunc={(id,name)=>{let copy = {...ids,sort_by:id && id.length>0 ? id.join(","):undefined};let copyname = { ...names,sortby_name:name};setNames(copyname);setIds(copy);chooseFunc(copy,copyname)}}
/>
}
</ul>

View File

@ -1,5 +1,4 @@
import React from 'react';
import { Tooltip } from 'antd';
import { getImageUrl } from 'educoder';
import issue from '../Img/issue.png';
import { Link } from "react-router-dom";
@ -9,7 +8,8 @@ import Copy from '../Component/copy';
// issue
function Datas({checkbox ,item , projectsId,owner}){
let host = window.location.hostname === "localhost" ? "testforgeplus.trustie.net" : window.location.hostname;
let protocol = window.location.protocol;
console.log("protocol:",protocol);
function statusTag(name){
switch (name) {
case "低":
@ -30,7 +30,7 @@ function Datas({checkbox ,item , projectsId,owner}){
<div className="ilog">
<span className={statusTag(item.priority_name)}>{item.priority_name}</span>
{ item.project_issues_index &&
<Copy value={`${host}/${owner}/${projectsId}/issues/${item.project_issues_index}`}><span className="number">#{item.project_issues_index}</span></Copy>
<Copy value={`${protocol}//${host}/${owner}/${projectsId}/issues/${item.project_issues_index}`}><span className="number">#{item.project_issues_index}</span></Copy>
}
</div>
<div style={{marginTop:"-2px"}}>
@ -41,7 +41,7 @@ function Datas({checkbox ,item , projectsId,owner}){
item.tags && item.tags.length>0?
item.tags.map((i,k)=>{
return(
<span style={{color: i.color}} className="ml8"><i className="iconfont icon-biaoji font-12"></i>{i.name}</span>
<span style={{color: i.color}} className="ml12"><i className="iconfont icon-biaoji font-12"></i>{i.name}</span>
)
})
:""

View File

@ -68,7 +68,9 @@ function EditMenus({
}
function chooseMenu(i){
setVisible(false);
if(!double){
setVisible(false);
}
let l = valueId;
let idStr = i && i.id ? i.id.toString() :i.name;
// idname

View File

@ -12,7 +12,7 @@ function NewPanel(props,ref){
const [ attachments , setAttachments ] = useState([]);
const [ receivers_login , setReceiversLogin ] = useState(undefined);
const { createFunc , title , desc , files , onCancel } = props;
const { createFunc , title , desc , files , onCancel , owner , projectsId } = props;
const { form: { getFieldDecorator, validateFields , setFieldsValue } } = props;
@ -29,12 +29,24 @@ function NewPanel(props,ref){
}
function UploadFunc(f){
let list = [];
let arr = [];
if(files && files.length>0 ){
let arr = files.map(i=>{return i.id});
list = arr && arr.length>0 ? f.concat(arr) : f ;
arr = files.map(i=>{return i.id});
}
list = arr && arr.length>0 ? f.concat(arr) : f ;
setFileList(list);
};
function deleteLoad(id){
let arr = [];
let list = files
if(list && list.length>0 ){
arr = list.filter(i=>i.id !== id);
}
console.log(arr.map(i=>{return i.id}));
setFileList(arr.map(i=>{return i.id}));
}
function changeAtWhoLoginList(loginList){
let list = new Set(receivers_login);
loginList.map(item => list.add(item));
@ -44,6 +56,7 @@ function NewPanel(props,ref){
function sureFunc(){
validateFields((error,values)=>{
if (!error) {
console.log(fileList);
createFunc(values,fileList,receivers_login,description);
}
})
@ -52,6 +65,8 @@ function NewPanel(props,ref){
function cancelFunc(){
if(onCancel){
onCancel();
}else{
window.history.back(-1);
}
}
return(
@ -72,6 +87,9 @@ function NewPanel(props,ref){
initValue={description}
onChange={onContentChange}
className="mt20"
isCanAtme = {true}
owner = {owner}
projectsId = {projectsId}
changeAtWhoLoginList = {changeAtWhoLoginList}
></MDEditor>
<div className="pb20">
@ -95,6 +113,7 @@ function NewPanel(props,ref){
attachments={attachments}
showNotification={props.showNotification}
canDelete={true}
deleteLoad={deleteLoad}
></Attachments>
}
</div>

View File

@ -91,8 +91,13 @@ function Details(props){
}
setNames(n);
data.start_date && setStartDate(moment(data.start_date).format('YYYY-MM-DD'));
console.log(data.due_date);
data.due_date && setDueDate(moment(data.due_date).format('YYYY-MM-DD'));
const {projectDetail} = props;
if(projectDetail){
const { author, name} = projectDetail;
document.title = `${data.subject}-疑修-${author.name}/${name}`;
}
}
}).catch(error=>{})
}
@ -131,7 +136,16 @@ function Details(props){
const url = `/v1/${owner}/${projectsId}/issue_priorities`;
axios.get(url).then(result=>{
if(result && result.data){
setPrioritiesList(result.data.priorities);
let priorities = result.data.priorities;
let array =[];
let colors = ["#1abcb1","#28be6c","#db3d1d","#db3d1d"];
if(priorities && priorities.length>0){
array = priorities.map((i,k)=>{
let arr = {...i,color:colors[k]}
return arr;
})
}
setPrioritiesList(array);
}
})
}
@ -307,6 +321,7 @@ function Details(props){
desc={details.description}
files={details.attachments}
createFunc={createFunc}
owner = {owner} projectsId = {projectsId}
/>
</div>
:

View File

@ -28,7 +28,8 @@ function List(props){
const [ allValue , setAllValue ] = useState([]);
const [ allIds , setAllIds ] = useState([]);
const [ checkAll , setCheckAll ] = useState(false);
const [ names , setNames ] = useState(undefined);
const [ updateIds , setUpdateIds ] = useState(undefined);
const [ page , setPage ] = useState(1);
@ -36,18 +37,64 @@ function List(props){
const [ total , setTotal ] = useState(undefined);
const [ issueTotal , setIssueTotal ] = useState(0);
const [ clearFlag , setClearFlag ] = useState(false);
const [ has_created_issues , setHas_created_issues] = useState(false);
const menuRef = useRef(null);
const owner = props.match.params.owner;
const projectsId = props.match.params.projectsId;
const permission = props && props.projectDetail && props.projectDetail.permission;
const { projectDetail } = props;
const states = cookie.load("states");
useEffect(()=>{
if(projectDetail){
const { author, name } = projectDetail;
document.title = `疑修-${author.name}/${name}`;
}
},[projectDetail])
useEffect(()=>{
if((updateIds && (updateIds.author_id || updateIds.issue_priorities_id || updateIds.issue_tag_ids || updateIds.milestone_id || updateIds.sort_by || updateIds.status_id ||updateIds.assigner_id)) || value){
setClearFlag(true);
}else{
setClearFlag(false);
}
},[updateIds,value])
useEffect(()=>{
if(states){
setUpdateIds({...states});
setAboutMe(states.participant_category);
setCategory(states.category);
setPage(states.page);
setLimit(states.limit);
setNames(states.names);
Init(states,states.page,states.names);
}else{
Init(updateIds,1);
}
},[])
// hook
const useUpdateEffect = (fn, inputs) => {
const didMountRef = useRef(false);
useEffect(() => {
if (didMountRef.current) fn();
else didMountRef.current = true;
}, inputs);
};
//
function handleAllDisabled(){
setTotal(undefined);
setLimit(defaultLimit);
Init(updateIds,1);
},[aboutMe,keyword,category])
}
// 使hook
useUpdateEffect(handleAllDisabled, [aboutMe,keyword,category]);
function getDirection(id){
if(!id) return undefined;
@ -69,18 +116,20 @@ function List(props){
}
// issue
function Init(params,p){
function Init(params,p,names){
const url = `/v1/${owner}/${projectsId}/issues`;
let getParams ={
participant_category:aboutMe,
keyword,category,
limit,
...params,
page:p || page,
sort_direction:getDirection(params && params.sort_by),
sort_by:getBy(params && params.sort_by)
}
console.log(getParams);
axios.get(url,{
params:{
participant_category:aboutMe,
keyword,category,
limit,
page:p || page,
...params,
sort_direction:getDirection(params && params.sort_by),
sort_by:getBy(params && params.sort_by)
}
params:{...getParams,names:undefined}
}).then(result=>{
if(result){
setIssueList(result.data.issues);
@ -90,8 +139,9 @@ function List(props){
const ids = result.data.issues.length>0 ? result.data.issues.map(i=>{return i.id}) : [];
setAllIds(ids);
setIssueTotal(result.data.total_issues_count);
setHas_created_issues(result.data.has_created_issues);
let d={participant_category:aboutMe,keyword,category,limit,page,...params}
let d={...getParams,names:{...names}}
let inFifteenMinutes = new Date(new Date().getTime() + 24 * 3600 * 1000);
cookie.save('states', {...d},{ expires: inFifteenMinutes,path:`/` });
}
@ -109,7 +159,7 @@ function List(props){
</Menu>
)
function chooseAboutMe(e){
setCategory("all");
setCategory("opened");
setAboutMe(e.key);
}
@ -120,6 +170,8 @@ function List(props){
setCategory("opened");
setTotal(undefined);
setUpdateIds(undefined);
setAllValue([]);
setValue(undefined);
Init();
//
menuRef.current && menuRef.current.clearChoose();
@ -133,6 +185,9 @@ function List(props){
if(e.target.checked){
setAllValue(allIds);
}else{
if(states){
setNames(states.names);
}
setAllValue([]);
}
}
@ -168,6 +223,7 @@ function List(props){
status_id: updateIds && updateIds.status_id
}).then(result=>{
if(result){
setAllValue([]);
setTotal(undefined);
Init();
cancelUpdate();
@ -176,9 +232,14 @@ function List(props){
}
//
function changepage(page){
setPage(page);
Init(updateIds,page);
function changepage(p){
setPage(p);
Init(updateIds,p);
if (document) { //
if (document.documentElement || document.body) {
document.documentElement.scrollTop = document.body.scrollTop = 0; //
}
}
}
// issue func
@ -197,14 +258,15 @@ function List(props){
}).catch(error=>{})
}
function chooseFunc(ids){
function chooseFunc(ids,n){
setNames(n);
if(allValue && allValue.length>0){
// ids便
setUpdateIds(ids);
}else{
setUpdateIds(ids);
setTotal(undefined);
Init(ids,1);
Init(ids,1,n);
}
}
@ -235,12 +297,16 @@ function List(props){
<Search
placeholder="输入关键字搜索疑修"
value={value}
onChange={e=>setValue(e.target.value)}
onChange={e=>{setValue(e.target.value);}}
onSearch={()=>setKeyword(value)}
style={{ width: 354 , height : 32 , marginLeft: 20 }}
allowClear
/>
<a className="color-blue ml25" onClick={clearCondition} style={{ display: "flex" , alignItems: "center"}}>
{
clearFlag &&
<a className="color-blue ml25" onClick={clearCondition} style={{ display: "flex" , alignItems: "center"}}>
<i className="iconfont icon-roundclose font-16 mr5"></i>清除筛选条件</a>
}
</div>
<div>
{
@ -253,7 +319,7 @@ function List(props){
<div className="lists">
<div className="listheader">
<div style={{display:"flex"}}>
<Checkbox value="all" style={{marginRight: "16px"}} checked={checkAll} onChange={chooseAll}></Checkbox>
<Checkbox value="all" style={{marginRight: "16px",display: (permission && permission !== "reporter") ?"block":"none"}} checked={checkAll} onChange={chooseAll}></Checkbox>
{
allValue && allValue.length>0 ?
<span>选择{allValue.length}个issue</span>
@ -272,6 +338,8 @@ function List(props){
owner={owner}
projectsId={projectsId}
chooseFunc={chooseFunc}
defaultNames={names}
defaultIds={allValue && allValue.length>0 ? undefined : updateIds}
/>
{
allValue && allValue.length>0 ?
@ -286,26 +354,26 @@ function List(props){
</div>
{
total === 0 &&
(issueTotal === 0 ?
<div className="dataempty"><img src={emp} alt="" /></div>
:
(!has_created_issues ?
<div className="listempty">
<img src={issueEmp} alt="" width="68px" />
<p className="font-22 mt5 mb10">欢迎使用疑修(Issue)</p>
<p className="font-15">疑修用于记录与跟踪待办事项项目bug功能需求等在使用之前请您先<Link to={`/${owner}/${projectsId}/issues/new`} className="color-blue">创建一个疑修</Link></p>
</div>
:
<div className="dataempty"><img src={emp} alt="" /></div>
)
}
{
total > 0 &&
<React.Fragment>
<Checkbox.Group name="issues" onChange={checkIssues} value={allValue} style={{ width: "100%" }}>
<Checkbox.Group name="issues" onChange={checkIssues} value={allValue} style={{ width: "100%"}}>
<div className="listdatas">
{issueList.map((item,key)=>{
return(
<Datas
key={key}
checkbox={ <Checkbox value={item.id} key={item.id} style={{marginRight: "16px"}}></Checkbox> }
checkbox={(permission && permission !== "reporter") && <Checkbox value={item.id} key={item.id} style={{marginRight: "16px"}}></Checkbox> }
item={item}
owner={owner}
projectsId={projectsId}

View File

@ -39,19 +39,13 @@ function New(props){
const projectsId = props.match.params.projectsId;
const permission = props && props.projectDetail && props.projectDetail.permission;
//
function updateDocumentTitle(){
// if(form_type === 'feedback'){
// document.title = ``
// }else if(form_type === 'new'){
// document.title = `-${author.name}/${name}`
// }else{
// subject && (document.title = `${subject}--${author.name}/${name}`);
// }
}
useEffect(()=>{
const {projectDetail} = props;
if(projectDetail){
const { author, name} = projectDetail;
document.title = `新建疑修-${author.name}/${name}`
}
},[])
//
@ -75,7 +69,16 @@ function New(props){
const url = `/v1/${owner}/${projectsId}/issue_priorities`;
axios.get(url).then(result=>{
if(result && result.data){
setPrioritiesList(result.data.priorities);
let priorities = result.data.priorities;
let array =[];
let colors = ["#1abcb1","#28be6c","#db3d1d","#db3d1d"];
if(priorities && priorities.length>0){
array = priorities.map((i,k)=>{
let arr = {...i,color:colors[k]}
return arr;
})
}
setPrioritiesList(array);
}
})
}
@ -183,7 +186,8 @@ function New(props){
<p className="font-20 color-grey-3 mt20 mb15">新建疑修</p>
<Box>
<LongWidth>
<NewPanel {...props} createFunc={createFunc}/>
<NewPanel {...props} createFunc={createFunc}
owner = {owner} projectsId = {projectsId}/>
</LongWidth>
<div className="shortwidth">
<EditMenus name="负责人" value={charegeId} names={names && names.assigner_name} imgFlag onChange={(ids,name)=>{setCharegeId(ids);let copyname = { ...names,assigner_name:name};setNames(copyname);}} list={chargeList} searchFlag searchFunc={(value)=>setCharge(value)} double={5}/>

View File

@ -56,16 +56,22 @@ function Sign(props){
const menu = (
<Menu onClick={arrayList} selectedKeys={[`${key}`]}>
<Menu.Item key={"1"} value="desc" createName="issues_count">
<Menu.Item key={"1"} value="desc" createName="created_at">
按疑修数量降序排序
</Menu.Item>
<Menu.Item key={"2"} value="asc" createName="issues_count">
<Menu.Item key={"2"} value="asc" createName="created_at">
按疑修数量升序排序
</Menu.Item>
<Menu.Item key={"3"} value="desc" createName="pull_requests_count">
<Menu.Item key={"3"} value="desc" createName="issues_count">
按疑修数量降序排序
</Menu.Item>
<Menu.Item key={"4"} value="asc" createName="issues_count">
按疑修数量升序排序
</Menu.Item>
<Menu.Item key={"5"} value="desc" createName="pull_requests_count">
按合并请求数量降序排序
</Menu.Item>
<Menu.Item key={"4"} value="asc" createName="pull_requests_count">
<Menu.Item key={"6"} value="asc" createName="pull_requests_count">
按合并请求数量升序排序
</Menu.Item>
</Menu>
@ -180,7 +186,7 @@ function Sign(props){
</div>
}
<div className="between bluebar">
<span>项目标记({total || 0})</span>
<span className="font-17">项目标记({total || 0})</span>
<Dropdown overlay={menu} trigger={["click"]} placement="bottomRight">
<a>{arrayName}<Icon type="caret-down" className="ml5 color-grey-6" /></a>
</Dropdown>

View File

@ -1,4 +1,4 @@
import React from 'react';
import React,{useEffect} from 'react';
import { Route, Switch } from "react-router-dom";
import Loadable from "react-loadable";
import Loading from "../../Loading";
@ -22,6 +22,15 @@ const New = Loadable({
});
function Index(props){
const pathname = props.history.location.pathname;
useEffect(() => {
if (document) { //
if (document.documentElement || document.body) {
document.documentElement.scrollTop = document.body.scrollTop = 0; //
}
}
}, [pathname]);
return(
<div className="pagebox">
<Switch>

View File

@ -148,6 +148,8 @@
display: block;
border:1px solid ;
border-color: rgba(70, 106, 255, 0.01);
min-width: 30px;
text-align: center;
}
}
}
@ -424,6 +426,7 @@
width: 100%;
height: 20px;
line-height: 20px;
font-weight: 600;
a{
position: absolute;
right: 0px;
@ -570,9 +573,11 @@
}
}
.descPanel{
margin:20px 0px;
margin-top:20px;
padding:20px;
background-color: #f7f8fd;
// background-color: #f7f8fd;
border:1px solid #c9d8ff;
border-radius: 2px;
}
// 新建页面
.explain{

View File

@ -151,13 +151,13 @@ class Index extends Component {
<Collaborator {...this.props} {...props} {...this.state} />
)}
></Route>
{/* 修改仓库信息 */}
<Route
{/* 修改仓库标记 */}
{/* <Route
path="/:owner/:projectsId/settings/labels"
render={(props) => (
<Tags {...this.props} {...props} {...this.state} />
)}
></Route>
></Route> */}
<Route
path="/:owner/:projectsId/settings/branches/:branch"
render={(props) => (

View File

@ -76,6 +76,7 @@ class Attachment extends Component {
};
deleteAttachment = (id) => {
const { deleteLoad } = this.props;
const url = `/attachments/${id}.json`;
axios
.delete(url, {})
@ -86,6 +87,7 @@ class Attachment extends Component {
Deleted: this.state.Deleted.concat(id),
});
this.props.showNotification("附件删除成功");
deleteLoad && deleteLoad(id);
} else {
this.props.showNotification(response.data.message);
}