mirror of https://github.com/fantasticit/think.git
refactor: format code
This commit is contained in:
parent
b14833c79f
commit
9bda18a4e5
|
@ -64,9 +64,7 @@ export const DocumentActions: React.FC<IProps> = ({
|
|||
<Space>
|
||||
<IconStar
|
||||
style={{
|
||||
color: star
|
||||
? 'rgba(var(--semi-amber-4), 1)'
|
||||
: 'rgba(var(--semi-grey-3), 1)',
|
||||
color: star ? 'rgba(var(--semi-amber-4), 1)' : 'rgba(var(--semi-grey-3), 1)',
|
||||
}}
|
||||
/>
|
||||
{text}
|
||||
|
@ -85,9 +83,7 @@ export const DocumentActions: React.FC<IProps> = ({
|
|||
</Dropdown.Menu>
|
||||
}
|
||||
>
|
||||
{children || (
|
||||
<Button onClick={prevent} icon={<IconMore />} theme="borderless" type="tertiary" />
|
||||
)}
|
||||
{children || <Button onClick={prevent} icon={<IconMore />} theme="borderless" type="tertiary" />}
|
||||
</Dropdown>
|
||||
{showCreateDocument && (
|
||||
<DocumentCreator
|
||||
|
|
|
@ -37,12 +37,7 @@ export const DocumentCard: React.FC<{ document: IDocument }> = ({ document }) =>
|
|||
<Space>
|
||||
<DocumentShare documentId={document.id} />
|
||||
<Tooltip key="edit" content="编辑" position="bottom">
|
||||
<Button
|
||||
type="tertiary"
|
||||
theme="borderless"
|
||||
icon={<IconEdit />}
|
||||
onClick={gotoEdit}
|
||||
/>
|
||||
<Button type="tertiary" theme="borderless" icon={<IconEdit />} onClick={gotoEdit} />
|
||||
</Tooltip>
|
||||
<DocumentStar documentId={document.id} />
|
||||
</Space>
|
||||
|
@ -62,10 +57,7 @@ export const DocumentCard: React.FC<{ document: IDocument }> = ({ document }) =>
|
|||
<div>
|
||||
<Text type="tertiary" size="small">
|
||||
<Space>
|
||||
<Avatar
|
||||
size="extra-extra-small"
|
||||
src={document.createUser && document.createUser.avatar}
|
||||
>
|
||||
<Avatar size="extra-extra-small" src={document.createUser && document.createUser.avatar}>
|
||||
<IconUser />
|
||||
</Avatar>
|
||||
创建者:
|
||||
|
|
|
@ -54,8 +54,7 @@ const renderChecked = (onChange, authKey: 'readable' | 'editable') => (checked,
|
|||
export const DocumentCollaboration: React.FC<IProps> = ({ wikiId, documentId }) => {
|
||||
const { user: currentUser } = useUser();
|
||||
const [visible, toggleVisible] = useToggle(false);
|
||||
const { users, loading, error, addUser, updateUser, deleteUser } =
|
||||
useCollaborationDocument(documentId);
|
||||
const { users, loading, error, addUser, updateUser, deleteUser } = useCollaborationDocument(documentId);
|
||||
const [inviteUser, setInviteUser] = useState('');
|
||||
|
||||
const [collaborationUsers, setCollaborationUsers] = useState([]);
|
||||
|
@ -126,12 +125,7 @@ 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" icon={<IconUserAdd />} onClick={toggleVisible}></Button>
|
||||
</Tooltip>
|
||||
<Modal
|
||||
title={'文档协作'}
|
||||
|
@ -146,24 +140,14 @@ export const DocumentCollaboration: React.FC<IProps> = ({ wikiId, documentId })
|
|||
<Tabs type="line">
|
||||
<TabPane tab="添加成员" itemKey="add">
|
||||
<div style={{ marginTop: 16 }}>
|
||||
<Input
|
||||
placeholder="输入对方用户名"
|
||||
value={inviteUser}
|
||||
onChange={setInviteUser}
|
||||
></Input>
|
||||
<Input placeholder="输入对方用户名" value={inviteUser} onChange={setInviteUser}></Input>
|
||||
<Paragraph style={{ marginTop: 16 }}>
|
||||
邀请成功后,请将该链接发送给对方。
|
||||
<span style={{ verticalAlign: 'middle' }}>
|
||||
<DocumentLinkCopyer wikiId={wikiId} documentId={documentId} />
|
||||
</span>
|
||||
</Paragraph>
|
||||
<Button
|
||||
theme="solid"
|
||||
block
|
||||
style={{ margin: '24px 0' }}
|
||||
disabled={!inviteUser}
|
||||
onClick={handleOk}
|
||||
>
|
||||
<Button theme="solid" block style={{ margin: '24px 0' }} disabled={!inviteUser} onClick={handleOk}>
|
||||
添加用户
|
||||
</Button>
|
||||
</div>
|
||||
|
@ -195,11 +179,7 @@ export const DocumentCollaboration: React.FC<IProps> = ({ wikiId, documentId })
|
|||
dataIndex="operate"
|
||||
key="operate"
|
||||
render={(_, document) => (
|
||||
<Popconfirm
|
||||
showArrow
|
||||
title="确认删除该成员?"
|
||||
onConfirm={() => handleDelete(document)}
|
||||
>
|
||||
<Popconfirm showArrow title="确认删除该成员?" onConfirm={() => handleDelete(document)}>
|
||||
<Button type="tertiary" theme="borderless" icon={<IconDelete />} />
|
||||
</Popconfirm>
|
||||
)}
|
||||
|
|
|
@ -15,12 +15,7 @@ interface IProps {
|
|||
|
||||
const { Text } = Typography;
|
||||
|
||||
export const CommentItem: React.FC<IProps> = ({
|
||||
comment,
|
||||
replyComment,
|
||||
editComment,
|
||||
deleteComment,
|
||||
}) => {
|
||||
export const CommentItem: React.FC<IProps> = ({ comment, replyComment, editComment, deleteComment }) => {
|
||||
if (!comment) return null;
|
||||
const { user } = useUser();
|
||||
const { createUser = {} } = comment;
|
||||
|
|
|
@ -42,12 +42,7 @@ const CommentInner = ({ data, depth, replyComment, editComment, deleteComment })
|
|||
);
|
||||
};
|
||||
|
||||
export const Comments: React.FC<IProps> = ({
|
||||
comments,
|
||||
replyComment,
|
||||
editComment,
|
||||
deleteComment,
|
||||
}) => {
|
||||
export const Comments: React.FC<IProps> = ({ comments, replyComment, editComment, deleteComment }) => {
|
||||
return (
|
||||
<CommentInner
|
||||
key={'root-menu'}
|
||||
|
|
|
@ -16,13 +16,7 @@ interface IProps {
|
|||
onCreate?: () => void;
|
||||
}
|
||||
|
||||
export const DocumentCreator: React.FC<IProps> = ({
|
||||
wikiId,
|
||||
parentDocumentId,
|
||||
visible,
|
||||
toggleVisible,
|
||||
onCreate,
|
||||
}) => {
|
||||
export const DocumentCreator: React.FC<IProps> = ({ wikiId, parentDocumentId, visible, toggleVisible, onCreate }) => {
|
||||
const { loading, create } = useCreateDocument();
|
||||
const [createChildDoc, setCreateChildDoc] = useState(false);
|
||||
const [templateId, setTemplateId] = useState('');
|
||||
|
@ -71,10 +65,7 @@ export const DocumentCreator: React.FC<IProps> = ({
|
|||
type="button"
|
||||
tabBarExtraContent={
|
||||
parentDocumentId && (
|
||||
<Checkbox
|
||||
checked={createChildDoc}
|
||||
onChange={(e) => setCreateChildDoc(e.target.checked)}
|
||||
>
|
||||
<Checkbox checked={createChildDoc} onChange={(e) => setCreateChildDoc(e.target.checked)}>
|
||||
为该文档创建子文档
|
||||
</Checkbox>
|
||||
)
|
||||
|
|
|
@ -1,16 +1,6 @@
|
|||
import Router from 'next/router';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import {
|
||||
Layout,
|
||||
Nav,
|
||||
Skeleton,
|
||||
Typography,
|
||||
Space,
|
||||
Button,
|
||||
Tooltip,
|
||||
Spin,
|
||||
Popover,
|
||||
} from '@douyinfe/semi-ui';
|
||||
import { Layout, Nav, Skeleton, Typography, Space, Button, Tooltip, Spin, Popover } from '@douyinfe/semi-ui';
|
||||
import { IconChevronLeft, IconArticle } from '@douyinfe/semi-icons';
|
||||
import { useUser } from 'data/user';
|
||||
import { useDocumentDetail } from 'data/document';
|
||||
|
@ -42,11 +32,7 @@ export const DocumentEditor: React.FC<IProps> = ({ documentId }) => {
|
|||
}, [width]);
|
||||
|
||||
const { user } = useUser();
|
||||
const {
|
||||
data: documentAndAuth,
|
||||
loading: docAuthLoading,
|
||||
error: docAuthError,
|
||||
} = useDocumentDetail(documentId);
|
||||
const { data: documentAndAuth, loading: docAuthLoading, error: docAuthError } = useDocumentDetail(documentId);
|
||||
const { document, authority } = documentAndAuth || {};
|
||||
|
||||
const goback = useCallback(() => {
|
||||
|
@ -64,11 +50,7 @@ export const DocumentEditor: React.FC<IProps> = ({ documentId }) => {
|
|||
loading={docAuthLoading}
|
||||
error={docAuthError}
|
||||
loadingContent={
|
||||
<Skeleton
|
||||
active
|
||||
placeholder={<Skeleton.Title style={{ width: 80, marginBottom: 8 }} />}
|
||||
loading={true}
|
||||
/>
|
||||
<Skeleton active placeholder={<Skeleton.Title style={{ width: 80, marginBottom: 8 }} />} loading={true} />
|
||||
}
|
||||
normalContent={() => (
|
||||
<Text ellipsis={{ showTooltip: true }} style={{ width: ~~(windowWith / 4) }}>
|
||||
|
@ -89,11 +71,7 @@ export const DocumentEditor: React.FC<IProps> = ({ documentId }) => {
|
|||
footer={
|
||||
<Space>
|
||||
{document && authority.readable && (
|
||||
<DocumentCollaboration
|
||||
key="collaboration"
|
||||
wikiId={document.wikiId}
|
||||
documentId={documentId}
|
||||
/>
|
||||
<DocumentCollaboration key="collaboration" wikiId={document.wikiId} documentId={documentId} />
|
||||
)}
|
||||
<DocumentShare key="share" documentId={documentId} />
|
||||
<DocumentStar key="star" documentId={documentId} />
|
||||
|
|
|
@ -76,9 +76,7 @@ export const Editor: React.FC<IProps> = ({ user, documentId, document }) => {
|
|||
</div>
|
||||
<CreateUser
|
||||
document={document}
|
||||
container={() =>
|
||||
window.document.querySelector('#js-reader-container .ProseMirror .title')
|
||||
}
|
||||
container={() => window.document.querySelector('#js-reader-container .ProseMirror .title')}
|
||||
/>
|
||||
</Content>
|
||||
</>
|
||||
|
|
|
@ -1,17 +1,7 @@
|
|||
import Router from 'next/router';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import cls from 'classnames';
|
||||
import {
|
||||
Layout,
|
||||
Nav,
|
||||
Space,
|
||||
Button,
|
||||
Typography,
|
||||
Skeleton,
|
||||
Tooltip,
|
||||
Popover,
|
||||
BackTop,
|
||||
} from '@douyinfe/semi-ui';
|
||||
import { Layout, Nav, Space, Button, Typography, Skeleton, Tooltip, Popover, BackTop } from '@douyinfe/semi-ui';
|
||||
import { IconEdit, IconArticle } from '@douyinfe/semi-icons';
|
||||
import { Seo } from 'components/seo';
|
||||
import { DataRender } from 'components/data-render';
|
||||
|
@ -46,11 +36,7 @@ export const DocumentReader: React.FC<IProps> = ({ documentId }) => {
|
|||
|
||||
const { user } = useUser();
|
||||
|
||||
const {
|
||||
data: documentAndAuth,
|
||||
loading: docAuthLoading,
|
||||
error: docAuthError,
|
||||
} = useDocumentDetail(documentId);
|
||||
const { data: documentAndAuth, loading: docAuthLoading, error: docAuthError } = useDocumentDetail(documentId);
|
||||
const { document, authority } = documentAndAuth || {};
|
||||
|
||||
const gotoEdit = useCallback(() => {
|
||||
|
@ -75,11 +61,7 @@ export const DocumentReader: React.FC<IProps> = ({ documentId }) => {
|
|||
/>
|
||||
}
|
||||
normalContent={() => (
|
||||
<Text
|
||||
strong
|
||||
ellipsis={{ showTooltip: true }}
|
||||
style={{ width: ~~(windowWidth / 4) }}
|
||||
>
|
||||
<Text strong ellipsis={{ showTooltip: true }} style={{ width: ~~(windowWidth / 4) }}>
|
||||
{document.title}
|
||||
</Text>
|
||||
)}
|
||||
|
@ -88,11 +70,7 @@ export const DocumentReader: React.FC<IProps> = ({ documentId }) => {
|
|||
footer={
|
||||
<Space>
|
||||
{document && authority.readable && (
|
||||
<DocumentCollaboration
|
||||
key="collaboration"
|
||||
wikiId={document.wikiId}
|
||||
documentId={documentId}
|
||||
/>
|
||||
<DocumentCollaboration key="collaboration" wikiId={document.wikiId} documentId={documentId} />
|
||||
)}
|
||||
{authority && authority.editable && (
|
||||
<Tooltip key="edit" content="编辑" position="bottom">
|
||||
|
@ -122,12 +100,7 @@ export const DocumentReader: React.FC<IProps> = ({ documentId }) => {
|
|||
return (
|
||||
<>
|
||||
<Seo title={document.title} />
|
||||
<Editor
|
||||
key={document.id}
|
||||
user={user}
|
||||
documentId={document.id}
|
||||
document={document}
|
||||
/>
|
||||
<Editor key={document.id} user={user} documentId={document.id} document={document} />
|
||||
<div className={styles.commentWrap}>
|
||||
<CommentEditor documentId={document.id} />
|
||||
</div>
|
||||
|
|
|
@ -5,11 +5,7 @@ import { useDocumentStar } from 'data/document';
|
|||
|
||||
interface IProps {
|
||||
documentId: string;
|
||||
render?: (arg: {
|
||||
star: boolean;
|
||||
text: string;
|
||||
toggleStar: () => Promise<void>;
|
||||
}) => React.ReactNode;
|
||||
render?: (arg: { star: boolean; text: string; toggleStar: () => Promise<void> }) => React.ReactNode;
|
||||
}
|
||||
|
||||
const { Text } = Typography;
|
||||
|
|
|
@ -13,14 +13,7 @@ export const DocumentStyle = () => {
|
|||
<div className={styles.item}>
|
||||
<Text>正文大小</Text>
|
||||
<Text style={{ fontSize: '0.8em' }}> {fontSize}px</Text>
|
||||
<Slider
|
||||
min={12}
|
||||
max={24}
|
||||
step={1}
|
||||
tooltipVisible={false}
|
||||
value={fontSize}
|
||||
onChange={setFontSize}
|
||||
/>
|
||||
<Slider min={12} max={24} step={1} tooltipVisible={false} value={fontSize} onChange={setFontSize} />
|
||||
</div>
|
||||
<div className={styles.item}>
|
||||
<Text>页面尺寸</Text>
|
||||
|
|
|
@ -38,16 +38,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 = ({ active, hover, disabled, onClick, onMouseEnter, cellSize, styles, id }: CellProperties) => {
|
||||
const baseStyles = getBaseStyles(cellSize);
|
||||
const cellStyles = {
|
||||
cell: getMergedStyle(baseStyles, styles, 'cell'),
|
||||
|
|
|
@ -101,18 +101,7 @@ export const GridSelect = ({
|
|||
}
|
||||
}
|
||||
return cells;
|
||||
}, [
|
||||
rows,
|
||||
cols,
|
||||
disabled,
|
||||
activeCell.x,
|
||||
activeCell.y,
|
||||
cellSize,
|
||||
hoverCell,
|
||||
styles,
|
||||
onClick,
|
||||
onHover,
|
||||
]);
|
||||
}, [rows, cols, disabled, activeCell.x, activeCell.y, cellSize, hoverCell, styles, onClick, onHover]);
|
||||
|
||||
const baseStyles = useMemo(() => getBaseStyles(cols, cellSize), [cols, cellSize]);
|
||||
|
||||
|
|
|
@ -5,13 +5,7 @@ export const IconAddColumnAfter: React.FC<{ style?: React.CSSProperties }> = ({
|
|||
<Icon
|
||||
style={style}
|
||||
svg={
|
||||
<svg
|
||||
viewBox="0 0 1024 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="18"
|
||||
height="18"
|
||||
>
|
||||
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="18" height="18">
|
||||
<path d="M469.333333 85.333333C516.266667 85.333333 554.666667 123.733333 554.666667 170.666667L554.666667 853.333333C554.666667 900.266667 516.266667 938.666667 469.333333 938.666667L85.333333 938.666667 85.333333 85.333333 469.333333 85.333333M170.666667 426.666667 170.666667 597.333333 469.333333 597.333333 469.333333 426.666667 170.666667 426.666667M170.666667 682.666667 170.666667 853.333333 469.333333 853.333333 469.333333 682.666667 170.666667 682.666667M170.666667 170.666667 170.666667 341.333333 469.333333 341.333333 469.333333 170.666667 170.666667 170.666667M640 469.333333 768 469.333333 768 341.333333 853.333333 341.333333 853.333333 469.333333 981.333333 469.333333 981.333333 554.666667 853.333333 554.666667 853.333333 682.666667 768 682.666667 768 554.666667 640 554.666667 640 469.333333Z"></path>
|
||||
</svg>
|
||||
}
|
||||
|
|
|
@ -5,13 +5,7 @@ export const IconAddColumnBefore: React.FC<{ style?: React.CSSProperties }> = ({
|
|||
<Icon
|
||||
style={style}
|
||||
svg={
|
||||
<svg
|
||||
viewBox="0 0 1024 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="18"
|
||||
height="18"
|
||||
>
|
||||
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="18" height="18">
|
||||
<path d="M554.666667 85.333333C507.733333 85.333333 469.333333 123.733333 469.333333 170.666667L469.333333 853.333333C469.333333 900.266667 507.733333 938.666667 554.666667 938.666667L938.666667 938.666667 938.666667 85.333333 554.666667 85.333333M853.333333 426.666667 853.333333 597.333333 554.666667 597.333333 554.666667 426.666667 853.333333 426.666667M853.333333 682.666667 853.333333 853.333333 554.666667 853.333333 554.666667 682.666667 853.333333 682.666667M853.333333 170.666667 853.333333 341.333333 554.666667 341.333333 554.666667 170.666667 853.333333 170.666667M384 469.333333 256 469.333333 256 341.333333 170.666667 341.333333 170.666667 469.333333 42.666667 469.333333 42.666667 554.666667 170.666667 554.666667 170.666667 682.666667 256 682.666667 256 554.666667 384 554.666667 384 469.333333Z"></path>
|
||||
</svg>
|
||||
}
|
||||
|
|
|
@ -5,13 +5,7 @@ export const IconAddRowAfter: React.FC<{ style?: React.CSSProperties }> = ({ sty
|
|||
<Icon
|
||||
style={style}
|
||||
svg={
|
||||
<svg
|
||||
viewBox="0 0 1024 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="18"
|
||||
height="18"
|
||||
>
|
||||
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="18" height="18">
|
||||
<path
|
||||
d="M938.666667 426.666667a85.333333 85.333333 0 0 1-85.333334 85.333333H170.666667a85.333333 85.333333 0 0 1-85.333334-85.333333V128h85.333334v85.333333h170.666666V128h85.333334v85.333333h170.666666V128h85.333334v85.333333h170.666666V128h85.333334v298.666667M170.666667 426.666667h170.666666V298.666667H170.666667v128m256 0h170.666666V298.666667h-170.666666v128m426.666666 0V298.666667h-170.666666v128h170.666666m-384 170.666666h85.333334v128h128v85.333334h-128v128h-85.333334v-128H341.333333v-85.333334h128v-128z"
|
||||
fill=""
|
||||
|
|
|
@ -5,13 +5,7 @@ export const IconAddRowBefore: React.FC<{ style?: React.CSSProperties }> = ({ st
|
|||
<Icon
|
||||
style={style}
|
||||
svg={
|
||||
<svg
|
||||
viewBox="0 0 1024 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="18"
|
||||
height="18"
|
||||
>
|
||||
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="18" height="18">
|
||||
<path
|
||||
d="M938.666667 597.333333a85.333333 85.333333 0 0 0-85.333334-85.333333H170.666667a85.333333 85.333333 0 0 0-85.333334 85.333333v298.666667h85.333334v-85.333333h170.666666v85.333333h85.333334v-85.333333h170.666666v85.333333h85.333334v-85.333333h170.666666v85.333333h85.333334v-298.666667M170.666667 597.333333h170.666666v128H170.666667v-128m256 0h170.666666v128h-170.666666v-128m426.666666 0v128h-170.666666v-128h170.666666m-384-170.666666h85.333334V298.666667h128V213.333333h-128V85.333333h-85.333334v128H341.333333v85.333334h128v128z"
|
||||
fill="currentColor"
|
||||
|
|
|
@ -5,13 +5,7 @@ export const IconClear: React.FC<{ style?: React.CSSProperties }> = ({ style = {
|
|||
<Icon
|
||||
style={style}
|
||||
svg={
|
||||
<svg
|
||||
viewBox="0 0 1170 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="1em"
|
||||
height="1em"
|
||||
>
|
||||
<svg viewBox="0 0 1170 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em">
|
||||
<path
|
||||
d="M1138.249143 551.936a109.494857 109.494857 0 0 0 0-154.843429l-364.982857-364.982857a109.494857 109.494857 0 0 0-154.916572 0L34.377143 616.009143a109.494857 109.494857 0 0 0 0 154.843428l218.989714 218.989715c20.48 20.553143 48.347429 32.109714 77.385143 32.109714h812.178286a27.355429 27.355429 0 0 0 27.355428-27.428571v-91.209143a27.355429 27.355429 0 0 0-27.355428-27.355429H814.08l324.022857-324.096z m-690.468572-142.848l313.417143 313.344-153.6 153.6H345.965714L163.401143 693.394286l284.452571-284.379429z"
|
||||
fill="currentColor"
|
||||
|
|
|
@ -5,13 +5,7 @@ export const IconDeleteColumn: React.FC<{ style?: React.CSSProperties }> = ({ st
|
|||
<Icon
|
||||
style={style}
|
||||
svg={
|
||||
<svg
|
||||
viewBox="0 0 1024 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="18"
|
||||
height="18"
|
||||
>
|
||||
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="18" height="18">
|
||||
<path d="M170.666667 85.333333 469.333333 85.333333C516.266667 85.333333 554.666667 123.733333 554.666667 170.666667L554.666667 853.333333C554.666667 900.266667 516.266667 938.666667 469.333333 938.666667L170.666667 938.666667C123.733333 938.666667 85.333333 900.266667 85.333333 853.333333L85.333333 170.666667C85.333333 123.733333 123.733333 85.333333 170.666667 85.333333M170.666667 426.666667 170.666667 597.333333 469.333333 597.333333 469.333333 426.666667 170.666667 426.666667M170.666667 682.666667 170.666667 853.333333 469.333333 853.333333 469.333333 682.666667 170.666667 682.666667M170.666667 170.666667 170.666667 341.333333 469.333333 341.333333 469.333333 170.666667 170.666667 170.666667M750.506667 512 640 401.493333 700.16 341.333333 810.666667 451.84 921.173333 341.333333 981.333333 401.493333 870.826667 512 981.333333 622.506667 921.173333 682.666667 810.666667 572.16 700.16 682.666667 640 622.506667 750.506667 512Z"></path>
|
||||
</svg>
|
||||
}
|
||||
|
|
|
@ -5,13 +5,7 @@ export const IconDeleteRow: React.FC<{ style?: React.CSSProperties }> = ({ style
|
|||
<Icon
|
||||
style={style}
|
||||
svg={
|
||||
<svg
|
||||
viewBox="0 0 1024 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="18"
|
||||
height="18"
|
||||
>
|
||||
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="18" height="18">
|
||||
<path d="M401.493333 554.666667 512 665.173333 622.506667 554.666667 682.666667 614.826667 572.16 725.333333 682.666667 835.84 622.506667 896 512 785.493333 401.493333 896 341.333333 835.84 451.84 725.333333 341.333333 614.826667 401.493333 554.666667M938.666667 384C938.666667 430.933333 900.266667 469.333333 853.333333 469.333333L170.666667 469.333333C123.733333 469.333333 85.333333 430.933333 85.333333 384L85.333333 256C85.333333 209.066667 123.733333 170.666667 170.666667 170.666667L853.333333 170.666667C900.266667 170.666667 938.666667 209.066667 938.666667 256L938.666667 384M170.666667 384 341.333333 384 341.333333 256 170.666667 256 170.666667 384M426.666667 384 597.333333 384 597.333333 256 426.666667 256 426.666667 384M682.666667 384 853.333333 384 853.333333 256 682.666667 256 682.666667 384Z"></path>
|
||||
</svg>
|
||||
}
|
||||
|
|
|
@ -5,13 +5,7 @@ export const IconDeleteTable: React.FC<{ style?: React.CSSProperties }> = ({ sty
|
|||
<Icon
|
||||
style={style}
|
||||
svg={
|
||||
<svg
|
||||
viewBox="0 0 1024 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="18"
|
||||
height="18"
|
||||
>
|
||||
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="18" height="18">
|
||||
<path d="M659.797 677.504l60.374-60.373 90.496 90.581 90.496-90.496 60.373 60.33L870.955 768l90.496 90.496-60.331 60.373-90.453-90.581-90.496 90.496-60.374-60.33L750.38 768l-90.496-90.496zM170.667 128H768a85.333 85.333 0 0 1 85.333 85.333v302.251a255.275 255.275 0 0 0-184.192 39.083H512v170.666h46.25a254.72 254.72 0 0 0-0.085 85.334H170.667a85.333 85.333 0 0 1-85.334-85.334v-512A85.333 85.333 0 0 1 170.667 128z m0 170.667v170.666h256V298.667h-256z m341.333 0v170.666h256V298.667H512z m-341.333 256v170.666h256V554.667h-256z"></path>
|
||||
</svg>
|
||||
}
|
||||
|
|
|
@ -5,13 +5,7 @@ export const IconMergeCell: React.FC<{ style?: React.CSSProperties }> = ({ style
|
|||
<Icon
|
||||
style={style}
|
||||
svg={
|
||||
<svg
|
||||
viewBox="0 0 1024 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="18"
|
||||
height="18"
|
||||
>
|
||||
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="18" height="18">
|
||||
<path d="M213.333333 426.666667H128V170.666667h341.333333v85.333333H213.333333v170.666667m597.333334 341.333333h-256v85.333333h341.333333v-256h-85.333333v170.666667M213.333333 768v-170.666667H128v256h341.333333v-85.333333H213.333333M896 170.666667h-341.333333v85.333333h256v170.666667h85.333333V170.666667M341.333333 554.666667v85.333333l128-128-128-128v85.333333H128v85.333334h213.333333m341.333334-85.333334V384l-128 128 128 128v-85.333333h213.333333v-85.333334h-213.333333z"></path>
|
||||
</svg>
|
||||
}
|
||||
|
|
|
@ -5,13 +5,7 @@ export const IconSplitCell: React.FC<{ style?: React.CSSProperties }> = ({ style
|
|||
<Icon
|
||||
style={style}
|
||||
svg={
|
||||
<svg
|
||||
viewBox="0 0 1024 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="18"
|
||||
height="18"
|
||||
>
|
||||
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="18" height="18">
|
||||
<path d="M810.016 598.016h86.016v256h-768v-256h86.016v170.016h596v-170.016zM128 170.016v256h86.016V256h596v170.016h86.016v-256h-768z m342.016 300v84h-128v86.016l-128-128 128-128v86.016h128z m212 0V384l128 128-128 128v-86.016h-128v-84h128z"></path>
|
||||
</svg>
|
||||
}
|
||||
|
|
|
@ -5,13 +5,7 @@ export const IconZoomIn: React.FC<{ style?: React.CSSProperties }> = ({ style =
|
|||
<Icon
|
||||
style={style}
|
||||
svg={
|
||||
<svg
|
||||
viewBox="0 0 1024 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
>
|
||||
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16">
|
||||
<path d="M637 443H519V309c0-4.4-3.6-8-8-8h-60c-4.4 0-8 3.6-8 8v134H325c-4.4 0-8 3.6-8 8v60c0 4.4 3.6 8 8 8h118v134c0 4.4 3.6 8 8 8h60c4.4 0 8-3.6 8-8V519h118c4.4 0 8-3.6 8-8v-60c0-4.4-3.6-8-8-8z"></path>
|
||||
<path d="M921 867L775 721c122.1-148.9 113.6-369.5-26-509-148-148.1-388.4-148.1-537 0-148.1 148.6-148.1 389 0 537 139.5 139.6 360.1 148.1 509 26l146 146c3.2 2.8 8.3 2.8 11 0l43-43c2.8-2.7 2.8-7.8 0-11zM696 696c-118.8 118.7-311.2 118.7-430 0-118.7-118.8-118.7-311.2 0-430 118.8-118.7 311.2-118.7 430 0 118.7 118.8 118.7 311.2 0 430z"></path>
|
||||
</svg>
|
||||
|
|
|
@ -5,13 +5,7 @@ export const IconZoomOut: React.FC<{ style?: React.CSSProperties }> = ({ style =
|
|||
<Icon
|
||||
style={style}
|
||||
svg={
|
||||
<svg
|
||||
viewBox="0 0 1024 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
>
|
||||
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="16" height="16">
|
||||
<path d="M637 443H325c-4.4 0-8 3.6-8 8v60c0 4.4 3.6 8 8 8h312c4.4 0 8-3.6 8-8v-60c0-4.4-3.6-8-8-8z"></path>
|
||||
<path d="M921 867L775 721c122.1-148.9 113.6-369.5-26-509-148-148.1-388.4-148.1-537 0-148.1 148.6-148.1 389 0 537 139.5 139.6 360.1 148.1 509 26l146 146c3.2 2.8 8.3 2.8 11 0l43-43c2.8-2.7 2.8-7.8 0-11zM696 696c-118.8 118.7-311.2 118.7-430 0-118.7-118.8-118.7-311.2 0-430 118.8-118.7 311.2-118.7 430 0 118.7 118.8 118.7 311.2 0 430z"></path>
|
||||
</svg>
|
||||
|
|
|
@ -29,10 +29,7 @@ const getTimeago = (date: number | string | Date) => {
|
|||
locale: zh,
|
||||
});
|
||||
|
||||
content = content
|
||||
.replace('about', '')
|
||||
.replace('less than a minute ago', 'just now')
|
||||
.replace('minute', 'min');
|
||||
content = content.replace('about', '').replace('less than a minute ago', 'just now').replace('minute', 'min');
|
||||
|
||||
return content;
|
||||
};
|
||||
|
|
|
@ -8,13 +8,7 @@ export const LogoImage = () => {
|
|||
return (
|
||||
<Link href={'/'} as={'/'}>
|
||||
<a style={{ width: 36, height: 36 }}>
|
||||
<svg
|
||||
viewBox="0 0 1024 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="36"
|
||||
height="36"
|
||||
>
|
||||
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="36" height="36">
|
||||
<path
|
||||
d="M512 959.948464A448.076077 448.076077 0 0 1 337.632578 99.243069a448.094728 448.094728 0 0 1 348.734844 825.553127 445.140995 445.140995 0 0 1-174.367422 35.152268z m0-876.27409c-236.180835 0-428.325626 192.144791-428.325626 428.305993s192.144791 428.335442 428.325626 428.335443 428.31581-192.144791 428.31581-428.335443S748.171019 83.674374 512 83.674374z"
|
||||
fill="var(--semi-color-primary)"
|
||||
|
|
|
@ -1,15 +1,6 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import Link from 'next/link';
|
||||
import {
|
||||
Typography,
|
||||
Dropdown,
|
||||
Badge,
|
||||
Button,
|
||||
Tabs,
|
||||
TabPane,
|
||||
Pagination,
|
||||
Notification,
|
||||
} from '@douyinfe/semi-ui';
|
||||
import { Typography, Dropdown, Badge, Button, Tabs, TabPane, Pagination, Notification } from '@douyinfe/semi-ui';
|
||||
import { IconMessage } from 'components/icons/IconMessage';
|
||||
import { useAllMessages, useReadMessages, useUnreadMessages } from 'data/message';
|
||||
import { EmptyBoxIllustration } from 'illustrations/empty-box';
|
||||
|
@ -21,14 +12,7 @@ import styles from './index.module.scss';
|
|||
const { Text } = Typography;
|
||||
const PAGE_SIZE = 6;
|
||||
|
||||
const MessagesRender = ({
|
||||
messageData,
|
||||
loading,
|
||||
error,
|
||||
onClick = null,
|
||||
page = 1,
|
||||
onPageChange = null,
|
||||
}) => {
|
||||
const MessagesRender = ({ messageData, loading, error, onClick = null, page = 1, onPageChange = null }) => {
|
||||
const total = (messageData && messageData.total) || 0;
|
||||
const messages = (messageData && messageData.data) || [];
|
||||
|
||||
|
@ -99,13 +83,7 @@ const MessagesRender = ({
|
|||
};
|
||||
|
||||
export const Message = () => {
|
||||
const {
|
||||
data: allMsgs,
|
||||
loading: allLoading,
|
||||
error: allError,
|
||||
page: allPage,
|
||||
setPage: allSetPage,
|
||||
} = useAllMessages();
|
||||
const { data: allMsgs, loading: allLoading, error: allError, page: allPage, setPage: allSetPage } = useAllMessages();
|
||||
const {
|
||||
data: readMsgs,
|
||||
loading: readLoading,
|
||||
|
|
|
@ -62,32 +62,11 @@ export const Resizeable: React.FC<IProps> = ({ width, height, onChange, children
|
|||
}, [width, height]);
|
||||
|
||||
return (
|
||||
<div
|
||||
id="js-resizeable-container"
|
||||
className={styles.resizable}
|
||||
ref={$container}
|
||||
style={{ width, height }}
|
||||
>
|
||||
<span
|
||||
className={styles.resizer + ' ' + styles.topLeft}
|
||||
ref={$topLeft}
|
||||
data-type={'topLeft'}
|
||||
></span>
|
||||
<span
|
||||
className={styles.resizer + ' ' + styles.topRight}
|
||||
ref={$topRight}
|
||||
data-type={'topRight'}
|
||||
></span>
|
||||
<span
|
||||
className={styles.resizer + ' ' + styles.bottomLeft}
|
||||
ref={$bottomLeft}
|
||||
data-type={'bottomLeft'}
|
||||
></span>
|
||||
<span
|
||||
className={styles.resizer + ' ' + styles.bottomRight}
|
||||
ref={$bottomRight}
|
||||
data-type={'bottomRight'}
|
||||
></span>
|
||||
<div id="js-resizeable-container" className={styles.resizable} ref={$container} style={{ width, height }}>
|
||||
<span className={styles.resizer + ' ' + styles.topLeft} ref={$topLeft} data-type={'topLeft'}></span>
|
||||
<span className={styles.resizer + ' ' + styles.topRight} ref={$topRight} data-type={'topRight'}></span>
|
||||
<span className={styles.resizer + ' ' + styles.bottomLeft} ref={$bottomLeft} data-type={'bottomLeft'}></span>
|
||||
<span className={styles.resizer + ' ' + styles.bottomRight} ref={$bottomRight} data-type={'bottomRight'}></span>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -44,8 +44,7 @@ const List: React.FC<{ data: IDocument[] }> = ({ data }) => {
|
|||
|
||||
<Text size="small" type="tertiary">
|
||||
创建者:
|
||||
{doc.createUser && doc.createUser.name} •{' '}
|
||||
<LocaleTime date={doc.updatedAt} timeago />
|
||||
{doc.createUser && doc.createUser.name} • <LocaleTime date={doc.updatedAt} timeago />
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -12,10 +12,7 @@ export const Seo: React.FC<IProps> = ({ title, needTitleSuffix = true }) => {
|
|||
return (
|
||||
<Helmet>
|
||||
<title>{needTitleSuffix ? buildTitle(title) : title}</title>
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width,initial-scale=1.0,viewport-fit=cover,maximum-scale=1"
|
||||
/>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0,viewport-fit=cover,maximum-scale=1" />
|
||||
<meta name="keyword" content={`云策文档 协作 文档 fantasticit`} />
|
||||
<meta name="description" content={`云策文档 协作 文档 fantasticit`} />
|
||||
</Helmet>
|
||||
|
|
|
@ -60,12 +60,7 @@ export const TemplateCard: React.FC<IProps> = ({
|
|||
{template.createUser && user && template.createUser.id === user.id && (
|
||||
<Space>
|
||||
<Tooltip key="edit" content="编辑模板" position="bottom">
|
||||
<Button
|
||||
type="tertiary"
|
||||
theme="borderless"
|
||||
icon={<IconEdit />}
|
||||
onClick={gotoEdit}
|
||||
/>
|
||||
<Button type="tertiary" theme="borderless" icon={<IconEdit />} onClick={gotoEdit} />
|
||||
</Tooltip>
|
||||
</Space>
|
||||
)}
|
||||
|
@ -85,10 +80,7 @@ export const TemplateCard: React.FC<IProps> = ({
|
|||
<div>
|
||||
<Text type="tertiary" size="small">
|
||||
<Space>
|
||||
<Avatar
|
||||
size="extra-extra-small"
|
||||
src={template.createUser && template.createUser.avatar}
|
||||
>
|
||||
<Avatar size="extra-extra-small" src={template.createUser && template.createUser.avatar}>
|
||||
<IconUser />
|
||||
</Avatar>
|
||||
创建者:
|
||||
|
|
|
@ -44,14 +44,7 @@ interface IProps {
|
|||
deleteTemplate: () => Promise<void>;
|
||||
}
|
||||
|
||||
export const Editor: React.FC<IProps> = ({
|
||||
user,
|
||||
data,
|
||||
loading,
|
||||
error,
|
||||
updateTemplate,
|
||||
deleteTemplate,
|
||||
}) => {
|
||||
export const Editor: React.FC<IProps> = ({ user, data, loading, error, updateTemplate, deleteTemplate }) => {
|
||||
if (!user) return null;
|
||||
const { width: windowWidth } = useWindowSize();
|
||||
const provider = useMemo(() => {
|
||||
|
@ -110,17 +103,9 @@ export const Editor: React.FC<IProps> = ({
|
|||
normalContent={() => (
|
||||
<>
|
||||
<Tooltip content="返回" position="bottom">
|
||||
<Button
|
||||
onClick={goback}
|
||||
icon={<IconChevronLeft />}
|
||||
style={{ marginRight: 16 }}
|
||||
/>
|
||||
<Button onClick={goback} icon={<IconChevronLeft />} style={{ marginRight: 16 }} />
|
||||
</Tooltip>
|
||||
<Text
|
||||
strong
|
||||
ellipsis={{ showTooltip: true }}
|
||||
style={{ width: ~~(windowWidth / 4) }}
|
||||
>
|
||||
<Text strong ellipsis={{ showTooltip: true }} style={{ width: ~~(windowWidth / 4) }}>
|
||||
{data.title}
|
||||
</Text>
|
||||
</>
|
||||
|
@ -135,11 +120,7 @@ export const Editor: React.FC<IProps> = ({
|
|||
<Tooltip position="bottom" content={isPublic ? '公开模板' : '个人模板'}>
|
||||
<Switch onChange={(v) => updateTemplate({ isPublic: v })}></Switch>
|
||||
</Tooltip>
|
||||
<Popconfirm
|
||||
title="删除模板"
|
||||
content="模板删除后不可恢复,谨慎操作!"
|
||||
onConfirm={handleDelte}
|
||||
>
|
||||
<Popconfirm title="删除模板" content="模板删除后不可恢复,谨慎操作!" onConfirm={handleDelte}>
|
||||
<Button type="danger">删除</Button>
|
||||
</Popconfirm>
|
||||
<Theme />
|
||||
|
@ -166,10 +147,7 @@ export const Editor: React.FC<IProps> = ({
|
|||
</div>
|
||||
</header>
|
||||
<main id="js-template-editor-container">
|
||||
<div
|
||||
className={cls(styles.contentWrap, editorWrapClassNames)}
|
||||
style={{ fontSize }}
|
||||
>
|
||||
<div className={cls(styles.contentWrap, editorWrapClassNames)} style={{ fontSize }}>
|
||||
<EditorContent editor={editor} />
|
||||
</div>
|
||||
<BackTop target={() => document.querySelector('#js-template-editor-container')} />
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
import React, { useState, useMemo } from 'react';
|
||||
import { List, Pagination } from '@douyinfe/semi-ui';
|
||||
import { DataRender } from 'components/data-render';
|
||||
import {
|
||||
IProps as ITemplateCardProps,
|
||||
TemplateCardPlaceholder,
|
||||
TemplateCard,
|
||||
} from 'components/template/card';
|
||||
import { IProps as ITemplateCardProps, TemplateCardPlaceholder, TemplateCard } from 'components/template/card';
|
||||
import { Empty } from 'components/empty';
|
||||
|
||||
const grid = {
|
||||
|
|
|
@ -5,12 +5,7 @@ import styles from './index.module.scss';
|
|||
export const BannerWrapper = ({ node }) => {
|
||||
return (
|
||||
<NodeViewWrapper id="js-bannber-container" className={styles.wrap}>
|
||||
<SemiBanner
|
||||
type={node.attrs.type}
|
||||
description={<NodeViewContent />}
|
||||
closeIcon={null}
|
||||
fullMode={false}
|
||||
/>
|
||||
<SemiBanner type={node.attrs.type} description={<NodeViewContent />} closeIcon={null} fullMode={false} />
|
||||
</NodeViewWrapper>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -40,9 +40,7 @@ export const DocumentChildrenWrapper = ({ editor }) => {
|
|||
<Link
|
||||
key={doc.id}
|
||||
href={{
|
||||
pathname: `${
|
||||
!isShare ? '' : '/share'
|
||||
}/wiki/[wikiId]/document/[documentId]`,
|
||||
pathname: `${!isShare ? '' : '/share'}/wiki/[wikiId]/document/[documentId]`,
|
||||
query: { wikiId: doc.wikiId, documentId: doc.id },
|
||||
}}
|
||||
>
|
||||
|
|
|
@ -14,11 +14,7 @@ export const IframeWrapper = ({ editor, node, updateAttributes }) => {
|
|||
<NodeViewContent as="div" className={styles.wrap}>
|
||||
{isEditable && (
|
||||
<div className={styles.handlerWrap}>
|
||||
<Input
|
||||
placeholder={'输入外链地址'}
|
||||
value={url}
|
||||
onChange={(url) => updateAttributes({ url })}
|
||||
></Input>
|
||||
<Input placeholder={'输入外链地址'} value={url} onChange={(url) => updateAttributes({ url })}></Input>
|
||||
</div>
|
||||
)}
|
||||
{url && (
|
||||
|
|
|
@ -97,12 +97,7 @@ export const MindWrapper = ({ editor, node, updateAttributes }) => {
|
|||
}, [isEditable]);
|
||||
|
||||
const content = (
|
||||
<div
|
||||
ref={$container}
|
||||
className={styles.renderWrap}
|
||||
tabIndex={0}
|
||||
style={{ width: '100%', height: '100%' }}
|
||||
>
|
||||
<div ref={$container} className={styles.renderWrap} tabIndex={0} style={{ width: '100%', height: '100%' }}>
|
||||
{!isEditable && (
|
||||
<div className={styles.mindHandlerWrap}>
|
||||
<Button
|
||||
|
|
|
@ -56,10 +56,7 @@ export const BackgroundColor = Extension.create<ColorOptions>({
|
|||
unsetBackgroundColor:
|
||||
() =>
|
||||
({ chain }) => {
|
||||
return chain()
|
||||
.setMark('textStyle', { backgroundColor: null })
|
||||
.removeEmptyTextStyle()
|
||||
.run();
|
||||
return chain().setMark('textStyle', { backgroundColor: null }).removeEmptyTextStyle().run();
|
||||
},
|
||||
};
|
||||
},
|
||||
|
|
|
@ -12,9 +12,7 @@ export const Blockquote = BuiltInBlockquote.extend({
|
|||
default: false,
|
||||
parseHTML: (element) => {
|
||||
const source = getMarkdownSource(element);
|
||||
const parentsIncludeBlockquote = getParents(element).some(
|
||||
(p) => p.nodeName.toLowerCase() === 'blockquote'
|
||||
);
|
||||
const parentsIncludeBlockquote = getParents(element).some((p) => p.nodeName.toLowerCase() === 'blockquote');
|
||||
|
||||
return source && !source.startsWith('>') && !parentsIncludeBlockquote;
|
||||
},
|
||||
|
|
|
@ -97,8 +97,7 @@ export const Indent = Extension.create<IndentOptions>({
|
|||
renderHTML: (attributes) => ({
|
||||
style: `margin-left: ${attributes.indent}px!important;`,
|
||||
}),
|
||||
parseHTML: (element) =>
|
||||
parseInt(element.style.marginLeft) || this.options.defaultIndentLevel,
|
||||
parseHTML: (element) => parseInt(element.style.marginLeft) || this.options.defaultIndentLevel,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -52,10 +52,7 @@ interface TextNodesWithPosition {
|
|||
const updateView = (state: EditorState<any>, dispatch: any) => dispatch(state.tr);
|
||||
|
||||
const regex = (s: string, disableRegex: boolean, caseSensitive: boolean): RegExp => {
|
||||
return RegExp(
|
||||
disableRegex ? s.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&') : s,
|
||||
caseSensitive ? 'gu' : 'gui'
|
||||
);
|
||||
return RegExp(disableRegex ? s.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&') : s, caseSensitive ? 'gu' : 'gui');
|
||||
};
|
||||
|
||||
function processSearches(
|
||||
|
@ -322,13 +319,8 @@ export const SearchNReplace = Extension.create<SearchOptions>({
|
|||
apply(ctx) {
|
||||
const { doc, docChanged } = ctx;
|
||||
|
||||
const {
|
||||
searchTerm,
|
||||
searchResultClass,
|
||||
searchResultCurrentClass,
|
||||
disableRegex,
|
||||
caseSensitive,
|
||||
} = extensionThis.options;
|
||||
const { searchTerm, searchResultClass, searchResultCurrentClass, disableRegex, caseSensitive } =
|
||||
extensionThis.options;
|
||||
|
||||
if (docChanged || searchTerm) {
|
||||
const { decorationsToReturn, results } = processSearches(
|
||||
|
|
|
@ -1,11 +1,6 @@
|
|||
import React from 'react';
|
||||
import { Button, Dropdown, Tooltip } from '@douyinfe/semi-ui';
|
||||
import {
|
||||
IconAlignLeft,
|
||||
IconAlignCenter,
|
||||
IconAlignRight,
|
||||
IconAlignJustify,
|
||||
} from '@douyinfe/semi-icons';
|
||||
import { IconAlignLeft, IconAlignCenter, IconAlignRight, IconAlignJustify } from '@douyinfe/semi-icons';
|
||||
import { isTitleActive } from '../services/isActive';
|
||||
|
||||
export const AlignMenu = ({ editor }) => {
|
||||
|
@ -32,48 +27,23 @@ export const AlignMenu = ({ editor }) => {
|
|||
render={
|
||||
<>
|
||||
<Tooltip content="左对齐">
|
||||
<Button
|
||||
onClick={toggle('left')}
|
||||
icon={<IconAlignLeft />}
|
||||
type="tertiary"
|
||||
theme="borderless"
|
||||
/>
|
||||
<Button onClick={toggle('left')} icon={<IconAlignLeft />} type="tertiary" theme="borderless" />
|
||||
</Tooltip>
|
||||
<Tooltip content="居中">
|
||||
<Button
|
||||
onClick={toggle('center')}
|
||||
icon={<IconAlignCenter />}
|
||||
type="tertiary"
|
||||
theme="borderless"
|
||||
/>
|
||||
<Button onClick={toggle('center')} icon={<IconAlignCenter />} type="tertiary" theme="borderless" />
|
||||
</Tooltip>
|
||||
<Tooltip content="右对齐">
|
||||
<Button
|
||||
onClick={toggle('right')}
|
||||
icon={<IconAlignRight />}
|
||||
type="tertiary"
|
||||
theme="borderless"
|
||||
/>
|
||||
<Button onClick={toggle('right')} icon={<IconAlignRight />} type="tertiary" theme="borderless" />
|
||||
</Tooltip>
|
||||
<Tooltip content="两端对齐">
|
||||
<Button
|
||||
onClick={toggle('justify')}
|
||||
icon={<IconAlignJustify />}
|
||||
type="tertiary"
|
||||
theme="borderless"
|
||||
/>
|
||||
<Button onClick={toggle('justify')} icon={<IconAlignJustify />} type="tertiary" theme="borderless" />
|
||||
</Tooltip>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<span>
|
||||
<Tooltip content="对齐方式" spacing={6}>
|
||||
<Button
|
||||
type="tertiary"
|
||||
theme="borderless"
|
||||
icon={current}
|
||||
disabled={isTitleActive(editor)}
|
||||
></Button>
|
||||
<Button type="tertiary" theme="borderless" icon={current} disabled={isTitleActive(editor)}></Button>
|
||||
</Tooltip>
|
||||
</span>
|
||||
</Dropdown>
|
||||
|
|
|
@ -1,11 +1,5 @@
|
|||
import { Space, Button } from '@douyinfe/semi-ui';
|
||||
import {
|
||||
IconDelete,
|
||||
IconTickCircle,
|
||||
IconAlertTriangle,
|
||||
IconClear,
|
||||
IconInfoCircle,
|
||||
} from '@douyinfe/semi-icons';
|
||||
import { IconDelete, IconTickCircle, IconAlertTriangle, IconClear, IconInfoCircle } from '@douyinfe/semi-icons';
|
||||
import { Tooltip } from 'components/tooltip';
|
||||
import { BubbleMenu } from './components/bubbleMenu';
|
||||
import { Divider } from '../components/divider';
|
||||
|
|
|
@ -41,8 +41,7 @@ export const BaseBubbleMenu: React.FC<{ editor: Editor }> = ({ editor }) => {
|
|||
className={'bubble-menu'}
|
||||
pluginKey="base-bubble-menu"
|
||||
shouldShow={() =>
|
||||
!editor.state.selection.empty &&
|
||||
OTHER_BUBBLE_MENU_TYPES.every((type) => !editor.isActive(type))
|
||||
!editor.state.selection.empty && OTHER_BUBBLE_MENU_TYPES.every((type) => !editor.isActive(type))
|
||||
}
|
||||
>
|
||||
<Space>
|
||||
|
|
|
@ -1,12 +1,6 @@
|
|||
import React from 'react';
|
||||
import { Button } from '@douyinfe/semi-ui';
|
||||
import {
|
||||
IconBold,
|
||||
IconItalic,
|
||||
IconStrikeThrough,
|
||||
IconUnderline,
|
||||
IconCode,
|
||||
} from '@douyinfe/semi-icons';
|
||||
import { IconBold, IconItalic, IconStrikeThrough, IconUnderline, IconCode } from '@douyinfe/semi-icons';
|
||||
import { Tooltip } from 'components/tooltip';
|
||||
import { isTitleActive } from '../services/isActive';
|
||||
import { ColorMenu } from './color';
|
||||
|
|
|
@ -43,12 +43,7 @@ export class BubbleMenuView {
|
|||
|
||||
public matchRenderContainer?: BubbleMenuPluginProps['matchRenderContainer'];
|
||||
|
||||
public shouldShow: Exclude<BubbleMenuPluginProps['shouldShow'], null> = ({
|
||||
view,
|
||||
state,
|
||||
from,
|
||||
to,
|
||||
}) => {
|
||||
public shouldShow: Exclude<BubbleMenuPluginProps['shouldShow'], null> = ({ view, state, from, to }) => {
|
||||
const { doc, selection } = state;
|
||||
const { empty } = selection;
|
||||
|
||||
|
@ -240,8 +235,7 @@ export class BubbleMenuView {
|
|||
|
||||
export const BubbleMenuPlugin = (options: BubbleMenuPluginProps) => {
|
||||
return new Plugin({
|
||||
key:
|
||||
typeof options.pluginKey === 'string' ? new PluginKey(options.pluginKey) : options.pluginKey,
|
||||
key: typeof options.pluginKey === 'string' ? new PluginKey(options.pluginKey) : options.pluginKey,
|
||||
view: (view) => new BubbleMenuView({ view, ...options }),
|
||||
});
|
||||
};
|
||||
|
|
|
@ -7,9 +7,7 @@ import { SearchNReplace } from '../../extensions/search';
|
|||
const { Text } = Typography;
|
||||
|
||||
export const Search = ({ editor }) => {
|
||||
const searchExtension = editor.extensionManager.extensions.find(
|
||||
(ext) => ext.name === SearchNReplace.name
|
||||
);
|
||||
const searchExtension = editor.extensionManager.extensions.find((ext) => ext.name === SearchNReplace.name);
|
||||
const currentIndex = searchExtension ? searchExtension.options.currentIndex : -1;
|
||||
const results = searchExtension ? searchExtension.options.results : [];
|
||||
const [searchValue, setSearchValue] = useState('');
|
||||
|
@ -58,16 +56,10 @@ export const Search = ({ editor }) => {
|
|||
<Button disabled={!results.length} onClick={() => editor.commands.replace()}>
|
||||
替换
|
||||
</Button>
|
||||
<Button
|
||||
disabled={!results.length}
|
||||
onClick={() => editor.commands.goToPrevSearchResult()}
|
||||
>
|
||||
<Button disabled={!results.length} onClick={() => editor.commands.goToPrevSearchResult()}>
|
||||
上一个
|
||||
</Button>
|
||||
<Button
|
||||
disabled={!results.length}
|
||||
onClick={() => editor.commands.goToNextSearchResult()}
|
||||
>
|
||||
<Button disabled={!results.length} onClick={() => editor.commands.goToNextSearchResult()}>
|
||||
下一个
|
||||
</Button>
|
||||
</Space>
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
export function getImageOriginSize(
|
||||
src: string
|
||||
): Promise<{ width: number | string; height: number | string }> {
|
||||
export function getImageOriginSize(src: string): Promise<{ width: number | string; height: number | string }> {
|
||||
return new Promise((resolve) => {
|
||||
const image = document.createElement('img');
|
||||
image.onload = function () {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
export const markInputRegex = (tag) =>
|
||||
new RegExp(`(<(${tag})((?: \\w+=".+?")+)?>([^<]+)</${tag}>)$`, 'gm');
|
||||
export const markInputRegex = (tag) => new RegExp(`(<(${tag})((?: \\w+=".+?")+)?>([^<]+)</${tag}>)$`, 'gm');
|
||||
|
||||
export const extractMarkAttributesFromMatch = ([, , , attrsString]) => {
|
||||
const attrRegex = /(\w+)="(.+?)"/g;
|
||||
|
|
|
@ -28,11 +28,7 @@ const tableMap = new WeakMap();
|
|||
export function isPlainURL(link, parent, index, side) {
|
||||
if (link.attrs.title || !/^\w+:/.test(link.attrs.href)) return false;
|
||||
const content = parent.child(index + (side < 0 ? -1 : 0));
|
||||
if (
|
||||
!content.isText ||
|
||||
content.text !== link.attrs.href ||
|
||||
content.marks[content.marks.length - 1] !== link
|
||||
)
|
||||
if (!content.isText || content.text !== link.attrs.href || content.marks[content.marks.length - 1] !== link)
|
||||
return false;
|
||||
if (index === (side < 0 ? 1 : parent.childCount - 1)) return true;
|
||||
const next = parent.child(index + (side < 0 ? -2 : 1));
|
||||
|
@ -133,8 +129,7 @@ export function openTag(tagName, attrs) {
|
|||
|
||||
str += Object.entries(attrs || {})
|
||||
.map(([key, value]) => {
|
||||
if ((ignoreAttrs[tagName] || []).includes(key) || defaultAttrs[tagName]?.[key] === value)
|
||||
return '';
|
||||
if ((ignoreAttrs[tagName] || []).includes(key) || defaultAttrs[tagName]?.[key] === value) return '';
|
||||
|
||||
return ` ${key}="${htmlEncode(value?.toString())}"`;
|
||||
})
|
||||
|
@ -162,8 +157,7 @@ function setIsInBlockTable(table, value) {
|
|||
rows.forEach((row) => tableMap.set(row, value));
|
||||
cells.forEach((cell) => {
|
||||
tableMap.set(cell, value);
|
||||
if (cell.childCount && cell.child(0).type.name === 'paragraph')
|
||||
tableMap.set(cell.child(0), value);
|
||||
if (cell.childCount && cell.child(0).type.name === 'paragraph') tableMap.set(cell.child(0), value);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -270,12 +264,7 @@ export function renderContent(state, node, forceRenderInline) {
|
|||
}
|
||||
}
|
||||
|
||||
export function renderHTMLNode(
|
||||
tagName,
|
||||
forceRenderInline = false,
|
||||
needNewLine = false,
|
||||
attrs = {}
|
||||
) {
|
||||
export function renderHTMLNode(tagName, forceRenderInline = false, needNewLine = false, attrs = {}) {
|
||||
return (state, node) => {
|
||||
renderTagOpen(state, tagName, Object.assign({}, node.attrs || {}, attrs));
|
||||
renderContent(state, node, forceRenderInline);
|
||||
|
|
|
@ -21,9 +21,7 @@ export const isRectSelected = (rect: any) => (selection: CellSelection) => {
|
|||
};
|
||||
|
||||
export const findTable = (selection: Selection) =>
|
||||
findParentNode((node) => node.type.spec.tableRole && node.type.spec.tableRole === 'table')(
|
||||
selection
|
||||
);
|
||||
findParentNode((node) => node.type.spec.tableRole && node.type.spec.tableRole === 'table')(selection);
|
||||
|
||||
export const isCellSelection = (selection: any) => {
|
||||
return selection instanceof CellSelection;
|
||||
|
@ -141,10 +139,7 @@ export const getCellsInTable = (selection: Selection) => {
|
|||
}
|
||||
};
|
||||
|
||||
export const findParentNodeClosestToPos = (
|
||||
$pos: ResolvedPos,
|
||||
predicate: (node: Node) => boolean
|
||||
) => {
|
||||
export const findParentNodeClosestToPos = ($pos: ResolvedPos, predicate: (node: Node) => boolean) => {
|
||||
for (let i = $pos.depth; i > 0; i--) {
|
||||
const node = $pos.node(i);
|
||||
if (predicate(node)) {
|
||||
|
@ -159,8 +154,7 @@ export const findParentNodeClosestToPos = (
|
|||
};
|
||||
|
||||
export const findCellClosestToPos = ($pos: ResolvedPos) => {
|
||||
const predicate = (node: Node) =>
|
||||
node.type.spec.tableRole && /cell/i.test(node.type.spec.tableRole);
|
||||
const predicate = (node: Node) => node.type.spec.tableRole && /cell/i.test(node.type.spec.tableRole);
|
||||
return findParentNodeClosestToPos($pos, predicate);
|
||||
};
|
||||
|
||||
|
|
|
@ -3,9 +3,7 @@ import { NodeType, Schema } from 'prosemirror-model';
|
|||
export function getNodeType(nameOrType: string | NodeType, schema: Schema): NodeType {
|
||||
if (typeof nameOrType === 'string') {
|
||||
if (!schema.nodes[nameOrType]) {
|
||||
throw Error(
|
||||
`There is no node type named '${nameOrType}'. Maybe you forgot to add the extension?`
|
||||
);
|
||||
throw Error(`There is no node type named '${nameOrType}'. Maybe you forgot to add the extension?`);
|
||||
}
|
||||
|
||||
return schema.nodes[nameOrType];
|
||||
|
|
|
@ -11,22 +11,11 @@ interface IProps {
|
|||
position?: Position;
|
||||
}
|
||||
|
||||
export const Tooltip: React.FC<IProps> = ({
|
||||
content,
|
||||
hideOnClick = false,
|
||||
position = 'top',
|
||||
children,
|
||||
}) => {
|
||||
export const Tooltip: React.FC<IProps> = ({ content, hideOnClick = false, position = 'top', children }) => {
|
||||
const [visible, toggleVisible] = useToggle(false);
|
||||
|
||||
return (
|
||||
<SemiTooltip
|
||||
visible={visible}
|
||||
content={content}
|
||||
zIndex={10000}
|
||||
trigger={'custom'}
|
||||
position={position}
|
||||
>
|
||||
<SemiTooltip visible={visible} content={content} zIndex={10000} trigger={'custom'} position={position}>
|
||||
<span
|
||||
onMouseEnter={() => {
|
||||
toggleVisible(true);
|
||||
|
|
|
@ -65,12 +65,7 @@ export const UserSetting: React.FC<IProps> = ({ visible, toggleVisible }) => {
|
|||
disabled
|
||||
placeholder="请输入账户名称"
|
||||
></Form.Input>
|
||||
<Form.Input
|
||||
label="邮箱"
|
||||
field="email"
|
||||
style={{ width: '100%' }}
|
||||
placeholder="请输入账户邮箱"
|
||||
></Form.Input>
|
||||
<Form.Input label="邮箱" field="email" style={{ width: '100%' }} placeholder="请输入账户邮箱"></Form.Input>
|
||||
</Form>
|
||||
</Modal>
|
||||
);
|
||||
|
|
|
@ -21,9 +21,7 @@ export const WikiOrDocumentCreator: React.FC<IProps> = ({ onCreateDocument, chil
|
|||
render={
|
||||
<Dropdown.Menu>
|
||||
<Dropdown.Item onClick={toggleVisible}>知识库</Dropdown.Item>
|
||||
{wikiId && (
|
||||
<Dropdown.Item onClick={toggleCreateDocumentModalVisible}>文档</Dropdown.Item>
|
||||
)}
|
||||
{wikiId && <Dropdown.Item onClick={toggleCreateDocumentModalVisible}>文档</Dropdown.Item>}
|
||||
</Dropdown.Menu>
|
||||
}
|
||||
>
|
||||
|
|
|
@ -9,10 +9,7 @@ import styles from './index.module.scss';
|
|||
|
||||
const { Text, Paragraph } = Typography;
|
||||
|
||||
export const WikiCard: React.FC<{ wiki: IWiki; shareMode?: boolean }> = ({
|
||||
wiki,
|
||||
shareMode = false,
|
||||
}) => {
|
||||
export const WikiCard: React.FC<{ wiki: IWiki; shareMode?: boolean }> = ({ wiki, shareMode = false }) => {
|
||||
return (
|
||||
<div className={styles.cardWrap}>
|
||||
<Link
|
||||
|
|
|
@ -29,17 +29,8 @@ export const WikiCreator: React.FC<IProps> = ({ visible, toggleVisible }) => {
|
|||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title="创建知识库"
|
||||
visible={visible}
|
||||
onOk={handleOk}
|
||||
onCancel={handleCancel}
|
||||
style={{ maxWidth: '96vw' }}
|
||||
>
|
||||
<Form
|
||||
initValues={{ name: '', description: '' }}
|
||||
getFormApi={(formApi) => ($form.current = formApi)}
|
||||
>
|
||||
<Modal title="创建知识库" visible={visible} onOk={handleOk} onCancel={handleCancel} style={{ maxWidth: '96vw' }}>
|
||||
<Form initValues={{ name: '', description: '' }} getFormApi={(formApi) => ($form.current = formApi)}>
|
||||
<Form.Input
|
||||
noLabel
|
||||
autofocus
|
||||
|
|
|
@ -67,11 +67,7 @@ export const Base: React.FC<IProps> = ({ wiki, update }) => {
|
|||
<div className={styles.placeholderWrapper}>
|
||||
{WIKI_AVATARS.map((cover) => {
|
||||
return (
|
||||
<div
|
||||
key={cover}
|
||||
className={styles.coverPlaceholder}
|
||||
onClick={() => setCover(cover)}
|
||||
>
|
||||
<div key={cover} className={styles.coverPlaceholder} onClick={() => setCover(cover)}>
|
||||
<img src={cover} alt="系统默认图片" />
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -1,14 +1,5 @@
|
|||
import React, { useState, useMemo, useEffect, useCallback } from 'react';
|
||||
import {
|
||||
Transfer,
|
||||
Button,
|
||||
Banner,
|
||||
Typography,
|
||||
RadioGroup,
|
||||
Radio,
|
||||
Toast,
|
||||
Checkbox,
|
||||
} from '@douyinfe/semi-ui';
|
||||
import { Transfer, Button, Banner, Typography, RadioGroup, Radio, Toast, Checkbox } from '@douyinfe/semi-ui';
|
||||
import { IconClose } from '@douyinfe/semi-icons';
|
||||
import { WIKI_STATUS_LIST, isPublicDocument, isPublicWiki } from '@think/domains';
|
||||
import { useWikiDetail, useWikiTocs } from 'data/wiki';
|
||||
|
@ -23,11 +14,7 @@ interface IProps {
|
|||
}
|
||||
|
||||
export const WorkspaceDocs: React.FC<IProps> = ({ wikiId }) => {
|
||||
const {
|
||||
data: workspace,
|
||||
loading: workspaceLoading,
|
||||
toggleStatus: toggleWorkspaceStatus,
|
||||
} = useWikiDetail(wikiId);
|
||||
const { data: workspace, loading: workspaceLoading, toggleStatus: toggleWorkspaceStatus } = useWikiDetail(wikiId);
|
||||
const { data: tocs, loading } = useWikiTocs(wikiId);
|
||||
const documents = flattenTree2Array(tocs).map((d) => {
|
||||
d.label = d.title;
|
||||
|
@ -101,11 +88,7 @@ export const WorkspaceDocs: React.FC<IProps> = ({ wikiId }) => {
|
|||
bordered
|
||||
icon={null}
|
||||
style={{ marginTop: 16 }}
|
||||
title={
|
||||
<div style={{ fontWeight: 600, fontSize: '14px', lineHeight: '20px' }}>
|
||||
当前知识库已经公开
|
||||
</div>
|
||||
}
|
||||
title={<div style={{ fontWeight: 600, fontSize: '14px', lineHeight: '20px' }}>当前知识库已经公开</div>}
|
||||
description={
|
||||
isPublic && (
|
||||
<div>
|
||||
|
@ -130,11 +113,7 @@ export const WorkspaceDocs: React.FC<IProps> = ({ wikiId }) => {
|
|||
<Title className={styles.title} heading={6}>
|
||||
是否公开知识库?
|
||||
</Title>
|
||||
<RadioGroup
|
||||
direction="vertical"
|
||||
value={nextStatus}
|
||||
onChange={(e) => setNextStatus(e.target.value)}
|
||||
>
|
||||
<RadioGroup direction="vertical" value={nextStatus} onChange={(e) => setNextStatus(e.target.value)}>
|
||||
{WIKI_STATUS_LIST.map((status) => {
|
||||
return <Radio value={status.value}>{status.label}</Radio>;
|
||||
})}
|
||||
|
|
|
@ -35,11 +35,7 @@ export const AddUser: React.FC<IProps> = ({ visible, toggleVisible, onOk }) => {
|
|||
>
|
||||
<div style={{ marginTop: 16 }}>
|
||||
{userRole === WikiUserRole.admin ? (
|
||||
<Banner
|
||||
style={{ marginBottom: 16 }}
|
||||
type="warning"
|
||||
description="请谨慎操作管理员权限!"
|
||||
/>
|
||||
<Banner style={{ marginBottom: 16 }} type="warning" description="请谨慎操作管理员权限!" />
|
||||
) : null}
|
||||
<Space>
|
||||
<Select value={userRole} onChange={setUserRole} style={{ width: 120 }}>
|
||||
|
@ -55,13 +51,7 @@ export const AddUser: React.FC<IProps> = ({ visible, toggleVisible, onOk }) => {
|
|||
style={{ width: 270 }}
|
||||
></Input>
|
||||
</Space>
|
||||
<Button
|
||||
theme="solid"
|
||||
block
|
||||
style={{ margin: '24px 0' }}
|
||||
onClick={handleOk}
|
||||
disabled={!userName}
|
||||
>
|
||||
<Button theme="solid" block style={{ margin: '24px 0' }} onClick={handleOk} disabled={!userName}>
|
||||
添加成员
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
@ -29,11 +29,7 @@ export const EditUser: React.FC<IProps> = ({ visible, toggleVisible, onOk }) =>
|
|||
>
|
||||
<div style={{ marginTop: 16 }}>
|
||||
{userRole === WikiUserRole.admin ? (
|
||||
<Banner
|
||||
style={{ marginBottom: 16 }}
|
||||
type="warning"
|
||||
description="请谨慎操作管理员权限!"
|
||||
/>
|
||||
<Banner style={{ marginBottom: 16 }} type="warning" description="请谨慎操作管理员权限!" />
|
||||
) : null}
|
||||
<Select value={userRole} onChange={setUserRole} style={{ width: '100%' }}>
|
||||
{WIKI_USER_ROLES.map((wikiStatus) => {
|
||||
|
|
|
@ -67,17 +67,8 @@ export const Users: React.FC<IProps> = ({ wikiId }) => {
|
|||
align="center"
|
||||
render={(_, data) => (
|
||||
<>
|
||||
<Button
|
||||
type="tertiary"
|
||||
theme="borderless"
|
||||
icon={<IconEdit />}
|
||||
onClick={() => editUser(data)}
|
||||
/>
|
||||
<Popconfirm
|
||||
showArrow
|
||||
title="确认删除该成员?"
|
||||
onConfirm={() => deleteUser(data)}
|
||||
>
|
||||
<Button type="tertiary" theme="borderless" icon={<IconEdit />} onClick={() => editUser(data)} />
|
||||
<Popconfirm showArrow title="确认删除该成员?" onConfirm={() => deleteUser(data)}>
|
||||
<Button type="tertiary" theme="borderless" icon={<IconDelete />} />
|
||||
</Popconfirm>
|
||||
</>
|
||||
|
|
|
@ -5,11 +5,7 @@ import { useWikiStar } from 'data/wiki';
|
|||
|
||||
interface IProps {
|
||||
wikiId: string;
|
||||
render?: (arg: {
|
||||
star: boolean;
|
||||
text: string;
|
||||
toggleStar: () => Promise<void>;
|
||||
}) => React.ReactNode;
|
||||
render?: (arg: { star: boolean; text: string; toggleStar: () => Promise<void> }) => React.ReactNode;
|
||||
onChange?: () => void;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,14 +16,7 @@ interface IProps {
|
|||
hoverable?: boolean;
|
||||
}
|
||||
|
||||
export const NavItem: React.FC<IProps> = ({
|
||||
icon,
|
||||
text,
|
||||
rightNode,
|
||||
href,
|
||||
isActive = false,
|
||||
hoverable = true,
|
||||
}) => {
|
||||
export const NavItem: React.FC<IProps> = ({ icon, text, rightNode, href, isActive = false, hoverable = true }) => {
|
||||
const right = rightNode ? <span className={styles.rightWrap}>{rightNode}</span> : null;
|
||||
const content = (
|
||||
<>
|
||||
|
@ -34,11 +27,7 @@ export const NavItem: React.FC<IProps> = ({
|
|||
|
||||
return (
|
||||
<div
|
||||
className={cls(
|
||||
styles.navItemWrap,
|
||||
isActive && styles.isActive,
|
||||
hoverable && styles.hoverable
|
||||
)}
|
||||
className={cls(styles.navItemWrap, isActive && styles.isActive, hoverable && styles.hoverable)}
|
||||
style={{ marginTop: 4 }}
|
||||
>
|
||||
{href ? (
|
||||
|
|
|
@ -40,12 +40,7 @@ const extractRelation = (treeData: Array<IDataNode>) => {
|
|||
};
|
||||
|
||||
export const WikiTocsManager: React.FC<IProps> = ({ wikiId }) => {
|
||||
const {
|
||||
data: tocs,
|
||||
loading: tocsLoading,
|
||||
error: tocsError,
|
||||
update: updateTocs,
|
||||
} = useWikiTocs(wikiId);
|
||||
const { data: tocs, loading: tocsLoading, error: tocsError, update: updateTocs } = useWikiTocs(wikiId);
|
||||
|
||||
const [treeData, setTreeData] = useState([]);
|
||||
const [changed, setChanged] = useState(false);
|
||||
|
|
|
@ -56,12 +56,7 @@ const AddDocument = () => {
|
|||
}, []);
|
||||
|
||||
return (
|
||||
<DocumenCreatorForm
|
||||
wikiId={wikiId}
|
||||
parentDocumentId={documentId}
|
||||
visible={visible}
|
||||
toggleVisible={toggleVisible}
|
||||
/>
|
||||
<DocumenCreatorForm wikiId={wikiId} parentDocumentId={documentId} visible={visible} toggleVisible={toggleVisible} />
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -81,9 +81,7 @@ export const useDocumentDetail = (documentId, options = null) => {
|
|||
* @returns
|
||||
*/
|
||||
export const useRecentDocuments = () => {
|
||||
const { data, error, mutate } = useSWR<IDocument[]>('/document/recent', (url) =>
|
||||
HttpClient.get(url)
|
||||
);
|
||||
const { data, error, mutate } = useSWR<IDocument[]>('/document/recent', (url) => HttpClient.get(url));
|
||||
const loading = !data && !error;
|
||||
return { data, error, loading, refresh: mutate };
|
||||
};
|
||||
|
@ -117,9 +115,7 @@ export const useDocumentStar = (documentId) => {
|
|||
* @returns
|
||||
*/
|
||||
export const useStaredDocuments = () => {
|
||||
const { data, error, mutate } = useSWR<IDocument[]>('/collector/documents', (url) =>
|
||||
HttpClient.post(url)
|
||||
);
|
||||
const { data, error, mutate } = useSWR<IDocument[]>('/collector/documents', (url) => HttpClient.post(url));
|
||||
const loading = !data && !error;
|
||||
|
||||
return { data, error, loading, refresh: mutate };
|
||||
|
|
|
@ -47,11 +47,9 @@ export const useOwnTemplates = () => {
|
|||
};
|
||||
|
||||
export const useTemplate = (templateId) => {
|
||||
const { data, error, mutate } = useSWR<ITemplate>(
|
||||
`/template/detail/${templateId}`,
|
||||
(url) => HttpClient.get(url),
|
||||
{ revalidateOnMount: true }
|
||||
);
|
||||
const { data, error, mutate } = useSWR<ITemplate>(`/template/detail/${templateId}`, (url) => HttpClient.get(url), {
|
||||
revalidateOnMount: true,
|
||||
});
|
||||
const loading = !data && !error;
|
||||
|
||||
const updateTemplate = async (data): Promise<ITemplate> => {
|
||||
|
|
|
@ -15,9 +15,7 @@ export type IWikiUserOpeateData = {
|
|||
* @returns
|
||||
*/
|
||||
export const useAllWikis = () => {
|
||||
const { data, error } = useSWR<{ data: IWiki[]; total: number }>('/wiki/list/all', (url) =>
|
||||
HttpClient.get(url)
|
||||
);
|
||||
const { data, error } = useSWR<{ data: IWiki[]; total: number }>('/wiki/list/all', (url) => HttpClient.get(url));
|
||||
|
||||
const loading = !data && !error;
|
||||
const list = (data && data.data) || [];
|
||||
|
@ -31,9 +29,7 @@ export const useAllWikis = () => {
|
|||
* @returns
|
||||
*/
|
||||
export const useJoinWikis = () => {
|
||||
const { data, error } = useSWR<{ data: IWiki[]; total: number }>('/wiki/list/join', (url) =>
|
||||
HttpClient.get(url)
|
||||
);
|
||||
const { data, error } = useSWR<{ data: IWiki[]; total: number }>('/wiki/list/join', (url) => HttpClient.get(url));
|
||||
|
||||
const loading = !data && !error;
|
||||
const list = (data && data.data) || [];
|
||||
|
@ -47,9 +43,8 @@ export const useJoinWikis = () => {
|
|||
* @returns
|
||||
*/
|
||||
export const useOwnWikis = () => {
|
||||
const { data, error, mutate } = useSWR<{ data: IWiki[]; total: number }>(
|
||||
'/wiki/list/own',
|
||||
(url) => HttpClient.get(url)
|
||||
const { data, error, mutate } = useSWR<{ data: IWiki[]; total: number }>('/wiki/list/own', (url) =>
|
||||
HttpClient.get(url)
|
||||
);
|
||||
|
||||
const createWiki = async (data: ICreateWiki) => {
|
||||
|
@ -81,9 +76,7 @@ export const useOwnWikis = () => {
|
|||
* @returns
|
||||
*/
|
||||
export const useWikiHomeDoc = (wikiId) => {
|
||||
const { data, error } = useSWR<IDocument>('/wiki/homedoc/' + wikiId, (url) =>
|
||||
HttpClient.get(url)
|
||||
);
|
||||
const { data, error } = useSWR<IDocument>('/wiki/homedoc/' + wikiId, (url) => HttpClient.get(url));
|
||||
const loading = !data && !error;
|
||||
return { data, error, loading };
|
||||
};
|
||||
|
@ -94,9 +87,8 @@ export const useWikiHomeDoc = (wikiId) => {
|
|||
* @returns
|
||||
*/
|
||||
export const useWikiTocs = (wikiId) => {
|
||||
const { data, error, mutate } = useSWR<Array<IDocument & { createUser: IUser }>>(
|
||||
`/wiki/tocs/${wikiId}`,
|
||||
(url) => (wikiId ? HttpClient.get(url) : null)
|
||||
const { data, error, mutate } = useSWR<Array<IDocument & { createUser: IUser }>>(`/wiki/tocs/${wikiId}`, (url) =>
|
||||
wikiId ? HttpClient.get(url) : null
|
||||
);
|
||||
const loading = !data && !error;
|
||||
|
||||
|
@ -115,9 +107,8 @@ export const useWikiTocs = (wikiId) => {
|
|||
* @returns
|
||||
*/
|
||||
export const useWikiDocs = (wikiId) => {
|
||||
const { data, error, mutate } = useSWR<Array<IDocument & { createUser: IUser }>>(
|
||||
`/wiki/docs/${wikiId}`,
|
||||
(url) => HttpClient.get(url)
|
||||
const { data, error, mutate } = useSWR<Array<IDocument & { createUser: IUser }>>(`/wiki/docs/${wikiId}`, (url) =>
|
||||
HttpClient.get(url)
|
||||
);
|
||||
const loading = !data && !error;
|
||||
return { data, loading, error, refresh: mutate };
|
||||
|
@ -129,9 +120,7 @@ export const useWikiDocs = (wikiId) => {
|
|||
* @returns
|
||||
*/
|
||||
export const useWikiDetail = (wikiId) => {
|
||||
const { data, error, mutate } = useSWR<IWiki>(wikiId ? `/wiki/detail/${wikiId}` : null, (url) =>
|
||||
HttpClient.get(url)
|
||||
);
|
||||
const { data, error, mutate } = useSWR<IWiki>(wikiId ? `/wiki/detail/${wikiId}` : null, (url) => HttpClient.get(url));
|
||||
const loading = !data && !error;
|
||||
|
||||
/**
|
||||
|
@ -165,9 +154,7 @@ export const useWikiDetail = (wikiId) => {
|
|||
* @returns
|
||||
*/
|
||||
export const useWikiUsers = (wikiId) => {
|
||||
const { data, error, mutate } = useSWR<IWikiUser[]>('/wiki/user/' + wikiId, (url) =>
|
||||
HttpClient.get(url)
|
||||
);
|
||||
const { data, error, mutate } = useSWR<IWikiUser[]>('/wiki/user/' + wikiId, (url) => HttpClient.get(url));
|
||||
const loading = !data && !error;
|
||||
|
||||
const addUser = async (data: IWikiUserOpeateData) => {
|
||||
|
@ -228,11 +215,9 @@ export const useWikiStar = (wikiId) => {
|
|||
* @returns
|
||||
*/
|
||||
export const useStaredWikis = () => {
|
||||
const { data, error, mutate } = useSWR<IWiki[]>(
|
||||
'/collector/wikis',
|
||||
(url) => HttpClient.post(url),
|
||||
{ revalidateOnFocus: true }
|
||||
);
|
||||
const { data, error, mutate } = useSWR<IWiki[]>('/collector/wikis', (url) => HttpClient.post(url), {
|
||||
revalidateOnFocus: true,
|
||||
});
|
||||
const loading = !data && !error;
|
||||
|
||||
return { data, error, loading, refresh: mutate };
|
||||
|
@ -243,9 +228,7 @@ export const useStaredWikis = () => {
|
|||
* @returns
|
||||
*/
|
||||
export const usePublicWikiHomeDoc = (wikiId) => {
|
||||
const { data, error } = useSWR<IDocument>('/wiki/public/homedoc/' + wikiId, (url) =>
|
||||
HttpClient.get(url)
|
||||
);
|
||||
const { data, error } = useSWR<IDocument>('/wiki/public/homedoc/' + wikiId, (url) => HttpClient.get(url));
|
||||
const loading = !data && !error;
|
||||
return { data, error, loading };
|
||||
};
|
||||
|
@ -256,9 +239,8 @@ export const usePublicWikiHomeDoc = (wikiId) => {
|
|||
* @returns
|
||||
*/
|
||||
export const usePublicWikiDetail = (wikiId) => {
|
||||
const { data, error, mutate } = useSWR<IWiki>(
|
||||
wikiId ? `/wiki/public/detail/${wikiId}` : null,
|
||||
(url) => HttpClient.post(url)
|
||||
const { data, error, mutate } = useSWR<IWiki>(wikiId ? `/wiki/public/detail/${wikiId}` : null, (url) =>
|
||||
HttpClient.post(url)
|
||||
);
|
||||
const loading = !data && !error;
|
||||
return { data, loading, error };
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
import { useEffect } from 'react';
|
||||
|
||||
export function useClickOutside(
|
||||
ref,
|
||||
handler: { in?: (evt: MouseEvent) => void; out?: (evt: MouseEvent) => void }
|
||||
) {
|
||||
export function useClickOutside(ref, handler: { in?: (evt: MouseEvent) => void; out?: (evt: MouseEvent) => void }) {
|
||||
useEffect(() => {
|
||||
const listener = (event) => {
|
||||
if (!ref.current || ref.current.contains(event.target)) {
|
||||
|
|
|
@ -2,11 +2,7 @@ import { useState, useCallback, useEffect, useRef } from 'react';
|
|||
|
||||
type PromiseAction = (...args: any[]) => Promise<any>;
|
||||
|
||||
export function useAsyncLoading<A extends PromiseAction>(
|
||||
action: A,
|
||||
wait = 200,
|
||||
initialLoading = false
|
||||
): [A, boolean] {
|
||||
export function useAsyncLoading<A extends PromiseAction>(action: A, wait = 200, initialLoading = false): [A, boolean] {
|
||||
const timerRef = useRef<any>(null);
|
||||
const [pending, setPending] = useState(false);
|
||||
const [loading, setLoading] = useState(initialLoading);
|
||||
|
|
|
@ -130,10 +130,7 @@ export const CreateDocumentIllustration = () => {
|
|||
transform="translate(-272.47643 -213.29715)"
|
||||
fill="#2f2e41"
|
||||
/>
|
||||
<polygon
|
||||
points="564.317 448.015 555.181 451.652 536.806 418.145 550.29 412.777 564.317 448.015"
|
||||
fill="#ffb8b8"
|
||||
/>
|
||||
<polygon points="564.317 448.015 555.181 451.652 536.806 418.145 550.29 412.777 564.317 448.015" fill="#ffb8b8" />
|
||||
<path
|
||||
d="M847.91639,675.22176l-6.55162,2.608-3.63169-5.72-.53284,7.37776-17.37645,6.917a4.20417,4.20417,0,0,1-5.054-6.23686l10.06143-15.10722-2.48926-6.25334,14.94226-4.93885Z"
|
||||
transform="translate(-272.47643 -213.29715)"
|
||||
|
|
|
@ -2,13 +2,7 @@ import React from 'react';
|
|||
|
||||
export const CreateWikiIllustration = () => {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
data-name="Layer 1"
|
||||
width="200"
|
||||
height="180"
|
||||
viewBox="0 0 892 500.74997"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" width="200" height="180" viewBox="0 0 892 500.74997">
|
||||
<path
|
||||
id="b2aec908-dac2-485e-9341-1f8763a52ddc-2673"
|
||||
data-name="Path 133"
|
||||
|
@ -238,10 +232,7 @@ export const CreateWikiIllustration = () => {
|
|||
fill="#cbcbcb"
|
||||
/>
|
||||
</g>
|
||||
<polygon
|
||||
points="208.552 488.809 220.675 488.808 226.443 442.047 208.55 442.048 208.552 488.809"
|
||||
fill="#a0616a"
|
||||
/>
|
||||
<polygon points="208.552 488.809 220.675 488.808 226.443 442.047 208.55 442.048 208.552 488.809" fill="#a0616a" />
|
||||
<path
|
||||
d="M359.45946,684.47563l23.87519-.001h.001a15.216,15.216,0,0,1,15.21515,15.2149v.49443l-39.09058.00145Z"
|
||||
transform="translate(-154 -199.62501)"
|
||||
|
|
|
@ -2,12 +2,7 @@ import React from 'react';
|
|||
|
||||
export const EmptyBoxIllustration = () => {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="200"
|
||||
height="180"
|
||||
viewBox="0 0 862.70323 644.78592"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="180" viewBox="0 0 862.70323 644.78592">
|
||||
<polygon
|
||||
points="629.943 612.644 612.777 612.644 604.608 546.435 629.943 546.435 629.943 612.644"
|
||||
fill="#9e616a"
|
||||
|
@ -35,10 +30,7 @@ export const EmptyBoxIllustration = () => {
|
|||
points="599.447 425.746 597.488 456.084 603.483 585.365 631.692 580.452 637.083 488.406 599.447 425.746"
|
||||
fill="#2f2e41"
|
||||
/>
|
||||
<polygon
|
||||
points="237.445 628.211 252.796 628.21 260.098 569.001 237.443 569.002 237.445 628.211"
|
||||
fill="#ffb6b6"
|
||||
/>
|
||||
<polygon points="237.445 628.211 252.796 628.21 260.098 569.001 237.443 569.002 237.445 628.211" fill="#ffb6b6" />
|
||||
<path
|
||||
d="M402.178,750.80612l4.32074-.00018,16.86888-6.86018,9.0412,6.85913H432.41A19.26648,19.26648,0,0,1,451.67546,770.07v.62605l-49.49658.00183Z"
|
||||
transform="translate(-168.64838 -127.60704)"
|
||||
|
@ -219,10 +211,7 @@ export const EmptyBoxIllustration = () => {
|
|||
transform="translate(-168.64838 -127.60704)"
|
||||
fill="#3f3d56"
|
||||
/>
|
||||
<polygon
|
||||
points="331.25 182.533 330.99 226.1 408.116 255.488 435.813 218.284 331.25 182.533"
|
||||
fill="#3f3d56"
|
||||
/>
|
||||
<polygon points="331.25 182.533 330.99 226.1 408.116 255.488 435.813 218.284 331.25 182.533" fill="#3f3d56" />
|
||||
<path
|
||||
d="M671.13144,337.72465a5.30105,5.30105,0,0,0-2.49688-1.73654l-98.40594-32.7777a5.10582,5.10582,0,0,0-.848-.20665,5.00894,5.00894,0,0,0-.95065-.07115l.15966-.99731.98511-.71323,23.36822-16.9188,78.04053,23.91705.13549,27.05154Z"
|
||||
transform="translate(-168.64838 -127.60704)"
|
||||
|
|
|
@ -2,13 +2,7 @@ import React from 'react';
|
|||
|
||||
export const ShareIllustration = () => {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
data-name="Layer 1"
|
||||
width="240"
|
||||
height="160"
|
||||
viewBox="0 0 803 259.00001"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" width="240" height="160" viewBox="0 0 803 259.00001">
|
||||
<path
|
||||
d="M979.75635,552.5h-29.5127a4.57,4.57,0,0,0-3.49853,1.61737,6.999,6.999,0,1,0,1.80566,13.1731l2.44776,7.95416A4.6111,4.6111,0,0,0,955.40625,578.5h19.188a4.611,4.611,0,0,0,4.40722-3.25537l5.1626-16.77692A4.61179,4.61179,0,0,0,979.75635,552.5ZM945.5,566a5,5,0,0,1,0-10c.09131,0,.17627.0221.2666.02692a4.56344,4.56344,0,0,0,.06983,2.44079l2.11181,6.86475A4.9367,4.9367,0,0,1,945.5,566Z"
|
||||
transform="translate(-198.5 -320.5)"
|
||||
|
@ -114,11 +108,7 @@ export const ShareIllustration = () => {
|
|||
transform="translate(-198.5 -320.5)"
|
||||
fill="#54a9ff"
|
||||
/>
|
||||
<path
|
||||
d="M760.5,365a31,31,0,0,1,62,0v14h-62Z"
|
||||
transform="translate(-198.5 -320.5)"
|
||||
fill="#2f2e41"
|
||||
/>
|
||||
<path d="M760.5,365a31,31,0,0,1,62,0v14h-62Z" transform="translate(-198.5 -320.5)" fill="#2f2e41" />
|
||||
<path
|
||||
d="M897,570.09139v2.76436a6.10561,6.10561,0,0,1-6.10432,6.10427H687.87181a6.10561,6.10561,0,0,1-6.10432-6.10427v-2.76436a6.10559,6.10559,0,0,1,6.10432-6.10428h3.60483a5.13409,5.13409,0,0,1-.19673-1.37081V458.99507a5.12294,5.12294,0,0,1,5.11954-5.11973h185.9686a5.12294,5.12294,0,0,1,5.11953,5.11973V562.6163a4.83952,4.83952,0,0,1-.19673,1.37081h3.60483A6.10559,6.10559,0,0,1,897,570.09139Z"
|
||||
transform="translate(-198.5 -320.5)"
|
||||
|
|
|
@ -42,13 +42,7 @@ const RecentDocs = () => {
|
|||
error={error}
|
||||
normalContent={() =>
|
||||
data && data.length ? (
|
||||
<Table
|
||||
dataSource={data}
|
||||
loading={loading}
|
||||
pagination={false}
|
||||
size="small"
|
||||
style={{ marginTop: 16 }}
|
||||
>
|
||||
<Table dataSource={data} loading={loading} pagination={false} size="small" style={{ marginTop: 16 }}>
|
||||
<Column
|
||||
title="标题"
|
||||
dataIndex="title"
|
||||
|
|
|
@ -40,12 +40,7 @@ const Page: NextPage = () => {
|
|||
</Title>
|
||||
<Button onClick={handleAdd}>新建模板</Button>
|
||||
</div>
|
||||
<Tabs
|
||||
type="button"
|
||||
style={{ marginTop: 16 }}
|
||||
activeKey={tab}
|
||||
onChange={(tab) => navigate(tab)}
|
||||
>
|
||||
<Tabs type="button" style={{ marginTop: 16 }} activeKey={tab} onChange={(tab) => navigate(tab)}>
|
||||
<TabPane tab="公开模板" itemKey="public">
|
||||
<TemplateList hook={usePublicTemplates} pageSize={9} />
|
||||
</TabPane>
|
||||
|
|
|
@ -54,9 +54,7 @@ const AllDocs = ({ wikiId }) => {
|
|||
<DocumentCard document={doc} />
|
||||
</List.Item>
|
||||
)}
|
||||
emptyContent={
|
||||
<Empty illustration={<CreateDocumentIllustration />} message={<DocumentCreator />} />
|
||||
}
|
||||
emptyContent={<Empty illustration={<CreateDocumentIllustration />} message={<DocumentCreator />} />}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
|
|
@ -48,9 +48,7 @@ const Workspaces = ({ hook }) => {
|
|||
<WikiCard wiki={wiki} />
|
||||
</List.Item>
|
||||
)}
|
||||
emptyContent={
|
||||
<Empty illustration={<CreateWikiIllustration />} message={<WikiCreator />} />
|
||||
}
|
||||
emptyContent={<Empty illustration={<CreateWikiIllustration />} message={<WikiCreator />} />}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
|
|
@ -46,10 +46,7 @@ HttpClient.interceptors.response.use(
|
|||
switch (status) {
|
||||
case 504:
|
||||
case 404:
|
||||
isBrowser &&
|
||||
Toast.error(
|
||||
(err.response && err.response.data && err.response.data.message) || '服务器异常'
|
||||
);
|
||||
isBrowser && Toast.error((err.response && err.response.data && err.response.data.message) || '服务器异常');
|
||||
break;
|
||||
case 401:
|
||||
if (isBrowser) {
|
||||
|
@ -58,10 +55,7 @@ HttpClient.interceptors.response.use(
|
|||
break;
|
||||
|
||||
default:
|
||||
isBrowser &&
|
||||
Toast.error(
|
||||
(err.response && err.response.data && err.response.data.message) || '未知错误!'
|
||||
);
|
||||
isBrowser && Toast.error((err.response && err.response.data && err.response.data.message) || '未知错误!');
|
||||
}
|
||||
return Promise.reject({
|
||||
statusCode: err.response.status,
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
export const DEFAULT_WIKI_AVATAR =
|
||||
'https://wipi.oss-cn-shanghai.aliyuncs.com/2022-02-01/default0-96.png';
|
||||
export const DEFAULT_WIKI_AVATAR = 'https://wipi.oss-cn-shanghai.aliyuncs.com/2022-02-01/default0-96.png';
|
||||
|
||||
export const WIKI_AVATARS = [
|
||||
DEFAULT_WIKI_AVATAR,
|
||||
|
|
|
@ -72,5 +72,4 @@ export const getWikiUserRoleText = (role: WikiUserRole) => {
|
|||
* @param currentStatus document 实例数据的 status 字段
|
||||
* @returns
|
||||
*/
|
||||
export const isPublicDocument = (currentStatus: IDocument['status']) =>
|
||||
currentStatus === DocumentStatus.public;
|
||||
export const isPublicDocument = (currentStatus: IDocument['status']) => currentStatus === DocumentStatus.public;
|
||||
|
|
|
@ -37,11 +37,7 @@ export class DocumentController {
|
|||
@HttpCode(HttpStatus.OK)
|
||||
@UseGuards(JwtGuard)
|
||||
async getDocumentDetail(@Request() req, @Param('id') documentId) {
|
||||
return await this.documentService.getDocumentDetail(
|
||||
req.user,
|
||||
documentId,
|
||||
req.headers['user-agent']
|
||||
);
|
||||
return await this.documentService.getDocumentDetail(req.user, documentId, req.headers['user-agent']);
|
||||
}
|
||||
|
||||
@UseInterceptors(ClassSerializerInterceptor)
|
||||
|
@ -119,16 +115,8 @@ export class DocumentController {
|
|||
@UseInterceptors(ClassSerializerInterceptor)
|
||||
@Post('public/detail/:id')
|
||||
@HttpCode(HttpStatus.OK)
|
||||
async getShareDocumentDetail(
|
||||
@Request() req,
|
||||
@Param('id') documentId,
|
||||
@Body() dto: ShareDocumentDto
|
||||
) {
|
||||
return await this.documentService.getPublicDocumentDetail(
|
||||
documentId,
|
||||
dto,
|
||||
req.headers['user-agent']
|
||||
);
|
||||
async getShareDocumentDetail(@Request() req, @Param('id') documentId, @Body() dto: ShareDocumentDto) {
|
||||
return await this.documentService.getPublicDocumentDetail(documentId, dto, req.headers['user-agent']);
|
||||
}
|
||||
|
||||
@UseInterceptors(ClassSerializerInterceptor)
|
||||
|
|
|
@ -1,10 +1,4 @@
|
|||
import {
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
Entity,
|
||||
PrimaryGeneratedColumn,
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm';
|
||||
import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';
|
||||
import { CollectType } from '@think/domains';
|
||||
|
||||
@Entity('collector')
|
||||
|
|
|
@ -1,10 +1,4 @@
|
|||
import {
|
||||
Entity,
|
||||
PrimaryGeneratedColumn,
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm';
|
||||
import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from 'typeorm';
|
||||
|
||||
@Entity('comment')
|
||||
export class CommentEntity {
|
||||
|
|
|
@ -1,10 +1,4 @@
|
|||
import {
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
Entity,
|
||||
PrimaryGeneratedColumn,
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm';
|
||||
import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';
|
||||
|
||||
@Entity('document_authority')
|
||||
export class DocumentAuthorityEntity {
|
||||
|
|
|
@ -1,10 +1,4 @@
|
|||
import {
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
Entity,
|
||||
PrimaryGeneratedColumn,
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm';
|
||||
import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';
|
||||
import { Exclude } from 'class-transformer';
|
||||
import { DocumentStatus } from '@think/domains';
|
||||
|
||||
|
|
|
@ -1,10 +1,4 @@
|
|||
import {
|
||||
Entity,
|
||||
PrimaryGeneratedColumn,
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm';
|
||||
import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from 'typeorm';
|
||||
|
||||
@Entity('message')
|
||||
export class MessageEntity {
|
||||
|
|
|
@ -1,10 +1,4 @@
|
|||
import {
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
Entity,
|
||||
PrimaryGeneratedColumn,
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm';
|
||||
import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';
|
||||
|
||||
@Entity('template')
|
||||
export class TemplateEntity {
|
||||
|
|
|
@ -1,11 +1,4 @@
|
|||
import {
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
Entity,
|
||||
PrimaryGeneratedColumn,
|
||||
UpdateDateColumn,
|
||||
BeforeInsert,
|
||||
} from 'typeorm';
|
||||
import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn, BeforeInsert } from 'typeorm';
|
||||
import { Exclude } from 'class-transformer';
|
||||
import * as bcrypt from 'bcryptjs';
|
||||
import { UserRole, UserStatus } from '@think/domains';
|
||||
|
|
|
@ -1,10 +1,4 @@
|
|||
import {
|
||||
Entity,
|
||||
PrimaryGeneratedColumn,
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm';
|
||||
import { Entity, PrimaryGeneratedColumn, Column, CreateDateColumn, UpdateDateColumn } from 'typeorm';
|
||||
|
||||
@Entity('view')
|
||||
export class ViewEntity {
|
||||
|
|
|
@ -1,10 +1,4 @@
|
|||
import {
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
Entity,
|
||||
PrimaryGeneratedColumn,
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm';
|
||||
import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';
|
||||
import { WikiUserRole, WikiUserStatus } from '@think/domains';
|
||||
|
||||
@Entity('wiki_user')
|
||||
|
|
|
@ -1,10 +1,4 @@
|
|||
import {
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
Entity,
|
||||
PrimaryGeneratedColumn,
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm';
|
||||
import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm';
|
||||
import { WikiStatus } from '@think/domains';
|
||||
import { DEFAULT_WIKI_AVATAR } from '@think/constants';
|
||||
|
||||
|
|
|
@ -7,8 +7,7 @@ export class HttpResponseExceptionFilter implements ExceptionFilter {
|
|||
const response = ctx.getResponse();
|
||||
const request = ctx.getRequest();
|
||||
const url = request.originalUrl;
|
||||
const status =
|
||||
exception instanceof HttpException ? exception.getStatus() : HttpStatus.INTERNAL_SERVER_ERROR;
|
||||
const status = exception instanceof HttpException ? exception.getStatus() : HttpStatus.INTERNAL_SERVER_ERROR;
|
||||
const errorResponse = {
|
||||
statusCode: status,
|
||||
message: exception.message,
|
||||
|
|
|
@ -3,12 +3,7 @@ import { DocumentStatus } from '@think/domains';
|
|||
import { getConfig } from '@think/config';
|
||||
import * as Y from 'yjs';
|
||||
import { TiptapTransformer } from '@hocuspocus/transformer';
|
||||
import {
|
||||
Server,
|
||||
onAuthenticatePayload,
|
||||
onChangePayload,
|
||||
onLoadDocumentPayload,
|
||||
} from '@hocuspocus/server';
|
||||
import { Server, onAuthenticatePayload, onChangePayload, onLoadDocumentPayload } from '@hocuspocus/server';
|
||||
import * as lodash from 'lodash';
|
||||
import { OutUser, UserService } from '@services/user.service';
|
||||
import { TemplateService } from '@services/template.service';
|
||||
|
|
|
@ -34,20 +34,17 @@ const DOCUMENT_PLACEHOLDERS = [
|
|||
}),
|
||||
state: Buffer.from(
|
||||
new Uint8Array([
|
||||
3, 3, 221, 238, 169, 254, 11, 0, 40, 0, 150, 148, 219, 254, 3, 88, 6, 105, 110, 100, 101,
|
||||
110, 116, 1, 125, 0, 7, 0, 215, 168, 212, 201, 8, 1, 6, 4, 0, 221, 238, 169, 254, 11, 1, 15,
|
||||
230, 156, 170, 229, 145, 189, 229, 144, 141, 230, 150, 135, 230, 161, 163, 2, 215, 168, 212,
|
||||
201, 8, 0, 0, 1, 71, 150, 148, 219, 254, 3, 0, 3, 5, 116, 105, 116, 108, 101, 15, 150, 148,
|
||||
219, 254, 3, 0, 1, 1, 7, 100, 101, 102, 97, 117, 108, 116, 1, 0, 23, 129, 150, 148, 219,
|
||||
254, 3, 0, 1, 0, 63, 199, 150, 148, 219, 254, 3, 0, 150, 148, 219, 254, 3, 24, 3, 9, 112,
|
||||
97, 114, 97, 103, 114, 97, 112, 104, 40, 0, 150, 148, 219, 254, 3, 88, 9, 116, 101, 120,
|
||||
116, 65, 108, 105, 103, 110, 1, 119, 4, 108, 101, 102, 116, 1, 0, 150, 148, 219, 254, 3, 88,
|
||||
1, 0, 7, 71, 150, 148, 219, 254, 3, 90, 6, 1, 0, 150, 148, 219, 254, 3, 98, 6, 132, 150,
|
||||
148, 219, 254, 3, 104, 6, 229, 156, 168, 230, 173, 164, 129, 150, 148, 219, 254, 3, 106, 7,
|
||||
132, 150, 148, 219, 254, 3, 113, 6, 231, 188, 150, 232, 190, 145, 129, 150, 148, 219, 254,
|
||||
3, 115, 32, 132, 150, 148, 219, 254, 3, 147, 1, 9, 230, 173, 163, 230, 150, 135, 46, 46, 46,
|
||||
2, 150, 148, 219, 254, 3, 5, 0, 88, 90, 8, 99, 6, 107, 7, 116, 32, 215, 168, 212, 201, 8, 1,
|
||||
0, 1,
|
||||
3, 3, 221, 238, 169, 254, 11, 0, 40, 0, 150, 148, 219, 254, 3, 88, 6, 105, 110, 100, 101, 110, 116, 1, 125, 0,
|
||||
7, 0, 215, 168, 212, 201, 8, 1, 6, 4, 0, 221, 238, 169, 254, 11, 1, 15, 230, 156, 170, 229, 145, 189, 229, 144,
|
||||
141, 230, 150, 135, 230, 161, 163, 2, 215, 168, 212, 201, 8, 0, 0, 1, 71, 150, 148, 219, 254, 3, 0, 3, 5, 116,
|
||||
105, 116, 108, 101, 15, 150, 148, 219, 254, 3, 0, 1, 1, 7, 100, 101, 102, 97, 117, 108, 116, 1, 0, 23, 129, 150,
|
||||
148, 219, 254, 3, 0, 1, 0, 63, 199, 150, 148, 219, 254, 3, 0, 150, 148, 219, 254, 3, 24, 3, 9, 112, 97, 114, 97,
|
||||
103, 114, 97, 112, 104, 40, 0, 150, 148, 219, 254, 3, 88, 9, 116, 101, 120, 116, 65, 108, 105, 103, 110, 1, 119,
|
||||
4, 108, 101, 102, 116, 1, 0, 150, 148, 219, 254, 3, 88, 1, 0, 7, 71, 150, 148, 219, 254, 3, 90, 6, 1, 0, 150,
|
||||
148, 219, 254, 3, 98, 6, 132, 150, 148, 219, 254, 3, 104, 6, 229, 156, 168, 230, 173, 164, 129, 150, 148, 219,
|
||||
254, 3, 106, 7, 132, 150, 148, 219, 254, 3, 113, 6, 231, 188, 150, 232, 190, 145, 129, 150, 148, 219, 254, 3,
|
||||
115, 32, 132, 150, 148, 219, 254, 3, 147, 1, 9, 230, 173, 163, 230, 150, 135, 46, 46, 46, 2, 150, 148, 219, 254,
|
||||
3, 5, 0, 88, 90, 8, 99, 6, 107, 7, 116, 32, 215, 168, 212, 201, 8, 1, 0, 1,
|
||||
])
|
||||
),
|
||||
},
|
||||
|
@ -73,11 +70,7 @@ export class DocumentService {
|
|||
@Inject(forwardRef(() => ViewService))
|
||||
private readonly viewService: ViewService
|
||||
) {
|
||||
this.collaborationService = new CollaborationService(
|
||||
this.userService,
|
||||
this,
|
||||
this.templateService
|
||||
);
|
||||
this.collaborationService = new CollaborationService(this.userService, this, this.templateService);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -121,13 +114,7 @@ export class DocumentService {
|
|||
* @param param0
|
||||
* @returns
|
||||
*/
|
||||
async operateDocumentAuth({
|
||||
currentUserId,
|
||||
documentId,
|
||||
targetUserId,
|
||||
readable = false,
|
||||
editable = false,
|
||||
}) {
|
||||
async operateDocumentAuth({ currentUserId, documentId, targetUserId, readable = false, editable = false }) {
|
||||
const doc = await this.documentRepo.findOne({ id: documentId });
|
||||
if (!doc) {
|
||||
throw new HttpException('文档不存在', HttpStatus.BAD_REQUEST);
|
||||
|
@ -347,10 +334,7 @@ export class DocumentService {
|
|||
const document = await this.documentRepo.save(res);
|
||||
|
||||
// 知识库成员权限继承
|
||||
const wikiUsers = await this.wikiService.getWikiUsers(
|
||||
{ userId: user.id, wikiId: dto.wikiId },
|
||||
true
|
||||
);
|
||||
const wikiUsers = await this.wikiService.getWikiUsers({ userId: user.id, wikiId: dto.wikiId }, true);
|
||||
|
||||
await Promise.all([
|
||||
await this.operateDocumentAuth({
|
||||
|
|
|
@ -13,10 +13,7 @@ import { CreateUserDto } from '@dtos/create-user.dto';
|
|||
import { LoginUserDto } from '@dtos/login-user.dto';
|
||||
import { UpdateUserDto } from '@dtos/update-user.dto';
|
||||
|
||||
export type OutUser = Omit<
|
||||
UserEntity,
|
||||
'comparePassword' | 'encryptPassword' | 'encrypt' | 'password'
|
||||
>;
|
||||
export type OutUser = Omit<UserEntity, 'comparePassword' | 'encryptPassword' | 'encrypt' | 'password'>;
|
||||
|
||||
@Injectable()
|
||||
export class UserService {
|
||||
|
|
|
@ -531,9 +531,7 @@ export class WikiService {
|
|||
if (docIds && Array.isArray(docIds)) {
|
||||
try {
|
||||
await Promise.all(
|
||||
docIds.map((docId) =>
|
||||
this.documentService.shareDocument(user, docId, { sharePassword: '' }, nextStatus)
|
||||
)
|
||||
docIds.map((docId) => this.documentService.shareDocument(user, docId, { sharePassword: '' }, nextStatus))
|
||||
);
|
||||
} catch (err) {
|
||||
operateDocumentError = true;
|
||||
|
@ -556,9 +554,7 @@ export class WikiService {
|
|||
const ret = await this.wikiRepo.save(newData);
|
||||
return {
|
||||
...ret,
|
||||
documentOperateMessage: operateDocumentError
|
||||
? '知识库操作成功,部分文档可能无编辑权限,未能修改成功'
|
||||
: null,
|
||||
documentOperateMessage: operateDocumentError ? '知识库操作成功,部分文档可能无编辑权限,未能修改成功' : null,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue