- {
- data.versions.map((item, key) => {
- return (
-
-
-
-
-
-
- {item.effective_date || "暂无截止时间"}
-
-
-
- {item.open_issues_count}个开启
-
-
-
- {item.close_issues_count}个关闭
-
-
- {
- data && data.user_admin_or_member ?
-
-
-
- 编辑
-
-
-
-
-
this.closemile(item)}>
- 删除
-
-
-
- : ''
- }
-
-
-
- {item.description}
-
-
+ {/* 里程碑列表展示 */}
+ {data && data.milestones && data.milestones.length === 0 &&
}
+ {data && data.milestones && data.milestones.length > 0 &&
+ {data.milestones.map((item, key)=>{
+ return
+
+
+
+ {item.name}
+
+
{item.description}
+
+
+
+
+ {item.effective_date || "暂无截止时间"}
+
+
+ {item.opened_issues_count || 0}个开启
+ |
+ {item.close_issues_count || 0}个关闭
+
+ {
+ (isManager || isDeveloper) &&
+
编辑
+
- )
- })
- }
+
+
+
this.closemile(item)}>
+ 删除
+
+
+
+ }
+
- }
- { data && data.versions && data.versions.length === 0 &&
}
+ })}
+
}
{
- data && data.versions_count > limit ?
-
-
+ data && data.total_count > limit ?
+
: ""
}
diff --git a/src/forge/Order/MilepostDetail.jsx b/src/forge/Order/MilepostDetail.jsx
new file mode 100644
index 000000000..863c8ad64
--- /dev/null
+++ b/src/forge/Order/MilepostDetail.jsx
@@ -0,0 +1,267 @@
+import React , { useRef , useState , useEffect } from 'react';
+import { Dropdown , Menu , Icon , Input , Checkbox , Pagination, Button , Tooltip ,Spin } from 'antd';
+import { Link } from "react-router-dom";
+import issueEmp from '../Issues/Img/issue-big.png';
+import AllMenus from './component/allMenus';
+import Datas from '../Issues/Component/datas';
+import axios from 'axios';
+import { FlexAJ } from '../Component/layout';
+import './milepost.scss';
+import './order.scss';
+import '../Issues/index.scss';
+const { Search } = Input;
+
+function MilepostDetail(props){
+ const [ milepost, setMilepost] = useState(undefined);
+ const [ issueList , setIssueList ] = useState(undefined);
+ const [ closedCount , setClosedCount ] = useState(0);
+ const [ openedCount , setOpenedCount ] = useState(0);
+
+ const[ aboutMe , setAboutMe ] = useState("aboutme");
+ const[ value , setValue ] = useState("");
+ const[ keyword , setKeyword ] = useState(undefined);
+
+ const [ category , setCategory] = useState("all");
+
+ const [ allValue , setAllValue ] = useState([]);
+ const [ allIds , setAllIds ] = useState([]);
+ const [ checkAll , setCheckAll ] = useState(false);
+
+ const [ updateIds , setUpdateIds ] = useState([]);
+ const [ limit, setLimit] = useState(10);
+ const [ page , setPage ] = useState(1);
+ const [ total , setTotal ] = useState(undefined);
+
+ const menuRef = useRef(null);
+ const { projectsId, mileId , owner } = props.match.params;
+ const {current_user, projectDetail, showLoginDialog, history} = props;
+ const permission = props && props.projectDetail && props.projectDetail.permission;
+
+ useEffect(()=>{
+ Init();
+ },[aboutMe, keyword, category, page, limit])
+
+ useEffect(()=>{
+ updateDocumentTitle()
+ }, [projectDetail, milepost])
+
+ // 更新网页标题
+ function updateDocumentTitle(){
+ if(projectDetail && milepost){
+ const { author, name} = projectDetail;
+ document.title = `${milepost.name}-里程碑-${author.name}/${name}`;
+ }
+ }
+
+ // 获取issue列表数据
+ function Init(params){
+ const url = `/v1/${owner}/${projectsId}/milestones/${mileId}.json`;
+ axios.get(url,{
+ params:{
+ page,
+ limit,
+ category,
+ // participant_category:aboutMe,
+ // 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){
+ const {milestone, issues, total_issues_count, closed_issues_count, opened_issues_count} = result.data;
+ setMilepost(milestone);
+ setIssueList(issues);
+ setTotal(total_issues_count);
+ setClosedCount(closed_issues_count);
+ setOpenedCount(opened_issues_count);
+ const ids = issues.length>0 ? issues.map(i=>{return i.id}) : [];
+ setAllIds(ids);
+ }
+ }).then(error=>{console.log("error:",error)})
+ }
+
+ // 第一个下拉搜索
+ const menu = (
+
+ )
+ function chooseAboutMe(e){
+ setCategory("all");
+ setAboutMe(e.key);
+ }
+
+ //清除筛选条件
+ function clearCondition(){
+ setKeyword(undefined);
+ setAboutMe("aboutme");
+ Init();
+ // 清除下拉选项
+ menuRef.current && menuRef.current.clearChoose();
+
+ }
+
+ // 全选所有issue
+ function chooseAll(e){
+ setCheckAll(e.target.checked);
+ if(e.target.checked){
+ setAllValue(allIds);
+ }else{
+ setAllValue([]);
+ }
+ }
+
+ // 选择列表里的issue
+ function checkIssues(value){
+ 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],
+ 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=>{})
+ }
+
+ // 切换页码
+ function changepage(page){
+ setPage(page);
+ }
+
+ function chooseFunc(ids){
+ if(allValue && allValue.length>0){
+ // 将ids保存下来以便修改
+ setUpdateIds(ids);
+ }else{
+ Init(ids);
+ }
+ }
+
+ return(
+
+ {milepost &&
+
+
{milepost.name}
+
+
+
+ {milepost.effective_date || '暂无截止时间'}
+
+ {(milepost.percent || milepost.percent===0) ? {milepost.percent > 0 ? milepost.percent.toFixed(2):milepost.percent}%完成 :"" }
+
+
+
+ {
+ (current_user && current_user.login) && ( projectDetail && projectDetail.permission && projectDetail.permission !== "Reporter") ?
+ 编辑里程碑
+ :""
+ }
+ {
+ current_user && current_user.login ?
+
+ :
+ }
+
+ }
+
+
+
+
+ {
+ allValue && allValue.length>0 ?
+
选择{allValue.length}个issue
+ :
+
+ - setCategory("all")}>全部{total}
+ - setCategory("opened")}>开启中{openedCount}
+ - setCategory("closed")}>已关闭{closedCount}
+
+ }
+
+
+
0}
+ owner={owner}
+ projectsId={projectsId}
+ chooseFunc={chooseFunc}
+ />
+ {
+ allValue && allValue.length>0 ?
+
+
+
+
+ :""
+ }
+
+
+ {
+ total === 0 &&
+
+

+
欢迎使用疑修(Issue)
+
疑修用于记录与跟踪待办事项、项目bug、功能需求等。在使用之前,请您先创建一个疑修
+
+ }
+ {
+ total > 0 &&
+
+
+
+ {issueList.map((item,key)=>{
+ return(
+ }
+ item={item}
+ owner={owner}
+ projectsId={projectsId}
+ />
+ )
+ })
+ }
+
+
+ {
+ total > 10 &&
+
+
{setPage(1);setLimit(pageSize);}}/>
+
+ }
+
+ }
+ {total === undefined &&
}
+
+
+ )
+}
+export default MilepostDetail;
\ No newline at end of file
diff --git a/src/forge/Order/MilepostDetail.js b/src/forge/Order/MilepostDetail_old.js
similarity index 74%
rename from src/forge/Order/MilepostDetail.js
rename to src/forge/Order/MilepostDetail_old.js
index 9505fe535..eb7c30dbb 100644
--- a/src/forge/Order/MilepostDetail.js
+++ b/src/forge/Order/MilepostDetail_old.js
@@ -1,14 +1,15 @@
import React, { Component } from "react";
import { Link } from 'react-router-dom';
-import { Dropdown, Menu, Icon, Pagination, Spin } from 'antd';
+import { Dropdown, Menu, Icon, Pagination, Spin, Button, Checkbox } from 'antd';
import './order.scss';
import { FlexAJ } from '../Component/layout';
import CheckProfile from '../Component/ProfileModal/Profile';
-
+import AllMenus from "../Issues/Component/allMenus";
import NoneData from '../Nodata';
import OrderItem from './OrderItem';
import axios from 'axios';
+import './milepost.scss';
/**
* issue_chosen:下拉的筛选列表,
@@ -22,6 +23,7 @@ import axios from 'axios';
* search_count:列表总条数
* issue_type:搜索条件
* status_type: issue的关闭和开启,1表示开启中的,2表示关闭的
+ * category: issue状态: 全部、开启、关闭
*/
class MilepostDetail extends Component {
constructor(props) {
@@ -47,7 +49,11 @@ class MilepostDetail extends Component {
status_ids: "状态",
done_ratios: '完成度',
paix: '排序',
- issueFlag:true
+ issueFlag:true,
+ checkAll: false,
+ allValue: [],
+ allIds: [],
+ category: 'all'
}
}
@@ -55,7 +61,6 @@ class MilepostDetail extends Component {
this.getSelectList();
const { page } = this.state;
this.getIssueList(page);
- //
}
componentDidUpdate=(prevProps)=>{
@@ -122,7 +127,7 @@ class MilepostDetail extends Component {
const { projectsId, meilid , owner } = this.props.match.params;
const { limit , order_name , order_type , issue_tag_id , author_id , assigned_to_id , tracker_id , status_id , done_ratio , status_type } = this.state;
- const url = `/${owner}/${projectsId}/milestones/${meilid}.json`;
+ const url = `/v1/${owner}/${projectsId}/milestones/${meilid}.json`;
let params = update ? {
page, limit , order_name:value , order_type:updateValue , issue_tag_id ,
author_id , assigned_to_id , tracker_id , status_id , done_ratio,
@@ -138,7 +143,7 @@ class MilepostDetail extends Component {
}).then((result) => {
if (result) {
this.setState({
- data: result.data,
+ data: result.data.milestone,
issues: result.data.issues,
search_count: params.status_type ==="1" ? result.data.open_issues_count : result.data.close_issues_count,
isSpin: false
@@ -211,7 +216,7 @@ class MilepostDetail extends Component {
this.getIssueList(page);
}
- openorder = (type) => {
+ category = (type) => {
this.setState({
status_type: type,
issue_tag_id : undefined,
@@ -233,9 +238,18 @@ class MilepostDetail extends Component {
}
+ // 全选所有issue
+ chooseAll = (e) =>{
+ const {allIds} = this.state;
+ this.setState({
+ checkAll: e.target.checked,
+ allValue: e.target.checked ? allIds : []
+ });
+ }
+
render() {
- const { issue_chosen, issues, limit, page, search_count, data, isSpin , status_type , issueFlag } = this.state;
+ const { issue_chosen, issues, limit, page, search_count, data, isSpin , status_type , issueFlag, checkAll, allValue, category } = this.state;
const { projectsId, meilid ,owner} = this.props.match.params;
const { current_user , showLoginDialog , projectDetail } = this.props;
const menu = (
@@ -247,42 +261,74 @@ class MilepostDetail extends Component {
)
return (
-
-
-
{data && data.name}
-
-
-
-
+
+
+
+
{data && data.name}
+
+
+
{
data && data.effective_date ?
- {data && data.effective_date}
+ {data && data.effective_date}
:
- 暂无截止时间
+ 暂无截止时间
}
- {data && (data.percent || data.percent===0) ? {data.percent > 0 ? data.percent.toFixed(2):data.percent}%完成 :"" }
-
-
+ {data && (data.percent || data.percent===0) ? {data.percent > 0 ? data.percent.toFixed(2):data.percent}%完成 :"" }
+
+
+
+ {
+ (current_user && current_user.login) && ( projectDetail && projectDetail.permission && projectDetail.permission !== "Reporter") ?
+ 编辑里程碑
+ :""
+ }
+ {
+ issueFlag ? (current_user && current_user.login ?
+
+ :)
+ :""
+ }
+
+
+
+
+
+
+
{
- (current_user && current_user.login) && ( projectDetail && projectDetail.permission && projectDetail.permission !== "Reporter") ?
-
编辑里程碑
- :""
- }
- {
- issueFlag ? (current_user && current_user.login ?
-
{this.props.history.push(`/${owner}/${projectsId}/issues/${meilid}/new`)}} className="topWrapper_btn">创建疑修
+ allValue && allValue.length>0 ?
+
选择{allValue.length}个issue
:
-
创建疑修
- ):""
+
+ - this.category("all")}>全部{total}
+ - this.category("opened")}>开启中{openedCount}
+ - this.category("closed")}>已关闭{closedCount}
+
}
-
-
-
-
-
+
+
0}
+ owner={owner}
+ projectsId={projectsId}
+ chooseFunc={chooseFunc}
+ />
+ {
+ allValue && allValue.length>0 ?
+
+
+
+
+
+ :""
+ }
+
+
+ {/*
- this.openorder("1")}>{data && data.open_issues_count}个开启中
@@ -352,7 +398,7 @@ class MilepostDetail extends Component {
:""
}
-
+ */}
)
diff --git a/src/forge/Order/component/allMenus.jsx b/src/forge/Order/component/allMenus.jsx
new file mode 100644
index 000000000..85cd991ce
--- /dev/null
+++ b/src/forge/Order/component/allMenus.jsx
@@ -0,0 +1,140 @@
+import React,{ useState , useEffect , forwardRef ,useImperativeHandle , useRef } from 'react';
+import Menus from '../../Issues/Component/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 [ chargeList , setChargeList ] = useState(undefined);
+ const [ charge , setCharge ] = useState(undefined);
+ const [ millstone , setMillstone ] = useState(undefined);
+ const [ millstoneList , setMillstoneList ] = 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(()=>{
+ 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);
+ }
+ })
+ }
+
+ function choose(id,name){
+ let copy = {...ids,author_id:id.join(",")};
+ let copyname = { ...names,author_name:name}
+ setIds(copy);setNames(copyname);
+ chooseFunc(copy);
+ }
+
+ // 获取里程碑列表
+ 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);
+ }
+ })
+ }
+ return(
+
+ { !update && setAuthor(value)}
+ chooseFunc={(id,name)=>choose(id,name,'author_name')}
+ />
+ }
+ 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)}}
+ />
+ setCharge(value)}
+ chooseFunc={(id,name)=>{let copy = {...ids,assigner_id:id.join(",")};let copyname = { ...names,assigner_name:name};setNames(copyname);setIds(copy);chooseFunc(copy)}}
+ />
+ { !update && {let copy = {...ids,sort_by:id.join(",")};let copyname = { ...names,sortby_name:name};setNames(copyname);setIds(copy);chooseFunc(copy)}}
+ />
+ }
+ {update && setMillstone(value)}
+ chooseFunc={(id,name)=>{let copy = {...ids,milestone_id:id.join(",")};let copyname = { ...names,milestone_name:name};setNames(copyname);setIds(copy);chooseFunc(copy)}}
+ />}
+
+ )
+}
+export default forwardRef(AllMenus);
\ No newline at end of file
diff --git a/src/forge/Order/milepost.scss b/src/forge/Order/milepost.scss
new file mode 100644
index 000000000..884134ed0
--- /dev/null
+++ b/src/forge/Order/milepost.scss
@@ -0,0 +1,90 @@
+.milepostBox{
+ border: none;
+ padding: 0;
+ .createMilepost{
+ text-align: right;
+ }
+}
+.flexSpaceBetween{
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+.milepostHead{
+ background-color:#fafcff;
+ border:1px solid rgba(42, 97, 255, 0.23);
+ color:#898d9d;
+ padding: 15px 15px 15px 20px;
+ border-radius:4px 4px 0px 0px;
+ .postStatus.active{
+ font-weight:700;
+ color:#333333;
+ }
+ .statusCount{
+ background-color:rgba(70, 106, 255, 0.09);
+ border-radius:10px;
+ margin-left: 5px;
+ padding: 4px 7px;
+ color:#666666;
+ font-weight: normal;
+ }
+}
+.pointBox{
+ cursor: pointer;
+}
+.milepostSort{
+ box-shadow:0px 0px 10px rgba(24, 54, 181, 0.17);
+}
+.milepostList{
+ border-left: 1px solid #d0d0d0;
+ border-right: 1px solid #d0d0d0;
+ .milepostItemBox{
+ border-bottom: 1px solid #d0d0d0;
+ padding: 15px 20px;
+ }
+ .milepostInfo{
+ display: inline-block;
+ width: 500px;
+ }
+ .actionMileBox{
+ width: 550px;
+ }
+}
+.createMilepostBtn{
+ width: 96px;
+ padding: 0;
+}
+.primaryColor, .primaryColor:link, .flexSpaceBetween .primaryColor{
+ color: $primary-color;
+}
+.effectiveDate, .flexSpaceBetween .effectiveDate{
+ color:#40424a;
+}
+.color-grey-89{
+ color: #898d9d;
+}
+.colorRed, .colorRed:hover{
+ color:#f30000;
+}
+.milestonesNoDate{
+ border:1px solid#d0d0d0;
+ border-top: none;
+}
+// 浅灰色按钮
+.grayButton{
+ width:108px;
+ height:32px;
+ text-align: center;
+ background-color:#fafbfc;
+ border:1px solid #d0d0d0;
+ border-radius:4px;
+ &:hover{
+ background-color: #f3f4f6;
+ }
+}
+
+// 里程碑详情页面
+.milepostDetail{
+ border: none;
+ padding: 0;
+}
\ No newline at end of file
diff --git a/src/forge/Order/order.scss b/src/forge/Order/order.scss
index bff07c9a8..d0e64df29 100644
--- a/src/forge/Order/order.scss
+++ b/src/forge/Order/order.scss
@@ -29,14 +29,6 @@
justify-content: space-between;
flex-wrap: wrap;
}
-
-.miledetail {
- padding:15px 20px;
- box-sizing: border-box;
- justify-content: space-between;
- border-bottom: 1px solid #eeeeee;
- flex-wrap: wrap;
-}
.topWrapper_nav {
display: flex;
}
diff --git a/src/forge/Upload/Index.js b/src/forge/Upload/Index.js
index ea8ab180e..616c90141 100644
--- a/src/forge/Upload/Index.js
+++ b/src/forge/Upload/Index.js
@@ -12,6 +12,19 @@ class Index extends Component {
}
}
componentDidMount=()=>{
+ const {defaultFileList} = this.props;
+ if(defaultFileList){
+ const files = [];
+ defaultFileList.map(i=>{
+ files.push({
+ uid: i.id,
+ name: i.title,
+ status: 'done',
+ url: i.url
+ })
+ })
+ this.setState({fileList: files})
+ }
this.checkInitFile();
}
componentDidUpdate=(prevProps)=>{