forgeplus-react/src/forge/Wiki/EditWiki.jsx

376 lines
11 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useEffect, useCallback, useState } from 'react';
import { Button, Checkbox, Form, Icon, Radio, Input, message } from 'antd';
import MDEditor from "../../modules/tpm/challengesnew/tpm-md-editor";
import DelModal from './components/ModalFun';
import { weekModal, monthModal } from './components/config';
import { getWiki, wikiPages, addWiki, updateWiki, markdownToTree, treeToMd } from './api';
import './Index.scss';
import { Base64 } from 'js-base64';
export default Form.create()(({ form, history, showNotification, projectDetail, match, project }) => {
const {location:{pathname, search}} = history;
const permission = projectDetail && projectDetail.permission && projectDetail.permission !== "Reporter";
const { getFieldDecorator, validateFields, setFieldsValue } = form;
let projectsId = match.params.projectsId;
let owner = match.params.owner;
let wikiName = ''
let key = '';
if (!pathname.endsWith('/wiki/add')) {
wikiName = decodeURI(pathname.split('/')[4]);
key = pathname.split('/')[5];
}else{
key = search.split('=').pop();
}
const [fileArrInit, setFileArrInit] = useState(null);
const [content, setContent] = useState("欢迎来到Wiki");
const [modal, setModal] = useState(false);
const [operateFlag, setOperateFlag ] = useState(false);
const [modalType, setModalType] = useState();
const [sidebar, setSidebar] = useState(undefined);
const [menuList, setMenuList] = useState(undefined);
useEffect(()=>{
if(projectDetail){
const { author, name} = projectDetail;
if(wikiName){
document.title = `编辑${wikiName}-维基-${author.name}/${name}`;
}else{
document.title = `新建维基-${author.name}/${name}`;
}
}
}, [projectDetail, wikiName])
useEffect(() => {
wikiName && project && getWiki({
owner,
repo: projectsId,
pageName: wikiName,
projectId: project.id
}).then(res => {
if (res && res.data) {
const content = Base64.decode(res.data.md_content);
setContent(content);
setFieldsValue({
title: search === "?copy" ? `${res.data.name}(复制)` : res.data.name,
md_content: content,
});
}
});
}, [owner, wikiName]);
// 加载wiki列表
useEffect(() => {
project && wikiPages({
owner: owner,
repo: projectsId,
projectId: project.id
}).then(res => {
if (res && res.message === "200" && Array.isArray(res.data)) {
setFileArrInit(res.data);
// 仓库存在没有创建过wiki的情况
if(res.data.length){
// 获取sidebar文件内容
getWiki({
owner,
repo: projectsId,
pageName: '_Sidebar',
projectId: project.id
}).then(res => {
if (res && res.data) {
const sidebarDecode = Base64.decode(res.data.md_content);
setSidebar(sidebarDecode);
key && setMenuList(markdownToTree(sidebarDecode))
}
});
}
} else {
setFileArrInit([]);
}
});
}, [project]);
const helper = useCallback(
(label, name, rules, widget, initialValue, rightComponent) => (
<Form.Item label={label} className="mb0">
{getFieldDecorator(name, { rules, initialValue, validateFirst: true, })(widget)}
{rightComponent}
</Form.Item>
), []);
function onContentChange(value) {
setContent(value);
setFieldsValue({
md_content: value
});
};
// 保存wiki文件包括新增和修改
function saveFile() {
if(operateFlag) {
setOperateFlag(true);
return;
};
validateFields((err, values) => {
if (!err) {
let regEn = /[\\/:*?"<>|[\]-]/g;
if (regEn.test(values.title)) {
message.error('文件名不能有特殊字符: \\ / : * ? \" < > | [ \] -');
setOperateFlag(false);
return;
}
const {md_content, title} = values;
if (wikiName && search!== "?copy") {
updateWiki({
owner,
repo: projectsId,
projectId: project.id,
pageName: wikiName,
title,
commit_message: '',
content_base64: Base64.encode(md_content)
}).then(res => dealRes(res, title));
} else {
// 由于wiki在底层是由wikiname标识的md文件所以对于所有的页面都不能重名
if (Array.isArray(fileArrInit)) {
for (const item of fileArrInit) {
if (item.name === title) {
message.error('不能与已有文件标题相同');
setOperateFlag(false);
return false;
}
}
}
addWiki({
owner,
repo: projectsId,
projectId: project.id,
pageName: title,
title,
message: '',
content_base64: Base64.encode(md_content)
}).then(res => dealRes(res, title));
}
}
})
}
function dealRes(res, title) {
if (res && (res.message === "201" || res.message === "200")) {
if(wikiName && search!== "?copy"){
// 如果有更改wiki文件名则修改sidebar
if(wikiName === title){
message.success("操作成功");
goBack();
}else{
// 找到相同的key值node修改title参数再保存sidebar
const newMenuList = menuList;
editTitleByKey(newMenuList, key, title);
updateSidebar(treeToMd(newMenuList), title);
}
}else{
// 根据路由判断是新增的一级页面还是子页面
if(search === "?copy"){
// 截断key的前几位获取父元素的key值
const keyArr = key.split('-');
keyArr.pop();
const list = menuList;
addChildrenByKey(list, keyArr.join('-'), title);
updateSidebar(treeToMd(list), title);
}else if(search.includes("?key")){
// 遍历menuList找到相同key的节点children push[[页面]]
const list = menuList;
addChildrenByKey(list, key, title);
updateSidebar(treeToMd(list), title);
}else{
if(fileArrInit.length){
updateSidebar(`${sidebar}\n[[${title}]]`, title);
}else{
// 仓库第一次创建wiki文件
addWiki({
owner,
repo: projectsId,
projectId: project.id,
pageName: "_Sidebar",
title: "_Sidebar",
message: '',
content_base64: Base64.encode(`[[${title}]]`)
}).then(res => {
if(res && res.message === "201"){
message.success("操作成功");
goBack();
}
});
}
}
}
} else if (res && res.message === "500") {
setOperateFlag(false);
message.error('请检查格式是否正确或文件名是否重复');
} else {
setOperateFlag(false);
showNotification(res.data || "操作失败");
}
}
function updateSidebar(content, newTitle){
updateWiki({
owner,
repo: projectsId,
projectId: project.id,
pageName: '_Sidebar',
title: '_Sidebar',
commit_message: '',
content_base64: Base64.encode(content)
}).then(res => {
if (res && res.message === "200") {
message.success("操作成功");
if(newTitle){
// 用户修改了wiki名称
history.push(`/${owner}/${projectsId}/wiki/${encodeURI(newTitle)}/${key}`)
return;
}
goBack();
}
});
}
// 递归menuList, 找到相同key值修改title名称
function editTitleByKey(list, key, newTitle){
for (let index = 0; index < list.length; index++) {
const element = list[index];
if (element.key == key) {
const {title} = element;
element.title = `${title.substring(0, title.indexOf('[['))}[[${newTitle}]]`;
return true;
}else if (element.children.length) {
let result = editTitleByKey(element.children, key, newTitle);
if (result) {
return result;
}
}
}
}
// 递归menuList 创建子页面
function addChildrenByKey(list, key, name){
for (let index = 0; index < list.length; index++) {
const element = list[index];
if (element.key == key) {
const {title} = element;
element.children.push({
title: `\t${title.substring(0, title.indexOf('- '))}[[${name}]]`,
children: []
});
return true;
}else if (element.children.length) {
let result = addChildrenByKey(element.children, key, name);
if (result) {
return result;
}
}
}
}
function goBack() {
history.go(-1);
}
function changeModal(e) {
setModal(e.target.checked);
if (!e.target.checked) {
setModalType();
}
}
function changeModalType(e) {
let value = e.target.value;
if (!content) {
setModalContent(value);
return;
}
DelModal({
title: '添加模版',
contentTitle: `您确定要添加“${value}”模板吗`,
content: `此操作会将“${value}”模板替换编辑栏内所有内容,请确认以防文件的丢失`,
okText: '确认添加',
onOk: () => {
setModalType(value);
setModal(true);
setModalContent(value);
}
});
}
function setModalContent(value) {
if (value === '周报') {
setContent(weekModal);
setFieldsValue({
md_content: weekModal
});
} else if (value === '月报') {
setContent(monthModal);
setFieldsValue({
md_content: monthModal
});
}
}
return (
<div className="wiki-main">
<div className="wiki-head">
<span className="head-title"><span className="back-wiki" onClick={goBack}>Wiki</span> <Icon type="right" /> {wikiName ? search === "?copy" ? '复制' : '编辑' : '新增'}页面</span>
</div>
<div >
<h4 className="mt20 mb0">标题</h4>
{helper(
"",
"title",
[
{ required: true, message: "请输入标题" },
// { pattern: /[^`\[\]\/:*?''<>|%-+_]/g, message: '不允许部分特殊字符' }
],
<Input
placeholder={"请输入标题"}
className="contact-input"
maxLength={50}
autoFocus
/>
)}
<Form.Item className="mb0 wiki-md">
<MDEditor
placeholder={"请输入wiki内容"}
height={500}
mdID={"order-new-description"}
initValue={content}
onChange={onContentChange}
className="mt20 wikiMEDEditor"
isFocus={false}
></MDEditor>
{getFieldDecorator('md_content', {
rules: [{ required: true, message: "请输入wiki内容" }],
validateFirst: true,
initialValue: "欢迎来到Wiki"
})(<Input style={{ display: 'none' }} />)}
</Form.Item>
<Checkbox checked={modal} onChange={changeModal}>添加模版</Checkbox>
<Radio.Group onChange={changeModalType} value={modalType}>
<Radio value='周报'>周报</Radio>
<Radio value='月报'>月报</Radio>
</Radio.Group>
</div>
{permission && <Button className="mt25" type="primary" onClick={saveFile}>保存</Button>}
</div>
)
})