forked from Gitlink/forgeplus-react
update
This commit is contained in:
parent
6a9bda3882
commit
a0391abdd9
|
|
@ -4,7 +4,7 @@ import { Spin } from 'antd';
|
|||
class Loading extends Component {
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
if (!prevProps.error && this.props.error) {
|
||||
console.log(this.props.error)
|
||||
// console.log(this.props.error)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +1,16 @@
|
|||
import React, { useEffect, useRef, useMemo } from 'react'
|
||||
import 'katex/dist/katex.min.css'
|
||||
import React, { useEffect, useRef, useMemo , useState } from 'react'
|
||||
import 'katex/dist/katex.min.css';
|
||||
import marked, { getTocContent, cleanToc, getMathExpressions, resetMathExpressions } from '../common/marked';
|
||||
import 'code-prettify';
|
||||
import dompurify from 'dompurify';
|
||||
import { getEmoji } from '../forge/Main/emoji';
|
||||
import axios from 'axios';
|
||||
|
||||
import { renderToString } from 'katex'
|
||||
|
||||
const preRegex = /<pre[^>]*>/g;
|
||||
const strRegexSub = /:([a-zA-Z_]+):/g;
|
||||
// const quoteRegex = /[#]()/g;
|
||||
const quoteRegex = /\[[#][0-9]{0,}\]\(\/\w{0,}\/\w{0,}\/issues\/[0-9]{0,}\)/g;
|
||||
function _unescape(str) {
|
||||
let div = document.createElement('div')
|
||||
div.innerHTML = str
|
||||
|
|
@ -22,8 +23,29 @@ export default ({
|
|||
value = '',
|
||||
className,
|
||||
style = {},
|
||||
url
|
||||
url,
|
||||
owner=undefined,
|
||||
projectsId=undefined
|
||||
}) => {
|
||||
const [ issues , setIssues ] = useState([]);
|
||||
|
||||
useEffect(()=>{
|
||||
if(owner&&projectsId){
|
||||
getIssueList();
|
||||
}
|
||||
},[owner,projectsId])
|
||||
|
||||
function getIssueList(){
|
||||
axios.get(`/v1/${owner}/${projectsId}/issues`,{params:{
|
||||
only_name:true,sort_direction:"desc",sort_by:"issues.created_on"
|
||||
}}).then(result=>{
|
||||
if(result){
|
||||
let data = result.data.issues;
|
||||
setIssues(data);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let str = String(value);
|
||||
const html = useMemo(() => {
|
||||
let rs = marked(str);
|
||||
|
|
@ -39,6 +61,26 @@ export default ({
|
|||
rs = rs.replace(matchStr[i],getEmoji(matchStr[i]));
|
||||
}
|
||||
}
|
||||
if(owner && projectsId && issues && issues.length>0){
|
||||
let matchQuote = str.match(quoteRegex);
|
||||
if(matchQuote && matchQuote.length>0){
|
||||
let getIndexReg = /(?<=#)(.+?)(?=\])/g;
|
||||
for(var x=0;x<matchQuote.length;x++){
|
||||
let getIndex = matchQuote[x].match(getIndexReg);
|
||||
if(getIndex && getIndex.length>0 && getIndex[0]){
|
||||
let index = getIndex[0];
|
||||
let filter = issues.filter(f=>f.project_issues_index.toString() === index);
|
||||
if(filter && filter.length === 1){
|
||||
let content = `#${index}:${filter[0].subject}`;
|
||||
rs = rs.replace(`#${index}`,content);
|
||||
}else{
|
||||
let content = `<span>#${index}(已删除)</span>`;
|
||||
rs = rs.replace(`<a href="`+`/${owner}/${projectsId}/issues/${index}`+`">#${index}</a>`,content);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rs = rs.replace(/(__special_katext_id_\d+__)/g, (_match, capture) => {
|
||||
const { type, expression } = math_expressions[capture];
|
||||
|
|
@ -47,7 +89,7 @@ export default ({
|
|||
rs = rs.replace(/▁/g, "▁▁▁")
|
||||
resetMathExpressions()
|
||||
return dompurify.sanitize(rs)
|
||||
}, [str]);
|
||||
}, [str,issues]);
|
||||
|
||||
// 锚点跳转,链接地址里含#对应的id
|
||||
useEffect(()=>{
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import Attachments from "../../Upload/attachment";
|
|||
import UploadImg from '../Img/UploadImg.png';
|
||||
|
||||
function NewPanel(props,ref){
|
||||
const [ description , setDescription ] = useState("");
|
||||
const [ description , setDescription ] = useState(undefined);
|
||||
const [ fileList , setFileList] = useState(undefined);
|
||||
const [ attachments , setAttachments ] = useState([]);
|
||||
const [ save , setSave ] = useState([]);
|
||||
|
|
@ -15,12 +15,11 @@ function NewPanel(props,ref){
|
|||
const { createFunc , title , desc , files , onCancel , owner , projectsId } = props;
|
||||
|
||||
const { form: { getFieldDecorator, validateFields , setFieldsValue } } = props;
|
||||
|
||||
useState(()=>{
|
||||
title && setTimeout(()=>{
|
||||
setFieldsValue({subject:title});
|
||||
desc && onContentChange(desc);
|
||||
},100)
|
||||
desc && setDescription(desc);
|
||||
files && setAttachments(files);
|
||||
files && setSave(files);
|
||||
},[title , desc , files])
|
||||
|
|
@ -84,7 +83,7 @@ function NewPanel(props,ref){
|
|||
<MDEditor
|
||||
placeholder={"请输入描述信息"}
|
||||
height={392}
|
||||
mdID={"order-new-description"}
|
||||
mdID={"issue-edit-description"}
|
||||
initValue={description}
|
||||
onChange={onContentChange}
|
||||
className="mt20"
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ function Details(props){
|
|||
const [ tag , setTag ] = useState(undefined);
|
||||
const [ branchList , setBranchList ] = useState(undefined);
|
||||
const [ branch , setBranch ] = useState(undefined);
|
||||
const [ desc , setDesc ] = useState(undefined);
|
||||
|
||||
const [ orderId , setOrderId ] = useState(undefined);
|
||||
|
||||
|
|
@ -91,6 +92,8 @@ function Details(props){
|
|||
let per = data && !data.user_permission;
|
||||
setEditFlag(per);
|
||||
|
||||
setDesc(data && data.description);
|
||||
|
||||
const aut = current_user && data.author && (data.author.login === current_user.login);
|
||||
const con = data.pull_fixed === false && aut;
|
||||
setAmountEditFlag(con);
|
||||
|
|
@ -277,10 +280,10 @@ function Details(props){
|
|||
if(result){
|
||||
window.scrollTo(0,0);
|
||||
props.showNotification("疑修更新成功!");
|
||||
// 刷新操作记录
|
||||
setCommentReload(Math.random());
|
||||
Init();
|
||||
setEdit(false);
|
||||
// 刷新操作记录
|
||||
setCommentReload(Math.random());
|
||||
}
|
||||
}).catch(error=>{})
|
||||
}else{
|
||||
|
|
@ -318,6 +321,7 @@ function Details(props){
|
|||
props.history.push(`/${owner}/${projectsId}/issues/${index}`);
|
||||
}else{
|
||||
setEdit(false);
|
||||
window.scrollTo(0,0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -367,7 +371,7 @@ function Details(props){
|
|||
{...props}
|
||||
onCancel={onCancel}
|
||||
title={details.subject}
|
||||
desc={details.description}
|
||||
desc={edit ? desc : undefined}
|
||||
files={copy ? undefined : details.attachments}
|
||||
createFunc={createFunc}
|
||||
owner = {owner} projectsId = {projectsId}
|
||||
|
|
@ -405,8 +409,8 @@ function Details(props){
|
|||
}
|
||||
</div>
|
||||
<div class="descPanel">
|
||||
{details.description ?
|
||||
<RenderHtml className="break_word_comments imageLayerParent" value={details.description} url={props.history.location} />
|
||||
{desc ?
|
||||
<RenderHtml owner={owner} projectsId={projectsId} className="break_word_comments imageLayerParent" value={desc} url={props.history.location} />
|
||||
:
|
||||
<span className="color-grey-9 ml3 mr3">暂无描述</span>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ function md_elocalStorage(editor, mdu, id) {
|
|||
return tid
|
||||
}
|
||||
|
||||
export default ({ mdID, onChange, onCMBeforeChange, onCMBlur, error = false, className = '', noStorage = false, imageExpand = true, placeholder = '', width = '100%', height = 400, initValue = '', emoji, watch, showNullButton = false, showResizeBar = false, startInit = true , forMember = true , isCanAtme = false , isQuoteIssue = false , changeAtWhoLoginList, owner, projectsId , isFocus = true}) => {
|
||||
export default ({ mdID, onChange, onCMBeforeChange, onCMBlur, error = false, className = '', noStorage = false, imageExpand = true, placeholder = '', width = '100%', height = 400, initValue = '', emoji, watch=true, showNullButton = false, showResizeBar = false, startInit = true , forMember = true , isCanAtme = false , isQuoteIssue = false , changeAtWhoLoginList, owner, projectsId , isFocus = true}) => {
|
||||
|
||||
const editorEl = useRef();
|
||||
const resizeBarEl = useRef();
|
||||
|
|
@ -130,11 +130,6 @@ export default ({ mdID, onChange, onCMBeforeChange, onCMBlur, error = false, cla
|
|||
})
|
||||
}
|
||||
|
||||
useEffect(()=>{
|
||||
if(initValue){
|
||||
console.log(initValue);
|
||||
}
|
||||
},[initValue])
|
||||
|
||||
// # 引用的弹框div
|
||||
const QuoteDiv = (
|
||||
|
|
@ -176,42 +171,44 @@ export default ({ mdID, onChange, onCMBeforeChange, onCMBlur, error = false, cla
|
|||
}
|
||||
|
||||
useEffect(()=>{
|
||||
if(quoteVisibleRef.current){
|
||||
const atWhoListDiv = document.getElementById("quoteDiv");
|
||||
const atWhoDivs = document.getElementsByClassName("quote");
|
||||
cmEl.addKeyMap({
|
||||
'Up':()=>{
|
||||
let index;
|
||||
for(let i = 0; i<atWhoDivs.length;i++){
|
||||
atWhoDivs[i].className === "quote active" && (index = i);
|
||||
if(cmEl){
|
||||
if(quoteVisibleRef.current){
|
||||
const atWhoListDiv = document.getElementById("quoteDiv");
|
||||
const atWhoDivs = document.getElementsByClassName("quote");
|
||||
cmEl.addKeyMap({
|
||||
'Up':()=>{
|
||||
let index;
|
||||
for(let i = 0; i<atWhoDivs.length;i++){
|
||||
atWhoDivs[i].className === "quote active" && (index = i);
|
||||
}
|
||||
if(index>0){
|
||||
index <=atWhoDivs.length-4 && (atWhoListDiv.scrollTop -=40)
|
||||
atWhoDivs[index].className = "quote";
|
||||
atWhoDivs[index-1].className = "quote active";
|
||||
}
|
||||
},
|
||||
'Down':()=>{
|
||||
let index;
|
||||
for(let i = 0; i<atWhoDivs.length;i++){
|
||||
atWhoDivs[i].className === "quote active" && (index = i);
|
||||
}
|
||||
if(index<atWhoDivs.length-1){
|
||||
index >=3 && (atWhoListDiv.scrollTop +=40)
|
||||
atWhoDivs[index].className = "quote";
|
||||
atWhoDivs[index+1].className = "quote active";
|
||||
}
|
||||
},
|
||||
'Enter':()=>{
|
||||
//找到classname为quote active的div,执行click事件
|
||||
if(document.getElementsByClassName("quote active")[0]){
|
||||
document.getElementsByClassName("quote active")[0].click();
|
||||
}
|
||||
}
|
||||
if(index>0){
|
||||
index <=atWhoDivs.length-4 && (atWhoListDiv.scrollTop -=40)
|
||||
atWhoDivs[index].className = "quote";
|
||||
atWhoDivs[index-1].className = "quote active";
|
||||
}
|
||||
},
|
||||
'Down':()=>{
|
||||
let index;
|
||||
for(let i = 0; i<atWhoDivs.length;i++){
|
||||
atWhoDivs[i].className === "quote active" && (index = i);
|
||||
}
|
||||
if(index<atWhoDivs.length-1){
|
||||
index >=3 && (atWhoListDiv.scrollTop +=40)
|
||||
atWhoDivs[index].className = "quote";
|
||||
atWhoDivs[index+1].className = "quote active";
|
||||
}
|
||||
},
|
||||
'Enter':()=>{
|
||||
//找到classname为quote active的div,执行click事件
|
||||
if(document.getElementsByClassName("quote active")[0]){
|
||||
document.getElementsByClassName("quote active")[0].click();
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
//移除上下、enter键监听
|
||||
cmEl && cmEl.removeKeyMap();
|
||||
})
|
||||
} else {
|
||||
//移除上下、enter键监听
|
||||
cmEl.removeKeyMap();
|
||||
}
|
||||
}
|
||||
},[quoteVisible])
|
||||
|
||||
|
|
@ -302,7 +299,7 @@ export default ({ mdID, onChange, onCMBeforeChange, onCMBlur, error = false, cla
|
|||
}
|
||||
})
|
||||
}
|
||||
if(e.shiftKey && e.code === "Digit3"){
|
||||
if(e.shiftKey && e.code === "Digit3" && isQuoteIssue){
|
||||
// 输入#键后在对应的位置显示可选的项目issue
|
||||
quoteVisibleRef.current = true;
|
||||
setQuoteVisible(true);
|
||||
|
|
@ -348,8 +345,7 @@ export default ({ mdID, onChange, onCMBeforeChange, onCMBlur, error = false, cla
|
|||
htmlDecode: "style,script,iframe",
|
||||
sequenceDiagram: true,
|
||||
autoFocus: false,
|
||||
watch: watch === undefined ? true : watch,
|
||||
|
||||
watch: watch,
|
||||
saveHTMLToTextarea: true,
|
||||
dialogMaskOpacity: 0.6,
|
||||
placeholder: placeholder,
|
||||
|
|
@ -471,10 +467,11 @@ export default ({ mdID, onChange, onCMBeforeChange, onCMBlur, error = false, cla
|
|||
}
|
||||
},[users])
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (cmEl) {
|
||||
let tid = null
|
||||
let ro
|
||||
let ro;
|
||||
if (onCMBlur) {
|
||||
editorInstance.cm.on('blur', () => { onCMBlur(editorInstance.getValue()) })
|
||||
}
|
||||
|
|
@ -750,15 +747,13 @@ export default ({ mdID, onChange, onCMBeforeChange, onCMBlur, error = false, cla
|
|||
document.removeEventListener('mouseup', onMouseUp)
|
||||
}
|
||||
}
|
||||
}, [
|
||||
editorInstance, resizeBarEl
|
||||
])
|
||||
}, [ editorInstance, resizeBarEl ])
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
{atWhoVisible && atWhoList}
|
||||
{quoteVisible && QuoteDiv }
|
||||
<div ref={editorEl} className={`df editormd-editing ${className} ${imageExpand && 'editormd-image-click-expand'} `}>
|
||||
{quoteVisible && QuoteDiv }
|
||||
<div className={`edu-back-greyf5 radius4 editormd ${error ? 'error' : ''}`} id={containerId} >
|
||||
<textarea style={{ display: 'none' }} id={editorBodyId} name="content"></textarea>
|
||||
<div className="CodeMirror cm-s-defualt"></div>
|
||||
|
|
|
|||
Loading…
Reference in New Issue