From 0d1345f957344415f2a9b20c57ed8cbc074101cf Mon Sep 17 00:00:00 2001 From: caishi <1149225589@qq.com> Date: Fri, 4 Dec 2020 19:26:14 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=86=E6=94=AF=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/forge/Main/IndexItem.js | 2 +- src/forge/Settings/Branch.js | 101 ++++++++-- src/forge/Settings/BranchRule.jsx | 313 ++++++++++++++++++++++++------ src/forge/Settings/Index.js | 6 +- src/forge/Settings/setting.scss | 40 ++++ src/forge/users/CIdispose.jsx | 1 - 6 files changed, 384 insertions(+), 79 deletions(-) diff --git a/src/forge/Main/IndexItem.js b/src/forge/Main/IndexItem.js index 87f336b1..ab9a6a29 100644 --- a/src/forge/Main/IndexItem.js +++ b/src/forge/Main/IndexItem.js @@ -63,7 +63,7 @@ class IndexItem extends Component { {/* {item.visits} */} {/* {item.category && item.category.id && {item.category.name}} */} - {item.last_update_time ? {item.time_ago} : ""} + {item.last_update_time ? {item.time_ago} : ""} {item.language && item.language.id ? {item.language.name} : ""} diff --git a/src/forge/Settings/Branch.js b/src/forge/Settings/Branch.js index 2a391bc6..cdb644b8 100644 --- a/src/forge/Settings/Branch.js +++ b/src/forge/Settings/Branch.js @@ -2,8 +2,11 @@ import React , { useEffect, useState } from 'react'; import SelectBranch from '../Branch/Select'; import Title from '../Component/Title'; import styled from 'styled-components'; -import { Blueline , FlexAJ , NumUl , GreenUnder , AlignCenter , WhiteBack } from '../Component/layout'; +import { AlignCenter , WhiteBack , FlexAJ } from '../Component/layout'; import axios from 'axios'; +import { Button, Select } from 'antd'; +import { getBranch } from '../GetData/getData'; + const Div = styled.div`{ padding:20px 30px; min-height:500px; @@ -11,6 +14,13 @@ const Div = styled.div`{ export default ((props)=>{ const [ branch , setBranch ] = useState("master"); + const [ branchList , setBranchList ] = useState(undefined); + const [ protectBranch , setProtectBranch ] = useState(undefined); + const [ protectBranchList , setProtectBranchList ] = useState(undefined); + + const [ count , setCount ] = useState(0); + const [ page , setPage ] = useState(1); + const { projectsId , owner } = props.match.params; const projectDetail = props.projectDetail; @@ -21,7 +31,36 @@ export default ((props)=>{ } },[defaultBranch]); + useEffect(()=>{ + if(owner){ + getBranchs(projectsId,owner); + getProtectBranchList(owner,projectsId); + } + },[owner]) + // 获取已经设置过分支保护的分支列表 + function getProtectBranchList(owner,repo){ + const url = `/${owner}/${repo}/protected_branches.json`; + axios.get(url,{ + params:{ + page,limit:15 + } + }).then(result=>{ + if(result){ + setCount(result.data.total_count); + setProtectBranchList(result.data.protected_branches); + } + }).catch(error=>{}) + } + + // 获取分支列表(下拉、过滤掉已经设置过分支保护的分支) + async function getBranchs(id,owner){ + let re = await getBranch(id,owner); + setBranchList(re); + + } + + // 设为默认分支 function resetSetting(){ const url = `/${owner}/${projectsId}.json`; axios.put(url, { @@ -36,15 +75,18 @@ export default ((props)=>{ console.log(error); }); } - function settingRule(){ - props.history.push(`/projects/${owner}/${projectsId}/setting/branch/new`); + + // 跳转 + function settingRule(protectBranch){ + props.history.push(`/projects/${owner}/${projectsId}/setting/branch/${protectBranch}`); } + return( 分支设置
-
-

默认分支

+
+

默认分支

默认分支被视作为代码库中的基本分支,是所有克隆、代码提交、合并请求的目标分支

{ resetSetting()}>设为默认分支
-
- - 保护分支规则 - settingRule()}>+ 新建规则 - - -
  • 限制分支的推送、合并。强制推送相关请去{props.history.push(`/projects/${owner}/${projectsId}/setting`)}}>仓库设置
  • -
  • 一个分支同时只能有一个保护分支规则生效,越早创建的规则优先级越高。
  • -
  • 保护分支规则只影响状态是【保护分支】的分支。【常规分支】和【只读分支】都不影响。
  • -
    +
    +

    分支保护

    + + + settingRule(protectBranch)}>设置分支保护 + + { + protectBranchList && protectBranchList.length > 0 && +
    + { + protectBranchList.map((item,key)=>{ + return( + + {item.branch_name} + + + ) + }) + } +
    + }
    diff --git a/src/forge/Settings/BranchRule.jsx b/src/forge/Settings/BranchRule.jsx index 9cdb951b..e11e7f61 100644 --- a/src/forge/Settings/BranchRule.jsx +++ b/src/forge/Settings/BranchRule.jsx @@ -1,21 +1,20 @@ import React, { forwardRef, useCallback, useState, useEffect } from "react"; -import { Form, Input, Select, Button } from "antd"; +import { Form, InputNumber , Select, Button , Checkbox , Radio } from "antd"; import Title from "../Component/Title"; -import { WhiteBack, Cancel } from "../Component/layout"; -import styled from "styled-components"; +import { Cancel } from "../Component/layout"; import axios from "axios"; -const { Option } = Select; -const Div = styled.div` -{ - padding: 20px 30px; -} -`; export default Form.create()( - forwardRef(({ form, match, history }) => { + forwardRef(({ form, match, history , showNotification }) => { + const [ protect , setProtect ] = useState(false); + const [ protects , setProtects ] = useState(false); + const [ mergeOptions , setMergeOptions ] = useState(undefined); + const [ approveOptions , setApproveOptions ] = useState(undefined); + const [ options , setOptions ] = useState(undefined); const [ list, setList ] = useState(undefined); - const { projectsId, owner } = match.params; - const { getFieldDecorator, validateFields } = form; + + const { projectsId, owner , branch } = match.params; + const { getFieldDecorator, validateFields , setFieldsValue } = form; useEffect(() => { const url = `/${owner}/${projectsId}/collaborators.json`; @@ -25,23 +24,65 @@ export default Form.create()( .catch((error) => {}); }, []); - function getMember(list) { - return ( - list && - list.length > 0 && - list.map((item, key) => { - return ( - item.role !== "Manager" && ( - - ) - ); - }) - ); + useEffect(()=>{ + if(branch){ + // 需要设置分支保护的分支名,获取分支保护详情 + getGuardDetail(owner,projectsId,branch); + } + },[branch]); + + function getGuardDetail(owner,projectsId,branch){ + const url = `/${owner}/${projectsId}/protected_branches/${branch}/edit.json`; + axios.get(url).then((result)=>{ + if(result){ + setProtect(result.data.protected); + setProtects(result.data.protected); + let protected_branch = result.data.protected_branch; + + if(protected_branch){ + let enable_push = protected_branch.enable_push_whitelist ? 2 : protected_branch.enable_push ? 1 : 0; + + setOptions(enable_push); + setMergeOptions(protected_branch.enable_merge_whitelist); + setApproveOptions(protected_branch.enable_approvals_whitelist); + + setFieldsValue({ + + enable_push, + ...protected_branch + }) + } + } + }).catch(error=>{}); } + function saveBranchRule() { validateFields((error, values) => { if (!error) { + let url = ""; + if(protects){ + // 为true则修改 + url = `/${owner}/${projectsId}/protected_branches/${branch}.json`; + }else{ + // 否则是保存 + url = `/${owner}/${projectsId}/protected_branches.json`; + } + axios({ + method:!protects ? "post" : (protect ? "patch" : "delete"), + url, + params: + { + branch_name:branch, + enable_push:values.enable_push !== 0 , + enable_push_whitelist:values.enable_push === 2 ? true : false, + ...values + } + }).then(result=>{ + if(result){ + showNotification("保存成功!"); + } + }).catch(error=>{}) } }); } @@ -50,49 +91,202 @@ export default Form.create()( (label, name, rules, widget, className, isRequired) => (
    {label} - - {getFieldDecorator(name, { rules, validateFirst: true })(widget)} + + {getFieldDecorator(name, { rules, validateFirst: true })(widget)}
    ), [] ); + // 启用分支保护 + function changeProtect(e){ + setProtect(e.target.checked); + } + // 切换保护选线 + function changeProtectOption(e){ + setOptions(e.target.value); + } + // 切换是否启用合并白名单 + function changeMergeOption(e){ + setMergeOptions(e.target.checked); + } + + // 是否启用批准仅限列入白名单的用户或团队 + function changeWhitelistUsernameOption(e){ + setApproveOptions(e.target.checked); + } return ( - +
    新建保护分支规则 -
    +
    +
    {helper( - "设置分支/通配符", - "sign", - [{ required: true, message: "请输入分支/通配符" }], - , + "", + "branchProtect", + [], + + 启用分支保护组织删除并限制Git推送和合并到分支 + , "setStyleRule" )} -

    - 例如:设置为“master”,则对名称为“master”的分支生效;设置为“*-stable“ - 或 ”release*“,则对名称符合此通配符的所有保护分支生效。 -

    - {helper( - "可推送代码成员", - "psuhmember", - [{ required: true, message: "请选择可推送代码成员" }], - , - "setSelectWidth" - )} - {helper( - "可合并Pull Request成员", - "pullmember", - [{ required: true, message: "请选择可合并Pull Request成员" }], - , - "setSelectWidth" - )} -
    +
    + {helper( + "", + "enable_push", + [], + + + + 禁用推送此分支不允许推送 + + + 启用推送任何拥有写访问权限的人将被允许推送到此分支(但不能强行推送) + + + 启用推送白名单只有列入白名单的用户或团队才能被允许推送到此分支(但不能强行推送) + + , + "" + )} +
    + {helper( + "", + "push_whitelist_usernames", + [], + , + "setStyleRule" + )} +
    + {helper( + "", + "enable_merge_whitelist", + [], + + 启用合并白名单仅允许白名单用户或团队合并合并请求到此分支 + , + "setStyleRule" + )} +
    + {helper( + "", + "merge_whitelist_usernames", + [], + , + "setStyleRule" + )} +
    + {helper( + "", + "enable_status_check", + [], + + 启用状态检查 + , + "setStyleRule" + )} +
    + {helper( + "所需的批准数", + "required_approvals", + [], + , + "inlineFlex" + )} + 只允许合并有足够审核人数的拉取请求 +
    + + {helper( + "", + "enable_approvals_whitelist", + [], + + 批准仅限列入白名单的用户或团队只有白名单用户或团队的审核才能计数 没有批准的白名单,任何有写访问权限的人的审核都将计数 + , + "setStyleRule" + )} +
    + {helper( + "", + "approvals_whitelist_usernames", + [], + , + "setStyleRule" + )} +
    + + {helper( + "", + "block_on_rejected_reviews", + [], + + 拒绝审核阻止了合并如果官方审查人员要求作出改动,即使有足够的批准,合并也不允许 + , + "setStyleRule" + )} + + {helper( + "", + "dismiss_stale_approvals", + [], + + 取消过时的批准当新的提交更改合并请求内容被推送到分支时,旧的批准将被撤销 + , + "setStyleRule" + )} + {helper( + "", + "require_signed_commits", + [], + + 需要签名提交 + , + "setStyleRule" + )} + {helper( + "", + "block_on_outdated_branch", + [], + + 如果拉取请求已经过时,阻止合并当头部分支落后基础分支时,不能合并 + , + "setStyleRule" + )} +
    + +
    @@ -105,8 +299,9 @@ export default Form.create()( 取消
    -
    - +
    +
    +
    ); }) ); diff --git a/src/forge/Settings/Index.js b/src/forge/Settings/Index.js index db80c8b3..1e294b35 100644 --- a/src/forge/Settings/Index.js +++ b/src/forge/Settings/Index.js @@ -65,7 +65,7 @@ class Index extends Component {

    - {/*
  • -1 ? "active" : "" } @@ -76,7 +76,7 @@ class Index extends Component { 分支设置

    -
  • */} +
  • -1 ? "active" : ""} > @@ -120,7 +120,7 @@ class Index extends Component { )} > ( )} diff --git a/src/forge/Settings/setting.scss b/src/forge/Settings/setting.scss index a9d5a103..dd2905a4 100644 --- a/src/forge/Settings/setting.scss +++ b/src/forge/Settings/setting.scss @@ -187,7 +187,29 @@ width: 100%; } } +.shortStyle{ + .setStyleRule{ + height: 35px; + } + .columsRadio{ + display: block; + height: 30px; + line-height: 30px; + } + .ant-row.ant-form-item{ + margin-bottom: 0px; + } +} +.inlineFlex{ + display: flex; + align-items: center; + & > span{ + margin-right: 10px; + color: #666; + } +} .setStyleRule{ + height: 35px; .ant-row.ant-form-item{ margin-bottom: 10px; } @@ -196,4 +218,22 @@ .ant-select.ant-select-enabled{ width: 100%; } +} +.setHeight{ + .ant-select-selection,.ant-select-selection__rendered{ + height: 40px; + line-height: 40px; + } +} +.protectBranchList{ + border:1px solid #eee; + border-radius: 5px; + margin-top: 25px; + &>div{ + padding:5px 15px; + border-bottom: 1px solid #eee; + } + &>div:last-child{ + border-bottom: none; + } } \ No newline at end of file diff --git a/src/forge/users/CIdispose.jsx b/src/forge/users/CIdispose.jsx index a0ec8f37..d53287e5 100644 --- a/src/forge/users/CIdispose.jsx +++ b/src/forge/users/CIdispose.jsx @@ -4,7 +4,6 @@ import { AlignCenter } from '../Component/layout'; import axios from 'axios'; import Modals from '../Component/Modal'; import PasswordAuthority from '../Component/PasswordAuthority'; -import { func } from 'prop-types'; const TIPS = "解除CI服务器绑定后,您所有的项目构建数据将被清空。确定解除绑定?"; function CIdispose(props){