diff --git a/README.md b/README.md index d5fee302..ea85be54 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,21 @@ # think +## 声明 + +1. 请先阅读[提问的智慧](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md) +2. 为什么停止开发了? + 1. 对于文档类产品,无法做出独立的 library 或 framework 给不同需求的团队(或个人),这使得我不确定这件事的意义 + 2. 对于独立编辑器开发,无论最终以何种形态存在,其表现还是为应用,而非框架(或依赖),能做到的也许只是一种示范 + 3. 作者本身专攻前端,对高性能、扩展性良好的后端架构心有余而力不足,同时也缺乏专业的运维知识(欢迎赐教) + 4. 对于 ProseMirror 和 yjs 本身还有许多玩法,但是精力不足 + 1. 类似金山文档的表格体验 + 2. 类似飞书文档的拖拽到节点前后生成分栏 + 3. markdown 、txt、office 文件的导入导出(office 方面可能需要后端协助,java poi 是一个可行的选择) + 4. 从 office 套件粘贴到编辑器,保留格式和图片(前端可独立完成,思路可参考 TinyCME 的 PowerPaste 和 RTF) + 5. 基于 yjs 的版本备份和恢复(部分同学提出增量保存 diff,个人还是建议全量 snapshot) + 6. 基于 yjs 的协同开发(比如结合 luckysheet) +3. 如果有好的工作和想法,可以和作者联系(发送邮件) + ## 简介 Think 是一款开源知识管理工具。通过独立的知识库空间,结构化地组织在线协作文档,实现知识的积累与沉淀,促进知识的复用与流通。同时支持多人协作文档。使用的技术如下: @@ -15,12 +31,6 @@ Think 是一款开源知识管理工具。通过独立的知识库空间,结 [云策文档](https://think.codingit.cn)已经部署上线,可前往注册使用。 -## 交流群 - -欢迎进群交流。 - -image - ## 预览
diff --git a/package.json b/package.json index a5989f3c..e02235f9 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "private": true, "author": "fantasticit", "scripts": { - "clean": "npx rimraf ./node_modules ./packages/**/node_modules", + "clean": "npx rimraf ./node_modules ./packages/**/node_modules ./packages/**/.next", "dev": "concurrently 'pnpm:dev:*'", "dev:server": "pnpm run --dir packages/server dev", "dev:client": "pnpm run --dir packages/client dev", diff --git a/packages/client/.eslintrc.js b/packages/client/.eslintrc.js index 47ca0669..1646ab3b 100644 --- a/packages/client/.eslintrc.js +++ b/packages/client/.eslintrc.js @@ -54,7 +54,21 @@ module.exports = { 'react/react-in-jsx-scope': 'off', 'react/prop-types': 'off', '@typescript-eslint/explicit-function-return-type': 'off', - 'simple-import-sort/imports': 'error', + 'simple-import-sort/imports': [ + 'error', + { + groups: [ + ['react'], + ['@douyinfe(.*)$'], + ['(@)?think(.*)$'], + ['(@)?tiptap(.*)$'], + ['^@?\\w'], + ['@/(.*)'], + ['^[./]'], + ['(.*).module.scss'], + ], + }, + ], 'simple-import-sort/exports': 'error', }, ignorePatterns: ['dist/', 'node_modules', 'scripts', 'examples'], diff --git a/packages/client/package.json b/packages/client/package.json index 7d00bb8f..2b9b732d 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -8,11 +8,14 @@ "pm2": "pm2 start npm --name @think/client -- start" }, "dependencies": { - "@douyinfe/semi-icons": "^2.3.1", - "@douyinfe/semi-next": "^2.3.1", - "@douyinfe/semi-ui": "^2.3.1", + "@douyinfe/semi-icons": "^2.18.0", + "@douyinfe/semi-next": "^2.18.0", + "@douyinfe/semi-ui": "^2.18.0", "@excalidraw/excalidraw": "^0.12.0", "@hocuspocus/provider": "^1.0.0-alpha.29", + "@react-pdf-viewer/core": "3.9.0", + "@react-pdf-viewer/default-layout": "3.9.0", + "@react-pdf-viewer/locales": "^1.0.0", "@think/config": "workspace:^1.0.0", "@think/constants": "workspace:^1.0.0", "@think/domains": "workspace:^1.0.0", @@ -60,15 +63,14 @@ "clone": "^2.1.2", "cross-env": "^7.0.3", "deep-equal": "^2.0.5", - "docx": "^7.3.0", "dompurify": "^2.3.5", - "downloadjs": "^1.4.7", - "html-to-docx": "^1.4.0", + "file-saver": "^2.0.5", "htmldiff-js": "^1.0.5", "interactjs": "^1.10.11", "katex": "^0.15.2", "kity": "^2.0.4", "lib0": "^0.2.47", + "lodash.pick": "^4.4.0", "lowlight": "^2.5.0", "markdown-it": "^12.3.2", "markdown-it-anchor": "^8.4.1", @@ -78,6 +80,7 @@ "markdown-it-sup": "^1.0.0", "next": "12.1.0", "next-pwa": "^5.5.2", + "pdfjs-dist": "3.1.81", "prosemirror-codemark": "^0.3.6", "prosemirror-commands": "^1.3.0", "prosemirror-markdown": "^1.7.0", @@ -93,7 +96,6 @@ "react-full-screen": "^1.1.1", "react-helmet": "^6.1.0", "react-lazy-load-image-component": "^1.5.4", - "react-pdf": "^5.7.2", "react-query": "^3.39.0", "react-split-pane": "^0.1.92", "react-visibility-sensor": "^5.1.1", @@ -110,6 +112,7 @@ "devDependencies": { "@types/node": "17.0.13", "@types/react": "17.0.38", + "@types/react-lazy-load-image-component": "^1.6.3", "@typescript-eslint/eslint-plugin": "^5.21.0", "@typescript-eslint/parser": "^5.21.0", "copy-webpack-plugin": "11.0.0", diff --git a/packages/client/src/components/admin/system-config/index.tsx b/packages/client/src/components/admin/system-config/index.tsx index c1b12c9c..8cc4228b 100644 --- a/packages/client/src/components/admin/system-config/index.tsx +++ b/packages/client/src/components/admin/system-config/index.tsx @@ -1,6 +1,7 @@ -import { TabPane, Tabs } from '@douyinfe/semi-ui'; import React from 'react'; +import { TabPane, Tabs } from '@douyinfe/semi-ui'; + import { Mail } from './mail'; import { System } from './system'; diff --git a/packages/client/src/components/admin/system-config/mail/index.tsx b/packages/client/src/components/admin/system-config/mail/index.tsx index 83b84eca..968dae5d 100644 --- a/packages/client/src/components/admin/system-config/mail/index.tsx +++ b/packages/client/src/components/admin/system-config/mail/index.tsx @@ -1,8 +1,10 @@ +import React, { useCallback } from 'react'; + import { Banner, Button, Form, Toast } from '@douyinfe/semi-ui'; + import { DataRender } from 'components/data-render'; import { useSystemConfig } from 'data/user'; import { useToggle } from 'hooks/use-toggle'; -import React, { useCallback } from 'react'; export const Mail = () => { const { data, loading, error, sendTestEmail, updateSystemConfig } = useSystemConfig(); diff --git a/packages/client/src/components/admin/system-config/system/index.tsx b/packages/client/src/components/admin/system-config/system/index.tsx index 0e66888e..ea95047d 100644 --- a/packages/client/src/components/admin/system-config/system/index.tsx +++ b/packages/client/src/components/admin/system-config/system/index.tsx @@ -1,9 +1,11 @@ +import React, { useCallback } from 'react'; + import { IconHelpCircle } from '@douyinfe/semi-icons'; import { Banner, Button, Form, Toast, Tooltip } from '@douyinfe/semi-ui'; + import { DataRender } from 'components/data-render'; import { useSystemConfig } from 'data/user'; import { useToggle } from 'hooks/use-toggle'; -import React, { useCallback } from 'react'; export const System = () => { const { data, loading, error, updateSystemConfig } = useSystemConfig(); diff --git a/packages/client/src/components/banner/index.tsx b/packages/client/src/components/banner/index.tsx index bd56e8dd..b5b12881 100644 --- a/packages/client/src/components/banner/index.tsx +++ b/packages/client/src/components/banner/index.tsx @@ -1,8 +1,10 @@ +import React, { useEffect, useRef } from 'react'; + import { IconClose } from '@douyinfe/semi-icons'; import { Banner as SemiBanner } from '@douyinfe/semi-ui'; import { BannerProps } from '@douyinfe/semi-ui/banner'; + import { useToggle } from 'hooks/use-toggle'; -import React, { useEffect, useRef } from 'react'; interface IProps extends BannerProps { duration?: number; diff --git a/packages/client/src/components/color-picker/index.tsx b/packages/client/src/components/color-picker/index.tsx index 8bcf22e0..e510e478 100644 --- a/packages/client/src/components/color-picker/index.tsx +++ b/packages/client/src/components/color-picker/index.tsx @@ -1,7 +1,9 @@ +import React, { useMemo } from 'react'; + import { Dropdown, SideSheet, Typography } from '@douyinfe/semi-ui'; + import { IsOnMobile } from 'hooks/use-on-mobile'; import { useToggle } from 'hooks/use-toggle'; -import React, { useMemo } from 'react'; import styles from './style.module.scss'; @@ -89,25 +91,26 @@ export const ColorPicker: React.FC<{ const [visible, toggleVisible] = useToggle(false); const content = useMemo( - () => ( -
-
onSetColor(null)}> - - 无颜色 -
+ () => + !visible ? null : ( +
+
onSetColor(null)}> + + 无颜色 +
-
- {colors.map((color) => { - return ( -
onSetColor(color)}> - -
- ); - })} +
+ {colors.map((color) => { + return ( +
onSetColor(color)}> + +
+ ); + })} +
-
- ), - [onSetColor, isMobile] + ), + [onSetColor, isMobile, visible] ); if (disabled) return {children}; @@ -132,7 +135,14 @@ export const ColorPicker: React.FC<{ ) : ( - + {children} )} diff --git a/packages/client/src/components/data-render/constant.tsx b/packages/client/src/components/data-render/constant.tsx index 37847854..1e436982 100644 --- a/packages/client/src/components/data-render/constant.tsx +++ b/packages/client/src/components/data-render/constant.tsx @@ -1,28 +1,34 @@ -import { Spin, Typography } from '@douyinfe/semi-ui'; -import { Empty } from 'illustrations/empty'; import React, { useMemo } from 'react'; +import { Spin, Typography } from '@douyinfe/semi-ui'; + +import { Empty } from 'illustrations/empty'; + const { Text } = Typography; -export const defaultLoading = ; +export const defaultLoading = ( +
+ +
+); export const defaultRenderError = (error) => { return {(error && error.message) || '未知错误'}; }; +const emptyStyle: React.CSSProperties = { + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + flexDirection: 'column', + position: 'relative', + top: '50%', + left: '50%', + transform: 'translate(-50%, -50%)', +}; + export const defaultEmpty = ( -
+
diff --git a/packages/client/src/components/data-render/index.tsx b/packages/client/src/components/data-render/index.tsx index db8627e5..9f1179a8 100644 --- a/packages/client/src/components/data-render/index.tsx +++ b/packages/client/src/components/data-render/index.tsx @@ -1,5 +1,7 @@ import React from 'react'; +import deepEqual from 'deep-equal'; + import { defaultEmpty, defaultLoading, defaultRenderError, Render } from './constant'; import { LoadingWrap } from './loading'; @@ -15,7 +17,7 @@ interface IProps { normalContent: RenderProps; } -export const DataRender: React.FC = ({ +export const _DataRender: React.FC = ({ loading, error, empty, @@ -36,3 +38,7 @@ export const DataRender: React.FC = ({ ); }; + +export const DataRender = React.memo(_DataRender, (prevProps, nextProps) => { + return deepEqual(prevProps, nextProps); +}); diff --git a/packages/client/src/components/data-render/loading.tsx b/packages/client/src/components/data-render/loading.tsx index d071d2d3..c696342a 100644 --- a/packages/client/src/components/data-render/loading.tsx +++ b/packages/client/src/components/data-render/loading.tsx @@ -1,6 +1,7 @@ -import { useToggle } from 'hooks/use-toggle'; import React, { useEffect, useRef } from 'react'; +import { useToggle } from 'hooks/use-toggle'; + import { Render } from './constant'; export const LoadingWrap = ({ loading, delay = 200, loadingContent, normalContent }) => { diff --git a/packages/client/src/components/document-creator/index.tsx b/packages/client/src/components/document-creator/index.tsx index 07933c05..fa1b0735 100644 --- a/packages/client/src/components/document-creator/index.tsx +++ b/packages/client/src/components/document-creator/index.tsx @@ -1,8 +1,10 @@ +import React from 'react'; + import { Button } from '@douyinfe/semi-ui'; + import { DocumentCreator as DocumenCreatorForm } from 'components/document/create'; import { useRouterQuery } from 'hooks/use-router-query'; import { useToggle } from 'hooks/use-toggle'; -import React from 'react'; interface IProps { onCreateDocument?: () => void; diff --git a/packages/client/src/components/document/actions/index.tsx b/packages/client/src/components/document/actions/index.tsx index 264cb982..1fd91309 100644 --- a/packages/client/src/components/document/actions/index.tsx +++ b/packages/client/src/components/document/actions/index.tsx @@ -1,7 +1,11 @@ +import React, { useCallback } from 'react'; + import { IconArticle, IconBranch, IconExport, IconHistory, IconMore, IconPlus, IconStar } from '@douyinfe/semi-icons'; import { Button, Dropdown, Space, Typography } from '@douyinfe/semi-ui'; import { ButtonProps } from '@douyinfe/semi-ui/button/Button'; + import { IDocument, IOrganization, IWiki } from '@think/domains'; + import cls from 'classnames'; import { DocumentCreator } from 'components/document/create'; import { DocumentDeletor } from 'components/document/delete'; @@ -12,7 +16,6 @@ import { DocumentStar } from 'components/document/star'; import { DocumentStyle } from 'components/document/style'; import { DocumentVersionTrigger } from 'components/document/version'; import { useToggle } from 'hooks/use-toggle'; -import React, { useCallback } from 'react'; import styles from './index.module.scss'; @@ -78,6 +81,7 @@ export const DocumentActions: React.FC = ({ position="bottomLeft" visible={popoverVisible} onVisibleChange={wrapOnVisibleChange} + stopPropagation={true} content={ {showCreateDocument && ( @@ -169,24 +173,6 @@ export const DocumentActions: React.FC = ({ /> )} - {!hideDocumentVersion && ( - { - return ( - - - - - 文档排版 - - - - ); - }} - /> - )} - {document && ( = ({ wikiId, documentId, disabled = false }) => { const { isMobile } = IsOnMobile.useHook(); const toastedUsersRef = useRef([]); const { user: currentUser } = useUser(); const [visible, toggleVisible] = useToggle(false); const [collaborationUsers, setCollaborationUsers] = useState([]); + const content = useMemo( - () => ( -
- -
- ), - [documentId] + () => + !visible ? null : ( +
+ +
+ ), + [visible, documentId] ); + const btn = useMemo( () => (
} + autoAdjustOverflow={false} + position={'bottomRight'} + style={{ padding: '12px 8px', paddingBottom: 0 }} + > + {`+${restNumber}`} + + ); + }, []); + useEffect(() => { const handler = (users) => { const joinUsers = users @@ -49,35 +87,40 @@ export const DocumentCollaboration: React.FC = ({ wikiId, documentId, di .filter((state) => state.user) .map((state) => ({ ...state.user, clientId: state.clientId })); - joinUsers + const otherUsers = joinUsers .filter(Boolean) .filter((joinUser) => { return joinUser.name !== currentUser.name; }) - .forEach((joinUser) => { - if (!toastedUsersRef.current.includes(joinUser.clientId)) { - Toast.info(`${joinUser.name}-${joinUser.clientId}加入文档`); - toastedUsersRef.current.push(joinUser.clientId); - } + .filter((joinUser) => { + return !toastedUsersRef.current.includes(joinUser.clientId); }); + if (otherUsers.length) { + Toast.info(`${otherUsers[0].name}等${otherUsers.length}个用户加入文档`); + + otherUsers.forEach((joinUser) => { + toastedUsersRef.current.push(joinUser.clientId); + }); + } + setCollaborationUsers(joinUsers); }; event.on(JOIN_USER, handler); return () => { - toastedUsersRef.current = []; event.off(JOIN_USER, handler); + toastedUsersRef.current = []; }; }, [currentUser]); return ( <> - + {collaborationUsers.map((user) => { return ( - + {user.name && user.name.charAt(0)} @@ -85,6 +128,7 @@ export const DocumentCollaboration: React.FC = ({ wikiId, documentId, di ); })} + {isMobile ? ( <> = ({ wikiId, documentId, di visible={visible} footer={null} onCancel={toggleVisible} - style={{ maxWidth: '96vw', maxHeight: '60vh', overflow: 'auto' }} + style={mobileContainerStyle} > {content} @@ -106,19 +150,7 @@ export const DocumentCollaboration: React.FC = ({ wikiId, documentId, di onVisibleChange={toggleVisible} trigger="click" position="bottomRight" - content={ -
- {content} -
- } + content={
{content}
} > {btn} diff --git a/packages/client/src/components/document/comments/comments/index.tsx b/packages/client/src/components/document/comments/comments/index.tsx index 3738ecb5..19abe1c1 100644 --- a/packages/client/src/components/document/comments/comments/index.tsx +++ b/packages/client/src/components/document/comments/comments/index.tsx @@ -1,6 +1,7 @@ -import type { IComment } from '@think/domains'; import React from 'react'; +import type { IComment } from '@think/domains'; + import { CommentItem } from './item'; interface IProps { diff --git a/packages/client/src/components/document/comments/comments/item/index.tsx b/packages/client/src/components/document/comments/comments/item/index.tsx index 566f77a1..2bbb07cb 100644 --- a/packages/client/src/components/document/comments/comments/item/index.tsx +++ b/packages/client/src/components/document/comments/comments/item/index.tsx @@ -1,9 +1,12 @@ +import React from 'react'; + import { IconUser } from '@douyinfe/semi-icons'; import { Avatar, Popconfirm, Skeleton, Space, Typography } from '@douyinfe/semi-ui'; + import type { IComment, IUser } from '@think/domains'; + import { LocaleTime } from 'components/locale-time'; import { useUser } from 'data/user'; -import React from 'react'; import styles from './index.module.scss'; diff --git a/packages/client/src/components/document/comments/index.tsx b/packages/client/src/components/document/comments/index.tsx index 5fcd67a3..c50c55e6 100644 --- a/packages/client/src/components/document/comments/index.tsx +++ b/packages/client/src/components/document/comments/index.tsx @@ -1,13 +1,17 @@ +import React, { useCallback, useRef, useState } from 'react'; + import { Avatar, Banner, Button, Pagination, Space, Spin, Typography } from '@douyinfe/semi-ui'; + +import { EditorContent, useEditor } from 'tiptap/core'; +import { CommentKit, CommentMenuBar } from 'tiptap/editor'; + import { DataRender } from 'components/data-render'; import { useComments } from 'data/comment'; import { useUser } from 'data/user'; import { useToggle } from 'hooks/use-toggle'; -import React, { useCallback, useRef, useState } from 'react'; -import { EditorContent, useEditor } from 'tiptap/core'; -import { CommentKit, CommentMenuBar } from 'tiptap/editor'; import { Comments } from './comments'; + import styles from './index.module.scss'; interface IProps { diff --git a/packages/client/src/components/document/create/index.tsx b/packages/client/src/components/document/create/index.tsx index 28464992..d3921584 100644 --- a/packages/client/src/components/document/create/index.tsx +++ b/packages/client/src/components/document/create/index.tsx @@ -1,12 +1,15 @@ +import { Dispatch, SetStateAction, useCallback, useEffect, useState } from 'react'; + import { Checkbox, Modal, TabPane, Tabs } from '@douyinfe/semi-ui'; + import { IDocument, IWiki } from '@think/domains'; + import { TemplateCardEmpty } from 'components/template/card'; import { TemplateList } from 'components/template/list'; import { useCreateDocument } from 'data/document'; import { useOwnTemplates, usePublicTemplates } from 'data/template'; import { useRouterQuery } from 'hooks/use-router-query'; import Router from 'next/router'; -import { Dispatch, SetStateAction, useCallback, useEffect, useState } from 'react'; import styles from './index.module.scss'; diff --git a/packages/client/src/components/document/delete/index.tsx b/packages/client/src/components/document/delete/index.tsx index edcf759d..9f923292 100644 --- a/packages/client/src/components/document/delete/index.tsx +++ b/packages/client/src/components/document/delete/index.tsx @@ -1,9 +1,11 @@ +import React, { useCallback, useMemo } from 'react'; + import { IconDelete } from '@douyinfe/semi-icons'; import { Popconfirm, Space, Typography } from '@douyinfe/semi-ui'; + import { useDeleteDocument } from 'data/document'; import { useRouterQuery } from 'hooks/use-router-query'; import Router from 'next/router'; -import React, { useCallback, useMemo } from 'react'; interface IProps { wikiId: string; diff --git a/packages/client/src/components/document/editor/editor.tsx b/packages/client/src/components/document/editor/editor.tsx index 981f994d..fd1899cd 100644 --- a/packages/client/src/components/document/editor/editor.tsx +++ b/packages/client/src/components/document/editor/editor.tsx @@ -1,9 +1,12 @@ +import React, { useEffect, useRef } from 'react'; + import { IAuthority, ILoginUser } from '@think/domains'; + +import { CollaborationEditor, ICollaborationRefProps } from 'tiptap/editor'; + import cls from 'classnames'; import { event, triggerChangeDocumentTitle, triggerJoinUser, USE_DOCUMENT_VERSION } from 'event'; import { useMount } from 'hooks/use-mount'; -import React, { useEffect, useRef } from 'react'; -import { CollaborationEditor, ICollaborationRefProps } from 'tiptap/editor'; import styles from './index.module.scss'; @@ -23,6 +26,7 @@ export const Editor: React.FC = ({ user: currentUser, documentId, author if (!editor) return; editor.commands.setContent(data); }; + event.on(USE_DOCUMENT_VERSION, handler); return () => { diff --git a/packages/client/src/components/document/editor/index.tsx b/packages/client/src/components/document/editor/index.tsx index 3a00816f..642e04f4 100644 --- a/packages/client/src/components/document/editor/index.tsx +++ b/packages/client/src/components/document/editor/index.tsx @@ -1,5 +1,8 @@ +import React, { useCallback, useEffect, useMemo, useState } from 'react'; + import { IconChevronLeft } from '@douyinfe/semi-icons'; import { Button, Nav, Skeleton, Space, Tooltip, Typography } from '@douyinfe/semi-ui'; + import { DataRender } from 'components/data-render'; import { Divider } from 'components/divider'; import { DocumentCollaboration } from 'components/document/collaboration'; @@ -16,10 +19,10 @@ import { IsOnMobile } from 'hooks/use-on-mobile'; import { useWindowSize } from 'hooks/use-window-size'; import { SecureDocumentIllustration } from 'illustrations/secure-document'; import Router from 'next/router'; -import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { DocumentActions } from '../actions'; import { Editor } from './editor'; + import styles from './index.module.scss'; const { Text } = Typography; @@ -28,6 +31,14 @@ interface IProps { documentId: string; } +const ErrorContent = () => { + return ( +
+ +
+ ); +}; + export const DocumentEditor: React.FC = ({ documentId }) => { const { isMobile } = IsOnMobile.useHook(); const { width: windowWith } = useWindowSize(); @@ -62,7 +73,7 @@ export const DocumentEditor: React.FC = ({ documentId }) => { {document && ( )} - + ), [documentId, document, authority] @@ -84,9 +95,7 @@ export const DocumentEditor: React.FC = ({ documentId }) => { mode="horizontal" header={ <> - - - ) : null - } - collapsible - > - {renderedList.map((list) => { - return ( - -
- {(list.data || []).map((ex) => ( -
selectEmoji(ex)}> - {ex} -
- ))} -
-
- ); - })} - -
- ), - [showClear, renderedList, selectEmoji, clear] + () => + !visible ? null : ( +
+ + 清除 + + ) : null + } + collapsible + > + {renderedList.map((list) => { + return ( + +
+ {(list.data || []).map((ex) => ( +
selectEmoji(ex)}> + {ex} +
+ ))} +
+
+ ); + })} +
+
+ ), + [visible, showClear, renderedList, selectEmoji, clear] ); useEffect(() => { diff --git a/packages/client/src/components/empty.tsx b/packages/client/src/components/empty.tsx index 9cb26a6d..de3f0df1 100644 --- a/packages/client/src/components/empty.tsx +++ b/packages/client/src/components/empty.tsx @@ -1,6 +1,7 @@ -import { Typography } from '@douyinfe/semi-ui'; import React from 'react'; +import { Typography } from '@douyinfe/semi-ui'; + interface IProps { illustration?: React.ReactNode; message: React.ReactNode; diff --git a/packages/client/src/components/grid-select/grid-cell.tsx b/packages/client/src/components/grid-select/grid-cell.tsx index c4d30b56..a472e2cb 100644 --- a/packages/client/src/components/grid-select/grid-cell.tsx +++ b/packages/client/src/components/grid-select/grid-cell.tsx @@ -1,11 +1,10 @@ import React, { MouseEventHandler } from 'react'; type CellProperties = { - active: boolean; hover: boolean; disabled: boolean; cellSize: number; - onClick: MouseEventHandler; + onMouseDown: MouseEventHandler; onMouseEnter: MouseEventHandler; styles: Record; id: string; @@ -38,7 +37,7 @@ const getMergedStyle = (baseStyles, styles, styleClass) => ({ ...(styles && styles[styleClass] ? styles[styleClass] : {}), }); -export const GridCell = ({ active, hover, disabled, onClick, onMouseEnter, cellSize, styles, id }: CellProperties) => { +export const GridCell = ({ hover, disabled, onMouseDown, onMouseEnter, cellSize, styles, id }: CellProperties) => { const baseStyles = getBaseStyles(cellSize); const cellStyles = { cell: getMergedStyle(baseStyles, styles, 'cell'), @@ -52,11 +51,10 @@ export const GridCell = ({ active, hover, disabled, onClick, onMouseEnter, cellS id={id} style={{ ...cellStyles.cell, - ...(active && cellStyles.active), ...(hover && cellStyles.hover), - ...(!active && disabled && cellStyles.disabled), + ...(disabled && cellStyles.disabled), }} - onClick={onClick} + onMouseDown={onMouseDown} onMouseEnter={onMouseEnter} /> ); diff --git a/packages/client/src/components/grid-select/grid-select.tsx b/packages/client/src/components/grid-select/grid-select.tsx index b262745d..52105c22 100644 --- a/packages/client/src/components/grid-select/grid-select.tsx +++ b/packages/client/src/components/grid-select/grid-select.tsx @@ -1,6 +1,7 @@ -import { Typography } from '@douyinfe/semi-ui'; import React, { useCallback, useMemo, useState } from 'react'; +import { Typography } from '@douyinfe/semi-ui'; + import { GridCell } from './grid-cell'; const { Text } = Typography; @@ -44,10 +45,6 @@ export const GridSelect = ({ cellSize = 16, styles, }: RegionSelectionProps) => { - const [activeCell, setActiveCell] = useState({ - x: -1, - y: -1, - }); const [hoverCell, setHoverCell] = useState(null); const onClick = useCallback( @@ -60,6 +57,15 @@ export const GridSelect = ({ [onSelect] ); + const onClickPanel = useCallback(() => { + if (hoverCell.x + 1 > 0 && hoverCell.y + 1 > 0) { + onSelect({ + rows: hoverCell.y + 1, + cols: hoverCell.x + 1, + }); + } + }, [hoverCell, onSelect]); + const onHover = useCallback(({ x, y, isCellDisabled }) => { if (isCellDisabled) { return setHoverCell(null); @@ -71,16 +77,17 @@ export const GridSelect = ({ const cells = []; for (let y = 0; y < rows; y++) { for (let x = 0; x < cols; x++) { - const isActive = x <= activeCell.x && y <= activeCell.y; const isHover = hoverCell && x <= hoverCell.x && y <= hoverCell.y; const isCellDisabled = disabled; cells.push( onClick({ x, y, isCellDisabled })} + onMouseDown={(e) => { + e.stopPropagation(); + onClick({ x, y, isCellDisabled }); + }} onMouseEnter={onHover.bind(null, { x, y, isCellDisabled })} - active={isActive} hover={isHover} disabled={isCellDisabled} styles={styles} @@ -90,12 +97,12 @@ export const GridSelect = ({ } } return cells; - }, [rows, cols, disabled, activeCell.x, activeCell.y, cellSize, hoverCell, styles, onClick, onHover]); + }, [rows, cols, disabled, cellSize, hoverCell, styles, onClick, onHover]); const baseStyles = useMemo(() => getBaseStyles(cols, cellSize), [cols, cellSize]); return ( -
+
= ({ style = {} }) => { + return ( + + + + + } + /> + ); +}; + +export const IconAddColAfter: React.FC<{ style?: React.CSSProperties }> = ({ style = {} }) => { + return ( + + + + + } + /> + ); +}; + +export const IconDeleteCol: React.FC<{ style?: React.CSSProperties }> = ({ style = {} }) => { + return ( + + + + + } + /> + ); +}; diff --git a/packages/client/src/components/icons/IconDocument.tsx b/packages/client/src/components/icons/IconDocument.tsx index 9df647e7..7a50f24f 100644 --- a/packages/client/src/components/icons/IconDocument.tsx +++ b/packages/client/src/components/icons/IconDocument.tsx @@ -1,6 +1,7 @@ -import { Icon } from '@douyinfe/semi-ui'; import React from 'react'; +import { Icon } from '@douyinfe/semi-ui'; + export const IconDocument: React.FC<{ style?: React.CSSProperties }> = ({ style = {} }) => { return ( = ({ style = {} }) => { return ( = ({ style = {} }) => { + return ( + + + + } + /> + ); +}; diff --git a/packages/client/src/components/icons/IconMessage.tsx b/packages/client/src/components/icons/IconMessage.tsx index 6aebdf4d..4ae6e6b8 100644 --- a/packages/client/src/components/icons/IconMessage.tsx +++ b/packages/client/src/components/icons/IconMessage.tsx @@ -1,6 +1,7 @@ -import { Icon } from '@douyinfe/semi-ui'; import React from 'react'; +import { Icon } from '@douyinfe/semi-ui'; + export const IconMessage: React.FC<{ style?: React.CSSProperties }> = ({ style = {} }) => { return ( = ({ style = {} }) => { return ( = ({ style = {} /> ); }; + +export const IconFilePDF: React.FC<{ style?: React.CSSProperties }> = ({ style = {} }) => { + return ( + + + + + } + /> + ); +}; diff --git a/packages/client/src/components/icons/IconPPT.tsx b/packages/client/src/components/icons/IconPPT.tsx new file mode 100644 index 00000000..12f24c65 --- /dev/null +++ b/packages/client/src/components/icons/IconPPT.tsx @@ -0,0 +1,15 @@ +import { Icon } from '@douyinfe/semi-ui'; + +export const IconFilePPT: React.FC<{ style?: React.CSSProperties }> = ({ style = {} }) => { + return ( + + + + + } + /> + ); +}; diff --git a/packages/client/src/components/icons/IconSearch.tsx b/packages/client/src/components/icons/IconSearch.tsx index d537475e..3bb58463 100644 --- a/packages/client/src/components/icons/IconSearch.tsx +++ b/packages/client/src/components/icons/IconSearch.tsx @@ -1,6 +1,7 @@ -import { Icon } from '@douyinfe/semi-ui'; import React from 'react'; +import { Icon } from '@douyinfe/semi-ui'; + export const IconSearch: React.FC<{ style?: React.CSSProperties }> = ({ style = {} }) => { return ( = ({ style = {} }) => { return ( = ({ style = {} }) => { return ( = ({ style = {} }) => { + return ( + + + + + } + /> + ); +}; diff --git a/packages/client/src/components/icons/IconWord.tsx b/packages/client/src/components/icons/IconWord.tsx index 3846fc95..5302652b 100644 --- a/packages/client/src/components/icons/IconWord.tsx +++ b/packages/client/src/components/icons/IconWord.tsx @@ -35,3 +35,17 @@ export const IconWord: React.FC<{ style?: React.CSSProperties }> = ({ style = {} /> ); }; + +export const IconFileWord: React.FC<{ style?: React.CSSProperties }> = ({ style = {} }) => { + return ( + + + + + } + /> + ); +}; diff --git a/packages/client/src/components/icons/index.tsx b/packages/client/src/components/icons/index.tsx index e62abd00..c4715c4c 100644 --- a/packages/client/src/components/icons/index.tsx +++ b/packages/client/src/components/icons/index.tsx @@ -7,6 +7,7 @@ export * from './IconCallout'; export * from './IconCenter'; export * from './IconClear'; export * from './IconCodeBlock'; +export * from './IconColumns'; export * from './IconCountdown'; export * from './IconDeleteColumn'; export * from './IconDeleteRow'; @@ -29,6 +30,7 @@ export * from './IconInfo'; export * from './IconJSON'; export * from './IconLayout'; export * from './IconLeft'; +export * from './IconLineHeight'; export * from './IconLink'; export * from './IconList'; export * from './IconMarkdown'; @@ -44,12 +46,14 @@ export * from './IconMindSide'; export * from './IconOrderedList'; export * from './IconOverview'; export * from './IconPDF'; +export * from './IconPPT'; export * from './IconQuote'; export * from './IconRight'; export * from './IconSearch'; export * from './IconSearchReplace'; export * from './IconSetting'; export * from './IconShare'; +export * from './IconSheet'; export * from './IconSplitCell'; export * from './IconStatus'; export * from './IconStructure'; diff --git a/packages/client/src/components/image-uploader/index.tsx b/packages/client/src/components/image-uploader/index.tsx index dfd625e4..098c97e5 100644 --- a/packages/client/src/components/image-uploader/index.tsx +++ b/packages/client/src/components/image-uploader/index.tsx @@ -1,10 +1,12 @@ +import React, { useCallback, useMemo, useState } from 'react'; +import { LazyLoadImage } from 'react-lazy-load-image-component'; + import { Button, ButtonGroup, Col, Popover, Row, SideSheet, Skeleton, Space, TabPane, Tabs } from '@douyinfe/semi-ui'; + import { Upload } from 'components/upload'; import { chunk } from 'helpers/chunk'; import { IsOnMobile } from 'hooks/use-on-mobile'; import { useToggle } from 'hooks/use-toggle'; -import React, { useCallback, useMemo, useState } from 'react'; -import { LazyLoadImage } from 'react-lazy-load-image-component'; import styles from './index.module.scss'; diff --git a/packages/client/src/components/image-viewer.tsx b/packages/client/src/components/image-viewer.tsx index e9c4a832..721b69cd 100644 --- a/packages/client/src/components/image-viewer.tsx +++ b/packages/client/src/components/image-viewer.tsx @@ -1,4 +1,5 @@ import { useEffect } from 'react'; + import Viewer from 'viewerjs'; interface IProps { diff --git a/packages/client/src/components/locale-time/index.tsx b/packages/client/src/components/locale-time/index.tsx index e8c619ea..372ea2f5 100644 --- a/packages/client/src/components/locale-time/index.tsx +++ b/packages/client/src/components/locale-time/index.tsx @@ -1,4 +1,5 @@ import React, { useEffect, useMemo, useRef, useState } from 'react'; + import * as timeagojs from 'timeago.js'; type Props = { diff --git a/packages/client/src/components/logo/index.tsx b/packages/client/src/components/logo/index.tsx index 4cbc5106..2cf5de17 100644 --- a/packages/client/src/components/logo/index.tsx +++ b/packages/client/src/components/logo/index.tsx @@ -1,4 +1,5 @@ import { Typography } from '@douyinfe/semi-ui'; + import Link from 'next/link'; import styles from './index.module.scss'; diff --git a/packages/client/src/components/members/add.tsx b/packages/client/src/components/members/add.tsx index 99fe3284..6712e271 100644 --- a/packages/client/src/components/members/add.tsx +++ b/packages/client/src/components/members/add.tsx @@ -1,7 +1,9 @@ -import { Banner, Input, Popconfirm, Select, Space } from '@douyinfe/semi-ui'; -import { AuthEnum, AuthEnumArray } from '@think/domains'; import React, { useCallback, useState } from 'react'; +import { Banner, Input, Popconfirm, Select, Space } from '@douyinfe/semi-ui'; + +import { AuthEnum, AuthEnumArray } from '@think/domains'; + interface IProps { onOk: (arg) => any; } diff --git a/packages/client/src/components/members/edit.tsx b/packages/client/src/components/members/edit.tsx index 777b1d31..34b702df 100644 --- a/packages/client/src/components/members/edit.tsx +++ b/packages/client/src/components/members/edit.tsx @@ -1,7 +1,9 @@ -import { Banner, Popconfirm, Select, Toast } from '@douyinfe/semi-ui'; -import { AuthEnum, AuthEnumArray, IAuth, IUser } from '@think/domains'; import React, { useCallback, useState } from 'react'; +import { Banner, Popconfirm, Select, Toast } from '@douyinfe/semi-ui'; + +import { AuthEnum, AuthEnumArray, IAuth, IUser } from '@think/domains'; + interface IProps { userWithAuth: { user: IUser; auth: IAuth }; updateUser: (arg) => any; diff --git a/packages/client/src/components/members/index.tsx b/packages/client/src/components/members/index.tsx index b34b6ade..0cefa7b2 100644 --- a/packages/client/src/components/members/index.tsx +++ b/packages/client/src/components/members/index.tsx @@ -1,12 +1,16 @@ +import React from 'react'; + import { IconDelete, IconEdit } from '@douyinfe/semi-icons'; import { Banner, Button, Popconfirm, Table, Typography } from '@douyinfe/semi-ui'; + import { AuthEnumTextMap } from '@think/domains'; + import { DataRender } from 'components/data-render'; import { LocaleTime } from 'components/locale-time'; -import React from 'react'; import { AddUser } from './add'; import { EditUser } from './edit'; + import styles from './index.module.scss'; interface IProps { diff --git a/packages/client/src/components/message/index.tsx b/packages/client/src/components/message/index.tsx index ae19d3bc..50ebd5ca 100644 --- a/packages/client/src/components/message/index.tsx +++ b/packages/client/src/components/message/index.tsx @@ -1,4 +1,7 @@ +import React, { useCallback, useMemo } from 'react'; + import { Badge, Button, Dropdown, Modal, Pagination, TabPane, Tabs, Typography } from '@douyinfe/semi-ui'; + import { DataRender } from 'components/data-render'; import { Empty } from 'components/empty'; import { IconMessage } from 'components/icons/IconMessage'; @@ -8,81 +11,83 @@ import { IsOnMobile } from 'hooks/use-on-mobile'; import { useToggle } from 'hooks/use-toggle'; import { EmptyBoxIllustration } from 'illustrations/empty-box'; import Link from 'next/link'; -import React, { useCallback } from 'react'; + +import { Placeholder } from './placeholder'; import styles from './index.module.scss'; -import { Placeholder } from './placeholder'; const { Text } = Typography; const PAGE_SIZE = 6; const MessagesRender = ({ messageData, loading, error, onClick = null, page = 1, onPageChange = null }) => { - const total = (messageData && messageData.total) || 0; - const messages = (messageData && messageData.data) || []; + const [messages, total] = useMemo( + () => [(messageData && messageData.data) || [], (messageData && messageData.total) || 0], + [messageData] + ); - const handleRead = (messageId) => { - onClick && onClick(messageId); - }; + const handleRead = useCallback( + (messageId) => { + onClick && onClick(messageId); + }, + [onClick] + ); + + const renderNormalContent = useCallback(() => { + return ( +
{ + e.preventDefault(); + e.stopPropagation(); + }} + > + {messages.length ? ( + <> + {messages.map((msg) => { + return ( +
handleRead(msg.id)}> + + +
+ + {msg.title} + +
+
+ +
+ ); + })} + {total > PAGE_SIZE && ( +
+ +
+ )} + + ) : ( + } message="暂无消息" /> + )} +
+ ); + }, [handleRead, messages, onPageChange, page, total]); return ( - } - error={error} - normalContent={() => { - return ( -
{ - e.preventDefault(); - e.stopPropagation(); - }} - > - {messages.length ? ( - <> - {messages.map((msg) => { - return ( -
handleRead(msg.id)}> - - -
- - {msg.title} - -
-
- -
- ); - })} - {total > PAGE_SIZE && ( -
- -
- )} - - ) : ( - } message="暂无消息" /> - )} -
- ); - }} - /> + } error={error} normalContent={renderNormalContent} /> ); }; @@ -106,60 +111,83 @@ const MessageBox = () => { setPage: unreadSetPage, } = useUnreadMessages(); - const clearAll = () => { + const clearAll = useCallback(() => { Promise.all( (unreadMsgs.data || []).map((msg) => { return readMessage(msg.id); }) ); - }; + }, [readMessage, unreadMsgs]); const openModalOnMobile = useCallback(() => { if (!isMobile) return; toggleVisible(true); }, [isMobile, toggleVisible]); - const content = ( - 0 ? ( - - 全部已读 - - ) : null - } - > - - - - - - - - - - + const content = useMemo( + () => + visible ? ( + 0 ? ( + + 全部已读 + + ) : null + } + > + + + + + + + + + + + ) : null, + [ + allError, + allLoading, + allMsgs, + allPage, + allSetPage, + clearAll, + readError, + readLoading, + readMessage, + readMsgs, + readPage, + readSetPage, + unreadError, + unreadLoading, + unreadMsgs, + unreadPage, + unreadSetPage, + visible, + ] ); const btn = ( @@ -197,6 +225,8 @@ const MessageBox = () => { ) : ( {content}
} @@ -210,5 +240,8 @@ const MessageBox = () => { export const Message = () => { const { loading, error } = useUser(); - return } />; + + const renderNormalContent = useCallback(() => , []); + + return ; }; diff --git a/packages/client/src/components/organization/delete/index.tsx b/packages/client/src/components/organization/delete/index.tsx index e9714636..5234d8bf 100644 --- a/packages/client/src/components/organization/delete/index.tsx +++ b/packages/client/src/components/organization/delete/index.tsx @@ -1,10 +1,13 @@ +import React, { useCallback } from 'react'; + import { IconDelete } from '@douyinfe/semi-icons'; import { Modal, Space, Typography } from '@douyinfe/semi-ui'; + import { IOrganization } from '@think/domains'; + import { useOrganizationDetail } from 'data/organization'; import { useRouterQuery } from 'hooks/use-router-query'; import Router from 'next/router'; -import React, { useCallback } from 'react'; interface IProps { organizationId: IOrganization['id']; diff --git a/packages/client/src/components/organization/index.tsx b/packages/client/src/components/organization/index.tsx index 9e658005..651bdbe5 100644 --- a/packages/client/src/components/organization/index.tsx +++ b/packages/client/src/components/organization/index.tsx @@ -1,5 +1,6 @@ import { Typography } from '@douyinfe/semi-ui'; import { Avatar } from '@douyinfe/semi-ui'; + import { DataRender } from 'components/data-render'; import { useOrganizationDetail } from 'data/organization'; import { useRouterQuery } from 'hooks/use-router-query'; diff --git a/packages/client/src/components/organization/public-switcher/index.tsx b/packages/client/src/components/organization/public-switcher/index.tsx index f9362af6..1cb4b6a2 100644 --- a/packages/client/src/components/organization/public-switcher/index.tsx +++ b/packages/client/src/components/organization/public-switcher/index.tsx @@ -1,9 +1,11 @@ import { Space } from '@douyinfe/semi-ui'; + import { LogoImage, LogoText } from 'components/logo'; import { useUser } from 'data/user'; import { useWindowSize } from 'hooks/use-window-size'; import { UserOrganizationsSwitcher } from '../switcher'; + import styles from './index.module.scss'; export const OrganizationPublicSwitcher = () => { diff --git a/packages/client/src/components/organization/setting/base/index.tsx b/packages/client/src/components/organization/setting/base/index.tsx index d4b1915b..874db1a3 100644 --- a/packages/client/src/components/organization/setting/base/index.tsx +++ b/packages/client/src/components/organization/setting/base/index.tsx @@ -1,14 +1,15 @@ -import { Avatar, Button, Form, Toast, Typography } from '@douyinfe/semi-ui'; +import { useCallback, useEffect, useRef, useState } from 'react'; + +import { Avatar, Button, Form, Toast } from '@douyinfe/semi-ui'; import { FormApi } from '@douyinfe/semi-ui/lib/es/form'; + import { ORGANIZATION_LOGOS } from '@think/constants'; import { IOrganization } from '@think/domains'; + import { DataRender } from 'components/data-render'; import { ImageUploader } from 'components/image-uploader'; -import { useCreateOrganization, useOrganizationDetail } from 'data/organization'; +import { useOrganizationDetail } from 'data/organization'; import { useToggle } from 'hooks/use-toggle'; -import { SingleColumnLayout } from 'layouts/single-column'; -import Router from 'next/router'; -import { useCallback, useEffect, useRef, useState } from 'react'; import styles from './index.module.scss'; diff --git a/packages/client/src/components/organization/setting/index.tsx b/packages/client/src/components/organization/setting/index.tsx index 0caf402d..39b55b87 100644 --- a/packages/client/src/components/organization/setting/index.tsx +++ b/packages/client/src/components/organization/setting/index.tsx @@ -1,8 +1,11 @@ -import { TabPane, Tabs } from '@douyinfe/semi-ui'; -import { IOrganization } from '@think/domains'; -import { Seo } from 'components/seo'; import React from 'react'; +import { TabPane, Tabs } from '@douyinfe/semi-ui'; + +import { IOrganization } from '@think/domains'; + +import { Seo } from 'components/seo'; + import { Base } from './base'; import { OrganizationMembers } from './members'; import { More } from './more'; diff --git a/packages/client/src/components/organization/setting/members/index.tsx b/packages/client/src/components/organization/setting/members/index.tsx index e8381078..121cabfb 100644 --- a/packages/client/src/components/organization/setting/members/index.tsx +++ b/packages/client/src/components/organization/setting/members/index.tsx @@ -1,7 +1,9 @@ +import React from 'react'; + import { IOrganization } from '@think/domains'; + import { Members } from 'components/members'; import { useOrganizationMembers } from 'data/organization'; -import React from 'react'; interface IProps { organizationId: IOrganization['id']; diff --git a/packages/client/src/components/organization/setting/more/index.tsx b/packages/client/src/components/organization/setting/more/index.tsx index 086c0126..339a5154 100644 --- a/packages/client/src/components/organization/setting/more/index.tsx +++ b/packages/client/src/components/organization/setting/more/index.tsx @@ -1,4 +1,5 @@ import { Banner, Button, Typography } from '@douyinfe/semi-ui'; + import { OrganizationDeletor } from 'components/organization/delete'; const { Paragraph } = Typography; diff --git a/packages/client/src/components/organization/switcher/index.tsx b/packages/client/src/components/organization/switcher/index.tsx index e2ee8ec0..7ce7e1c0 100644 --- a/packages/client/src/components/organization/switcher/index.tsx +++ b/packages/client/src/components/organization/switcher/index.tsx @@ -1,11 +1,13 @@ +import { useMemo } from 'react'; + import { IconAppCenter, IconApps, IconSmallTriangleDown } from '@douyinfe/semi-icons'; import { Button, Dropdown, Space, Typography } from '@douyinfe/semi-ui'; import { Avatar } from '@douyinfe/semi-ui'; + import { DataRender } from 'components/data-render'; import { useOrganizationDetail, useUserOrganizations } from 'data/organization'; import { useRouterQuery } from 'hooks/use-router-query'; import Link from 'next/link'; -import { useMemo } from 'react'; import styles from './index.module.scss'; diff --git a/packages/client/src/components/resizeable/resizeable.tsx b/packages/client/src/components/resizeable/resizeable.tsx index d7a959de..71db4fe4 100644 --- a/packages/client/src/components/resizeable/resizeable.tsx +++ b/packages/client/src/components/resizeable/resizeable.tsx @@ -1,7 +1,8 @@ +import React, { useEffect, useRef } from 'react'; + import cls from 'classnames'; import { useClickOutside } from 'hooks/use-click-outside'; import interact from 'interactjs'; -import React, { useEffect, useRef } from 'react'; import styles from './style.module.scss'; diff --git a/packages/client/src/components/search/index.tsx b/packages/client/src/components/search/index.tsx index 2b53418b..30ec2080 100644 --- a/packages/client/src/components/search/index.tsx +++ b/packages/client/src/components/search/index.tsx @@ -1,6 +1,10 @@ +import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; + import { IconSearch as SemiIconSearch } from '@douyinfe/semi-icons'; import { Button, Dropdown, Input, Modal, Spin, Typography } from '@douyinfe/semi-ui'; + import { IDocument } from '@think/domains'; + import { DataRender } from 'components/data-render'; import { DocumentStar } from 'components/document/star'; import { Empty } from 'components/empty'; @@ -14,7 +18,6 @@ import { useRouterQuery } from 'hooks/use-router-query'; import { useToggle } from 'hooks/use-toggle'; import Link from 'next/link'; import Router from 'next/router'; -import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { HttpClient } from 'services/http-client'; import styles from './index.module.scss'; diff --git a/packages/client/src/components/size-setter.tsx b/packages/client/src/components/size-setter.tsx index a575e4c0..5f312612 100644 --- a/packages/client/src/components/size-setter.tsx +++ b/packages/client/src/components/size-setter.tsx @@ -1,6 +1,7 @@ +import { useCallback, useRef } from 'react'; + import { Button, Dropdown, Form } from '@douyinfe/semi-ui'; import { FormApi } from '@douyinfe/semi-ui/lib/es/form'; -import { useCallback, useRef } from 'react'; type ISize = { width: number | string; height: number | string }; @@ -11,6 +12,9 @@ interface IProps { onOk: (arg: ISize) => void; } +const containerStyle = { padding: '0 12px 12px' }; +const inlineBlockStyle = { display: 'inline-block' }; + export const SizeSetter: React.FC = ({ width, maxWidth, height, onOk, children }) => { const $form = useRef(); @@ -27,7 +31,7 @@ export const SizeSetter: React.FC = ({ width, maxWidth, height, onOk, ch position={'bottomLeft'} spacing={10} render={ -
+
($form.current = formApi)} labelPosition="left"> @@ -38,7 +42,7 @@ export const SizeSetter: React.FC = ({ width, maxWidth, height, onOk, ch
} > - {children} + {children} ); }; diff --git a/packages/client/src/components/template/card/index.tsx b/packages/client/src/components/template/card/index.tsx index 86b365ef..e194aac4 100644 --- a/packages/client/src/components/template/card/index.tsx +++ b/packages/client/src/components/template/card/index.tsx @@ -1,13 +1,16 @@ +import { useCallback } from 'react'; + import { IconEdit, IconPlus, IconUser } from '@douyinfe/semi-icons'; import { Avatar, Button, Modal, Skeleton, Space, Tooltip, Typography } from '@douyinfe/semi-ui'; + import type { ITemplate } from '@think/domains'; + import cls from 'classnames'; import { IconDocument } from 'components/icons/IconDocument'; import { TemplateReader } from 'components/template/reader'; import { useUser } from 'data/user'; import { useToggle } from 'hooks/use-toggle'; import Router from 'next/router'; -import { useCallback } from 'react'; import styles from './index.module.scss'; @@ -21,6 +24,17 @@ export interface IProps { onClosePreview?: () => void; } +const bodyStyle = { + overflow: 'auto', +}; +const titleContainerStyle = { + marginBottom: 12, + whiteSpace: 'nowrap', + textOverflow: 'ellipsis', + overflow: 'hidden', +} as React.CSSProperties; +const flexStyle = { display: 'flex' }; + export const TemplateCard: React.FC = ({ template, onClick, @@ -35,26 +49,35 @@ export const TemplateCard: React.FC = ({ Router.push(`/template/${template.id}/`); }, [template]); + const cancel = useCallback(() => { + toggleVisible(false); + onClosePreview && onClosePreview(); + }, [toggleVisible, onClosePreview]); + + const preview = useCallback(() => { + toggleVisible(true); + onOpenPreview && onOpenPreview(); + }, [toggleVisible, onOpenPreview]); + + const useTemplate = useCallback(() => { + onClick && onClick(template.id); + }, [onClick, template.id]); + return ( <> { - toggleVisible(false); - onClosePreview && onClosePreview(); - }} + onCancel={cancel} footer={null} fullScreen > -
+
@@ -68,14 +91,7 @@ export const TemplateCard: React.FC = ({
-
+
{template.title}
@@ -92,28 +108,16 @@ export const TemplateCard: React.FC = ({
-
+
已使用 {template.usageAmount}次
- - {onClick && ( - - )}
diff --git a/packages/client/src/components/template/editor/index.tsx b/packages/client/src/components/template/editor/index.tsx index c221a21d..f0a6e13a 100644 --- a/packages/client/src/components/template/editor/index.tsx +++ b/packages/client/src/components/template/editor/index.tsx @@ -1,5 +1,10 @@ +import React, { useCallback, useEffect, useMemo, useState } from 'react'; + import { IconChevronLeft } from '@douyinfe/semi-icons'; import { Button, Nav, Popconfirm, Space, Switch, Tooltip, Typography } from '@douyinfe/semi-ui'; + +import { CollaborationEditor } from 'tiptap/editor'; + import { DocumentStyle } from 'components/document/style'; import { Seo } from 'components/seo'; import { Theme } from 'components/theme'; @@ -10,8 +15,6 @@ import { useDocumentStyle } from 'hooks/use-document-style'; import { useMount } from 'hooks/use-mount'; 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'; diff --git a/packages/client/src/components/template/list/index.tsx b/packages/client/src/components/template/list/index.tsx index b74eedb6..122bc0cf 100644 --- a/packages/client/src/components/template/list/index.tsx +++ b/packages/client/src/components/template/list/index.tsx @@ -1,8 +1,10 @@ +import React, { useEffect } from 'react'; + import { List, Pagination } from '@douyinfe/semi-ui'; + import { DataRender } from 'components/data-render'; import { Empty } from 'components/empty'; import { IProps as ITemplateCardProps, TemplateCard, TemplateCardPlaceholder } from 'components/template/card'; -import React, { useEffect, useMemo, useState } from 'react'; const grid = { gutter: 16, @@ -29,15 +31,9 @@ export const TemplateList: React.FC = ({ onClosePreview, pageSize = 5, }) => { - const { data, loading, error, refresh } = hook(); - const [page, onPageChange] = useState(1); - - const arr = useMemo(() => { - const arr = (data && data.data) || []; - const start = (page - 1) * pageSize; - const end = page * pageSize; - return arr.slice(start, end); - }, [data, page, pageSize]); + const { data, loading, error, page, setPage, refresh } = hook(pageSize); + const list = (data && data.data) || []; + const total = (data && data.total) || 0; useEffect(() => { refresh(); @@ -62,7 +58,7 @@ export const TemplateList: React.FC = ({ <> { if (idx === 0 && firstListItem) { return {firstListItem}; @@ -82,7 +78,7 @@ export const TemplateList: React.FC = ({ }} emptyContent={} > - {data.data.length > pageSize ? ( + {total > pageSize ? ( = ({ justifyContent: 'center', }} pageSize={pageSize} - total={data.data.length} + total={total} currentPage={page} - onChange={(cPage) => onPageChange(cPage)} + onChange={(cPage) => setPage(cPage)} /> ) : null} diff --git a/packages/client/src/components/template/reader/index.tsx b/packages/client/src/components/template/reader/index.tsx index f33d79cd..8266ff37 100644 --- a/packages/client/src/components/template/reader/index.tsx +++ b/packages/client/src/components/template/reader/index.tsx @@ -1,9 +1,12 @@ +import React from 'react'; + import { Spin } from '@douyinfe/semi-ui'; + +import { ReaderEditor } from 'tiptap/editor'; + import { DataRender } from 'components/data-render'; import { Seo } from 'components/seo'; import { useTemplate } from 'data/template'; -import React from 'react'; -import { ReaderEditor } from 'tiptap/editor'; interface IProps { templateId: string; diff --git a/packages/client/src/components/theme/index.tsx b/packages/client/src/components/theme/index.tsx index 35de542e..0e568f9a 100644 --- a/packages/client/src/components/theme/index.tsx +++ b/packages/client/src/components/theme/index.tsx @@ -1,7 +1,9 @@ +import React, { useCallback } from 'react'; + import { IconDesktop, IconMoon, IconSun } from '@douyinfe/semi-icons'; import { Button, Dropdown } from '@douyinfe/semi-ui'; + import { Theme as ThemeState, ThemeEnum } from 'hooks/use-theme'; -import React, { useCallback } from 'react'; export const Theme = () => { const { userPrefer, theme, toggle } = ThemeState.useHook(); diff --git a/packages/client/src/components/tooltip/index.tsx b/packages/client/src/components/tooltip/index.tsx index 7d4732f3..2cc80ebb 100644 --- a/packages/client/src/components/tooltip/index.tsx +++ b/packages/client/src/components/tooltip/index.tsx @@ -1,7 +1,9 @@ +import React from 'react'; + import { Tooltip as SemiTooltip } from '@douyinfe/semi-ui'; import { Position } from '@douyinfe/semi-ui/tooltip'; + import { useToggle } from 'hooks/use-toggle'; -import React from 'react'; interface IProps { content: React.ReactNode; diff --git a/packages/client/src/components/upload/index.tsx b/packages/client/src/components/upload/index.tsx index 58653092..98cbb078 100644 --- a/packages/client/src/components/upload/index.tsx +++ b/packages/client/src/components/upload/index.tsx @@ -1,7 +1,9 @@ +import React from 'react'; + import { IconUpload } from '@douyinfe/semi-icons'; import { Button, Toast, Upload as SemiUpload } from '@douyinfe/semi-ui'; + import { useAsyncLoading } from 'hooks/use-async-loading'; -import React from 'react'; import { uploadFile } from 'services/file'; interface IProps { diff --git a/packages/client/src/components/user/index.tsx b/packages/client/src/components/user/index.tsx index ec2d7d08..1c943e88 100644 --- a/packages/client/src/components/user/index.tsx +++ b/packages/client/src/components/user/index.tsx @@ -1,9 +1,11 @@ +import React, { useCallback } from 'react'; + import { IconSpin } from '@douyinfe/semi-icons'; import { Avatar, Button, Dropdown, Modal, Toast, Typography } from '@douyinfe/semi-ui'; + import { useUser } from 'data/user'; import { useToggle } from 'hooks/use-toggle'; import Router from 'next/router'; -import React, { useCallback } from 'react'; import { ResetPassword } from './reset-password'; import { UserSetting } from './setting'; diff --git a/packages/client/src/components/user/reset-password/index.tsx b/packages/client/src/components/user/reset-password/index.tsx index f65f66fa..32af3a22 100644 --- a/packages/client/src/components/user/reset-password/index.tsx +++ b/packages/client/src/components/user/reset-password/index.tsx @@ -1,8 +1,10 @@ +import React, { useCallback, useState } from 'react'; + import { Button, Col, Form, Row, Toast } from '@douyinfe/semi-ui'; + import { useResetPassword, useSystemPublicConfig, useUser, useVerifyCode } from 'data/user'; import { useInterval } from 'hooks/use-interval'; import { useToggle } from 'hooks/use-toggle'; -import React, { useCallback, useState } from 'react'; export const ResetPassword = ({ onSuccess }) => { const [email, setEmail] = useState(''); @@ -53,7 +55,7 @@ export const ResetPassword = ({ onSuccess }) => { return ( diff --git a/packages/client/src/components/user/setting/index.tsx b/packages/client/src/components/user/setting/index.tsx index 2e02996c..17912b6d 100644 --- a/packages/client/src/components/user/setting/index.tsx +++ b/packages/client/src/components/user/setting/index.tsx @@ -1,10 +1,12 @@ +import { Dispatch, SetStateAction, useCallback, useEffect, useRef, useState } from 'react'; + import { Avatar, Button, Col, Form, Modal, Row, Space, Toast } from '@douyinfe/semi-ui'; import { FormApi } from '@douyinfe/semi-ui/lib/es/form'; + import { Upload } from 'components/upload'; import { useSystemPublicConfig, useUser, useVerifyCode } from 'data/user'; import { useInterval } from 'hooks/use-interval'; import { useToggle } from 'hooks/use-toggle'; -import { Dispatch, SetStateAction, useCallback, useEffect, useRef, useState } from 'react'; interface IProps { visible: boolean; diff --git a/packages/client/src/components/wiki-creator/index.tsx b/packages/client/src/components/wiki-creator/index.tsx index 2936d04c..b616458b 100644 --- a/packages/client/src/components/wiki-creator/index.tsx +++ b/packages/client/src/components/wiki-creator/index.tsx @@ -1,7 +1,9 @@ +import React from 'react'; + import { Button } from '@douyinfe/semi-ui'; + import { WikiCreator as WikiCreatorForm } from 'components/wiki/create'; import { useToggle } from 'hooks/use-toggle'; -import React from 'react'; export const WikiCreator: React.FC = ({ children }) => { const [visible, toggleVisible] = useToggle(false); diff --git a/packages/client/src/components/wiki-or-document-creator/index.tsx b/packages/client/src/components/wiki-or-document-creator/index.tsx index 15da5495..92d38afc 100644 --- a/packages/client/src/components/wiki-or-document-creator/index.tsx +++ b/packages/client/src/components/wiki-or-document-creator/index.tsx @@ -1,10 +1,12 @@ +import React from 'react'; + import { IconPlus } from '@douyinfe/semi-icons'; import { Button, Dropdown } from '@douyinfe/semi-ui'; + import { DocumentCreator } from 'components/document/create'; import { WikiCreator } from 'components/wiki/create'; import { useRouterQuery } from 'hooks/use-router-query'; import { useToggle } from 'hooks/use-toggle'; -import React from 'react'; interface IProps { onCreateDocument?: () => void; diff --git a/packages/client/src/components/wiki/card/index.tsx b/packages/client/src/components/wiki/card/index.tsx index a818eeb7..9b5ff663 100644 --- a/packages/client/src/components/wiki/card/index.tsx +++ b/packages/client/src/components/wiki/card/index.tsx @@ -1,5 +1,6 @@ import { IconUser } from '@douyinfe/semi-icons'; import { Avatar, Skeleton, Space, Typography } from '@douyinfe/semi-ui'; + import { IconDocument } from 'components/icons/IconDocument'; import { LocaleTime } from 'components/locale-time'; import { WikiStar } from 'components/wiki/star'; diff --git a/packages/client/src/components/wiki/create/index.tsx b/packages/client/src/components/wiki/create/index.tsx index d66d8a66..02d8d506 100644 --- a/packages/client/src/components/wiki/create/index.tsx +++ b/packages/client/src/components/wiki/create/index.tsx @@ -1,10 +1,13 @@ +import { Dispatch, SetStateAction, useRef } from 'react'; + import { Form, Modal } from '@douyinfe/semi-ui'; import { FormApi } from '@douyinfe/semi-ui/lib/es/form'; + import type { IWiki } from '@think/domains'; + import { ICreateWiki, useOwnWikis } from 'data/wiki'; import { useRouterQuery } from 'hooks/use-router-query'; import Router from 'next/router'; -import { Dispatch, SetStateAction, useRef } from 'react'; interface IProps { visible: boolean; diff --git a/packages/client/src/components/wiki/delete/index.tsx b/packages/client/src/components/wiki/delete/index.tsx index a1c189f8..4ba29f81 100644 --- a/packages/client/src/components/wiki/delete/index.tsx +++ b/packages/client/src/components/wiki/delete/index.tsx @@ -1,9 +1,11 @@ +import React, { useCallback } from 'react'; + import { IconDelete } from '@douyinfe/semi-icons'; import { Modal, Space, Typography } from '@douyinfe/semi-ui'; + import { useOwnWikis } from 'data/wiki'; import { useRouterQuery } from 'hooks/use-router-query'; import Router from 'next/router'; -import React, { useCallback } from 'react'; interface IProps { wikiId: string; diff --git a/packages/client/src/components/wiki/documents-share/index.tsx b/packages/client/src/components/wiki/documents-share/index.tsx index 83e5516c..388c3c5f 100644 --- a/packages/client/src/components/wiki/documents-share/index.tsx +++ b/packages/client/src/components/wiki/documents-share/index.tsx @@ -1,9 +1,12 @@ +import React, { useCallback, useEffect, useMemo, useState } from 'react'; + import { IconClose } from '@douyinfe/semi-icons'; import { Banner, Button, Checkbox, Toast, Transfer, Typography } from '@douyinfe/semi-ui'; + import { isPublicDocument } from '@think/domains'; + import { flattenTree2Array } from 'components/wiki/tocs/utils'; import { useWikiDetail, useWikiTocs } from 'data/wiki'; -import React, { useCallback, useEffect, useMemo, useState } from 'react'; import styles from './index.module.scss'; diff --git a/packages/client/src/components/wiki/pin-card/index.tsx b/packages/client/src/components/wiki/pin-card/index.tsx index 588842f6..64974662 100644 --- a/packages/client/src/components/wiki/pin-card/index.tsx +++ b/packages/client/src/components/wiki/pin-card/index.tsx @@ -1,5 +1,7 @@ import { Avatar, Skeleton, Space, Typography } from '@douyinfe/semi-ui'; + import { IWiki } from '@think/domains'; + import { IconDocument } from 'components/icons/IconDocument'; import { LocaleTime } from 'components/locale-time'; import { WikiStar } from 'components/wiki/star'; diff --git a/packages/client/src/components/wiki/placeholder/index.tsx b/packages/client/src/components/wiki/placeholder/index.tsx index d8211d01..4a107c39 100644 --- a/packages/client/src/components/wiki/placeholder/index.tsx +++ b/packages/client/src/components/wiki/placeholder/index.tsx @@ -1,6 +1,7 @@ -import { Skeleton } from '@douyinfe/semi-ui'; import React from 'react'; +import { Skeleton } from '@douyinfe/semi-ui'; + export const WorkspacePlaceholder = () => { const placeholder = (
Promise; } +const getFormValueFromWiki = (wiki) => { + return pick(wiki, ['name', 'description', 'avatar']); +}; + export const Base: React.FC = ({ wiki, update }) => { const $form = useRef(); const [currentCover, setCurrentCover] = useState(''); - const onSubmit = () => { + const onSubmit = useCallback(() => { $form.current.validate().then((values) => { update(values).then(() => { Toast.success('操作成功'); }); }); - }; + }, [update]); - const setCover = (url) => { + const setCover = useCallback((url) => { $form.current.setValue('avatar', url); setCurrentCover(url); - }; + }, []); useEffect(() => { if (!wiki) return; - $form.current.setValues(wiki); + $form.current.setValues(getFormValueFromWiki(wiki)); setCurrentCover(wiki.avatar); }, [wiki]); return ( ($form.current = formApi)} onSubmit={onSubmit} diff --git a/packages/client/src/components/wiki/setting/import/index.tsx b/packages/client/src/components/wiki/setting/import/index.tsx index eeb81188..f74b0ee8 100644 --- a/packages/client/src/components/wiki/setting/import/index.tsx +++ b/packages/client/src/components/wiki/setting/import/index.tsx @@ -1,9 +1,12 @@ +import { useCallback, useEffect, useRef, useState } from 'react'; + import { Button, Toast, Typography, Upload } from '@douyinfe/semi-ui'; + import type { IWiki } from '@think/domains'; + import { useCreateDocument } from 'data/document'; import { useRouterQuery } from 'hooks/use-router-query'; import { useToggle } from 'hooks/use-toggle'; -import { useCallback, useEffect, useRef, useState } from 'react'; import { createMarkdownParser, MarkdownParse } from './parser'; @@ -94,7 +97,7 @@ export const Import: React.FC = ({ wikiId }) => {
{ const parse = (filename: string, markdown: string) => { try { const prosemirrorNode = markdownToProsemirror({ + editor, schema: editor.schema, content: markdown, needTitle: true, diff --git a/packages/client/src/components/wiki/setting/index.tsx b/packages/client/src/components/wiki/setting/index.tsx index 1ad8098f..ba86e6a3 100644 --- a/packages/client/src/components/wiki/setting/index.tsx +++ b/packages/client/src/components/wiki/setting/index.tsx @@ -1,9 +1,12 @@ +import React from 'react'; + import { TabPane, Tabs } from '@douyinfe/semi-ui'; + import { IWiki } from '@think/domains'; + import { Seo } from 'components/seo'; import { WikiTocsManager } from 'components/wiki/tocs/manager'; import { useWikiDetail } from 'data/wiki'; -import React from 'react'; import { Base } from './base'; import { Import } from './import'; diff --git a/packages/client/src/components/wiki/setting/more/index.tsx b/packages/client/src/components/wiki/setting/more/index.tsx index 43079f49..3d15480c 100644 --- a/packages/client/src/components/wiki/setting/more/index.tsx +++ b/packages/client/src/components/wiki/setting/more/index.tsx @@ -1,4 +1,5 @@ import { Banner, Button, Typography } from '@douyinfe/semi-ui'; + import { WikiDeletor } from 'components/wiki/delete'; interface IProps { diff --git a/packages/client/src/components/wiki/setting/privacy/index.tsx b/packages/client/src/components/wiki/setting/privacy/index.tsx index c7dc3911..aa523b52 100644 --- a/packages/client/src/components/wiki/setting/privacy/index.tsx +++ b/packages/client/src/components/wiki/setting/privacy/index.tsx @@ -1,10 +1,13 @@ +import React, { useCallback, useEffect, useMemo, useState } from 'react'; + import { IconClose } from '@douyinfe/semi-icons'; import { Banner, Button, Checkbox, Radio, RadioGroup, Toast, Transfer, Typography } from '@douyinfe/semi-ui'; + import { isPublicDocument, isPublicWiki, WIKI_STATUS_LIST } from '@think/domains'; + import { flattenTree2Array } from 'components/wiki/tocs/utils'; import { useWikiDetail, useWikiTocs } from 'data/wiki'; import { buildUrl } from 'helpers/url'; -import React, { useCallback, useEffect, useMemo, useState } from 'react'; import styles from './index.module.scss'; diff --git a/packages/client/src/components/wiki/setting/users/index.tsx b/packages/client/src/components/wiki/setting/users/index.tsx index ded43f0c..71f0219c 100644 --- a/packages/client/src/components/wiki/setting/users/index.tsx +++ b/packages/client/src/components/wiki/setting/users/index.tsx @@ -1,6 +1,7 @@ +import React from 'react'; + import { Members } from 'components/members'; import { useWikiMembers } from 'data/wiki'; -import React from 'react'; interface IProps { wikiId: string; diff --git a/packages/client/src/components/wiki/star/index.tsx b/packages/client/src/components/wiki/star/index.tsx index 794c9e55..286a201c 100644 --- a/packages/client/src/components/wiki/star/index.tsx +++ b/packages/client/src/components/wiki/star/index.tsx @@ -1,8 +1,11 @@ +import React from 'react'; + import { IconStar } from '@douyinfe/semi-icons'; import { Button, Tooltip } from '@douyinfe/semi-ui'; + import { IOrganization, IWiki } from '@think/domains'; + import { useWikiStarToggle } from 'data/star'; -import React from 'react'; interface IProps { organizationId: IOrganization['id']; diff --git a/packages/client/src/components/wiki/tocs/index.module.scss b/packages/client/src/components/wiki/tocs/index.module.scss index 98a8c3d8..75ffabfe 100644 --- a/packages/client/src/components/wiki/tocs/index.module.scss +++ b/packages/client/src/components/wiki/tocs/index.module.scss @@ -48,6 +48,7 @@ font-size: 14px; cursor: pointer; align-items: center; + color: var(--semi-color-text-0); > span { margin-right: 6px; diff --git a/packages/client/src/components/wiki/tocs/index.tsx b/packages/client/src/components/wiki/tocs/index.tsx index 55512a08..94e2da0e 100644 --- a/packages/client/src/components/wiki/tocs/index.tsx +++ b/packages/client/src/components/wiki/tocs/index.tsx @@ -1,34 +1,38 @@ +import { useMemo } from 'react'; + import { IconPlus, IconSmallTriangleDown } from '@douyinfe/semi-icons'; import { Avatar, Button, Dropdown, Skeleton, Typography } from '@douyinfe/semi-ui'; + import { IDocument } from '@think/domains'; + import cls from 'classnames'; import { DataRender } from 'components/data-render'; import { IconOverview, IconSetting } from 'components/icons'; -import { findParents } from 'components/wiki/tocs/utils'; import { useStarDocumentsInWiki, useStarWikisInOrganization } from 'data/star'; import { useWikiDetail, useWikiTocs } from 'data/wiki'; import { triggerCreateDocument } from 'event'; import Link from 'next/link'; import { useRouter } from 'next/router'; -import { useEffect, useMemo, useState } from 'react'; + +import { Tree } from './tree'; import styles from './index.module.scss'; -import { Tree } from './tree'; interface IProps { wikiId: string; - documentId?: string; docAsLink?: string; getDocLink?: (arg: IDocument) => string; } const { Text } = Typography; +const defaultGetDocLink = (document) => + `/app/org/${document.organizationId}/wiki/${document.wikiId}/doc/${document.id}`; + export const WikiTocs: React.FC = ({ wikiId, - documentId = null, docAsLink = '/app/org/[organizationId]/wiki/[wikiId]/doc/[documentId]', - getDocLink = (document) => `/app/org/${document.organizationId}/wiki/${document.wikiId}/doc/${document.id}`, + getDocLink = defaultGetDocLink, }) => { const { pathname, query } = useRouter(); const { data: wiki, loading: wikiLoading, error: wikiError } = useWikiDetail(wikiId); @@ -39,15 +43,8 @@ export const WikiTocs: React.FC = ({ loading: starDocumentsLoading, error: starDocumentsError, } = useStarDocumentsInWiki(query.organizationId, wikiId); - const [parentIds, setParentIds] = useState>([]); const otherStarWikis = useMemo(() => (starWikis || []).filter((wiki) => wiki.id !== wikiId), [starWikis, wikiId]); - useEffect(() => { - if (!tocs || !tocs.length) return; - const parentIds = findParents(tocs, documentId); - setParentIds(parentIds); - }, [tocs, documentId]); - return (
@@ -139,7 +136,9 @@ export const WikiTocs: React.FC = ({ {wiki.name} - + + +
) : ( @@ -276,15 +275,7 @@ export const WikiTocs: React.FC = ({ ( - - )} + normalContent={() => } />
@@ -315,14 +306,7 @@ export const WikiTocs: React.FC = ({ loading={tocsLoading} error={tocsError} normalContent={() => ( - + )} />
diff --git a/packages/client/src/components/wiki/tocs/manager/index.tsx b/packages/client/src/components/wiki/tocs/manager/index.tsx index 1ae3fbfe..2d0b7f70 100644 --- a/packages/client/src/components/wiki/tocs/manager/index.tsx +++ b/packages/client/src/components/wiki/tocs/manager/index.tsx @@ -1,9 +1,10 @@ -import { Banner, Button, Toast, Tree, Typography } from '@douyinfe/semi-ui'; -import { DataRender } from 'components/data-render'; -import { Resizeable } from 'components/resizeable'; -import { useWikiTocs } from 'data/wiki'; import React, { useCallback, useEffect, useState } from 'react'; +import { Banner, Button, Toast, Tree, Typography } from '@douyinfe/semi-ui'; + +import { DataRender } from 'components/data-render'; +import { useWikiTocs } from 'data/wiki'; + import styles from './index.module.scss'; interface IProps { @@ -18,7 +19,7 @@ interface IDataNode { children?: Array; } -const { Title, Text } = Typography; +const { Text } = Typography; const extractRelation = (treeData: Array) => { const res = []; @@ -41,6 +42,8 @@ const extractRelation = (treeData: Array) => { return res; }; +const marginBottomStyle = { marginBottom: 16 }; + export const WikiTocsManager: React.FC = ({ wikiId }) => { const { data: tocs, loading: tocsLoading, error: tocsError, update: updateTocs } = useWikiTocs(wikiId); @@ -105,6 +108,10 @@ export const WikiTocsManager: React.FC = ({ wikiId }) => { [treeData] ); + const renderNorContent = useCallback(() => { + return ; + }, [treeData, onDrop]); + const submit = useCallback(() => { const data = extractRelation(treeData); updateTocs(data).then(() => { @@ -121,16 +128,10 @@ export const WikiTocsManager: React.FC = ({ wikiId }) => { icon={null} closeIcon={null} description={在下方进行拖拽以重新整理目录结构} - style={{ marginBottom: 16 }} + style={marginBottomStyle} />
- { - return ; - }} - /> +
: null} + {id && v ?