mirror of https://github.com/fantasticit/think.git
client: improve render editor
This commit is contained in:
parent
6768ecc0e2
commit
a534e799c1
|
@ -51,19 +51,18 @@ export const DocumentEditor: React.FC<IProps> = ({ documentId }) => {
|
|||
}, [document, documentId]);
|
||||
|
||||
const actions = useMemo(
|
||||
() =>
|
||||
docAuthLoading ? null : (
|
||||
<Space>
|
||||
{document && authority.readable && (
|
||||
<DocumentCollaboration key="collaboration" wikiId={document.wikiId} documentId={documentId} />
|
||||
)}
|
||||
<DocumentShare key="share" documentId={documentId} />
|
||||
<DocumentVersion key="version" documentId={documentId} onSelect={triggerUseDocumentVersion} />
|
||||
<DocumentStar key="star" documentId={documentId} />
|
||||
<DocumentStyle />
|
||||
</Space>
|
||||
),
|
||||
[docAuthLoading, documentId, document, authority]
|
||||
() => (
|
||||
<Space>
|
||||
{document && authority.readable && (
|
||||
<DocumentCollaboration key="collaboration" wikiId={document.wikiId} documentId={documentId} />
|
||||
)}
|
||||
<DocumentShare key="share" documentId={documentId} />
|
||||
<DocumentVersion key="version" documentId={documentId} onSelect={triggerUseDocumentVersion} />
|
||||
<DocumentStar key="star" documentId={documentId} />
|
||||
<DocumentStyle />
|
||||
</Space>
|
||||
),
|
||||
[documentId, document, authority]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -120,36 +119,18 @@ export const DocumentEditor: React.FC<IProps> = ({ documentId }) => {
|
|||
{isMobile && <div className={styles.mobileToolbar}>{actions}</div>}
|
||||
</header>
|
||||
<main className={styles.contentWrap}>
|
||||
<DataRender
|
||||
loading={docAuthLoading}
|
||||
loadingContent={
|
||||
<div style={{ margin: '10vh auto' }}>
|
||||
<Spin tip="正在为您读取文档中...">
|
||||
{/* FIXME: semi-design 的问题,不加 div,文字会换行! */}
|
||||
<div></div>
|
||||
</Spin>
|
||||
</div>
|
||||
}
|
||||
error={docAuthError}
|
||||
errorContent={
|
||||
<div style={{ margin: '10vh', textAlign: 'center' }}>
|
||||
<SecureDocumentIllustration />
|
||||
</div>
|
||||
}
|
||||
normalContent={() => {
|
||||
return (
|
||||
<>
|
||||
<Seo title={document.title} />
|
||||
<Editor
|
||||
user={user}
|
||||
documentId={document.id}
|
||||
authority={authority}
|
||||
className={editorWrapClassNames}
|
||||
style={{ fontSize }}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
{docAuthError && (
|
||||
<div style={{ margin: '10vh', textAlign: 'center' }}>
|
||||
<SecureDocumentIllustration />
|
||||
</div>
|
||||
)}
|
||||
{document && <Seo title={document.title} />}
|
||||
<Editor
|
||||
user={user}
|
||||
documentId={documentId}
|
||||
authority={authority}
|
||||
className={editorWrapClassNames}
|
||||
style={{ fontSize }}
|
||||
/>
|
||||
</main>
|
||||
</div>
|
||||
|
|
|
@ -76,34 +76,31 @@ export const DocumentReader: React.FC<IProps> = ({ documentId }) => {
|
|||
}, [document]);
|
||||
|
||||
const actions = useMemo(
|
||||
() =>
|
||||
docAuthLoading ? null : (
|
||||
<Space>
|
||||
{document && authority.readable && (
|
||||
<DocumentCollaboration key="collaboration" wikiId={document.wikiId} documentId={documentId} />
|
||||
)}
|
||||
{authority && authority.editable && (
|
||||
<Tooltip key="edit" content="编辑" position="bottom">
|
||||
<Button icon={<IconEdit />} onMouseDown={gotoEdit} />
|
||||
</Tooltip>
|
||||
)}
|
||||
{authority && authority.readable && (
|
||||
<>
|
||||
<DocumentShare key="share" documentId={documentId} />
|
||||
<DocumentVersion key="version" documentId={documentId} />
|
||||
<DocumentStar key="star" documentId={documentId} />
|
||||
</>
|
||||
)}
|
||||
<DocumentStyle />
|
||||
</Space>
|
||||
),
|
||||
[docAuthLoading, document, documentId, authority, gotoEdit]
|
||||
() => (
|
||||
<Space>
|
||||
{document && authority.readable && (
|
||||
<DocumentCollaboration key="collaboration" wikiId={document.wikiId} documentId={documentId} />
|
||||
)}
|
||||
{authority && authority.editable && (
|
||||
<Tooltip key="edit" content="编辑" position="bottom">
|
||||
<Button icon={<IconEdit />} onMouseDown={gotoEdit} />
|
||||
</Tooltip>
|
||||
)}
|
||||
{authority && authority.readable && (
|
||||
<>
|
||||
<DocumentShare key="share" documentId={documentId} />
|
||||
<DocumentVersion key="version" documentId={documentId} />
|
||||
<DocumentStar key="star" documentId={documentId} />
|
||||
</>
|
||||
)}
|
||||
<DocumentStyle />
|
||||
</Space>
|
||||
),
|
||||
[document, documentId, authority, gotoEdit]
|
||||
);
|
||||
|
||||
const editBtnStyle = useMemo(() => getEditBtnStyle(isMobile ? 16 : 100), [isMobile]);
|
||||
|
||||
if (!documentId) return null;
|
||||
|
||||
return (
|
||||
<div className={styles.wrap}>
|
||||
<Header className={styles.headerWrap}>
|
||||
|
@ -134,50 +131,31 @@ export const DocumentReader: React.FC<IProps> = ({ documentId }) => {
|
|||
<Layout className={styles.contentWrap}>
|
||||
<div ref={setContainer}>
|
||||
<div className={cls(styles.editorWrap, editorWrapClassNames)} style={{ fontSize }}>
|
||||
<DataRender
|
||||
loading={docAuthLoading}
|
||||
error={docAuthError}
|
||||
loadingContent={
|
||||
<div style={{ margin: '10vh auto' }}>
|
||||
<Spin tip="正在为您读取文档中...">
|
||||
{/* FIXME: semi-design 的问题,不加 div,文字会换行! */}
|
||||
<div></div>
|
||||
</Spin>
|
||||
<div id="js-reader-container">
|
||||
{document && <Seo title={document.title} />}
|
||||
{user && (
|
||||
<CollaborationEditor
|
||||
editable={false}
|
||||
user={user}
|
||||
id={documentId}
|
||||
type="document"
|
||||
renderInEditorPortal={renderAuthor}
|
||||
onAwarenessUpdate={triggerJoinUser}
|
||||
/>
|
||||
)}
|
||||
{user && (
|
||||
<div className={styles.commentWrap}>
|
||||
<CommentEditor documentId={documentId} />
|
||||
</div>
|
||||
}
|
||||
normalContent={() => {
|
||||
return (
|
||||
<div id="js-reader-container">
|
||||
<Seo title={document.title} />
|
||||
{user && (
|
||||
<CollaborationEditor
|
||||
editable={false}
|
||||
user={user}
|
||||
id={documentId}
|
||||
type="document"
|
||||
initialContent={document.content}
|
||||
renderInEditorPortal={renderAuthor}
|
||||
onAwarenessUpdate={triggerJoinUser}
|
||||
/>
|
||||
)}
|
||||
{user && (
|
||||
<div className={styles.commentWrap}>
|
||||
<CommentEditor documentId={document.id} />
|
||||
</div>
|
||||
)}
|
||||
{!isMobile && authority && authority.editable && container && (
|
||||
<BackTop style={editBtnStyle} onClick={gotoEdit} target={() => container} visibilityHeight={200}>
|
||||
<IconEdit />
|
||||
</BackTop>
|
||||
)}
|
||||
<ImageViewer containerSelector="#js-reader-container" />
|
||||
{container && (
|
||||
<BackTop style={{ bottom: 65, right: isMobile ? 16 : 100 }} target={() => container} />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{!isMobile && authority && authority.editable && container && (
|
||||
<BackTop style={editBtnStyle} onClick={gotoEdit} target={() => container} visibilityHeight={200}>
|
||||
<IconEdit />
|
||||
</BackTop>
|
||||
)}
|
||||
<ImageViewer containerSelector="#js-reader-container" />
|
||||
{container && <BackTop style={{ bottom: 65, right: isMobile ? 16 : 100 }} target={() => container} />}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Layout>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { IconChevronLeft } from '@douyinfe/semi-icons';
|
||||
import { Button, Nav, Popconfirm, Space, Spin, Switch, Tooltip, Typography } from '@douyinfe/semi-ui';
|
||||
import { Button, Nav, Popconfirm, Space, Switch, Tooltip, Typography } from '@douyinfe/semi-ui';
|
||||
import cls from 'classnames';
|
||||
import { DataRender } from 'components/data-render';
|
||||
import { DocumentStyle } from 'components/document/style';
|
||||
import { Seo } from 'components/seo';
|
||||
import { Theme } from 'components/theme';
|
||||
|
@ -52,68 +51,55 @@ export const TemplateEditor: React.FC<IProps> = ({ templateId }) => {
|
|||
}, [data]);
|
||||
|
||||
return (
|
||||
<DataRender
|
||||
loading={loading}
|
||||
loadingContent={
|
||||
<div style={{ margin: 24 }}>
|
||||
<Spin></Spin>
|
||||
</div>
|
||||
}
|
||||
error={error}
|
||||
normalContent={() => {
|
||||
return (
|
||||
<>
|
||||
<Seo title={data.title} />
|
||||
<div className={styles.wrap}>
|
||||
<header>
|
||||
<Nav
|
||||
style={{ overflow: 'auto' }}
|
||||
mode="horizontal"
|
||||
header={
|
||||
<>
|
||||
<Tooltip content="返回" position="bottom">
|
||||
<Button onClick={goback} icon={<IconChevronLeft />} style={{ marginRight: 16 }} />
|
||||
</Tooltip>
|
||||
<Text strong ellipsis={{ showTooltip: true }} style={{ width: ~~(windowWidth / 4) }}>
|
||||
{title}
|
||||
</Text>
|
||||
</>
|
||||
}
|
||||
footer={
|
||||
<Space>
|
||||
<DocumentStyle />
|
||||
<Tooltip position="bottom" content={isPublic ? '公开模板' : '个人模板'}>
|
||||
<Switch checked={isPublic} onChange={(v) => updateTemplate({ isPublic: v })}></Switch>
|
||||
</Tooltip>
|
||||
<Popconfirm title="删除模板" content="模板删除后不可恢复,谨慎操作!" onConfirm={handleDelte}>
|
||||
<Button type="danger">删除</Button>
|
||||
</Popconfirm>
|
||||
<Theme />
|
||||
<User />
|
||||
</Space>
|
||||
}
|
||||
></Nav>
|
||||
</header>
|
||||
<main className={styles.contentWrap}>
|
||||
<div className={styles.editorWrap}>
|
||||
<div className={cls(styles.contentWrap, editorWrapClassNames)} style={{ fontSize }}>
|
||||
{mounted && (
|
||||
<CollaborationEditor
|
||||
menubar
|
||||
editable
|
||||
user={user}
|
||||
id={data.id}
|
||||
type="template"
|
||||
onTitleUpdate={setTitle}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
<>
|
||||
{data && <Seo title={data.title} />}
|
||||
<div className={styles.wrap}>
|
||||
<header>
|
||||
<Nav
|
||||
style={{ overflow: 'auto' }}
|
||||
mode="horizontal"
|
||||
header={
|
||||
<>
|
||||
<Tooltip content="返回" position="bottom">
|
||||
<Button onClick={goback} icon={<IconChevronLeft />} style={{ marginRight: 16 }} />
|
||||
</Tooltip>
|
||||
<Text strong ellipsis={{ showTooltip: true }} style={{ width: ~~(windowWidth / 4) }}>
|
||||
{title}
|
||||
</Text>
|
||||
</>
|
||||
}
|
||||
footer={
|
||||
<Space>
|
||||
<DocumentStyle />
|
||||
<Tooltip position="bottom" content={isPublic ? '公开模板' : '个人模板'}>
|
||||
<Switch checked={isPublic} onChange={(v) => updateTemplate({ isPublic: v })}></Switch>
|
||||
</Tooltip>
|
||||
<Popconfirm title="删除模板" content="模板删除后不可恢复,谨慎操作!" onConfirm={handleDelte}>
|
||||
<Button type="danger">删除</Button>
|
||||
</Popconfirm>
|
||||
<Theme />
|
||||
<User />
|
||||
</Space>
|
||||
}
|
||||
></Nav>
|
||||
</header>
|
||||
<main className={styles.contentWrap}>
|
||||
<div className={styles.editorWrap}>
|
||||
<div className={cls(styles.contentWrap, editorWrapClassNames)} style={{ fontSize }}>
|
||||
{mounted && data && (
|
||||
<CollaborationEditor
|
||||
menubar
|
||||
editable
|
||||
user={user}
|
||||
id={data.id}
|
||||
type="template"
|
||||
onTitleUpdate={setTitle}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,89 +0,0 @@
|
|||
import { IconChevronLeft } from '@douyinfe/semi-icons';
|
||||
import { Button, Nav, Popconfirm, Space, Switch, Tooltip, Typography } from '@douyinfe/semi-ui';
|
||||
import { ILoginUser, ITemplate } from '@think/domains';
|
||||
import cls from 'classnames';
|
||||
import { DocumentStyle } from 'components/document/style';
|
||||
import { Theme } from 'components/theme';
|
||||
import { User } from 'components/user';
|
||||
import { useDocumentStyle } from 'hooks/use-document-style';
|
||||
import { useWindowSize } from 'hooks/use-window-size';
|
||||
import Router from 'next/router';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { CollaborationEditor } from 'tiptap/editor';
|
||||
|
||||
import styles from './index.module.scss';
|
||||
|
||||
const { Text } = Typography;
|
||||
|
||||
interface IProps {
|
||||
user: ILoginUser;
|
||||
data: ITemplate;
|
||||
updateTemplate: (arg) => Promise<ITemplate>;
|
||||
deleteTemplate: () => Promise<void>;
|
||||
}
|
||||
|
||||
export const Editor: React.FC<IProps> = ({ user, data, updateTemplate, deleteTemplate }) => {
|
||||
const { width: windowWidth } = useWindowSize();
|
||||
const [title, setTitle] = useState(data.title);
|
||||
const [isPublic, setPublic] = useState(false);
|
||||
const { width, fontSize } = useDocumentStyle();
|
||||
const editorWrapClassNames = useMemo(() => {
|
||||
return width === 'standardWidth' ? styles.isStandardWidth : styles.isFullWidth;
|
||||
}, [width]);
|
||||
|
||||
const goback = useCallback(() => {
|
||||
Router.back();
|
||||
}, []);
|
||||
|
||||
const handleDelte = useCallback(() => {
|
||||
deleteTemplate().then(() => {
|
||||
goback();
|
||||
});
|
||||
}, [deleteTemplate, goback]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!data) return;
|
||||
setPublic(data.isPublic);
|
||||
}, [data]);
|
||||
|
||||
return (
|
||||
<div className={styles.wrap}>
|
||||
<header>
|
||||
<Nav
|
||||
style={{ overflow: 'auto' }}
|
||||
mode="horizontal"
|
||||
header={
|
||||
<>
|
||||
<Tooltip content="返回" position="bottom">
|
||||
<Button onClick={goback} icon={<IconChevronLeft />} style={{ marginRight: 16 }} />
|
||||
</Tooltip>
|
||||
<Text strong ellipsis={{ showTooltip: true }} style={{ width: ~~(windowWidth / 4) }}>
|
||||
{title}
|
||||
</Text>
|
||||
</>
|
||||
}
|
||||
footer={
|
||||
<Space>
|
||||
<DocumentStyle />
|
||||
<Tooltip position="bottom" content={isPublic ? '公开模板' : '个人模板'}>
|
||||
<Switch onChange={(v) => updateTemplate({ isPublic: v })}></Switch>
|
||||
</Tooltip>
|
||||
<Popconfirm title="删除模板" content="模板删除后不可恢复,谨慎操作!" onConfirm={handleDelte}>
|
||||
<Button type="danger">删除</Button>
|
||||
</Popconfirm>
|
||||
<Theme />
|
||||
<User />
|
||||
</Space>
|
||||
}
|
||||
></Nav>
|
||||
</header>
|
||||
<main className={styles.contentWrap}>
|
||||
<div className={styles.editorWrap}>
|
||||
<div className={cls(styles.contentWrap, editorWrapClassNames)} style={{ fontSize }}>
|
||||
<CollaborationEditor menubar editable user={user} id={data.id} type="template" onTitleUpdate={setTitle} />
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
};
|
Loading…
Reference in New Issue