mirror of https://github.com/fantasticit/think.git
feat: improve loading state content
This commit is contained in:
parent
da0f601423
commit
6113ecc101
|
@ -92,7 +92,7 @@ export const CommentEditor: React.FC<IProps> = ({ documentId }) => {
|
|||
error={error}
|
||||
loadingContent={
|
||||
<>
|
||||
{Array.from({ length: 5 }, (_, i) => i).map((i) => (
|
||||
{Array.from({ length: 3 }, (_, i) => i).map((i) => (
|
||||
<CommentItemPlaceholder key={i} />
|
||||
))}
|
||||
</>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useMemo, useEffect, useRef } from 'react';
|
||||
import React, { useMemo, useEffect } from 'react';
|
||||
import { useEditor, EditorContent } from '@tiptap/react';
|
||||
import { Layout } from '@douyinfe/semi-ui';
|
||||
import { IDocument, ILoginUser } from '@think/domains';
|
||||
|
@ -10,6 +10,7 @@ import {
|
|||
getCollaborationCursorExtension,
|
||||
getProvider,
|
||||
destoryProvider,
|
||||
DocumentSkeleton,
|
||||
} from 'tiptap';
|
||||
import { DataRender } from 'components/data-render';
|
||||
import { ImageViewer } from 'components/image-viewer';
|
||||
|
@ -26,8 +27,6 @@ interface IProps {
|
|||
}
|
||||
|
||||
export const Editor: React.FC<IProps> = ({ user, documentId, document }) => {
|
||||
if (!user) return null;
|
||||
|
||||
const provider = useMemo(() => {
|
||||
return getProvider({
|
||||
targetId: documentId,
|
||||
|
@ -70,6 +69,7 @@ export const Editor: React.FC<IProps> = ({ user, documentId, document }) => {
|
|||
return (
|
||||
<DataRender
|
||||
loading={loading}
|
||||
loadingContent={<DocumentSkeleton />}
|
||||
error={null}
|
||||
normalContent={() => {
|
||||
return (
|
||||
|
|
|
@ -27,6 +27,10 @@
|
|||
}
|
||||
}
|
||||
|
||||
.editorContainer {
|
||||
min-height: 240px;
|
||||
}
|
||||
|
||||
.commentWrap {
|
||||
padding: 16px 0;
|
||||
border-top: 1px solid var(--semi-color-border);
|
||||
|
|
|
@ -28,14 +28,13 @@ interface IProps {
|
|||
|
||||
export const DocumentReader: React.FC<IProps> = ({ documentId }) => {
|
||||
if (!documentId) return null;
|
||||
|
||||
const { width: windowWidth } = useWindowSize();
|
||||
const { width, fontSize } = useDocumentStyle();
|
||||
const editorWrapClassNames = useMemo(() => {
|
||||
return width === 'standardWidth' ? styles.isStandardWidth : styles.isFullWidth;
|
||||
}, [width]);
|
||||
|
||||
const { user } = useUser();
|
||||
|
||||
const { data: documentAndAuth, loading: docAuthLoading, error: docAuthError } = useDocumentDetail(documentId);
|
||||
const { document, authority } = documentAndAuth || {};
|
||||
|
||||
|
@ -53,13 +52,7 @@ export const DocumentReader: React.FC<IProps> = ({ documentId }) => {
|
|||
<DataRender
|
||||
loading={docAuthLoading}
|
||||
error={docAuthError}
|
||||
loadingContent={
|
||||
<Skeleton
|
||||
active
|
||||
placeholder={<Skeleton.Title style={{ width: 80, marginBottom: 8 }} />}
|
||||
loading={true}
|
||||
/>
|
||||
}
|
||||
loadingContent={<Skeleton active placeholder={<Skeleton.Title style={{ width: 80 }} />} loading={true} />}
|
||||
normalContent={() => (
|
||||
<Text strong ellipsis={{ showTooltip: true }} style={{ width: ~~(windowWidth / 4) }}>
|
||||
{document.title}
|
||||
|
@ -101,7 +94,9 @@ export const DocumentReader: React.FC<IProps> = ({ documentId }) => {
|
|||
return (
|
||||
<>
|
||||
<Seo title={document.title} />
|
||||
<Editor key={document.id} user={user} documentId={document.id} document={document} />
|
||||
<div className={styles.editorContainer}>
|
||||
{user && <Editor key={document.id} user={user} documentId={document.id} document={document} />}
|
||||
</div>
|
||||
<div className={styles.commentWrap}>
|
||||
<CommentEditor documentId={document.id} />
|
||||
</div>
|
||||
|
|
|
@ -23,7 +23,6 @@ import { User } from 'components/user';
|
|||
import { Theme } from 'components/theme';
|
||||
import { ImageViewer } from 'components/image-viewer';
|
||||
import { useDocumentStyle } from 'hooks/use-document-style';
|
||||
import { useWindowSize } from 'hooks/use-window-size';
|
||||
import { usePublicDocument } from 'data/document';
|
||||
import { DocumentSkeleton } from 'tiptap';
|
||||
import { DocumentContent } from './content';
|
||||
|
@ -41,7 +40,6 @@ export const DocumentPublicReader: React.FC<IProps> = ({ documentId, hideLogo =
|
|||
if (!documentId) return null;
|
||||
|
||||
const { data, loading, error, query } = usePublicDocument(documentId);
|
||||
const { width: windowWidth } = useWindowSize();
|
||||
const { width, fontSize } = useDocumentStyle();
|
||||
const editorWrapClassNames = useMemo(() => {
|
||||
return width === 'standardWidth' ? styles.isStandardWidth : styles.isFullWidth;
|
||||
|
@ -100,9 +98,7 @@ export const DocumentPublicReader: React.FC<IProps> = ({ documentId, hideLogo =
|
|||
<DataRender
|
||||
loading={loading}
|
||||
error={error}
|
||||
loadingContent={
|
||||
<Skeleton active placeholder={<Skeleton.Title style={{ width: 80, marginBottom: 8 }} />} loading={true} />
|
||||
}
|
||||
loadingContent={<Skeleton active placeholder={<Skeleton.Title style={{ width: 80 }} />} loading={true} />}
|
||||
normalContent={() => (
|
||||
<Breadcrumb>
|
||||
<Breadcrumb.Item>
|
||||
|
|
|
@ -216,23 +216,7 @@ export const WikiTocs: React.FC<IProps> = ({
|
|||
<div className={styles.treeWrap}>
|
||||
<DataRender
|
||||
loading={tocsLoading}
|
||||
loadingContent={
|
||||
<NavItem
|
||||
icon={
|
||||
<Skeleton.Avatar
|
||||
size="small"
|
||||
style={{
|
||||
marginRight: 8,
|
||||
width: 24,
|
||||
height: 24,
|
||||
borderRadius: 4,
|
||||
}}
|
||||
></Skeleton.Avatar>
|
||||
}
|
||||
text={<Skeleton.Title style={{ width: 120 }} />}
|
||||
rightNode={<IconPlus />}
|
||||
/>
|
||||
}
|
||||
loadingContent={<NavItem icon={null} text={<Skeleton.Title style={{ width: '100%' }} />} />}
|
||||
error={tocsError}
|
||||
normalContent={() => (
|
||||
<Tree
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import type { NextPage } from 'next';
|
||||
import type { IDocument } from '@think/domains';
|
||||
import Link from 'next/link';
|
||||
import React from 'react';
|
||||
import { Typography, Button, Table, Spin, List } from '@douyinfe/semi-ui';
|
||||
import React, { useMemo } from 'react';
|
||||
import { Typography, Button, Table, List } from '@douyinfe/semi-ui';
|
||||
import { useToggle } from 'hooks/use-toggle';
|
||||
import { Seo } from 'components/seo';
|
||||
import { DataRender } from 'components/data-render';
|
||||
|
@ -31,6 +31,45 @@ const grid = {
|
|||
const RecentDocs = () => {
|
||||
const { data, error, loading, refresh } = useRecentDocuments();
|
||||
|
||||
const columns = useMemo(
|
||||
() => [
|
||||
<Column
|
||||
title="标题"
|
||||
dataIndex="title"
|
||||
key="title"
|
||||
render={(_, document: IDocument) => {
|
||||
return (
|
||||
<Link href={'/wiki/[wikiId]/document/[docId]'} as={`/wiki/${document.wikiId}/document/${document.id}`}>
|
||||
<a style={{ color: 'inherit', textDecoration: 'none' }}>{document.title}</a>
|
||||
</Link>
|
||||
);
|
||||
}}
|
||||
/>,
|
||||
<Column title="阅读量" dataIndex="views" key="views" />,
|
||||
<Column
|
||||
title="更新时间"
|
||||
dataIndex="updatedAt"
|
||||
key="updatedAt"
|
||||
render={(date) => <LocaleTime date={date} timeago />}
|
||||
/>,
|
||||
<Column
|
||||
title="操作"
|
||||
dataIndex="operate"
|
||||
key="operate"
|
||||
render={(_, document) => (
|
||||
<DocumentActions
|
||||
wikiId={document.wikiId}
|
||||
documentId={document.id}
|
||||
onStar={refresh}
|
||||
onDelete={refresh}
|
||||
showCreateDocument
|
||||
/>
|
||||
)}
|
||||
/>,
|
||||
],
|
||||
[]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Title heading={3} style={{ margin: '24px 0 0' }}>
|
||||
|
@ -38,47 +77,16 @@ const RecentDocs = () => {
|
|||
</Title>
|
||||
<DataRender
|
||||
loading={loading}
|
||||
loadingContent={<Spin />}
|
||||
loadingContent={
|
||||
<Table dataSource={[]} loading={true} pagination={false} size="small" style={{ marginTop: 16 }}>
|
||||
{columns}
|
||||
</Table>
|
||||
}
|
||||
error={error}
|
||||
normalContent={() =>
|
||||
data && data.length ? (
|
||||
<Table dataSource={data} loading={loading} pagination={false} size="small" style={{ marginTop: 16 }}>
|
||||
<Column
|
||||
title="标题"
|
||||
dataIndex="title"
|
||||
key="title"
|
||||
render={(_, document: IDocument) => {
|
||||
return (
|
||||
<Link
|
||||
href={'/wiki/[wikiId]/document/[docId]'}
|
||||
as={`/wiki/${document.wikiId}/document/${document.id}`}
|
||||
>
|
||||
<a style={{ color: 'inherit', textDecoration: 'none' }}>{document.title}</a>
|
||||
</Link>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<Column title="阅读量" dataIndex="views" key="views" />
|
||||
<Column
|
||||
title="更新时间"
|
||||
dataIndex="updatedAt"
|
||||
key="updatedAt"
|
||||
render={(date) => <LocaleTime date={date} timeago />}
|
||||
/>
|
||||
<Column
|
||||
title="操作"
|
||||
dataIndex="operate"
|
||||
key="operate"
|
||||
render={(_, document) => (
|
||||
<DocumentActions
|
||||
wikiId={document.wikiId}
|
||||
documentId={document.id}
|
||||
onStar={refresh}
|
||||
onDelete={refresh}
|
||||
showCreateDocument
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{columns}
|
||||
</Table>
|
||||
) : (
|
||||
<Empty message="最近访问的文档会出现在此处" />
|
||||
|
|
|
@ -4,8 +4,8 @@ import { Skeleton } from '@douyinfe/semi-ui';
|
|||
export const DocumentSkeleton = () => {
|
||||
const placeholder = (
|
||||
<>
|
||||
<Skeleton.Title style={{ width: 240, height: '1.8em', marginBottom: 12, marginTop: 12 }} />
|
||||
<Skeleton.Paragraph style={{ width: '100%' }} rows={15} />
|
||||
<Skeleton.Title style={{ width: 240, height: '2.4em', marginBottom: 12, marginTop: 12 }} />
|
||||
<Skeleton.Paragraph style={{ width: '100%', height: 27 }} rows={7} />
|
||||
</>
|
||||
);
|
||||
|
||||
|
|
Loading…
Reference in New Issue