Merge remote-tracking branch 'upstream/gitlink_server' into gitlink_server

This commit is contained in:
黄心宇 2024-03-18 14:08:50 +08:00
commit aef127f135
17 changed files with 67 additions and 65 deletions

12
package-lock.json generated
View File

@ -172,7 +172,7 @@
"dependencies": { "dependencies": {
"jsesc": { "jsesc": {
"version": "2.5.2", "version": "2.5.2",
"resolved": "http://173.15.15.82:8081/repository/npm-all/jsesc/-/jsesc-2.5.2.tgz", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
"integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA=="
} }
} }
@ -245,7 +245,7 @@
"dependencies": { "dependencies": {
"chalk": { "chalk": {
"version": "2.4.2", "version": "2.4.2",
"resolved": "http://173.15.15.82:8081/repository/npm-all/chalk/-/chalk-2.4.2.tgz", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"requires": { "requires": {
"ansi-styles": "^3.2.1", "ansi-styles": "^3.2.1",
@ -341,12 +341,12 @@
}, },
"globals": { "globals": {
"version": "11.12.0", "version": "11.12.0",
"resolved": "http://173.15.15.82:8081/repository/npm-all/globals/-/globals-11.12.0.tgz", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
"integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="
}, },
"ms": { "ms": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "http://173.15.15.82:8081/repository/npm-all/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
} }
} }
@ -7248,7 +7248,7 @@
}, },
"promise": { "promise": {
"version": "7.3.1", "version": "7.3.1",
"resolved": "http://173.15.15.82:8081/repository/npm-all/promise/-/promise-7.3.1.tgz", "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
"integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
"requires": { "requires": {
"asap": "~2.0.3" "asap": "~2.0.3"
@ -9677,7 +9677,7 @@
}, },
"chalk": { "chalk": {
"version": "2.4.2", "version": "2.4.2",
"resolved": "http://173.15.15.82:8081/repository/npm-all/chalk/-/chalk-2.4.2.tgz", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"requires": { "requires": {
"ansi-styles": "^3.2.1", "ansi-styles": "^3.2.1",

View File

@ -14,9 +14,10 @@ function Index(props){
const [ content , setContent ] = useState(undefined); const [ content , setContent ] = useState(undefined);
const [ edit , setEdit ] = useState(false); const [ edit , setEdit ] = useState(false);
const [ fileList , setFileList ] = useState(undefined); const [ fileList , setFileList ] = useState(undefined);
const [ editOpration , setEditOpration ] = useState(false); // const [ editOpration , setEditOpration ] = useState(false);
const { owner , projectsId } = props.match.params; const { owner , projectsId } = props.match.params;
const { isManager , isDeveloper , current_user, projectDetail } = props; const { isManager , isDeveloper , current_user, projectDetail } = props;
const editOpration = current_user && current_user.login && isManager
useEffect(()=>{ useEffect(()=>{
if(owner && projectsId && projectDetail){ if(owner && projectsId && projectDetail){
@ -25,11 +26,11 @@ function Index(props){
} }
},[owner,projectsId, projectDetail]) },[owner,projectsId, projectDetail])
useEffect(()=>{ // useEffect(()=>{
if( (current_user && current_user.login) && (isManager === true || isDeveloper === true)){ // if( (current_user && current_user.login) && (isManager === true || isDeveloper === true)){
setEditOpration(true); // setEditOpration(true);
} // }
},[isManager , isDeveloper]) // },[isManager , isDeveloper])
function Init(){ function Init(){
const url = `/${owner}/${projectsId}/about.json`; const url = `/${owner}/${projectsId}/about.json`;
axios.get(url).then(result=>{ axios.get(url).then(result=>{

View File

@ -1,5 +1,7 @@
import React from 'react'; import React from 'react';
import './index.scss'; import './index.scss';
import publicImg from '../../img/gitlink-gz.png';
import qqImg from '../../img/gitlink-qq.png';
function acce({type}){ function acce({type}){
return( return(
@ -14,11 +16,11 @@ function acce({type}){
<p style={{fontSize:'1.6em',color:"#141519"}}>欢迎加入GitLink</p> <p style={{fontSize:'1.6em',color:"#141519"}}>欢迎加入GitLink</p>
<ul className="foot_ewm"> <ul className="foot_ewm">
<li> <li>
<img src={require('../../img/gitlink-gz.png')} alt="" /> <img src={publicImg} alt="" />
<span>开源发展委员会<br/>公众号</span> <span>开源发展委员会<br/>公众号</span>
</li> </li>
<li> <li>
<img src={require('../../img/gitlink-qq.png')} alt="" /> <img src={qqImg} alt="" />
<span>GitLink官方<br/>QQ群</span> <span>GitLink官方<br/>QQ群</span>
</li> </li>
</ul> </ul>

View File

@ -50,6 +50,7 @@
width: 7em; width: 7em;
height: 7em; height: 7em;
margin-bottom: 0.8em; margin-bottom: 0.8em;
border-radius: 3px;
} }
span{ span{
display: block; display: block;

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 54 KiB

View File

@ -16,8 +16,8 @@ function NewPanel(props,ref){
const { form: { getFieldDecorator, validateFields , setFieldsValue } } = props; const { form: { getFieldDecorator, validateFields , setFieldsValue } } = props;
useState(()=>{ useState(()=>{
title && setTimeout(()=>{ setTimeout(()=>{
setFieldsValue({subject:title}); title && setFieldsValue({subject:title});
desc && onContentChange(desc); desc && onContentChange(desc);
},100) },100)
files && setAttachments(files); files && setAttachments(files);

View File

@ -3,7 +3,7 @@ import CopyTool from '../../Component/CopyTool';
import { truncateCommitId } from '../../common/util'; import { truncateCommitId } from '../../common/util';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { getImageUrl , turnbar } from 'educoder'; import { getImageUrl , turnbar } from 'educoder';
import { Button, Dropdown , Input, Menu , message, Modal, Select, Spin, Table, Tooltip , Radio } from 'antd'; import { Button, Dropdown , Input, Menu , message, Modal, Select, Spin, Table, Tooltip , Radio , Popover } from 'antd';
import Modals from '../../Component/PublicModal/Index'; import Modals from '../../Component/PublicModal/Index';
import './Index.scss'; import './Index.scss';
@ -34,7 +34,7 @@ function Index(props) {
const { projectsId , owner } = props.match.params; const { projectsId , owner } = props.match.params;
const { isManager , isDeveloper , projectDetail , defaultBranch, getDetail } = props; const { isManager , isDeveloper , projectDetail , defaultBranch, getDetail } = props;
useEffect(()=>{ useEffect(()=>{
getList(chooseStatus); getList();
},[name, reload, pageSize, current,chooseStatus]) },[name, reload, pageSize, current,chooseStatus])
useEffect(()=>{ useEffect(()=>{
@ -131,9 +131,13 @@ function Index(props) {
width: "300px", width: "300px",
className: "branchActionColumn", className: "branchActionColumn",
render: (txt, item,key) => { render: (txt, item,key) => {
console.log("-----:",item.is_deleted);
return ( return (
item.is_deleted ? <div style={{textAlign:"right"}}><Button onClick={()=>restoreBranch(item.branch_id,item.name)}>恢复分支</Button></div>: item.is_deleted ?
<div style={{textAlign:"right"}}>
<Popover content={<span>将基于 Commits<span className="color-blue ml3 mr3">{truncateCommitId(item.commit_id)}</span>创建分支</span>}>
<Button onClick={()=>restoreBranch(item.branch_id,item.name)}>恢复分支</Button>
</Popover>
</div>:
<div className="treeabout"> <div className="treeabout">
{ {
(isManager || isDeveloper) && (projectDetail && projectDetail.type!==2) && (isManager || isDeveloper) && (projectDetail && projectDetail.type!==2) &&
@ -166,7 +170,7 @@ function Index(props) {
}) })
} }
function getList(state) { function getList() {
const url = `/v1/${owner}/${projectsId}/branches.json`; const url = `/v1/${owner}/${projectsId}/branches.json`;
Axios.get(url,{ Axios.get(url,{
params:{ params:{
@ -303,7 +307,13 @@ function Index(props) {
className='branchListTable' className='branchListTable'
dataSource={list} dataSource={list}
columns={columns} columns={columns}
pagination={{current: current, pageSize: pageSize, total: total, showSizeChanger: true, onShowSizeChange:onShowSizeChange, showQuickJumper: true, onChange: changePage}} pagination={{current: current,
pageSize: pageSize,
total: total,
showSizeChanger: true,
onShowSizeChange:onShowSizeChange,
showQuickJumper: true, onChange: changePage,hideOnSinglePage:true
}}
> >
</Table> </Table>
{/* { {/* {
@ -386,7 +396,7 @@ function Index(props) {
> >
<div className="contents mb30" style={{justifyContent: 'flex-start'}}> <div className="contents mb30" style={{justifyContent: 'flex-start'}}>
<i className='iconfont icon-shanchu_tc_icon1 font-36 mr18' style={{color: '#ca0002'}}></i> <i className='iconfont icon-shanchu_tc_icon1 font-36 mr18' style={{color: '#ca0002'}}></i>
<p style={{color: '#333'}}>确定删除{visible.name}分支?</p> <p style={{color: '#333'}}>删除分支本操作将会关闭已开启的Pull Request</p>
</div> </div>
</Modals> </Modals>
<Modal <Modal

View File

@ -18,7 +18,7 @@ export default Form.create()(({ form, history, showNotification, projectDetail,
let wikiName = '' let wikiName = ''
let key = ''; let key = '';
if (!pathname.endsWith('/wiki/add')) { if (!pathname.endsWith('/wiki/add')) {
wikiName = decodeURI(pathname.split('/')[4]); wikiName = pathname.split('/')[4];
key = pathname.split('/')[5]; key = pathname.split('/')[5];
}else{ }else{
key = search.split('=').pop(); key = search.split('=').pop();
@ -116,12 +116,6 @@ export default Form.create()(({ form, history, showNotification, projectDetail,
}; };
validateFields((err, values) => { validateFields((err, values) => {
if (!err) { if (!err) {
let regEn = /[\\/:*?"<>|[\]-]/g;
if (regEn.test(values.title)) {
message.error('文件名不能有特殊字符: \\ / : * ? \" < > | [ \] -');
setOperateFlag(false);
return;
}
const {md_content, title} = values; const {md_content, title} = values;
if (wikiName && search!== "?copy") { if (wikiName && search!== "?copy") {
updateWiki({ updateWiki({
@ -130,7 +124,7 @@ export default Form.create()(({ form, history, showNotification, projectDetail,
projectId: project.id, projectId: project.id,
pageName: wikiName, pageName: wikiName,
title, title,
commit_message: '', message: '',
content_base64: Base64.encode(md_content) content_base64: Base64.encode(md_content)
}).then(res => dealRes(res, title)); }).then(res => dealRes(res, title));
} else { } else {
@ -223,7 +217,7 @@ export default Form.create()(({ form, history, showNotification, projectDetail,
projectId: project.id, projectId: project.id,
pageName: '_Sidebar', pageName: '_Sidebar',
title: '_Sidebar', title: '_Sidebar',
commit_message: '', message: '',
content_base64: Base64.encode(content) content_base64: Base64.encode(content)
}).then(res => { }).then(res => {
if (res && res.message === "200") { if (res && res.message === "200") {
@ -333,7 +327,7 @@ export default Form.create()(({ form, history, showNotification, projectDetail,
"title", "title",
[ [
{ required: true, message: "请输入标题" }, { required: true, message: "请输入标题" },
// { pattern: /[^`\[\]\/:*?''<>|%-+_]/g, message: '' } { pattern: /^(?!-).*$/, message: '不能以-开头' }
], ],
<Input <Input
placeholder={"请输入标题"} placeholder={"请输入标题"}

View File

@ -115,7 +115,7 @@ export default (props) => {
project && checkItem.name && getWiki({ project && checkItem.name && getWiki({
owner: owner, owner: owner,
repo: projectsId, repo: projectsId,
pageName: checkItem.name, pageName: checkItem.sub_url,
projectId: project.id projectId: project.id
}).then(res => { }).then(res => {
if (res && res.message === "200") { if (res && res.message === "200") {
@ -190,11 +190,6 @@ export default (props) => {
setAddMenuError("不能仅输入空格"); setAddMenuError("不能仅输入空格");
return; return;
} }
const regEn = /[\\/:*?"<>|[\]-]/g;
if (regEn.test(menuName)) {
setAddMenuError("不能有特殊字符: \\ / : * ? \" < > | [ \] -");
return;
}
// //
const oneMenuList = fileList.filter(item=>!item.title.trim().startsWith('[[')).map(i=>i.title.trim()) const oneMenuList = fileList.filter(item=>!item.title.trim().startsWith('[[')).map(i=>i.title.trim())
if(oneMenuList.includes(`- ${menuName}`)){ if(oneMenuList.includes(`- ${menuName}`)){
@ -215,7 +210,7 @@ export default (props) => {
projectId: project.id, projectId: project.id,
pageName: '_Sidebar', pageName: '_Sidebar',
title: '_Sidebar', title: '_Sidebar',
commit_message: '', message: '',
content_base64: Base64.encode(treeToMd(sidebarList)) content_base64: Base64.encode(treeToMd(sidebarList))
}).then(res => { }).then(res => {
if (res && res.message === "200") { if (res && res.message === "200") {
@ -233,7 +228,7 @@ export default (props) => {
} }
function goEdit(params) { function goEdit(params) {
history.push(`/${owner}/${projectsId}/wiki/${encodeURI(checkItem.name)}/${checkItem.key}/edit${params}`); history.push(`/${owner}/${projectsId}/wiki/${encodeURI(checkItem.sub_url)}/${checkItem.key}/edit${params}`);
} }
function preview() { function preview() {

View File

@ -63,7 +63,7 @@ export default (props) => {
projectsId && checkItem.name && getWiki({ projectsId && checkItem.name && getWiki({
owner: owner, owner: owner,
repo: projectsId, repo: projectsId,
pageName: checkItem.name, pageName: checkItem.sub_url,
projectId: projectId, projectId: projectId,
}).then(res => { }).then(res => {
if (res && res.message === "200") { if (res && res.message === "200") {

View File

@ -116,13 +116,16 @@ export function markdownToTree(markdownText){
lines.map((item, index) =>{ lines.map((item, index) =>{
const title = item.trim(); const title = item.trim();
const isFile = title.startsWith('[[') && title.endsWith(']]'); const isFile = title.startsWith('[[') && title.endsWith(']]');
const titleStr = isFile ? title.substring(2, title.length - 2) : title.substring(2, title.length)
const node = { const node = {
// 带空格+[[]]或者- 标识 // 带空格+[[]]或者- 标识
title: item, title: item,
children: [], children: [],
key: undefined, key: undefined,
// 纯内容 // 纯内容
titleStr: isFile ? title.substring(2, title.length - 2) : title.substring(2, title.length), titleStr,
// 编码后的title,获取wiki内容用title_sub
title_sub: encodeURIComponent(titleStr),
// 是否是wiki文件 // 是否是wiki文件
isFile: isFile isFile: isFile
} }

View File

@ -163,7 +163,7 @@ export default function Sidebar(props) {
const {node, children, key} = item; const {node, children, key} = item;
if(isFile){ if(isFile){
// //
deleteWiki({owner: owner, repo: projectsId, projectId: project.id, pageName: title}).then(res => { deleteWiki({owner: owner, repo: projectsId, projectId: project.id, pageName: item.title_sub}).then(res => {
if(res && res.message === "204"){ if(res && res.message === "204"){
// key // key
const menuListByDel = findSameKeyByDel(menuList, key); const menuListByDel = findSameKeyByDel(menuList, key);
@ -267,7 +267,7 @@ export default function Sidebar(props) {
projectId: project.id, projectId: project.id,
pageName: '_Sidebar', pageName: '_Sidebar',
title: '_Sidebar', title: '_Sidebar',
commit_message: '', message: '',
content_base64: Base64.encode(content) content_base64: Base64.encode(content)
}).then(res => { }).then(res => {
if (res && res.message === "200") { if (res && res.message === "200") {
@ -303,20 +303,18 @@ export default function Sidebar(props) {
e.stopPropagation(); e.stopPropagation();
setVisible(item); setVisible(item);
setIsEditName(type); setIsEditName(type);
let title = item.title.trim(); const {titleStr, title_sub} = item;
const isFile = title.startsWith('[[') && title.endsWith(']]');
title = isFile ? title.substring(2,title.length-2) : title.substring(2, title.length);
type === 2 && getWiki({ type === 2 && getWiki({
owner: owner, owner: owner,
repo: projectsId, repo: projectsId,
pageName: title, pageName: title_sub,
projectId: project.id projectId: project.id
}).then(res => { }).then(res => {
if (res && res.message === "200") { if (res && res.message === "200") {
setWikiContent(res.data.md_content); setWikiContent(res.data.md_content);
} }
}) })
setMenuName(title); setMenuName(titleStr);
} }
// //
@ -329,9 +327,8 @@ export default function Sidebar(props) {
setAddMenuError("不能仅输入空格"); setAddMenuError("不能仅输入空格");
return; return;
} }
const regEn = /[\\/:*?"<>|[\]-]/g; if (isEditName === 2 && /^-/.test(menuName)) {
if (regEn.test(menuName)) { setAddMenuError('不能以-开头');
setAddMenuError('不能有特殊字符: \\ / : * ? \" < > | [ \] -');
return; return;
} }
if(!isEditName){ if(!isEditName){
@ -356,14 +353,15 @@ export default function Sidebar(props) {
}else{ }else{
// isEditName 1 2 // isEditName 1 2
const titleToJudge = isEditName === 2 ? `[[${menuName}]]` : `- ${menuName}`; const titleToJudge = isEditName === 2 ? `[[${menuName}]]` : `- ${menuName}`;
const {title, key} = visible; const {key, titleStr, title_sub} = visible;
if(title.trim() === titleToJudge){ //
if(titleStr === menuName){
setAddMenuError("请修改名称"); setAddMenuError("请修改名称");
return return
} }
// //
const list = findBrotherNodesByKey(menuList, key) || []; const list = findBrotherNodesByKey(menuList, key) || [];
if(list.map(item=>item.title.trim()).includes(titleToJudge)){ if(list.map(item=>item.titleStr).includes(menuName)){
setAddMenuError("不能与同级目录名称相同"); setAddMenuError("不能与同级目录名称相同");
return return
} }
@ -381,17 +379,16 @@ export default function Sidebar(props) {
}) })
if(isEditName === 2){ if(isEditName === 2){
// -> wiki // -> wiki
const oldTitle = title.substring(title.indexOf('[[')+2, title.indexOf(']]'))
updateWiki({ updateWiki({
owner, owner,
repo: projectsId, repo: projectsId,
projectId: project.id, projectId: project.id,
// //
pageName: oldTitle, pageName: title_sub,
// //
title: menuName, title: menuName,
content_base64: wikiContent, content_base64: wikiContent,
commit_message: '', message: '',
}).then(res=>{ }).then(res=>{
if(res && res.message === '200'){ if(res && res.message === '200'){
// wikisidebar // wikisidebar

View File

@ -59,10 +59,8 @@ export default function UploadWiki(props) {
message.error('只能上传md、txt文件'); message.error('只能上传md、txt文件');
return false; return false;
} }
if (/^-/.test(file.name)) {
let regEn = /[\\/:*?"<>|[\]-]/g; message.error('文件名不能以-开头');
if (regEn.test(file.name)) {
message.error('文件名不能有特殊字符: \\ / : * ? \" < > | [ \] -');
return false; return false;
} }
@ -86,7 +84,7 @@ export default function UploadWiki(props) {
projectId: project.id, projectId: project.id,
pageName: '_Sidebar', pageName: '_Sidebar',
title: '_Sidebar', title: '_Sidebar',
commit_message: '', message: '',
content_base64: Base64.encode(treeToMd(sidebarList)) content_base64: Base64.encode(treeToMd(sidebarList))
}).then(res => { }).then(res => {
if (res && res.message === "200") { if (res && res.message === "200") {

View File

@ -2139,7 +2139,8 @@ input.ant-input-number-input:focus {
} }
/* md代码类样式渲染 */ /* md代码类样式渲染 */
.new_li .markdown-body ul>li ,.markdown-body ul>li { /* issues/3984: ,.markdown-body ul>li */
.new_li .markdown-body ul>li {
list-style-type: disc !important; list-style-type: disc !important;
margin-bottom: 0 !important; margin-bottom: 0 !important;
white-space: pre-wrap; white-space: pre-wrap;