mirror of https://github.com/fantasticit/think.git
client: imporve reader
This commit is contained in:
parent
3337ea5593
commit
cfadcf22a0
|
@ -15,17 +15,19 @@ import {
|
|||
Tooltip,
|
||||
Typography,
|
||||
} from '@douyinfe/semi-ui';
|
||||
import { IUser } from '@think/domains';
|
||||
import { DataRender } from 'components/data-render';
|
||||
import { DocumentLinkCopyer } from 'components/document/link';
|
||||
import { useDoumentMembers } from 'data/document';
|
||||
import { useUser } from 'data/user';
|
||||
import { event, JOIN_USER } from 'event';
|
||||
import { useToggle } from 'hooks/use-toggle';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
|
||||
interface IProps {
|
||||
wikiId: string;
|
||||
documentId: string;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
const { Paragraph } = Typography;
|
||||
|
@ -45,7 +47,8 @@ const renderChecked = (onChange, authKey: 'readable' | 'editable') => (checked,
|
|||
return <Checkbox style={{ display: 'inline-block' }} checked={checked} onChange={handle} />;
|
||||
};
|
||||
|
||||
export const DocumentCollaboration: React.FC<IProps> = ({ wikiId, documentId }) => {
|
||||
export const DocumentCollaboration: React.FC<IProps> = ({ wikiId, documentId, disabled = false }) => {
|
||||
const toastedUsersRef = useRef<Array<IUser['id']>>([]);
|
||||
const { user: currentUser } = useUser();
|
||||
const [visible, toggleVisible] = useToggle(false);
|
||||
const { users, loading, error, addUser, updateUser, deleteUser } = useDoumentMembers(documentId);
|
||||
|
@ -84,8 +87,9 @@ export const DocumentCollaboration: React.FC<IProps> = ({ wikiId, documentId })
|
|||
}
|
||||
|
||||
newCollaborationUsers.forEach((newUser) => {
|
||||
if (currentUser && newUser.name !== currentUser.name) {
|
||||
if (currentUser && newUser.name !== currentUser.name && !toastedUsersRef.current.includes(newUser.id)) {
|
||||
Toast.info(`${newUser.name}加入文档`);
|
||||
toastedUsersRef.current.push(newUser.id);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -95,6 +99,7 @@ export const DocumentCollaboration: React.FC<IProps> = ({ wikiId, documentId })
|
|||
event.on(JOIN_USER, handler);
|
||||
|
||||
return () => {
|
||||
toastedUsersRef.current = [];
|
||||
event.off(JOIN_USER, handler);
|
||||
};
|
||||
}, [collaborationUsers, currentUser]);
|
||||
|
@ -120,7 +125,13 @@ export const DocumentCollaboration: React.FC<IProps> = ({ wikiId, documentId })
|
|||
})}
|
||||
</AvatarGroup>
|
||||
<Tooltip content="邀请他人协作" position="bottom">
|
||||
<Button theme="borderless" type="tertiary" icon={<IconUserAdd />} onClick={toggleVisible}></Button>
|
||||
<Button
|
||||
theme="borderless"
|
||||
type="tertiary"
|
||||
disabled={disabled}
|
||||
icon={<IconUserAdd />}
|
||||
onClick={toggleVisible}
|
||||
></Button>
|
||||
</Tooltip>
|
||||
<Modal
|
||||
title={'文档协作'}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { IconArticle, IconEdit } from '@douyinfe/semi-icons';
|
||||
import { BackTop, Button, Layout, Nav, Popover, Skeleton, Space, Spin, Tooltip, Typography } from '@douyinfe/semi-ui';
|
||||
import { IconEdit } from '@douyinfe/semi-icons';
|
||||
import { BackTop, Button, Layout, Nav, Skeleton, Space, Tooltip, Typography } from '@douyinfe/semi-ui';
|
||||
import cls from 'classnames';
|
||||
import { DataRender } from 'components/data-render';
|
||||
import { DocumentCollaboration } from 'components/document/collaboration';
|
||||
|
@ -55,11 +55,14 @@ export const DocumentReader: React.FC<IProps> = ({ documentId }) => {
|
|||
const { user } = useUser();
|
||||
const { data: documentAndAuth, loading: docAuthLoading, error: docAuthError } = useDocumentDetail(documentId);
|
||||
const { document, authority } = documentAndAuth || {};
|
||||
const [readable, editable] = useMemo(() => {
|
||||
if (!authority) return [false, false];
|
||||
return [authority.readable, authority.editable];
|
||||
}, [authority]);
|
||||
|
||||
const renderAuthor = useCallback(
|
||||
(element) => {
|
||||
if (!document) return null;
|
||||
|
||||
const target = element && element.querySelector('.ProseMirror .title');
|
||||
|
||||
if (target) {
|
||||
|
@ -75,29 +78,28 @@ export const DocumentReader: React.FC<IProps> = ({ documentId }) => {
|
|||
Router.push(`/wiki/${document.wikiId}/document/${document.id}/edit`);
|
||||
}, [document]);
|
||||
|
||||
const actions = useMemo(
|
||||
() => (
|
||||
const actions = useMemo(() => {
|
||||
console.log({ readable, editable });
|
||||
return (
|
||||
<Space>
|
||||
{document && authority.readable && (
|
||||
<DocumentCollaboration key="collaboration" wikiId={document.wikiId} documentId={documentId} />
|
||||
{document && (
|
||||
<DocumentCollaboration
|
||||
disabled={!readable}
|
||||
key="collaboration"
|
||||
wikiId={document.wikiId}
|
||||
documentId={documentId}
|
||||
/>
|
||||
)}
|
||||
{authority && authority.editable && (
|
||||
<Tooltip key="edit" content="编辑" position="bottom">
|
||||
<Button icon={<IconEdit />} onMouseDown={gotoEdit} />
|
||||
<Button disabled={!editable} icon={<IconEdit />} onMouseDown={gotoEdit} />
|
||||
</Tooltip>
|
||||
)}
|
||||
{authority && authority.readable && (
|
||||
<>
|
||||
<DocumentShare key="share" documentId={documentId} />
|
||||
<DocumentVersion key="version" documentId={documentId} />
|
||||
<DocumentStar key="star" documentId={documentId} />
|
||||
</>
|
||||
)}
|
||||
<DocumentShare disabled={!readable} key="share" documentId={documentId} />
|
||||
<DocumentVersion disabled={!readable} key="version" documentId={documentId} />
|
||||
<DocumentStar disabled={!readable} key="star" documentId={documentId} />
|
||||
<DocumentStyle />
|
||||
</Space>
|
||||
),
|
||||
[document, documentId, authority, gotoEdit]
|
||||
);
|
||||
}, [document, documentId, readable, editable, gotoEdit]);
|
||||
|
||||
const editBtnStyle = useMemo(() => getEditBtnStyle(isMobile ? 16 : 100), [isMobile]);
|
||||
|
||||
|
@ -133,7 +135,7 @@ export const DocumentReader: React.FC<IProps> = ({ documentId }) => {
|
|||
<div className={cls(styles.editorWrap, editorWrapClassNames)} style={{ fontSize }}>
|
||||
<div id="js-reader-container">
|
||||
{document && <Seo title={document.title} />}
|
||||
{user && (
|
||||
{user && readable && (
|
||||
<CollaborationEditor
|
||||
editable={false}
|
||||
user={user}
|
||||
|
|
|
@ -10,12 +10,13 @@ import React, { useEffect, useMemo, useState } from 'react';
|
|||
|
||||
interface IProps {
|
||||
documentId: string;
|
||||
render?: (arg: { isPublic: boolean; toggleVisible: (arg: boolean) => void }) => React.ReactNode;
|
||||
disabled?: boolean;
|
||||
render?: (arg: { isPublic: boolean; disabled: boolean; toggleVisible: (arg: boolean) => void }) => React.ReactNode;
|
||||
}
|
||||
|
||||
const { Text } = Typography;
|
||||
|
||||
export const DocumentShare: React.FC<IProps> = ({ documentId, render }) => {
|
||||
export const DocumentShare: React.FC<IProps> = ({ documentId, disabled = false, render }) => {
|
||||
const [visible, toggleVisible] = useToggle(false);
|
||||
const { data, loading, error, toggleStatus } = useDocumentDetail(documentId);
|
||||
const [sharePassword, setSharePassword] = useState('');
|
||||
|
@ -34,9 +35,9 @@ export const DocumentShare: React.FC<IProps> = ({ documentId, render }) => {
|
|||
return (
|
||||
<>
|
||||
{render ? (
|
||||
render({ isPublic, toggleVisible })
|
||||
render({ isPublic, disabled, toggleVisible })
|
||||
) : (
|
||||
<Button type="primary" theme="light" onClick={toggleVisible}>
|
||||
<Button disabled={disabled} type="primary" theme="light" onClick={toggleVisible}>
|
||||
{isPublic ? '分享中' : '分享'}
|
||||
</Button>
|
||||
)}
|
||||
|
|
|
@ -5,17 +5,23 @@ import React from 'react';
|
|||
|
||||
interface IProps {
|
||||
documentId: string;
|
||||
render?: (arg: { star: boolean; text: string; toggleStar: () => Promise<void> }) => React.ReactNode;
|
||||
disabled?: boolean;
|
||||
render?: (arg: {
|
||||
star: boolean;
|
||||
disabled: boolean;
|
||||
text: string;
|
||||
toggleStar: () => Promise<void>;
|
||||
}) => React.ReactNode;
|
||||
}
|
||||
|
||||
export const DocumentStar: React.FC<IProps> = ({ documentId, render }) => {
|
||||
export const DocumentStar: React.FC<IProps> = ({ documentId, disabled = false, render }) => {
|
||||
const { data, toggle: toggleStar } = useDocumentCollectToggle(documentId);
|
||||
const text = data ? '取消收藏' : '收藏文档';
|
||||
|
||||
return (
|
||||
<>
|
||||
{render ? (
|
||||
render({ star: data, toggleStar, text })
|
||||
render({ star: data, disabled, toggleStar, text })
|
||||
) : (
|
||||
<Tooltip content={text} position="bottom">
|
||||
<Button
|
||||
|
@ -24,6 +30,7 @@ export const DocumentStar: React.FC<IProps> = ({ documentId, render }) => {
|
|||
style={{
|
||||
color: data ? 'rgba(var(--semi-amber-4), 1)' : 'rgba(var(--semi-grey-3), 1)',
|
||||
}}
|
||||
disabled={disabled}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
|
|
@ -14,13 +14,14 @@ import styles from './index.module.scss';
|
|||
|
||||
interface IProps {
|
||||
documentId: string;
|
||||
disabled?: boolean;
|
||||
onSelect?: (data) => void;
|
||||
}
|
||||
|
||||
const { Sider, Content } = Layout;
|
||||
const { Title } = Typography;
|
||||
|
||||
export const DocumentVersion: React.FC<IProps> = ({ documentId, onSelect }) => {
|
||||
export const DocumentVersion: React.FC<IProps> = ({ documentId, disabled = false, onSelect }) => {
|
||||
const [visible, toggleVisible] = useToggle(false);
|
||||
const { data, loading, error, refresh } = useDocumentVersion(documentId);
|
||||
const [selectedVersion, setSelectedVersion] = useState(null);
|
||||
|
@ -65,7 +66,7 @@ export const DocumentVersion: React.FC<IProps> = ({ documentId, onSelect }) => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<Button type="primary" theme="light" onClick={toggleVisible}>
|
||||
<Button type="primary" theme="light" disabled={disabled} onClick={toggleVisible}>
|
||||
文档版本
|
||||
</Button>
|
||||
<Modal
|
||||
|
@ -87,7 +88,7 @@ export const DocumentVersion: React.FC<IProps> = ({ documentId, onSelect }) => {
|
|||
theme="light"
|
||||
type="primary"
|
||||
style={{ marginRight: 8 }}
|
||||
disabled={loading || error}
|
||||
disabled={loading || !!error}
|
||||
loading={loading}
|
||||
onClick={() => refresh()}
|
||||
>
|
||||
|
|
|
@ -139,7 +139,7 @@ export const useDocumentDetail = (documentId) => {
|
|||
const { data, error, isLoading, refetch } = useQuery(
|
||||
DocumentApiDefinition.getDetailById.client(documentId),
|
||||
() => getDocumentDetail(documentId),
|
||||
{ staleTime: 3000 }
|
||||
{ staleTime: 3000, refetchOnReconnect: true, refetchOnMount: true, refetchOnWindowFocus: true }
|
||||
);
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
display: flex;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 100px;
|
||||
overflow: hidden;
|
||||
flex-direction: column;
|
||||
|
||||
|
|
Loading…
Reference in New Issue