forked from Gitlink/forgeplus-react
Merge branch 'newVersion_forge' into dev_chain
This commit is contained in:
commit
9fe7d6471c
|
@ -100,7 +100,7 @@ export function initAxiosInterceptors(props) {
|
|||
// TODO 读取到package.json中的配置?
|
||||
var proxy = "http://localhost:3000"
|
||||
// proxy = "https://pre-newweb.educoder.net"
|
||||
proxy = "https://testforgeplus.trustie.net/"
|
||||
proxy = "https://testforgeplus.trustie.net"
|
||||
|
||||
// 在这里使用requestMap控制,避免用户通过双击等操作发出重复的请求;
|
||||
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
import React , { useState , useEffect } from 'react';
|
||||
import { AutoComplete } from 'antd';
|
||||
import { getImageUrl } from "educoder";
|
||||
import axios from 'axios';
|
||||
const Option = AutoComplete.Option;
|
||||
|
||||
export default ({ getUser })=>{
|
||||
const [ searchKey , setSearchKey ] = useState(undefined);
|
||||
const [ userDataSource , setUserDataSource ] = useState(undefined);
|
||||
|
||||
function getUserList(e){
|
||||
const url = `/users/list.json`;
|
||||
axios.get(url, {
|
||||
params: {
|
||||
search: e,
|
||||
},
|
||||
})
|
||||
.then((result) => {
|
||||
if (result) {
|
||||
setUserDataSource(result.data.users);
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log(error);
|
||||
});
|
||||
};
|
||||
|
||||
function changeInputUser(value){
|
||||
setSearchKey(value);
|
||||
getUserList(value);
|
||||
}
|
||||
|
||||
function selectInputUser(id, option){
|
||||
setSearchKey(option.props.searchValue);
|
||||
getUserList(option.props.searchValue);
|
||||
getUser && getUser(id);
|
||||
}
|
||||
const source =
|
||||
userDataSource && userDataSource.map((item, key) => {
|
||||
return (
|
||||
<Option
|
||||
key={key}
|
||||
value={`${item.user_id}`}
|
||||
searchValue={`${item.username}`}
|
||||
>
|
||||
<img
|
||||
className="user_img radius"
|
||||
width="28"
|
||||
height="28"
|
||||
src={getImageUrl(`images/${item && item.image_url}`)}
|
||||
alt=""
|
||||
/>
|
||||
<span className="ml10" style={{ "vertical-align": "middle" }}>
|
||||
{item.username}
|
||||
<span className="color-grey ml10">({item.login})</span>
|
||||
</span>
|
||||
</Option>
|
||||
);
|
||||
});
|
||||
return(
|
||||
<AutoComplete
|
||||
dataSource={source}
|
||||
value={searchKey}
|
||||
style={{ width: 300 }}
|
||||
onChange={changeInputUser}
|
||||
onSelect={selectInputUser}
|
||||
placeholder="搜索需要添加的用户..."
|
||||
/>
|
||||
)
|
||||
}
|
|
@ -49,11 +49,12 @@ export const WhiteBack = styled.div`{
|
|||
}`
|
||||
export const Blueline = styled.a`{
|
||||
height:32px;
|
||||
line-height:32px;
|
||||
line-height:30px;
|
||||
border-radius:2px;
|
||||
border:1px solid rgba(80,145,255,1);
|
||||
color:rgba(80,145,255,1);
|
||||
padding:0px 12px;
|
||||
display:inline-block;
|
||||
}`
|
||||
export const Redline = styled.a`{
|
||||
height:32px;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import React, { Component } from "react";
|
||||
import { Popconfirm, Select } from "antd";
|
||||
import { Popconfirm, Select } from "antd";
|
||||
import "./list.css";
|
||||
import axios from "axios";
|
||||
import Meditor from "../Newfile/m_editor";
|
||||
|
@ -16,17 +16,85 @@ class CoderRootFileDetail extends Component {
|
|||
super(props);
|
||||
this.state = {
|
||||
value: undefined,
|
||||
language: undefined
|
||||
language: undefined,
|
||||
languages: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount = () => {
|
||||
const { detail } = this.props;
|
||||
|
||||
this.setState({
|
||||
value: detail.content,
|
||||
});
|
||||
this.languages_total();
|
||||
};
|
||||
|
||||
languages_total = () => {
|
||||
const { detail } = this.props;
|
||||
const file_name = detail.path.split("/").pop().split(".").pop();
|
||||
let languages = [];
|
||||
let default_language = "javascript";
|
||||
let all_languages = {
|
||||
apex: ["apex", "apxc"],
|
||||
azcli: ["azcli"],
|
||||
bat: ["bat"],
|
||||
clojure: ["clj"],
|
||||
coffee: ["coffee"],
|
||||
cpp: ["cpp"],
|
||||
csharp: ["cs"],
|
||||
csp: ["csp"],
|
||||
css: ["css"],
|
||||
dockerfile: ["dockerfile", "docker", "yml"],
|
||||
fsharp: ["fs"],
|
||||
go: ["go"],
|
||||
html: ["html", "htm", "erb"],
|
||||
ini: ["ini"],
|
||||
java: ["java", "class"],
|
||||
javascript: ["js"],
|
||||
json: ["json"],
|
||||
less: ["less"],
|
||||
lua: ["lua"],
|
||||
markdown: ["markdown", "md", "rmd"],
|
||||
msdax: ["dax"],
|
||||
mysql: ["sql"],
|
||||
objective: ["m", "mm", "o", "out"],
|
||||
perl: ["perl"],
|
||||
pgsql: ["sql"],
|
||||
php: ["php"],
|
||||
postiats: ["postiats"],
|
||||
powerquery: [""],
|
||||
powershell: ["ps1"],
|
||||
pug: ["pug"],
|
||||
python: ["py"],
|
||||
r: ["r"],
|
||||
razor: ["cshtml"],
|
||||
redis: ["rdb"],
|
||||
ruby: ["rb"],
|
||||
rust: ["rs"],
|
||||
sb: ["sb"],
|
||||
scheme: ["scm", "ss"],
|
||||
scss: ["scss"],
|
||||
shell: ["sh"],
|
||||
solidity: ["sol"],
|
||||
sql: ["sql"],
|
||||
st: ["st"],
|
||||
swift: ["swift"],
|
||||
typescript: ["ts"],
|
||||
vb: ["vbp", "frm", "frx", "bas", "cls"],
|
||||
xml: ["xml"],
|
||||
yaml: ["yml"],
|
||||
};
|
||||
for (var item in all_languages) {
|
||||
languages.push(item);
|
||||
let item_values = all_languages[item];
|
||||
if (item_values.indexOf(file_name) !== -1) {
|
||||
default_language = item;
|
||||
}
|
||||
}
|
||||
this.state.languages = languages;
|
||||
this.state.language = default_language;
|
||||
};
|
||||
|
||||
select_language = (e) => {
|
||||
this.setState({
|
||||
language: e,
|
||||
|
@ -39,7 +107,6 @@ class CoderRootFileDetail extends Component {
|
|||
// readOnly: false,
|
||||
// });
|
||||
};
|
||||
|
||||
|
||||
// 编辑文件
|
||||
|
||||
|
@ -73,7 +140,6 @@ class CoderRootFileDetail extends Component {
|
|||
});
|
||||
};
|
||||
|
||||
|
||||
updateCode = (value) => {
|
||||
this.setState({
|
||||
value,
|
||||
|
@ -81,73 +147,30 @@ class CoderRootFileDetail extends Component {
|
|||
};
|
||||
|
||||
render() {
|
||||
const { readOnly , detail, current_user, isManager, isDeveloper } = this.props;
|
||||
const { language } = this.state;
|
||||
const {
|
||||
readOnly,
|
||||
detail,
|
||||
current_user,
|
||||
isManager,
|
||||
isDeveloper,
|
||||
} = this.props;
|
||||
const { language, languages } = this.state;
|
||||
let flag = current_user && current_user.login && (isManager || isDeveloper);
|
||||
const Option = Select.Option;
|
||||
const languages = [
|
||||
"apex",
|
||||
"azcli",
|
||||
"bat",
|
||||
"clojure",
|
||||
"coffee",
|
||||
"cpp",
|
||||
"csharp",
|
||||
"csp",
|
||||
"css",
|
||||
"dockerfile",
|
||||
"fsharp",
|
||||
"go",
|
||||
"handlebars",
|
||||
"html",
|
||||
"ini",
|
||||
"java",
|
||||
"javascript",
|
||||
"json",
|
||||
"less",
|
||||
"lua",
|
||||
"markdown",
|
||||
"msdax",
|
||||
"mysql",
|
||||
"objective",
|
||||
"perl",
|
||||
"pgsql",
|
||||
"php",
|
||||
"postiats",
|
||||
"powerquery",
|
||||
"powershell",
|
||||
"pug",
|
||||
"python",
|
||||
"r",
|
||||
"razor",
|
||||
"redis",
|
||||
"redshift",
|
||||
"ruby",
|
||||
"rust",
|
||||
"sb",
|
||||
"scheme",
|
||||
"scss",
|
||||
"shell",
|
||||
"solidity",
|
||||
"sql",
|
||||
"st",
|
||||
"swift",
|
||||
"typescript",
|
||||
"vb",
|
||||
"xml",
|
||||
"yaml",
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="mb20">
|
||||
<div className="grid-item branchTitle">
|
||||
<div className="grid-item">
|
||||
<span className="ml20 color-grey-6 font-16">{bytesToSize(detail && detail.size)}</span>
|
||||
<span className="ml20 color-grey-6 font-16">
|
||||
{bytesToSize(detail && detail.size)}
|
||||
</span>
|
||||
</div>
|
||||
<p className="text-right">
|
||||
{flag && (
|
||||
<div>
|
||||
{readOnly ? (
|
||||
<a onClick={()=>this.EditFile(false)} className="ml20">
|
||||
<a onClick={() => this.EditFile(false)} className="ml20">
|
||||
<i className="iconfont icon-bianji1 font-15 color-grey-6"></i>
|
||||
</a>
|
||||
) : (
|
||||
|
@ -160,14 +183,19 @@ class CoderRootFileDetail extends Component {
|
|||
onChange={this.select_language}
|
||||
>
|
||||
<Option value={undefined}>请选择文本语言</Option>
|
||||
{languages.map((item, key) => {
|
||||
return <Option value={item}>{item}</Option>;
|
||||
})}
|
||||
{languages &&
|
||||
languages.map((item, key) => {
|
||||
return (
|
||||
<Option value={item} key={key}>
|
||||
{item}
|
||||
</Option>
|
||||
);
|
||||
})}
|
||||
</Select>
|
||||
<button
|
||||
type="button"
|
||||
className="ant-btn ant-btn-sm ml20"
|
||||
onClick={()=>this.EditFile(true)}
|
||||
onClick={() => this.EditFile(true)}
|
||||
>
|
||||
<span>取 消</span>
|
||||
</button>
|
||||
|
@ -187,20 +215,22 @@ class CoderRootFileDetail extends Component {
|
|||
</Popconfirm>
|
||||
</div>
|
||||
)}
|
||||
{
|
||||
detail.image_type && detail.direct_download ?
|
||||
<div className="ml20">
|
||||
<a href={detail.download_url} className="color-blue font-15">
|
||||
下载原始文件
|
||||
</a>
|
||||
</div>:""
|
||||
}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
{detail.image_type && detail.direct_download ? (
|
||||
{detail.image_type ? (
|
||||
<div className="edu-txt-center pt20 pb20">
|
||||
<img alt="" src={detail.download_url} style={{maxWidth:"80%"}}/>
|
||||
<img
|
||||
alt=""
|
||||
src={detail.download_url}
|
||||
style={{ maxWidth: "80%" }}
|
||||
/>
|
||||
</div>
|
||||
) : detail.direct_download ? (
|
||||
<div className="mt20 text-center">
|
||||
<a href={detail.download_url} className="color-blue font-15">
|
||||
下载原始文件
|
||||
</a>
|
||||
</div>
|
||||
) : (
|
||||
<Meditor
|
||||
|
|
|
@ -12,7 +12,7 @@ class UserSubmitComponent extends Component {
|
|||
this.state = {
|
||||
submitType: "0",
|
||||
filename: "",
|
||||
isSpin: false
|
||||
isSpin: false,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -22,19 +22,19 @@ class UserSubmitComponent extends Component {
|
|||
});
|
||||
};
|
||||
|
||||
// 命名文件
|
||||
changeFileName = (e) => {
|
||||
this.setState({
|
||||
filename: e.target.value,
|
||||
});
|
||||
};
|
||||
// 命名文件
|
||||
changeFileName = (e) => {
|
||||
this.setState({
|
||||
filename: e.target.value,
|
||||
});
|
||||
};
|
||||
|
||||
// 提交变更
|
||||
subMitFrom = () => {
|
||||
const { filepath, content,editor_type } = this.props;
|
||||
const { filepath, content, editor_type } = this.props;
|
||||
const { branch, projectsId } = this.props.match.params;
|
||||
const { submitType, filename } = this.state;
|
||||
this.setState({isSpin: true})
|
||||
this.setState({ isSpin: true });
|
||||
let path = editor_type === "upload" ? filepath : filepath.substr(1);
|
||||
this.props.form.validateFieldsAndScroll((err, values) => {
|
||||
if (!err) {
|
||||
|
@ -48,28 +48,28 @@ class UserSubmitComponent extends Component {
|
|||
message: values.desc,
|
||||
})
|
||||
.then((result) => {
|
||||
this.setState({isSpin: false})
|
||||
this.setState({ isSpin: false });
|
||||
if (result.data && result.data.name) {
|
||||
let url = values.branchname
|
||||
? `/projects/${projectsId}/coders?branch=${values.branchname}`
|
||||
: `/projects/${projectsId}/coders`;
|
||||
? `/projects/${projectsId}/coders?branch=${values.branchname}`
|
||||
: `/projects/${projectsId}/coders`;
|
||||
this.props.history.push(url);
|
||||
this.props.showNotification("文件新建成功!");
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
this.setState({isSpin: false})
|
||||
this.setState({ isSpin: false });
|
||||
console.log(error);
|
||||
});
|
||||
}else{
|
||||
this.setState({isSpin: false})
|
||||
} else {
|
||||
this.setState({ isSpin: false });
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 确认修改文件
|
||||
UpdateFile = () => {
|
||||
this.setState({isSpin: true})
|
||||
this.setState({ isSpin: true });
|
||||
const { branch, detail, content, filepath } = this.props;
|
||||
const { projectsId } = this.props.match.params;
|
||||
const { submitType } = this.state;
|
||||
|
@ -86,28 +86,28 @@ class UserSubmitComponent extends Component {
|
|||
message: values.desc,
|
||||
})
|
||||
.then((result) => {
|
||||
this.setState({isSpin: false})
|
||||
this.setState({ isSpin: false });
|
||||
if (result.data && result.data.status === 1) {
|
||||
let url = values.branchname
|
||||
? `/projects/${projectsId}/coders?branch=${values.branchname}`
|
||||
: `/projects/${projectsId}/coders`;
|
||||
|
||||
|
||||
this.props.history.push(url);
|
||||
this.props.showNotification("修改成功!");
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
this.setState({isSpin: false})
|
||||
this.setState({ isSpin: false });
|
||||
console.log(error);
|
||||
});
|
||||
}else{
|
||||
this.setState({isSpin: false})
|
||||
} else {
|
||||
this.setState({ isSpin: false });
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { submitType,filename, isSpin } = this.state;
|
||||
const { submitType, filename, isSpin } = this.state;
|
||||
const { getFieldDecorator } = this.props.form;
|
||||
|
||||
const { branch, projectsId } = this.props.match.params;
|
||||
|
@ -160,81 +160,89 @@ class UserSubmitComponent extends Component {
|
|||
<span className="color-grey-8">提交变更</span>
|
||||
</span>
|
||||
<Spin spinning={isSpin}>
|
||||
<div className="userScrew">
|
||||
<div className="screwPanel">
|
||||
<Form>
|
||||
<Form.Item style={{display: editor_type === "upload" ? "block" : "none"}}>
|
||||
{getFieldDecorator("path", {
|
||||
rules: [],
|
||||
})(
|
||||
// <Input
|
||||
// placeholder={`/${
|
||||
// projectDetail && projectDetail.identifier
|
||||
// }${filepath}`}
|
||||
// readOnly
|
||||
// />
|
||||
<div className="setInputAddon">
|
||||
<Input
|
||||
addonBefore={`/${
|
||||
projectDetail && projectDetail.identifier
|
||||
}/`}
|
||||
value={filename ? filename: filepath}
|
||||
onChange={this.changeFileName}
|
||||
placeholder="文件路径..."
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
{getFieldDecorator("desc", {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: "请添加描述信息",
|
||||
},
|
||||
],
|
||||
})(
|
||||
<TextArea
|
||||
placeholder={`必填,描述主要修改类型和内容`}
|
||||
authSize={{ minRows: 3, maxRows: 5 }}
|
||||
/>
|
||||
)}
|
||||
</Form.Item>
|
||||
<Radio.Group value={submitType} onChange={this.changeSubmittype}>
|
||||
<Radio value="0" className="mb10">
|
||||
<i className="iconfont icon-banbenku font-16 mr5"></i>
|
||||
直接提交至<span className="color-orange">{branch}</span>分支
|
||||
</Radio>
|
||||
<Radio value="1">
|
||||
<Icon type="pull-request" className="mr5" />
|
||||
为此提交创建一个<span className="font-bd">新的分支</span>
|
||||
并发起合并请求
|
||||
</Radio>
|
||||
</Radio.Group>
|
||||
{changeSubmitBranch()}
|
||||
</Form>
|
||||
<div className="userScrew">
|
||||
<div className="screwPanel">
|
||||
<Form>
|
||||
<Form.Item
|
||||
style={{
|
||||
display: editor_type === "upload" ? "block" : "none",
|
||||
}}
|
||||
>
|
||||
{getFieldDecorator("path", {
|
||||
rules: [],
|
||||
})(
|
||||
// <Input
|
||||
// placeholder={`/${
|
||||
// projectDetail && projectDetail.identifier
|
||||
// }${filepath}`}
|
||||
// readOnly
|
||||
// />
|
||||
<div className="setInputAddon">
|
||||
<Input
|
||||
addonBefore={`/${
|
||||
projectDetail && projectDetail.identifier
|
||||
}/`}
|
||||
value={filename ? filename : filepath}
|
||||
onChange={this.changeFileName}
|
||||
placeholder="文件路径..."
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
{getFieldDecorator("desc", {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: "请添加描述信息",
|
||||
},
|
||||
],
|
||||
})(
|
||||
<TextArea
|
||||
placeholder={`必填,描述主要修改类型和内容`}
|
||||
authSize={{ minRows: 3, maxRows: 5 }}
|
||||
/>
|
||||
)}
|
||||
</Form.Item>
|
||||
<Radio.Group
|
||||
value={submitType}
|
||||
onChange={this.changeSubmittype}
|
||||
>
|
||||
<Radio value="0" className="mb10">
|
||||
<i className="iconfont icon-banbenku font-16 mr5"></i>
|
||||
直接提交至<span className="color-orange">{branch}</span>分支
|
||||
</Radio>
|
||||
<Radio value="1">
|
||||
<Icon type="pull-request" className="mr5" />
|
||||
为此提交创建一个<span className="font-bd">新的分支</span>
|
||||
并发起合并请求
|
||||
</Radio>
|
||||
</Radio.Group>
|
||||
{changeSubmitBranch()}
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt20">
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={
|
||||
editor_type === "update" ? this.UpdateFile : this.subMitFrom
|
||||
}
|
||||
className="mr30"
|
||||
>
|
||||
提交变更
|
||||
</Button>
|
||||
<Button
|
||||
type="primary grey"
|
||||
onClick={() => {
|
||||
this.props.history.push(`/projects/${projectsId}/coders`);
|
||||
}}
|
||||
className="mr20"
|
||||
>
|
||||
取消
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt20">
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={editor_type === "update" ? this.UpdateFile : this.subMitFrom}
|
||||
className="mr30"
|
||||
>
|
||||
提交变更
|
||||
</Button>
|
||||
<Button
|
||||
type="primary grey"
|
||||
onClick={() => {
|
||||
this.props.history.push(`/projects/${projectsId}/coders`);
|
||||
}}
|
||||
className="mr20"
|
||||
>
|
||||
取消
|
||||
</Button>
|
||||
</div>
|
||||
</Spin>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -174,16 +174,7 @@
|
|||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
.required{
|
||||
position: relative;
|
||||
&::before{
|
||||
content: "*";
|
||||
color: red;
|
||||
position: absolute;
|
||||
left: -10px;
|
||||
top: -2px;
|
||||
}
|
||||
}
|
||||
|
||||
.hooksNew{
|
||||
.ant-select.ant-select-enabled{
|
||||
width: 100%;
|
||||
|
|
|
@ -274,3 +274,51 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
.warningBox{
|
||||
border-radius:5px 5px 0px 0px;
|
||||
border:1px solid rgba(219,39,41,1);
|
||||
border-radius:5px 5px 0px 0px;
|
||||
.warningTitle{
|
||||
height:40px;
|
||||
line-height: 40px;
|
||||
background:rgba(255,232,230,1);
|
||||
border-radius:5px 5px 0px 0px;
|
||||
border-bottom:1px solid rgba(219,39,41,1);
|
||||
color: #DB2729;
|
||||
font-size: 16px;
|
||||
padding:0px 30px;
|
||||
}
|
||||
.warningContent{
|
||||
padding:20px 30px;
|
||||
}
|
||||
.warningDelete{
|
||||
display: block;
|
||||
height:26px;
|
||||
line-height: 26px;
|
||||
padding:0px 15px;
|
||||
background:rgba(247,48,48,1);
|
||||
border-radius:20px;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
// 组织成员管理
|
||||
.teamMemberTable{
|
||||
.ant-table-small{
|
||||
border:none;
|
||||
}
|
||||
.ant-table-body{
|
||||
margin:0px!important;
|
||||
thead tr{
|
||||
background-color: #F1F8FF;
|
||||
color: #333;
|
||||
}
|
||||
tbody tr:hover:not(.ant-table-expanded-row):not(.ant-table-row-selected) > td{
|
||||
background-color: #fff;
|
||||
}
|
||||
tbody tr td{
|
||||
border-bottom: 1px solid #eee!important;
|
||||
padding:15px 8px!important;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
import React, { forwardRef , useCallback } from 'react';
|
||||
import { Form , Input , Cascader , Radio ,Checkbox , Divider , Button } from 'antd';
|
||||
import { WhiteBack , FlexAJ } from '../Component/layout';
|
||||
import Title from '../Component/Title';
|
||||
import styled from 'styled-components';
|
||||
import { locData } from "../Utils/locData";
|
||||
const TextArea = Input.TextArea;
|
||||
|
||||
const Div = styled.div`{
|
||||
padding:20px 30px;
|
||||
}`
|
||||
const radioStyle = {
|
||||
display: 'block',
|
||||
height: '30px',
|
||||
lineHeight: '30px',
|
||||
};
|
||||
export default Form.create()(
|
||||
forwardRef(({ form })=>{
|
||||
const { getFieldDecorator } = form;
|
||||
const helper = useCallback(
|
||||
(label, name, rules, widget , isRequired ) => (
|
||||
<div>
|
||||
<span className={isRequired?"required":""}>{label}</span>
|
||||
<Form.Item>
|
||||
{getFieldDecorator(name, { rules, validateFirst: true })(widget)}
|
||||
</Form.Item>
|
||||
</div>
|
||||
),
|
||||
[]
|
||||
);
|
||||
return(
|
||||
<div>
|
||||
<WhiteBack>
|
||||
<Title>基本设置</Title>
|
||||
<Div>
|
||||
<Form>
|
||||
{helper(
|
||||
"组织名称:",
|
||||
"name",
|
||||
[{ required: true, message: "请输入组织名称" }],
|
||||
<Input placeholder="请输入组织名称" />,true
|
||||
)}
|
||||
{helper(
|
||||
"组织描述:",
|
||||
"desc",
|
||||
[],
|
||||
<TextArea placeholder="请输入组织名称" />
|
||||
)}
|
||||
{helper(
|
||||
"官方网站:",
|
||||
"web",
|
||||
[],
|
||||
<Input placeholder="请输入官方网站" />
|
||||
)}
|
||||
{helper(
|
||||
'所在地区:',
|
||||
"area",
|
||||
[],
|
||||
<Cascader placeholder="请选择城市" options={locData}/>
|
||||
)}
|
||||
{helper(
|
||||
'可见性:',
|
||||
"opacity",
|
||||
[],
|
||||
<Radio.Group>
|
||||
<Radio value="0" style={radioStyle}>公开</Radio>
|
||||
<Radio value="0" style={radioStyle}>受限<span>(仅对登录用户可见)</span></Radio>
|
||||
<Radio value="0" style={radioStyle}>私有<span>(仅对组织成员可见)</span></Radio>
|
||||
</Radio.Group>
|
||||
)}
|
||||
{helper(
|
||||
'权限:',
|
||||
"operation",
|
||||
[],
|
||||
<Checkbox value="0" style={radioStyle}>仓库管理员可以添加或移除团队的访问权限</Checkbox>
|
||||
)}
|
||||
<Divider/>
|
||||
{helper(
|
||||
'最大仓库数:',
|
||||
"number",
|
||||
[],
|
||||
<Input value="-1" style={{width:"350px"}}/>
|
||||
)}
|
||||
<Button type={"primary"}>更新仓库设置</Button>
|
||||
</Form>
|
||||
</Div>
|
||||
</WhiteBack>
|
||||
<WhiteBack className="padding20 mt20">
|
||||
<div className="warningBox">
|
||||
<div className="warningTitle">删除当前组织</div>
|
||||
<div className="warningContent">
|
||||
<p className="font-16 mb15">删除操作会永久清除该组织的信息,并且不可恢复!</p>
|
||||
<FlexAJ>
|
||||
<div>
|
||||
<span className="required">密码:</span>
|
||||
<Input type="password" style={{width:"350px"}} />
|
||||
</div>
|
||||
<a className="warningDelete">删除组织</a>
|
||||
</FlexAJ>
|
||||
</div>
|
||||
</div>
|
||||
</WhiteBack>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
)
|
|
@ -0,0 +1,71 @@
|
|||
import React from 'react';
|
||||
import { WhiteBack , Banner , Blueline } from '../Component/layout';
|
||||
import styled from 'styled-components';
|
||||
|
||||
const SpanName = styled.span`{
|
||||
font-size:16px;
|
||||
color:#333;
|
||||
}`
|
||||
const SpanFoot = styled.span`{
|
||||
margin-right:5px;
|
||||
color:#333
|
||||
}`
|
||||
const ALink = styled.a`{
|
||||
border:1px solid #F73030;
|
||||
color:#F73030!important;
|
||||
height:32px;
|
||||
line-height:30px;
|
||||
display:block;
|
||||
padding:0px 15px;
|
||||
border-radius:2px;
|
||||
}`
|
||||
const ImgContent = styled.img`{
|
||||
height:44px;
|
||||
width:44px;
|
||||
border-radius:50%;
|
||||
margin:5px 20px 5px 0px;
|
||||
}`
|
||||
|
||||
export default ()=>{
|
||||
return(
|
||||
<WhiteBack>
|
||||
<Banner>组织团队管理</Banner>
|
||||
<div className="groupBox">
|
||||
<div>
|
||||
<p className="g-head">
|
||||
<SpanName>oweners</SpanName>
|
||||
<span className="df">
|
||||
<ALink>离开团队</ALink>
|
||||
<Blueline className="ml15">团队设置</Blueline>
|
||||
</span>
|
||||
</p>
|
||||
<div className="g-body">
|
||||
<ImgContent src="https://dss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3331079987,1190181307&fm=111&gp=0.jpg"/>
|
||||
<ImgContent src="https://dss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3331079987,1190181307&fm=111&gp=0.jpg"/>
|
||||
</div>
|
||||
<p className="g-foot">
|
||||
<SpanFoot>2 名成员</SpanFoot>
|
||||
<SpanFoot>1 个项目</SpanFoot>
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="g-head">
|
||||
<SpanName>oweners</SpanName>
|
||||
<span className="df">
|
||||
<ALink>离开团队</ALink>
|
||||
<Blueline className="ml15">团队设置</Blueline>
|
||||
</span>
|
||||
</p>
|
||||
<div className="g-body">
|
||||
<ImgContent src="https://dss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3331079987,1190181307&fm=111&gp=0.jpg"/>
|
||||
<ImgContent src="https://dss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3331079987,1190181307&fm=111&gp=0.jpg"/>
|
||||
</div>
|
||||
<p className="g-foot">
|
||||
<SpanFoot>2 名成员</SpanFoot>
|
||||
<SpanFoot>1 个项目</SpanFoot>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</WhiteBack>
|
||||
)
|
||||
}
|
|
@ -1,16 +1,46 @@
|
|||
import React from 'react';
|
||||
import React , { useEffect , useState } from 'react';
|
||||
import { Box , Long , Short , Gap } from '../Component/layout';
|
||||
import Title from '../Component/Title';
|
||||
import Setnav from '../Component/Setnav';
|
||||
|
||||
export default (()=>{
|
||||
import { Route, Switch } from "react-router-dom";
|
||||
import Loadable from "react-loadable";
|
||||
import Loading from "../../Loading";
|
||||
|
||||
|
||||
const Group = Loadable({
|
||||
loader: () => import("./TeamSettingGroup"),
|
||||
loading: Loading,
|
||||
});
|
||||
const Member = Loadable({
|
||||
loader: () => import("./TeamSettingMember"),
|
||||
loading: Loading,
|
||||
});
|
||||
const Common = Loadable({
|
||||
loader: () => import("./TeamSettingCommon"),
|
||||
loading: Loading,
|
||||
});
|
||||
export default (( props )=>{
|
||||
const pathname = props.location.pathname;
|
||||
const organizeId = props.match.params.organizeId;
|
||||
|
||||
function returnActive (pathname){
|
||||
let a = 0;
|
||||
if(pathname === `/organize/${organizeId}/setting/member`){
|
||||
a = 1;
|
||||
}else if(pathname === `/organize/${organizeId}/setting/group`){
|
||||
a = 2;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
const active = returnActive(pathname);
|
||||
const array = {list:[
|
||||
{name:'基本设置',icon:"icon-base",href:""},
|
||||
{name:'组织成员',icon:"icon-zuzhichengyuan",href:""},
|
||||
{name:'组织团队',icon:"icon-zuzhixiangmu",href:""},
|
||||
{name:'组织成员管理',icon:"icon-zuzhichengyuan",href:""},
|
||||
{name:'组织团队管理',icon:"icon-zuzhixiangmu",href:""},
|
||||
{name:'管理web钩子',icon:"icon-zhongqingdianxinicon10",href:""}
|
||||
],
|
||||
active:0
|
||||
active
|
||||
}
|
||||
return(
|
||||
<Box>
|
||||
|
@ -19,6 +49,26 @@ export default (()=>{
|
|||
</Short>
|
||||
<Long>
|
||||
<Gap>
|
||||
<Switch>
|
||||
<Route
|
||||
path="/organize/:organizeId/setting/group"
|
||||
render={() => (
|
||||
<Group {...props} />
|
||||
)}
|
||||
></Route>
|
||||
<Route
|
||||
path="/organize/:organizeId/setting/member"
|
||||
render={() => (
|
||||
<Member {...props} />
|
||||
)}
|
||||
></Route>
|
||||
<Route
|
||||
path="/organize/:organizeId/setting"
|
||||
render={() => (
|
||||
<Common {...props} />
|
||||
)}
|
||||
></Route>
|
||||
</Switch>
|
||||
</Gap>
|
||||
</Long>
|
||||
</Box>
|
||||
|
|
|
@ -0,0 +1,152 @@
|
|||
import React, { useState } from 'react';
|
||||
import { WhiteBack , Blueline , AlignCenter , FlexAJ } from '../Component/layout';
|
||||
import { Menu , Table , Pagination , Icon , Tooltip } from 'antd';
|
||||
import Sort from '../Component/Sort';
|
||||
import Title from '../Component/Title';
|
||||
import Search from '../Component/Search';
|
||||
import SearchUser from '../Component/SearchUser';
|
||||
import styled from 'styled-components';
|
||||
import { getImageUrl } from 'educoder';
|
||||
|
||||
const Img = styled.img`{
|
||||
width:30px;
|
||||
height:30px;
|
||||
border-radius:50%;
|
||||
}`
|
||||
|
||||
const demoData = [
|
||||
{
|
||||
img:"images/avatars/User/g",
|
||||
name:"蔡世",
|
||||
email:"1149225589@qq.com",
|
||||
team:"caicaizi",
|
||||
role:"管理者",
|
||||
operation:"移除成员",
|
||||
}
|
||||
]
|
||||
export default (()=>{
|
||||
const [ choiceId , serChoiceId ] = useState(undefined);
|
||||
const [ page , setPage ] = useState(1);
|
||||
const [ limit , setLimit ] = useState(15);
|
||||
const [ total , setTotal ] = useState(0);
|
||||
const [ data , setData ] = useState(demoData);
|
||||
|
||||
// 获取搜索用户框里面选择的用户ID,方便添加组织成员
|
||||
function getUser(id){
|
||||
console.log(id);
|
||||
serChoiceId(id);
|
||||
}
|
||||
// 搜索
|
||||
function onSearch(value){
|
||||
console.log(value);
|
||||
}
|
||||
// 切换分页
|
||||
function ChangePage(page){
|
||||
setPage(page);
|
||||
}
|
||||
|
||||
const menu=(
|
||||
<Menu>
|
||||
<Menu.Item key="all">全部</Menu.Item>
|
||||
<Menu.Item key="Manager">管理员</Menu.Item>
|
||||
<Menu.Item key="Developer">开发者</Menu.Item>
|
||||
<Menu.Item key="Reporter">报告者</Menu.Item>
|
||||
</Menu>
|
||||
)
|
||||
const roleTitle = (
|
||||
<div><span className="mr3">角色</span>
|
||||
<Tooltip placement='bottom' title=
|
||||
{
|
||||
<div>
|
||||
<div className="mb3">管理员:拥有仓库设置功能、代码库读、写操作</div>
|
||||
<div className="mb3">开发人员:只拥有代码库读、写操作</div>
|
||||
<div className="mb3">报告者:只拥有代码库读操作</div>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<Icon type="question-circle"></Icon>
|
||||
</Tooltip>
|
||||
</div>
|
||||
);
|
||||
const columns = [
|
||||
{
|
||||
title: '头像',
|
||||
dataIndex: 'Img',
|
||||
width:"7%",
|
||||
render:(value,item)=>{
|
||||
return(
|
||||
<Img src={getImageUrl(item.img)}></Img>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '用户名',
|
||||
dataIndex: 'name',
|
||||
width:"13%",
|
||||
align:"center"
|
||||
},
|
||||
{
|
||||
title: '邮箱',
|
||||
dataIndex: 'email',
|
||||
width:"25%",
|
||||
},
|
||||
{
|
||||
title: '所属团队',
|
||||
dataIndex: 'team',
|
||||
width:"20%",
|
||||
},
|
||||
{
|
||||
title: roleTitle,
|
||||
dataIndex: 'role',
|
||||
width:"20%",
|
||||
render:(value,item)=>{
|
||||
return(
|
||||
item.role
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
dataIndex: 'operation',
|
||||
width:"15%",
|
||||
render:(value,item)=>{
|
||||
return <a className="color-grey-8">移除成员</a>
|
||||
}
|
||||
}
|
||||
]
|
||||
return(
|
||||
<WhiteBack>
|
||||
<Title>
|
||||
<span>组织成员管理</span>
|
||||
<AlignCenter>
|
||||
<SearchUser getUser={getUser}/>
|
||||
<Blueline className="ml30">+ 添加用户</Blueline>
|
||||
</AlignCenter>
|
||||
</Title>
|
||||
<FlexAJ className="padding20-30">
|
||||
<div style={{width:"580px"}}>
|
||||
<Search placeholder="输入用户名或邮箱、团队名搜索" onSearch={onSearch}/>
|
||||
</div>
|
||||
<Sort menu={menu}>
|
||||
<a className="color-blue">角色筛选<i className="iconfont icon-sanjiaoxing-down ml3 font-14"></i></a>
|
||||
</Sort>
|
||||
</FlexAJ>
|
||||
<div className="pl30 pr30 pb30">
|
||||
<Table
|
||||
size="small"
|
||||
columns={columns}
|
||||
dataSource={data}
|
||||
pagination={false}
|
||||
className="teamMemberTable"
|
||||
></Table>
|
||||
{
|
||||
total > limit ?
|
||||
<div className="edu-txt-center mt30 mb20">
|
||||
<Pagination simple defaultCurrent={page} total={total} pageSize={limit} onChange={ChangePage}></Pagination>
|
||||
</div>
|
||||
:""
|
||||
}
|
||||
</div>
|
||||
</WhiteBack>
|
||||
)
|
||||
})
|
|
@ -95,6 +95,20 @@ ul,ol,dl{
|
|||
font-size: 16px;
|
||||
color: #999;
|
||||
}
|
||||
form.ant-form{
|
||||
color:#333;
|
||||
}
|
||||
.required{
|
||||
position: relative;
|
||||
&::before{
|
||||
content: "*";
|
||||
color: red;
|
||||
position: absolute;
|
||||
left: -10px;
|
||||
top: 0px;
|
||||
line-height: 22px;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 1000px){
|
||||
.main{
|
||||
width: 750px;
|
||||
|
|
Loading…
Reference in New Issue