forgeplus-react/src/forge/Merge/CreateMerge.js

439 lines
14 KiB
JavaScript
Raw Normal View History

import React, { Component } from 'react';
import { Input, Select, Spin, Alert } from 'antd';
import axios from 'axios';
import MergeForm from './merge_form';
import MergeFooter from './merge_footer';
import '../Order/order.css';
import './merge.css';
/**
* 根据url获取目标仓库目标分支源仓库源分支
* 路由规则owner/projectId/compare/merge...pullowner:pullBranch
* 可能存在的情况
* 1代码库首页跳转仓库相同目标分支为默认分支owner/projectId/compare/pullBranch
* 2代码库分支列表仓库相同目标分支为默认分支owner/projectId/compare/pullBranch
* 3合并请求列表页新建无数据时的提示仓库相同目标都为默认分支owner/projectId/compare
* 4新建页面切换分支切换目标仓库刷新页面等存在所有可能情况
*/
function getBranchParams(pathname) {
const result = {
// 目标仓库所有者
mergeOwner: undefined,
// 目标分支
mergeBranch: 'master',
// 源仓库所有者
pullOwner: undefined,
// 源分支
pullBranch: 'master',
// 仓库名称
projectId: undefined,
};
// 去掉第一个字符/
const _pathname = pathname.slice(1);
const [ownerProject, branchUrl] = _pathname.split('/compare');
const [mergeOwner, projectId] = ownerProject.split('/');
// 同仓库时
result.mergeOwner = mergeOwner;
result.pullOwner = mergeOwner;
result.projectId = projectId;
if (branchUrl) {
// 如果存在具体的分支
const _branchUrl = branchUrl.slice(1);
if (_branchUrl.indexOf('...') > -1) {
// 存在源分支与目标分支
const [mergeBranch, pullObj] = _branchUrl.split('...');
result.mergeBranch = mergeBranch;
if (pullObj.indexOf(':') > -1) {
// 存在源仓库
const [pullOwner, pullBranch] = pullObj.split(':');
result.pullOwner = pullOwner;
result.pullBranch = pullBranch;
} else {
result.pullBranch = pullObj;
}
} else {
result.pullBranch = _branchUrl;
}
}
return result;
}
const Option = Select.Option;
class CreateMerge extends Component {
constructor(props) {
super(props);
const { pullBranch, mergeBranch } = getBranchParams(
this.props.location.pathname
);
this.state = {
data: undefined,
pullBranches: undefined,
mergeBranches: undefined,
mergeProjects: undefined,
merge: mergeBranch || 'master',
pull: pullBranch || 'master',
id: undefined,
// isFork: false,
projects_names: undefined,
isSpin: true,
showMessage: false,
merge_head: false, // 是否向fork后的源项目发起合并请求
defaultMessage: '必须选择不同的分支',
project_id: undefined, // 当前项目的id也即开始发送合并请求的源项目id
merge_project_user: undefined,
comparesData: undefined, //提交和文件的内容保存compare接口返回的数据
// 比较分支时的加载效果
isCompareSpin: true,
// 是否是初次加载用这个字段来控制提示组件和文件组件的显示、隐藏比直接用isCompareSpin交互友好些
isFirstLoading: true,
};
}
componentDidMount = () => {
// 初始化时根据url获取目标仓库、分支源仓库、分支
// 再获取对应的仓库列表、分支列表
// 再调用比较接口
const branchParams = getBranchParams(this.props.location.pathname);
console.log('componentDidMount branchParams', branchParams);
this.getMergeInfo(branchParams);
};
componentDidUpdate = (preProps) => {
// url变化触发时切换源分支、切换目标仓库、切换目标分支回退
const oldPathname = preProps.location.pathname;
const newPathname = this.props.location.pathname;
if (oldPathname !== newPathname) {
const branchParams = getBranchParams(newPathname);
console.log('componentDidUpdate branchParams', branchParams);
this.getMergeInfo(branchParams);
}
};
//获取新建合并请求数据
getMergeInfo = (branchParams) => {
this.setState({ isSpin: true });
const { pullOwner, pullBranch, mergeOwner, mergeBranch, projectId } =
branchParams;
const url = `/${pullOwner}/${projectId}/pulls/new.json`;
axios
.get(url)
.then((result) => {
if (result) {
2021-10-13 16:38:43 +08:00
// 如果url上的分支不存在取默认值master
const noMergeBranch =
(result.data.branches || []).filter(
(branch) => branch.name === mergeBranch
).length === 0;
const noPullBranch =
(result.data.branches || []).filter(
(branch) => branch.name === pullBranch
).length === 0;
this.setState({
// isFork: result.data.is_fork,
projects_names: result.data.projects_names,
mergeProjects: result.data.merge_projects,
pullBranches: result.data.branches,
mergeBranches: result.data.branches,
project_id: result.data.project_id,
id: result.data.id,
merge: mergeBranch,
pull: pullBranch,
});
2021-10-13 16:38:43 +08:00
if (!noMergeBranch && !noPullBranch) {
this.compareProject(result.data.id, branchParams);
} else {
const _message = [];
noMergeBranch && _message.push('目标分支不存在');
noPullBranch && _message.push('源分支不存在');
this.setState({
showMessage: true,
defaultMessage: _message.join(' , '),
isCompareSpin: false,
});
}
}
if (pullOwner !== mergeOwner) {
2021-10-13 16:38:43 +08:00
this.getBranchList(branchParams);
}
this.setState({ isSpin: false });
})
.catch((error) => {
this.setState({ isSpin: false });
console.log(error);
});
};
// compare接口获取分支对比信息
compareProject = (baseid, branchParams) => {
// const { project } = this.props;
// const { owner, projectsId } = this.props.match.params;
const projectObj = this.props.project;
const { pullOwner, pullBranch, mergeOwner, mergeBranch, projectId } =
branchParams;
let url = `/${mergeOwner}/${projectId}/compare`;
if (projectObj) {
if (baseid === projectObj.id) {
url += `/${pullBranch}...${mergeBranch}.json`;
} else {
url += `/${mergeBranch}...${pullOwner}/${projectId}:${pullBranch}.json`;
}
this.setState({ isSpin: false, isCompareSpin: true });
axios
.get(url)
.then((result) => {
if (result) {
if (result.data.status === 0) {
this.setState({
showMessage: false,
});
} else {
this.setState({
showMessage: true,
defaultMessage: result.data.message,
});
}
this.setState({
comparesData: result.data,
});
}
this.setState({
isFirstLoading: false,
isSpin: false,
isCompareSpin: false,
});
})
.catch((error) => {
this.setState({ isSpin: false, isCompareSpin: false });
});
}
};
// 根据所有者、仓库名,获取分支列表,目前仅涉及目标仓库分支查询
2021-10-13 16:38:43 +08:00
getBranchList = ({ mergeOwner, projectId, mergeBranch }) => {
this.setState({ isSpin: true });
2021-10-13 16:38:43 +08:00
const url = `/${mergeOwner}/${projectId}/pulls/get_branches.json`;
axios
.get(url)
.then((result) => {
if (result) {
2021-10-13 16:38:43 +08:00
const noMergeBranch =
(result.data || []).filter((branch) => branch.name === mergeBranch)
.length === 0;
this.setState({
mergeBranches: result.data,
2021-10-13 16:38:43 +08:00
merge: noMergeBranch ? 'master' : mergeBranch,
});
}
this.setState({ isSpin: false });
})
.catch((error) => {
this.setState({ isSpin: false });
console.log(error);
});
};
// 切换分支事件
selectBrach = (type, value) => {
const { pullOwner, pullBranch, mergeOwner, mergeBranch, projectId } =
getBranchParams(this.props.location.pathname);
let _url = `/${mergeOwner}/${projectId}/compare/`;
// type为pull时pullBranch取value否则取原有值
// type为pull时mergeBranch取原有值否则取value
let _pullBranch = type === 'pull' ? value : pullBranch;
let _mergeBranch = type === 'pull' ? mergeBranch : value;
if (pullOwner === mergeOwner) {
// 如果仓库相同, compare/目标分支...源分支
_url += `${_mergeBranch}...${_pullBranch}`;
} else {
// 如果仓库不同, compare/目标分支...源分支
_url += `${_mergeBranch}...${pullOwner}:${_pullBranch}`;
}
this.props.history.push(_url);
};
// 切换仓库响应事件,目前仅目标分支可切换仓库
selectProjectName = (value) => {
const { projects_names, id } = this.state;
const { pullOwner, pullBranch } = getBranchParams(
this.props.location.pathname
);
let arr =
projects_names && projects_names.filter((item) => item.id === value);
let identifier = arr && arr[0].project_id;
let login = arr && arr[0].project_user_login;
// 目标仓库与源仓库不是一个仓库
let is_fork = parseInt(value, 10) !== parseInt(id, 10);
this.setState({
isSpin: true,
// merge_head: is_fork,
data: {
is_original: is_fork,
fork_project_id: is_fork ? id : '',
merge_user_login: is_fork
? projects_names[0].project_user_login
: undefined,
},
});
if (login === pullOwner) {
// 如果切换后, 仓库与源仓库一致了
this.props.history.push(
`/${login}/${identifier}/compare/master...${pullBranch}`
);
} else {
this.props.history.push(
`/${login}/${identifier}/compare/master...${pullOwner}:${pullBranch}`
);
}
// this.newMergelist(login, identifier);
};
// 渲染分支列表
renderBrances = (list) => {
if (list && list.length > 0) {
return list.map((item, key) => {
return (
<Option key={key + 1} value={item.name}>
{item.name}
</Option>
);
});
}
};
// 渲染项目列表
renderProjectNames = (list) => {
if (list && list.length > 0) {
return list.map((item, key) => {
return (
<Option key={key + 1} value={item.id}>
{item.project_name}
</Option>
);
});
}
};
// 渲染html内容
withHtml = (html) => {
return <div dangerouslySetInnerHTML={{ __html: html }}></div>;
};
render() {
const {
data,
pullBranches,
mergeBranches,
mergeProjects,
pull,
merge,
isSpin,
isCompareSpin,
isFirstLoading,
showMessage,
defaultMessage,
projects_names,
id,
comparesData,
} = this.state;
let { project } = this.props;
return (
<div>
2021-10-13 16:38:43 +08:00
<Spin spinning={isSpin || isCompareSpin}>
<div className="main">
<div className="merge-header width100 inline-block">
<div className="width40 pull-left">
<div className="color-grey-3 mb10 fwb">源分支:</div>
<Input.Group compact className="display-flex">
<Select
value={id}
className="hide-1 task-hide flex1"
disabled
>
{this.renderProjectNames(projects_names)}
</Select>
<Select
value={pull}
onSelect={(e) => this.selectBrach('pull', e)}
showSearch
className="merge-flex1 flex1"
>
{this.renderBrances(pullBranches)}
</Select>
</Input.Group>
</div>
<div className="width10 pull-left text-center mt25">
<i
className={'iconfont icon-youjiang color-grey-c font-32'}
></i>
</div>
<div className="width40 pull-left">
<div>
<div className="color-grey-3 mb10 fwb">目标分支:</div>
<Input.Group compact className="display-flex">
<Select
value={project && project.id}
className="hide-1 task-hide flex1"
onSelect={(e) => this.selectProjectName(e)}
>
{this.renderProjectNames(mergeProjects)}
</Select>
<Select
value={merge}
onSelect={(e) => this.selectBrach('merge', e)}
showSearch
className="merge-flex1 flex1"
>
{this.renderBrances(mergeBranches)}
</Select>
</Input.Group>
</div>
</div>
</div>
{/* 非加载状态且有提示 */}
{!isCompareSpin && showMessage && (
<div className="mb20">
<Alert
description={this.withHtml(defaultMessage)}
type="error"
/>
</div>
)}
{/* 非加载状态且可以提交 */}
{!isCompareSpin && !showMessage && (
<MergeForm
{...this.props}
merge_type="new"
data={data}
merge={merge}
pull={pull}
files_count={
comparesData &&
comparesData.diff &&
comparesData.diff.files_count
}
commits_count={comparesData && comparesData.commits_count}
></MergeForm>
)}
</div>
{!isFirstLoading && (
<MergeFooter
{...this.props}
merge={merge}
pull={pull}
comparesData={comparesData}
></MergeFooter>
)}
</Spin>
</div>
);
}
}
export default CreateMerge;