Merge branch 'gitlink_server' of https://git.trustie.net/Gitlink/forgeplus-react into gitlink_server

This commit is contained in:
谢思 2021-11-30 11:20:20 +08:00
commit 684f9dbfe1
19 changed files with 139 additions and 271 deletions

View File

@ -171,10 +171,10 @@ function About(props, ref) {
<div className="noOperation">DevOps开启功能暂未对项目创建者以外的角色开放可以联系项目创建者进行开启开启后便可查看构建信息</div>:"" <div className="noOperation">DevOps开启功能暂未对项目创建者以外的角色开放可以联系项目创建者进行开启开启后便可查看构建信息</div>:""
} }
<a href={"https://forum.trustie.net/forums/3110/detail"} target="_blank" style={{ color: "#5091FF"}}> <a href={"https://forum.trustie.net/forums/3110/detail"} target="_blank" style={{ color: "#5091FF"}}>
了解什么是DevOps 了解什么是引擎
</a> </a>
<a href={"https://forum.trustie.net/forums/3080/detail"} target="_blank" style={{ color: "#5091FF"}}> <a href={"https://forum.trustie.net/forums/3080/detail"} target="_blank" style={{ color: "#5091FF"}}>
如何使用DevOps 如何使用引擎Engine功能
</a> </a>
{ {
AuthorLogin === CurrentLogin ? AuthorLogin === CurrentLogin ?

View File

@ -2,84 +2,82 @@ import React, { useState , forwardRef, useEffect } from 'react';
import { Form , Modal , Input , Radio } from 'antd'; import { Form , Modal , Input , Radio } from 'antd';
import Axios from 'axios'; import Axios from 'axios';
import CheckProfile from '../Component/ProfileModal/Profile'; import CheckProfile from '../Component/ProfileModal/Profile';
function AddProjectModal(props){
const { getFieldDecorator, validateFields , setFieldsValue } = props && props.form;
const [ visible , setVisible ] = useState(false);
export default Form.create()( useEffect(()=>{
forwardRef((props)=>{ if(!visible){
const { getFieldDecorator, validateFields , setFieldsValue } = props && props.form; setFieldsValue({
const [ visible , setVisible ] = useState(false); code:undefined,
role:"developer"
useEffect(()=>{
if(!visible){
setFieldsValue({
code:undefined,
role:"developer"
})
}
},[visible])
function onOk() {
validateFields((error,values)=>{
if(!error){
const url = `/applied_projects.json`;
Axios.post(url,{
applied_project:{
...values
}
}).then(result=>{
if(result && result.data){
setVisible(false);
props.showNotification("申请加入项目成功,等待审核!");
}
}).catch(error=>{})
}
}) })
} }
function checkValue(rule, value, callback){ },[visible])
if(!value){
callback(); function onOk() {
validateFields((error,values)=>{
if(!error){
const url = `/applied_projects.json`;
Axios.post(url,{
applied_project:{
...values
}
}).then(result=>{
if(result && result.data){
setVisible(false);
props.showNotification("申请加入项目成功,等待审核!");
}
}).catch(error=>{})
} }
})
}
function checkValue(rule, value, callback){
if(!value){
callback("请输入6位数的邀请码");
}else{
if(value.length < 6 || value.length > 6){ if(value.length < 6 || value.length > 6){
callback("请输入6位数的邀请码"); callback("请输入6位数的邀请码");
} }
callback(); }
} }
return( return(
<React.Fragment> <React.Fragment>
<Modal <Modal
title="加入项目" title="加入项目"
width="480px" width="480px"
visible={visible} visible={visible}
centered={true} centered={true}
onOk={onOk} onOk={onOk}
onCancel={()=>setVisible(false)} onCancel={()=>setVisible(false)}
> >
<Form layout={'inline'} className="inviteForm"> <Form layout={'inline'} className="inviteForm">
<Form.Item label="项目邀请码"> <Form.Item label="项目邀请码">
{getFieldDecorator("code",{ {getFieldDecorator("code",{
rules:[ rules:[
{required:true,message:"请输入6位项目邀请码"}, {required:true,message:" "},
{validator:checkValue} {validator:checkValue}
] ]
})( })(
<Input placeholder="请输入6位项目邀请码" autoComplete={"off"} maxLength="6" style={{width:"300px"}}/> <Input placeholder="请输入6位项目邀请码" autoComplete={"off"} maxLength={6} style={{width:"300px"}}/>
)} )}
</Form.Item> </Form.Item>
<Form.Item label="选择角色"> <Form.Item label="选择角色">
{getFieldDecorator("role",{ {getFieldDecorator("role",{
rules:[{required:true,message:"请选择角色"}] rules:[{required:true,message:"请选择角色"}]
})( })(
<Radio.Group defaultValue={"developer"}> <Radio.Group>
<Radio value="manager">管理员</Radio> <Radio value="manager">管理员</Radio>
<Radio value="developer">开发者</Radio> <Radio value="developer">开发者</Radio>
<Radio value="reporter">报告者</Radio> <Radio value="reporter">报告者</Radio>
</Radio.Group> </Radio.Group>
)} )}
</Form.Item> </Form.Item>
</Form> </Form>
</Modal> </Modal>
<CheckProfile {...props} sureFunc={()=>setVisible(true)}>加入项目</CheckProfile> <CheckProfile {...props} sureFunc={()=>setVisible(true)}>加入项目</CheckProfile>
</React.Fragment> </React.Fragment>
) )
}) }
) export default Form.create()(forwardRef(AddProjectModal));

View File

@ -127,6 +127,9 @@
width: 110px; width: 110px;
text-align: right; text-align: right;
} }
.ant-form-explain{
position: absolute;
}
} }
// 右上角小铃铛单独样式 // 右上角小铃铛单独样式

View File

@ -340,7 +340,7 @@ function CoderDepot(props){
function createIssue(){ function createIssue(){
if(baseOper){ if(baseOper){
window.open(`/${owner}/${projectsId}/issues/new`,'_blank'); props.history.push(`/${owner}/${projectsId}/issues/new`);
}else{ }else{
props.showLoginDialog(`/${owner}/${projectsId}/issues/new`); props.showLoginDialog(`/${owner}/${projectsId}/issues/new`);
} }

View File

@ -46,7 +46,7 @@ function Index(props) {
return( return(
<Spin spinning={isSpin}> <Spin spinning={isSpin}>
<div style={{paddingTop:"10px",minHeight:"400px"}}> <div style={{paddingTop:"10px",minHeight:"400px",paddingBottom:"30px"}}>
{ {
list && list.length>0 && list.map((item,key)=>{ list && list.length>0 && list.map((item,key)=>{
return( return(

View File

@ -224,7 +224,7 @@ export default Form.create()(
<Checkbox defaultChecked={!stable}>这是一个预览版本</Checkbox> <Checkbox defaultChecked={!stable}>这是一个预览版本</Checkbox>
)} )}
</Form.Item> </Form.Item>
<p className="pt20" style={{borderTop:"1px solid #eee"}}> <p className="pt20 pb20" style={{borderTop:"1px solid #eee"}}>
<Button onClick={submit} type="primary" className="mr30 btnblue"> <Button onClick={submit} type="primary" className="mr30 btnblue">
{versionId ? "保存" : "创建"}发行版 {versionId ? "保存" : "创建"}发行版
</Button> </Button>

View File

@ -167,8 +167,8 @@ class MergeForm extends Component {
this.setState({ this.setState({
isSpin: false, isSpin: false,
}); });
const { pull_request_id } = result.data; const { pull_request_number } = result.data;
this.props.history.push(`/${owner}/${projectsId}/pulls/${pull_request_id}`); this.props.history.push(`/${owner}/${projectsId}/pulls/${pull_request_number}`);
const { getDetail } = this.props; const { getDetail } = this.props;
getDetail && getDetail(); getDetail && getDetail();
} else { } else {

View File

@ -1,3 +1,11 @@
.editorBorderBox .CodeMirror
{
height: unset;
}
.editorBorderBox .CodeMirror .CodeMirror-scroll{
min-height: 300px;
}
.setInputAddon{ .setInputAddon{
width: 350px; width: 350px;
margin-right: 20px; margin-right: 20px;
@ -9,12 +17,16 @@
border-right: none!important; border-right: none!important;
} }
.editorBorder .editorBorderBox{ .editorBorder .editorBorderBox{
border:1px solid #eee; border:1px solid #d0d0d0;
border-radius: 2px; border-radius: 2px;
border-bottom: none;
} }
.editorBorder .editorBorderSubmitBox{ .editorBorder .editorBorderSubmitBox{
padding:20px 0px!important; padding:20px 0px!important;
} }
.editorBorderSubmitBox{
border-top: 1px solid #d0d0d0;
}
.userScrew{ .userScrew{
margin:20px 0px; margin:20px 0px;
border:1px solid #f4f4f4; border:1px solid #f4f4f4;

View File

@ -1,6 +1,9 @@
import React, { Component } from "react"; import React, { Component } from "react";
import Editor from "react-monaco-editor"; import {UnControlled as CodeMirror} from 'react-codemirror2';
// import {UnControlled as CodeMirror} from 'react-codemirror2' import 'codemirror/addon/selection/active-line.js';
import 'codemirror/mode/javascript/javascript.js';
import 'codemirror/mode/clike/clike';
import 'codemirror/mode/css/css';
import UserSubmitComponent from "./UserSubmitComponent"; import UserSubmitComponent from "./UserSubmitComponent";
@ -12,6 +15,7 @@ class m_editor extends Component {
super(props); super(props);
this.state = { this.state = {
editorValue: this.props.content, editorValue: this.props.content,
changeValue:this.props.content,
prevHeight:0 prevHeight:0
}; };
} }
@ -22,18 +26,18 @@ class m_editor extends Component {
}) })
} }
} }
changeEditor = (editorValue) => { changeEditor = (editorValue,data) => {
this.setState({ this.setState({
editorValue, changeValue:editorValue.getValue(),
}); });
}; };
render() { render() {
const { editorValue } = this.state; const { editorValue , changeValue } = this.state;
const { readOnly, editorType, language , currentBranch , descName } = this.props; const { readOnly, editorType, currentBranch , descName } = this.props;
const editor_options = { const editor_options = {
lineNumbers: "on", lineNumbers: "on",
wordWrap: true, //强制换行 lineWrapping: true, //强制换行
selectOnLineNumbers: true, selectOnLineNumbers: true,
lineHeight: 24, lineHeight: 24,
renderLineHighlight: "line", renderLineHighlight: "line",
@ -46,84 +50,29 @@ class m_editor extends Component {
automaticLayout: true, // 自适应布局 automaticLayout: true, // 自适应布局
overviewRulerBorder: false, // 不要滚动条的边框 overviewRulerBorder: false, // 不要滚动条的边框
scrollBeyondLastLine: false, // 取消代码后面一大段空白 scrollBeyondLastLine: false, // 取消代码后面一大段空白
styleActiveLine:true,//光标代码高亮
minimap: { minimap: {
// 不要小地图 // 不要小地图
enabled: false, enabled: false,
}, },
}; };
const handleEditorMount = (editor, monaco) => {
editor.onDidChangeModelDecorations(() => {
requestAnimationFrame(updateEditorHeight); // folding
});
const updateEditorHeight = () => {
const editorElement = editor.getDomNode();
if (!editorElement) {
return;
}
const padding = 40;
const lineHeight = editor.getOption(
monaco.editor.EditorOption.lineHeight
);
const lineCount = editor.getModel().getLineCount() || 1;
let height =
editor.getTopForLineNumber(lineCount + 1) +
lineHeight +
padding ;
if(height<400){height = 400;}
if (this.state.prevHeight !== height) {
this.setState({
prevHeight:height
})
// setPrevHeight(height);
editorElement.style.height = `${height}px`;
editor.layout();
}
};
updateEditorHeight(); // typing
};
return ( return (
<React.Fragment> <React.Fragment>
<div className="editorBorderBox"> <div className="editorBorderBox">
<Editor <CodeMirror
language={language ? language : "plaintext"}
theme={"vs-grey"}
placeholder="请输入内容" placeholder="请输入内容"
value={editorValue} value={editorValue}
options={editor_options} options={editor_options}
onChange={this.changeEditor} onChange={this.changeEditor}
editorWillMount={this.editorWillMount}
editorDidMount={handleEditorMount}
/> />
{/* <CodeMirror
value={editorValue}
options={{
theme: 'monokai',
mode: 'JavaScript',
extraKeys: {"Ctrl": "autocomplete"},//ctrl可以弹出提示
styleActiveLine: true,
lineNumbers: true,
readOnly:true
}}
/> */}
</div> </div>
{!readOnly && ( {!readOnly && (
<div className="editorBorderSubmitBox" style={{marginTop:"20px",padding:"20px"}}> <div className="editorBorderSubmitBox" style={{padding:"20px"}}>
<UserSubmitComponent <UserSubmitComponent
{...this.props} {...this.props}
{...this.state} {...this.state}
filepath={`${this.props.filepath}`} filepath={`${this.props.filepath}`}
content={editorValue} content={changeValue}
editor_type={editorType} editor_type={editorType}
currentBranch={currentBranch} currentBranch={currentBranch}
descName={descName} descName={descName}

View File

@ -236,7 +236,7 @@ class MilepostDetail extends Component {
<span >暂无截止时间</span> <span >暂无截止时间</span>
} }
</span> </span>
<span className="font-weight-bold">{data && data.percent && data.percent.toFixed(2)}%完成 </span> {data && (data.percent || data.percent===0) ? <span className="font-weight-bold"> {data.percent > 0 ? data.percent.toFixed(2):data.percent}%完成 </span> :"" }
</span> </span>
<div className="milepostdiv"> <div className="milepostdiv">
{ {

View File

@ -226,6 +226,7 @@ class order extends Component {
// 翻页 // 翻页
ChangePage = (page) => { ChangePage = (page) => {
window.scrollTo(0,0);
this.setState({ this.setState({
isSpin: true, isSpin: true,
checkedValue: [], checkedValue: [],

View File

@ -445,7 +445,7 @@ class NewTags extends Component {
message: "请填写标记名字", message: "请填写标记名字",
}, },
], ],
})(<Input placeholder="名称10字以内" maxLength="10" />)} })(<Input placeholder="名称15字以内" maxLength="15" />)}
</Form.Item> </Form.Item>
<Form.Item className="inputcount"> <Form.Item className="inputcount">

View File

@ -1,106 +1,13 @@
import { notification ,message} from 'antd';
import axios from 'axios';
import cookie from 'react-cookies';
import Login from './components/Login';
let actionUrl = ''; import javaFetch from '../javaFetch';
if (window.location.href.indexOf('localhost') > -1) {
// actionUrl = 'http://117.50.100.12:8008';
// actionUrl = 'http://192.168.31.74:8081';
actionUrl = "https://test-search.trustie.net";
} else if(window.location.href.indexOf('testforgeplus')>-1){
actionUrl = "https://test-search.trustie.net";
// actionUrl = 'https://testforgeplus.trustie.net';
axios.defaults.withCredentials = true;
}else if (window.location.href.indexOf('forgeplus') > -1) {
actionUrl = "https://wiki-api.trustie.net";
axios.defaults.withCredentials = true;
}
let settings = JSON.parse(localStorage.chromesetting);
let actionUrl = settings && settings.common.wiki;
const service = javaFetch(actionUrl);
export const httpUrl = actionUrl; export const httpUrl = actionUrl;
export const TokenKey = 'autologin_trustie';
// 创建axios实例
const service = axios.create({
baseURL: httpUrl,
timeout: 10000, // 请求超时时间
});
// request拦截器
service.interceptors.request.use(config => {
if (cookie.load(TokenKey)) {
console.log(cookie.load(TokenKey));
config.headers['Authorization'] = cookie.load(TokenKey); // 让每个请求携带自定义token 请根据实际情况自行修改
}
if (window.location.port === "3007") {
// 模拟token为登录用户
const taskToken = sessionStorage.taskToken;
if (config.url.indexOf('?') === -1) {
config.url = `${config.url}?token=${taskToken}`;
} else {
config.url = `${config.url}&token=${taskToken}`;
}
}
return config;
}, error => {
// Do something with request error
console.log(error); // for debug
// Promise.reject(error);
});
// respone拦截器
service.interceptors.response.use(
response => {
const res = response||{};
if (res.status === 400) {
message.error(res.data.message || '操作失败');
return Promise.reject('error');
}
if (res.status === 401) {
message.error(res.data.message || '登录信息已过期');
return Promise.reject('error');
}
if (res.status === 403) {
message.error(res.data.message || '无权限!');
return Promise.reject('error');
}
if (res.status === 40001) {
notification.open({
message: "提示",
description: '账户或密码错误!',
});
return Promise.reject('error');
}
if (response.status !== 200 && res.status !== 200) {
notification.open({
message: "提示",
description: res.message,
});
} else {
return response.data;
}
},
error => {
console.log(error);
let res = error.response||{};
if (res.status === 400) {
message.error(res.data.message || '操作失败');
return Promise.reject('error');
}
if (res.status === 401) {
message.error(res.data.message || '登录信息已过期');
Login();
return Promise.reject('error');
}
if (res.status === 403) {
message.error(res.data.message || '无权限!');
return Promise.reject('error');
}
notification.open({
message: "提示",
description: error.message,
});
return Promise.reject(error);
}
);
export default service; export default service;

View File

@ -4,22 +4,16 @@ import cookie from 'react-cookies';
import Login from './Wiki/components/Login'; import Login from './Wiki/components/Login';
export const TokenKey = 'autologin_trustie'; export const TokenKey = 'autologin_trustie';
export default function javaFetch(productUrl,testUrl,developUrl ){
let actionUrl=''; export default function javaFetch(actionUrl){
if (window.location.href.indexOf('localhost') > -1) { if (window.location.href.indexOf('localhost') < 0) {
actionUrl = developUrl;
} else if(window.location.href.indexOf('testforgeplus')>-1){
actionUrl = testUrl;
axios.defaults.withCredentials = true;
}else if (window.location.href.indexOf('forgeplus') > -1) {
actionUrl = productUrl;
axios.defaults.withCredentials = true; axios.defaults.withCredentials = true;
} }
// 创建axios实例 // 创建axios实例
const service = axios.create({ const service = axios.create({
baseURL: actionUrl, baseURL: actionUrl,
timeout: 10000, // 请求超时时间 timeout: 1800000, // 请求超时时间
}); });
// request拦截器 // request拦截器
@ -98,8 +92,6 @@ export default function javaFetch(productUrl,testUrl,developUrl ){
} }
); );
console.log(service);
console.log(typeof service);
return {service,actionUrl}; return service;
} }

View File

@ -297,7 +297,7 @@ class Infos extends Component {
} }
{ {
current_user && current_user.login && current_user.login === username ? current_user && current_user.login && current_user.login === username ?
<Menu.Item key="4"><Link to={`/${user && user.login}/devops/CIService`}><i className="iconfont icon-gongzuoliu1"></i>DevOps</Link></Menu.Item> <Menu.Item key="4"><Link to={`/${user && user.login}/devops/CIService`}><i className="iconfont icon-gongzuoliu1"></i>DevOps</Link></Menu.Item>
:"" :""
} }
<Menu.Item key="5"> <Menu.Item key="5">

View File

@ -147,7 +147,7 @@ class InfosUser extends Component {
let list = button_lists.map((item, key) => { let list = button_lists.map((item, key) => {
return ( return (
<span key={key} className="pr15"> <span key={key} className={`pr15`}>
<Button <Button
type={ type={
(category && category === item.type) || (!category && !item.type) (category && category === item.type) || (!category && !item.type)

View File

@ -9,6 +9,7 @@ import Pie from '../Echart/Pie';
import Cloud from '../Echart/Cloud'; import Cloud from '../Echart/Cloud';
import Radar from '../Echart/Radar'; import Radar from '../Echart/Radar';
import Round from '../Echart/Round'; import Round from '../Echart/Round';
import Nodata from '../../Nodata';
import { DatePicker } from 'antd'; import { DatePicker } from 'antd';
import moment from 'moment'; import moment from 'moment';
@ -120,7 +121,7 @@ function Index(props) {
} }
}).then(result=>{ }).then(result=>{
if(result && result.data){ if(result && result.data){
setCloudData(result.data); setCloudData({categories:[]});
} }
}).catch(error=>{}) }).catch(error=>{})
} }
@ -148,7 +149,7 @@ function Index(props) {
</div> </div>
} }
{ {
percentData && percentData && percentData.length >0 &&
<div className="pBox"> <div className="pBox">
<div className="progress"> <div className="progress">
{ {
@ -200,7 +201,12 @@ function Index(props) {
</FlexAJ> </FlexAJ>
<div className="echartBox"> <div className="echartBox">
<p>展示你擅长关注感兴趣的专业范围通过你参与项目收藏项目关注项目复刻项目等数据来统计</p> <p>展示你擅长关注感兴趣的专业范围通过你参与项目收藏项目关注项目复刻项目等数据来统计</p>
<Cloud data={cloudData}/> {
cloudData && cloudData.length >0?
<Cloud data={cloudData}/>
:
<Nodata _html="暂无数据" small={true}/>
}
</div> </div>
</div> </div>
</div> </div>

View File

@ -203,7 +203,7 @@ body{
background-image: url('./Img/top-2.png'); background-image: url('./Img/top-2.png');
height: 139px; height: 139px;
width: 353px; width: 353px;
padding:30px 24px; padding:15px 24px;
color: #fff; color: #fff;
margin:0px 17px; margin:0px 17px;
border-radius: 11px; border-radius: 11px;

View File

@ -19,7 +19,7 @@ body>.-task-title {
min-width: 1200px; min-width: 1200px;
max-width: unset; max-width: unset;
height: 100%; height: 100%;
min-height: 100%; min-height: 70vh;
overflow: hidden; overflow: hidden;
} }
.newHeaders{ .newHeaders{