mirror of https://github.com/fantasticit/think.git
client: optimize render actions
parent
a3b2e3d97d
commit
eef782f096
|
@ -1,5 +1,5 @@
|
||||||
import { IconMore, IconPlus, IconStar } from '@douyinfe/semi-icons';
|
import { IconMore, IconPlus, IconStar } from '@douyinfe/semi-icons';
|
||||||
import { Button, Dropdown, Space, Typography } from '@douyinfe/semi-ui';
|
import { Button, Dropdown, Popover, Space, Typography } from '@douyinfe/semi-ui';
|
||||||
import { DocumentCreator } from 'components/document/create';
|
import { DocumentCreator } from 'components/document/create';
|
||||||
import { DocumentDeletor } from 'components/document/delete';
|
import { DocumentDeletor } from 'components/document/delete';
|
||||||
import { DocumentLinkCopyer } from 'components/document/link';
|
import { DocumentLinkCopyer } from 'components/document/link';
|
||||||
|
@ -29,22 +29,40 @@ export const DocumentActions: React.FC<IProps> = ({
|
||||||
showCreateDocument,
|
showCreateDocument,
|
||||||
children,
|
children,
|
||||||
}) => {
|
}) => {
|
||||||
const [visible, toggleVisible] = useToggle(false);
|
const [popoverVisible, togglePopoverVisible] = useToggle(false);
|
||||||
|
const [createVisible, toggleCreateVisible] = useToggle(false);
|
||||||
|
|
||||||
const prevent = useCallback((e) => {
|
const create = useCallback(() => {
|
||||||
e.preventDefault();
|
togglePopoverVisible(false);
|
||||||
e.stopPropagation();
|
toggleCreateVisible(true);
|
||||||
}, []);
|
}, [togglePopoverVisible, toggleCreateVisible]);
|
||||||
|
|
||||||
|
const wrapedOnDelete = useCallback(() => {
|
||||||
|
togglePopoverVisible(false);
|
||||||
|
onDelete && onDelete();
|
||||||
|
}, [onDelete, togglePopoverVisible]);
|
||||||
|
|
||||||
|
const wrapOnVisibleChange = useCallback(
|
||||||
|
(visible) => {
|
||||||
|
togglePopoverVisible(visible);
|
||||||
|
onVisibleChange && onVisibleChange();
|
||||||
|
},
|
||||||
|
[onVisibleChange, togglePopoverVisible]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Dropdown
|
<Popover
|
||||||
onVisibleChange={onVisibleChange}
|
showArrow
|
||||||
render={
|
style={{ padding: 0 }}
|
||||||
|
trigger="click"
|
||||||
|
visible={popoverVisible}
|
||||||
|
onVisibleChange={wrapOnVisibleChange}
|
||||||
|
content={
|
||||||
<Dropdown.Menu>
|
<Dropdown.Menu>
|
||||||
{showCreateDocument && (
|
{showCreateDocument && (
|
||||||
<Dropdown.Item onClick={prevent}>
|
<Dropdown.Item onClick={create}>
|
||||||
<Text onClick={toggleVisible}>
|
<Text>
|
||||||
<Space>
|
<Space>
|
||||||
<IconPlus />
|
<IconPlus />
|
||||||
新建子文档
|
新建子文档
|
||||||
|
@ -52,15 +70,16 @@ export const DocumentActions: React.FC<IProps> = ({
|
||||||
</Text>
|
</Text>
|
||||||
</Dropdown.Item>
|
</Dropdown.Item>
|
||||||
)}
|
)}
|
||||||
<Dropdown.Item onClick={prevent}>
|
|
||||||
<DocumentStar
|
<DocumentStar
|
||||||
documentId={documentId}
|
documentId={documentId}
|
||||||
render={({ star, toggleStar, text }) => (
|
render={({ star, toggleStar, text }) => (
|
||||||
<Text
|
<Dropdown.Item
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
toggleStar().then(onStar);
|
toggleStar().then(onStar);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<Text>
|
||||||
<Space>
|
<Space>
|
||||||
<IconStar
|
<IconStar
|
||||||
style={{
|
style={{
|
||||||
|
@ -70,27 +89,40 @@ export const DocumentActions: React.FC<IProps> = ({
|
||||||
{text}
|
{text}
|
||||||
</Space>
|
</Space>
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
</Dropdown.Item>
|
||||||
/>
|
)}
|
||||||
</Dropdown.Item>
|
/>
|
||||||
<Dropdown.Item onClick={prevent}>
|
|
||||||
<DocumentLinkCopyer wikiId={wikiId} documentId={documentId} />
|
<DocumentLinkCopyer
|
||||||
</Dropdown.Item>
|
wikiId={wikiId}
|
||||||
|
documentId={documentId}
|
||||||
|
render={({ copy, children }) => {
|
||||||
|
return <Dropdown.Item onClick={copy}>{children}</Dropdown.Item>;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
<Dropdown.Divider />
|
<Dropdown.Divider />
|
||||||
<Dropdown.Item onClick={prevent}>
|
|
||||||
<DocumentDeletor wikiId={wikiId} documentId={documentId} onDelete={onDelete} />
|
<DocumentDeletor
|
||||||
</Dropdown.Item>
|
wikiId={wikiId}
|
||||||
|
documentId={documentId}
|
||||||
|
onDelete={wrapedOnDelete}
|
||||||
|
render={({ children }) => {
|
||||||
|
return <Dropdown.Item>{children}</Dropdown.Item>;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</Dropdown.Menu>
|
</Dropdown.Menu>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{children || <Button onClick={prevent} icon={<IconMore />} theme="borderless" type="tertiary" />}
|
{children || <Button icon={<IconMore />} theme="borderless" type="tertiary" />}
|
||||||
</Dropdown>
|
</Popover>
|
||||||
|
|
||||||
{showCreateDocument && (
|
{showCreateDocument && (
|
||||||
<DocumentCreator
|
<DocumentCreator
|
||||||
wikiId={wikiId}
|
wikiId={wikiId}
|
||||||
parentDocumentId={documentId}
|
parentDocumentId={documentId}
|
||||||
visible={visible}
|
visible={createVisible}
|
||||||
toggleVisible={toggleVisible}
|
toggleVisible={toggleCreateVisible}
|
||||||
onCreate={onCreate}
|
onCreate={onCreate}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -1,52 +1,61 @@
|
||||||
import { IconDelete } from '@douyinfe/semi-icons';
|
import { IconDelete } from '@douyinfe/semi-icons';
|
||||||
import { Modal, Space, Typography } from '@douyinfe/semi-ui';
|
import { Modal, Popconfirm, Space, Typography } from '@douyinfe/semi-ui';
|
||||||
import { useDeleteDocument } from 'data/document';
|
import { useDeleteDocument } from 'data/document';
|
||||||
import { useRouterQuery } from 'hooks/use-router-query';
|
import { useRouterQuery } from 'hooks/use-router-query';
|
||||||
import Router from 'next/router';
|
import Router from 'next/router';
|
||||||
import React, { useCallback } from 'react';
|
import React, { useCallback, useMemo } from 'react';
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
wikiId: string;
|
wikiId: string;
|
||||||
documentId: string;
|
documentId: string;
|
||||||
onDelete?: () => void;
|
onDelete?: () => void;
|
||||||
|
render?: (arg: { children: React.ReactNode }) => React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { Text } = Typography;
|
const { Text } = Typography;
|
||||||
|
|
||||||
export const DocumentDeletor: React.FC<IProps> = ({ wikiId, documentId, onDelete }) => {
|
export const DocumentDeletor: React.FC<IProps> = ({ wikiId, documentId, render, onDelete }) => {
|
||||||
const { wikiId: currentWikiId, documentId: currentDocumentId } =
|
const { wikiId: currentWikiId, documentId: currentDocumentId } =
|
||||||
useRouterQuery<{ wikiId?: string; documentId?: string }>();
|
useRouterQuery<{ wikiId?: string; documentId?: string }>();
|
||||||
const { deleteDocument: api, loading } = useDeleteDocument(documentId);
|
const { deleteDocument: api, loading } = useDeleteDocument(documentId);
|
||||||
|
|
||||||
const deleteAction = useCallback(() => {
|
const deleteAction = useCallback(() => {
|
||||||
Modal.error({
|
api().then(() => {
|
||||||
title: '确定删除吗?',
|
const navigate = () => {
|
||||||
content: <Text>文档删除后不可恢复!</Text>,
|
if (wikiId !== currentWikiId || documentId !== currentDocumentId) {
|
||||||
onOk: () => {
|
return;
|
||||||
api().then(() => {
|
}
|
||||||
const navigate = () => {
|
Router.push({
|
||||||
if (wikiId !== currentWikiId || documentId !== currentDocumentId) {
|
pathname: `/wiki/${wikiId}`,
|
||||||
return;
|
|
||||||
}
|
|
||||||
Router.push({
|
|
||||||
pathname: `/wiki/${wikiId}`,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
onDelete ? onDelete() : navigate();
|
|
||||||
});
|
});
|
||||||
},
|
};
|
||||||
okButtonProps: { loading, type: 'danger' },
|
|
||||||
style: { maxWidth: '96vw' },
|
onDelete ? onDelete() : navigate();
|
||||||
});
|
});
|
||||||
}, [wikiId, documentId, api, loading, onDelete, currentWikiId, currentDocumentId]);
|
}, [wikiId, documentId, api, onDelete, currentWikiId, currentDocumentId]);
|
||||||
|
|
||||||
|
const content = useMemo(
|
||||||
|
() => (
|
||||||
|
<Text type="danger">
|
||||||
|
<Space>
|
||||||
|
<IconDelete />
|
||||||
|
删除
|
||||||
|
</Space>
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Text type="danger" onClick={deleteAction}>
|
<Popconfirm
|
||||||
<Space>
|
title="确定删除吗?"
|
||||||
<IconDelete />
|
content="文档删除后不可恢复!"
|
||||||
删除
|
onConfirm={deleteAction}
|
||||||
</Space>
|
okButtonProps={{ loading }}
|
||||||
</Text>
|
zIndex={1070}
|
||||||
|
showArrow
|
||||||
|
>
|
||||||
|
{render ? render({ children: content }) : content}
|
||||||
|
</Popconfirm>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,21 +7,28 @@ import React, { useCallback } from 'react';
|
||||||
interface IProps {
|
interface IProps {
|
||||||
wikiId: string;
|
wikiId: string;
|
||||||
documentId: string;
|
documentId: string;
|
||||||
|
render?: (arg: { copy: () => void; children: React.ReactNode }) => React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { Text } = Typography;
|
const { Text } = Typography;
|
||||||
|
|
||||||
export const DocumentLinkCopyer: React.FC<IProps> = ({ wikiId, documentId }) => {
|
export const DocumentLinkCopyer: React.FC<IProps> = ({ wikiId, documentId, render }) => {
|
||||||
const handle = useCallback(() => {
|
const handle = useCallback(() => {
|
||||||
copy(buildUrl(`/wiki/${wikiId}/document/${documentId}`));
|
copy(buildUrl(`/wiki/${wikiId}/document/${documentId}`));
|
||||||
}, [wikiId, documentId]);
|
}, [wikiId, documentId]);
|
||||||
|
|
||||||
return (
|
const content = (
|
||||||
|
<Space>
|
||||||
|
<IconLink />
|
||||||
|
复制链接
|
||||||
|
</Space>
|
||||||
|
);
|
||||||
|
|
||||||
|
return render ? (
|
||||||
|
<>{render({ copy: handle, children: content })}</>
|
||||||
|
) : (
|
||||||
<Text onClick={handle} style={{ cursor: 'pointer' }}>
|
<Text onClick={handle} style={{ cursor: 'pointer' }}>
|
||||||
<Space>
|
{content}
|
||||||
<IconLink />
|
|
||||||
复制链接
|
|
||||||
</Space>
|
|
||||||
</Text>
|
</Text>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue