forgeplus-react/src/forge/Issues/Pages/list.jsx

420 lines
14 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React , { useRef , useState , useEffect } from 'react';
import { Dropdown , Menu , Icon , Input , Checkbox , Pagination, Button , Tooltip ,Spin } from 'antd';
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 AllMenus from '../Component/allMenus';
import CheckProfile from '../../Component/ProfileModal/Profile';
import Datas from '../Component/datas';
import DelBox from '../Component/delBox';
import axios from 'axios';
import cookie from 'react-cookies';
import emp from '../Img/emp.png';
const { Search } = Input;
const defaultLimit = 15;
function List(props){
const [ visible , setVisible ] = useState(false);
const [ issueList , setIssueList ] = useState(undefined);
const [ closedCount , setClosedCount ] = useState(0);
const [ openedCount , setOpenedCount ] = useState(0);
const[ aboutMe , setAboutMe ] = useState("all");
const[ value , setValue ] = useState("");
const[ keyword , setKeyword ] = useState(undefined);
const [ category , setCategory] = useState("opened");
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);
const [ limit , setLimit ] = useState(15);
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 , current_user} = props;
useEffect(()=>{
if(projectDetail){
const { author, name } = projectDetail;
document.title = `疑修-${author.name}/${name}`;
}
},[projectDetail])
useEffect(()=>{
const datas = cookie.load('issuestates');
let states = datas === "undefined" ? undefined : datas;
if(states){
setAboutMe(states.participant_category);
setCategory(states.category);
setPage(states.page);
setLimit(states.limit || defaultLimit);
setUpdateIds({...states});
setNames(states.names);
if(states.participant_category ==="all" && states.category === "opened" && states.page === 1 && states.limit===defaultLimit)
Init({...states},states.page,states.names);
}else{
Init();
}
},[])
useEffect(()=>{
let v = allValue && allValue > 0;
if((updateIds && !v && (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])
// 自定义一个初始不更新的hook
const useUpdateEffect = (fn, inputs) => {
const didMountRef = useRef(false);
useEffect(() => {
if (didMountRef.current) fn();
else didMountRef.current = true;
}, inputs);
};
// 定义处理函数
function handleAllDisabled(){
Init(updateIds,page,names);
}
// 使用自定义hook
useUpdateEffect(handleAllDisabled, [aboutMe,keyword,category,limit]);
// useEffect(()=>{
// Init(updateIds,page,names);
// },[aboutMe,keyword,category,limit])
function getDirection(id){
if(!id) return undefined;
if(id === "1" || id === "3" || id === "5"){
return "desc"
}else{
return "asc"
}
}
function getBy(id){
if(!id) return undefined;
if(id === "1" || id === "2"){
return "issues.created_on"
}else if(id === "3" || id === "4"){
return "issues.updated_on"
}else{
return "issue_priorities.position"
}
}
// 获取issue列表数据
function Init(params,p,names){
const datas = cookie.load('issuestates');
let states = datas === "undefined" ? undefined : datas;
if(states){
cookie.remove('issuestates');
}
const url = `/v1/${owner}/${projectsId}/issues`;
axios.get(url,{
params:{
...params,
page:p || 1,
keyword,
participant_category:aboutMe,
category,
limit,
sort_direction:getDirection(params && params.sort_by),
sort_by:getBy(params && params.sort_by),
}
}).then(result=>{
if(result){
setIssueList(result.data.issues);
setTotal(result.data.total_count);
setClosedCount(result.data.closed_count);
setOpenedCount(result.data.opened_count);
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);
const d = {...params,keyword,participant_category:aboutMe,category,limit,page:p || 1,
sort_direction:getDirection(params && params.sort_by),
sort_by:getBy(params && params.sort_by),names:names};
let inFifteenMinutes = new Date(new Date().getTime() + 24 * 3600 * 1000);
cookie.save('issuestates', {...d},{ expires: inFifteenMinutes,path:`/` });
}
}).then(error=>{})
}
// 第一个下拉搜索
const menu = (
<Menu selectedKeys={[`${aboutMe}`]} onClick={chooseAboutMe}>
<Menu.Item key={"all"}>全部</Menu.Item>
<Menu.Item key={"aboutme"}><Tooltip title="指我创建的、我负责的和@我的疑修">与我相关</Tooltip></Menu.Item>
<Menu.Item key={"assignedme"}>我负责的</Menu.Item>
<Menu.Item key={"authoredme"}>我创建的</Menu.Item>
<Menu.Item key={"atme"}>@我的</Menu.Item>
</Menu>
)
function chooseAboutMe(e){
setPage(1);
setCategory("opened");
setAboutMe(e.key);
}
//清除筛选条件
function clearCondition(){
setKeyword(undefined);
setAboutMe("all");
setCategory("opened");
setTotal(undefined);
setUpdateIds(undefined);
setAllValue([]);
setValue(undefined);
setNames(undefined);
setValue(undefined);
Init();
// 清除下拉选项
menuRef.current && menuRef.current.clearChoose();
}
// 全选所有issue
function chooseAll(e){
setCheckAll(e.target.checked);
// 清除下拉选项
menuRef.current && menuRef.current.clearChoose();
if(e.target.checked){
setAllValue(allIds);
}else{
setAllValue([]);
}
}
// 选择列表里的issue
function checkIssues(value){
// 清除下拉选项
menuRef.current && menuRef.current.clearChoose();
setAllValue(value);
if(value.length === allIds.length){
setCheckAll(true);
}else{
setCheckAll(false);
}
}
// 取消
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 && updateIds.assigner_id.split(","),
ids: allValue,
issue_tag_ids: updateIds && updateIds.issue_tag_ids && updateIds.issue_tag_ids.split(","),
milestone_id: updateIds && updateIds.milestone_id,
priority_id: updateIds && updateIds.issue_priorities_id,
status_id: updateIds && updateIds.status_id
}).then(result=>{
if(result){
setUpdateIds(undefined);
setAllValue([]);
setTotal(undefined);
Init();
cancelUpdate();
}
}).catch(error=>{})
}
// 切换页码
function changepage(p){
setPage(p);
Init(updateIds,p,names);
if (document) { // 可以排除不需要置顶的页面
if (document.documentElement || document.body) {
document.documentElement.scrollTop = document.body.scrollTop = 0; // 切换路由时手动置顶
}
}
}
// 删除issue相关 func
function onSuccess(){
const url = `/v1/${owner}/${projectsId}/issues/batch_destroy`;
axios.delete(url,{
params:{ids:allValue}
}).then(result=>{
if(result){
setUpdateIds(undefined);
setAllValue([]);
setVisible(false);
setCheckAll(false);
props.showNotification("疑修删除成功!");
Init();
}
}).catch(error=>{})
}
function chooseFunc(ids,n){
setNames(n);
setPage(1);
if(allValue && allValue.length>0){
// 将ids保存下来以便修改
setUpdateIds(ids);
}else{
setUpdateIds(ids);
setTotal(undefined);
Init(ids,1,n);
}
}
function chageLimit(c,p){
setPage(1);
setLimit(p);
}
function changeCategory(value){
setCategory(value);
setPage(1);
setTotal(undefined);
}
function changeSearchValueFunc(e){
setValue(e.target.value);
if(e.target.value===""){
setKeyword(undefined);
}
}
return(
<div>
<DelBox visible={visible} onCancel={()=>setVisible(false)} onSuccess={onSuccess}/>
<div className="pageheader">
<div>
{
(current_user && current_user.login) &&
<Dropdown overlay={menu} trigger={['click']} placement="bottomLeft" arrow={{pointAtCenter: true}}>
<span className="dorpdownButton mr20">
<span>{aboutMe === "all" ? "全部":aboutMe === "aboutme"?"与我相关":aboutMe === "assignedme"?"我负责的":aboutMe === "authoredme"?"我创建的":"@我的"}</span>
<Icon type="caret-down" className="ml5 color-grey-6" />
</span>
</Dropdown>
}
<Search
placeholder="输入关键字搜索疑修"
value={value}
onChange={changeSearchValueFunc}
onSearch={()=>setKeyword(value)}
style={{ width: 354 , height : 32 }}
allowClear
/>
{
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>
{
permission && permission !== "Reporter" &&
<Link to={`/${owner}/${projectsId}/issues/sign`} className="dorpdownButton"><img src={bj} alt="" className="mr5" />标记管理</Link>
}
<CheckProfile {...props} sureFunc={()=>{props.history.push(`/${owner}/${projectsId}/issues/new`)}} checklogin className="operateButton ml20">创建疑修</CheckProfile>
</div>
</div>
<div className="lists">
<div className="listheader">
<div style={{display:"flex"}}>
<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>
:
<ul className="statusul">
<li className={category === "all" ?"active":""} onClick={()=>{changeCategory("all")}}>全部<span>{issueTotal}</span></li>
<li className={category === "opened" ?"active":""} onClick={()=>{changeCategory("opened")}}>开启中<span>{openedCount}</span></li>
<li className={category === "closed" ?"active":""} onClick={()=>{changeCategory("closed")}}>已关闭<span>{closedCount}</span></li>
</ul>
}
</div>
<div className="menusul">
<AllMenus
ref={menuRef}
update={allValue && allValue.length>0}
owner={owner}
projectsId={projectsId}
chooseFunc={chooseFunc}
defaultNames={names}
defaultIds={allValue && allValue.length>0 ? undefined : updateIds}
/>
{
allValue && allValue.length>0 ?
<div>
<Button type="primary" ghost onClick={sureUpdate}>确定</Button>
<Button type="danger" ghost className="ml10" onClick={()=>setVisible(true)}>删除</Button>
<Button ghost className="ml10 mr10" onClick={cancelUpdate}>取消</Button>
</div>
:""
}
</div>
</div>
{
total === 0 &&
(!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功能需求等在使用之前请您先<CheckProfile {...props} checklogin sureFunc={()=>{props.history.push(`/${owner}/${projectsId}/issues/new`)}} className="color-blue">创建一个疑修</CheckProfile></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%"}}>
<div className="listdatas">
{issueList.map((item,key)=>{
return(
<Datas
key={key}
checkbox={(permission && permission !== "Reporter") && <Checkbox value={item.id} key={item.id} style={{marginRight: "16px"}}></Checkbox> }
item={item}
owner={owner}
projectsId={projectsId}
/>
)
})
}
</div>
</Checkbox.Group>
{
total > defaultLimit &&
<div className="pt25 pb30" style={{textAlign:"right"}}>
<Pagination total={total} onShowSizeChange={chageLimit} current={page} pageSize={limit} onChange={changepage} showSizeChanger pageSizeOptions={[15,30,40,50]} showQuickJumper />
</div>
}
</React.Fragment>
}
{total === undefined && <div style={{height:344,display:"flex",alignItems:"center",justifyContent:"center"}}><Spin /></div> }
</div>
</div>
)
}
export default List;