Merge pull request '修改头像的bug,提取copyUrl组件,优化函数式模态框组件' (#20) from tongChong/forgeplus-react:feature_wikis into pre_develop_dev

This commit is contained in:
baladiwei 2021-08-23 11:47:44 +08:00
commit 39fef1ce3c
8 changed files with 104 additions and 171 deletions

View File

@ -0,0 +1,44 @@
import React, { useState, useCallback, memo } from 'react';
import { Tooltip } from 'antd';
CopyTool.defaultProps = {
beforeText: '复制', //
afterText: '复制成功', //
className: '', //svgclass
inputId: 'copyText', //ID
};
function CopyTool({ beforeText, afterText, className,inputId }) {
const [title, setTitle] = useState(() => {
return beforeText;
});
//
const copyUrl = useCallback(() => {
let inputDom = document.getElementById(inputId);
if (!inputDom) {
console.error("您的CopyTool未设置正确的inputId");
return;
}
inputDom.select();
if (document.execCommand('copy')) {
document.execCommand('copy');
}
setTitle(afterText);
inputDom.blur();
}, []);
return (
<Tooltip
placement="top"
title={title}
onVisibleChange={() => { setTitle(beforeText) }}
>
<i className={`iconfont icon-fuzhiicon ${className}`} style={{ color: '#466aff' }} onClick={copyUrl}></i>
</Tooltip>
);
}
export default memo(CopyTool);

View File

@ -2,7 +2,7 @@ import React, { useEffect, useCallback, useState } from 'react';
import { Button, Dropdown, Icon, Input, Menu, Tooltip, Select, Upload, message, Spin } from 'antd';
import { getImageUrl, timeAgo } from 'educoder';
import cookie from 'react-cookies';
// import Loading from "../../Loading";
import CopyTool from '../Component/CopyTool';
import DelModal from './components/ModalFun';
import Welcome from './Welcome';
import { wikiPages, getWiki, deleteWiki } from './api';
@ -14,15 +14,12 @@ const InputGroup = Input.Group;
const { Option } = Select;
export default (props) => {
const { match, current_user, history, showNotification, project, projectDetail } = props;
// const permission = projectDetail && projectDetail.permission !== "Reporter";
const { match, history, showNotification, project, projectDetail } = props;
const permission = projectDetail && projectDetail.permission && projectDetail.permission !== "Reporter";
let projectsId = match.params.projectsId;
let owner = match.params.owner;
console.log(project);
const [fileArrInit, setFileArrInit] = useState(null);
const [checkItem, setCheckItem] = useState({});
const [itemDetail, setItemDetail] = useState({});
@ -85,7 +82,7 @@ export default (props) => {
DelModal({
title: '删除页面',
contentTitle: `您确定要删除“${item.name}”此页面吗?`,
content: '此操作将删除该页面,请进行确认以防文件的丢失',
content: '此操作将删除该页面,请进行确认以防文件的丢失',
onOk: () => {
deleteWiki({
owner: owner,
@ -109,17 +106,6 @@ export default (props) => {
window.location.href = `/users/${login}`;
}
//
const copyUrl = useCallback(() => {
let wikiUrl = document.getElementById("wikiUrl");
wikiUrl.select();
if (document.execCommand('copy')) {
document.execCommand('copy');
}
message.success('复制成功');
wikiUrl.blur();
}, [])
function addFile() {
history.push(`/projects/${owner}/${projectsId}/wiki/add`);
}
@ -231,6 +217,7 @@ export default (props) => {
<Button type="default" className="ml10">导出<Icon type="caret-down" /></Button>
</Dropdown>
<Button type="default" className="ml10" onClick={preview}>预览</Button>
</div>
</div>
@ -246,8 +233,8 @@ export default (props) => {
{
fileArr.map(item => {
return <div className="wiki-nav-title-parent">
<div className={`wiki-nav-title ${item.name === checkItem.name ? 'active' : ''}`} key={item.name} onClick={() => { setCheckItem(item) }}>
return <div className="wiki-nav-title-parent" key={item.name}>
<div className={`wiki-nav-title ${item.name === checkItem.name ? 'active' : ''}`} onClick={() => { setCheckItem(item) }}>
<div className="nav-title-left">
<i className="iconfont icon-wenjianjia2 mr3"></i>
<span className="nav-title-left-text">{item.name}</span>
@ -266,9 +253,7 @@ export default (props) => {
<Option value="SSH">SSH</Option>
</Select>
<Input id="wikiUrl" value={urlType === 'HTTPS' ? checkItem.wiki_clone_link.https : checkItem.wiki_clone_link.ssh} />
<Tooltip placement="bottom" title={'复制'}>
<i className="iconfont icon-fuzhiicon copy-svg" onClick={copyUrl}></i>
</Tooltip>
<CopyTool className="copy-wiki" inputId="wikiUrl" />
</InputGroup>}
</div>
@ -277,9 +262,9 @@ export default (props) => {
<div className="wiki-content-head">
<div className="wiki-content-head-left">
<h3 className="wiki-detail-title">{checkItem.name}</h3>
<span className="user-box mr10" onClick={() => { goUser(current_user.login) }}>
<span className="user-box mr10" onClick={() => { checkItem.commit && goUser(checkItem.commit.author.name) }}>
{itemDetail.image_url && <img alt="头像" className="head-log-small" src={getImageUrl(`/${itemDetail.image_url}`)} />}
<span >{checkItem.commit ? checkItem.commit.author.name : ''}</span>
<span >{itemDetail.userName}</span>
</span>
<span className="time-ago">上次修改于{checkItem.commit && timeAgo(checkItem.commit.author.when)}</span>
</div>

View File

@ -199,7 +199,7 @@ body {
word-break: break-all;
}
.copy-svg {
.copy-wiki {
display: inline-flex;
align-items: center;
justify-content: center;

View File

@ -1,5 +1,6 @@
import React, { useEffect, useCallback, useState } from 'react';
import { Input, Button, Tooltip, Select, Dropdown, Icon, Menu, message } from 'antd';
import { Input, Button, Select, Dropdown, Icon, Menu, message } from 'antd';
import CopyTool from '../Component/CopyTool';
import { wikiPages, getWiki, } from './api';
import { httpUrl } from './fetch';
import './Index.scss';
@ -59,16 +60,6 @@ export default (props) => {
});
}, [project, checkItem]);
const copyUrl = useCallback(() => {
let wikiUrl = document.getElementById("wikiUrl");
wikiUrl.select();
if (document.execCommand('copy')) {
document.execCommand('copy');
}
message.success('复制成功');
wikiUrl.blur();
}, []);
function goEdit() {
history.push(`/projects/${owner}/${projectsId}/wiki/edit/${checkItem.name}`);
}
@ -113,9 +104,7 @@ export default (props) => {
<Option value="SSH">SSH</Option>
</Select>
<Input id="wikiUrl" value={urlType === 'HTTPS' ? checkItem.wiki_clone_link.https : checkItem.wiki_clone_link.ssh} />
<Tooltip placement="bottom" title={'复制'}>
<i className="iconfont icon-fuzhiicon copy-svg" onClick={copyUrl}></i>
</Tooltip>
<CopyTool className="copy-wiki" inputId="wikiUrl"/>
</InputGroup>
}

View File

@ -1,10 +1,9 @@
import React, { useState } from 'react';
import * as ReactDOM from 'react-dom';
import LoginDialog from '../../../../modules/login/LoginDialog';
import './index.scss';
// 使
export default function DelModal(props) {
// 使
export default function Login(props) {
const div = document.createElement('div');
document.body.appendChild(div);
@ -16,9 +15,6 @@ export default function DelModal(props) {
}
function render() {
/**
* Sync render blocks React event. Let's make this async.
*/
setTimeout(() => {
ReactDOM.render(
<MyLoginDialog afterClose={destroy} />

View File

@ -1,56 +0,0 @@
.delete-modal {
.ant-modal-header {
padding: 9px 24px;
background: #f8f8f8;
border-bottom: 1px solid #eee;
}
.ant-modal-title {
text-align: left;
}
.ant-modal-close {
top: 0px !important;
}
.ant-modal-close-x {
font-size: 24px;
}
.ant-modal-body {
text-align: center;
}
.delete-title {
display: flex;
justify-content: center;
align-items: center;
margin: 2rem 0 1rem !important;
font-size: 16px;
color: #333;
letter-spacing: 0;
line-height: 29px;
font-weight: 400;
}
.red-circle {
align-self: flex-start;
color: #ca0002;
font-size: 1.5rem !important;
}
.delete-descibe {
font-size: 14px;
color: #666;
line-height: 33px;
font-weight: 400;
}
.ant-modal-footer {
padding: 2rem 0;
text-align: center;
border: 0;
.ant-btn {
width: 6rem;
}
}
.foot-submit {
margin-left: 3rem;
color: #df0002;
&:hover {
border-color: #df0002;
}
}
}

View File

@ -1,23 +1,33 @@
/* eslint-disable react/jsx-no-duplicate-props */
import React, { useState } from 'react';
import * as ReactDOM from 'react-dom';
import { Modal, Button } from 'antd';
import './index.scss';
InitModal.defaultProps = {
okText: '确认', //
cancelText: '取消', //
className: '', //
inputId: 'copyText', //ID
};
// 使
export default function DelModal(props) {
renderModal({ ...props, type: 'delete' })
}
export function confirmModal(props) {
// 使
export function Confirm(props) {
renderModal({ ...props, type: 'confirm' })
}
function renderModal(props) {
const type = props.type;
const { type, afterClose } = props;
const div = document.createElement('div');
document.body.appendChild(div);
function destroy() {
afterClose && afterClose();
const unmountResult = ReactDOM.unmountComponentAtNode(div);
if (unmountResult && div.parentNode) {
div.parentNode.removeChild(div);
@ -26,18 +36,26 @@ function renderModal(props) {
function modalType(type) {
if (type === 'delete') {
return <DeleteModal title="删除页面" contentTitle="确定要删除吗?" afterClose={destroy} {...props} />
return <InitModal
title="删除"
contentTitle="确定要删除吗?"
okText="确认删除"
{...props}
afterClose={destroy}
contentTitle={<React.Fragment>
<i className="red-circle iconfont icon-shanchu_tc_icon mr3"></i>
{props.contentTitle}
</React.Fragment>}
/>
} else if (type === 'confirm') {
return <ConfirmModal title="选择" afterClose={destroy} {...props} />
return <InitModal title="选择" afterClose={destroy} {...props} />
} else {
return <ConfirmModal title="选择" afterClose={destroy} {...props} />
return <InitModal title="选择" afterClose={destroy} {...props} />
}
}
function render() {
/**
* Sync render blocks React event. Let's make this async.
*/
setTimeout(() => {
ReactDOM.render(
modalType(type),
@ -48,16 +66,17 @@ function renderModal(props) {
render();
}
//
function DeleteModal({
//
function InitModal({
onCancel,
onOk,
title,
contentTitle,
content,
afterClose,
okText,
cancelText,
afterClose,
className,
}) {
const [visible, setVisible] = useState(true);
@ -78,71 +97,20 @@ function DeleteModal({
onCancel={onCancelModal}
afterClose={afterClose}
title={title}
className="myself-modal"
className={`myself-modal ${className}`}
centered
footer={[
<Button key="back" onClick={onCancelModal}>
{cancelText||'取消'}
<Button type="default" key="back" onClick={onCancelModal}>
{cancelText}
</Button>,
<Button className="foot-submit" key="submit" onClick={onSuccess}>
{okText||'确认删除'}
{okText}
</Button>,
]}
>
<div>
<p className="delete-title">
<i className="red-circle iconfont icon-shanchu_tc_icon mr3"></i>
{contentTitle}</p>
<p className="delete-descibe">{content}</p>
</div>
</Modal>
)
}
//
function ConfirmModal({
onCancel,
onOk,
title,
contentTitle,
content,
okText,
cancelText,
afterClose,
}) {
const [visible, setVisible] = useState(true);
function onCancelModal() {
setVisible(false);
onCancel && onCancel()
}
function onSuccess() {
setVisible(false);
onOk && onOk();
}
return (
<Modal
visible={visible}
onCancel={onCancelModal}
afterClose={afterClose}
title={title}
className="myself-modal"
centered
footer={[
<Button key="back" onClick={onCancelModal}>
{cancelText||'取消'}
</Button>,
<Button className="foot-submit" key="submit" onClick={onSuccess}>
{okText||'确认'}
</Button>,
]}
>
<div>
{contentTitle && <p className="delete-title">{contentTitle}</p>}
<p className="delete-descibe">{content}</p>
{contentTitle && <p className="content-title">{contentTitle}</p>}
<p className="content-descibe">{content}</p>
</div>
</Modal>
)

View File

@ -16,7 +16,7 @@
.ant-modal-body {
text-align: center;
}
.delete-title {
.content-title {
display: flex;
justify-content: center;
align-items: center;
@ -32,7 +32,7 @@
color: #ca0002;
font-size: 1.5rem !important;
}
.delete-descibe {
.content-descibe {
font-size: 14px;
color: #666;
line-height: 33px;
@ -53,4 +53,11 @@
border-color: #df0002;
}
}
.ant-btn-default:hover,
.ant-btn-default:active,
.ant-btn-default:focus {
background: #f3f4f6;
color: #333;
border-color: #d0d0d0;
}
}