Skip to content

Commit

Permalink
feat: edit group reply (#426)
Browse files Browse the repository at this point in the history
Co-authored-by: Trim21 <[email protected]>
  • Loading branch information
y-young and trim21 authored Mar 24, 2023
1 parent a1aba15 commit facb65f
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 5 deletions.
12 changes: 7 additions & 5 deletions packages/design/components/Topic/Comment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -184,16 +184,18 @@ const Comment: FC<CommentProps> = ({
<Button type='secondary' size='small'>
+1
</Button>
{user.id === creator.id ? (
{user.id === creator.id && (
<>
<Button type='text' size='small'>
编辑
</Button>
{!replies?.length && (
<Button.Link type='text' size='small' to={`/group/reply/${props.id}/edit`}>
编辑
</Button.Link>
)}
<Button type='text' size='small' onClick={handleDeleteReply}>
删除
</Button>
</>
) : null}
)}
</>
)}
</div>
Expand Down
12 changes: 12 additions & 0 deletions packages/design/components/Topic/__test__/Comment.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,18 @@ describe('Normal Comment', () => {
expect(getByText('删除')).toBeInTheDocument();
});

it('hide edit button if there are subreplies', () => {
const user = { ...mockedCurrentUser, id: 1 };
const props = buildProps(false, repliesComment, '233', 233, user);
const { container } = render(<Comment {...props} />);
// 选取主评论的操作区域
const actions = container.querySelector(
'.bgm-comment__box > .bgm-comment__opinions',
)?.textContent;
expect(actions?.includes('编辑')).toBeFalsy();
expect(actions?.includes('删除')).toBeTruthy();
});

it('do not show opinions if not login', () => {
const props = buildProps(false, singleComment, '233', 233, null as any);
const { container } = render(<Comment {...props} />);
Expand Down
19 changes: 19 additions & 0 deletions packages/website/src/hooks/use-group-post.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { ok } from 'oazapfts';
import type { KeyedMutator } from 'swr';
import useSWR from 'swr';

import { ozaClient } from '@bangumi/client';

export interface UseGroupPostRet {
data: ozaClient.GroupReply;
mutate: KeyedMutator<ozaClient.GroupReply>;
}

function useGroupPost(id: number): UseGroupPostRet {
const { data, mutate } = useSWR(`/group/post/${id}`, async () => ok(ozaClient.getGroupPost(id)), {
suspense: true,
});
return { data, mutate };
}

export default useGroupPost;
12 changes: 12 additions & 0 deletions packages/website/src/pages/index/group/reply/[id].tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react';
import { Outlet } from 'react-router-dom';

import ErrorBoundary from '@bangumi/website/components/ErrorBoundary';

const GroupReplyPage = () => (
<ErrorBoundary fallback={{ 404: <>数据库中没有查询到指定话题,话题可能正在审核或已被删除。</> }}>
<Outlet />
</ErrorBoundary>
);

export default GroupReplyPage;
14 changes: 14 additions & 0 deletions packages/website/src/pages/index/group/reply/[id]/edit.module.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.form {
display: flex;
flex-direction: column;
gap: 1rem;
}

.tipText {
display: block;
margin-bottom: 10px;
}

.topicLink {
padding: 0 10px;
}
96 changes: 96 additions & 0 deletions packages/website/src/pages/index/group/reply/[id]/edit.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import type { TopicDetail } from 'packages/client/client';
import React, { useState } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { useSWRConfig } from 'swr';

import { ozaClient } from '@bangumi/client';
import { EditorForm, toast, Typography } from '@bangumi/design';
import useGroupPost from '@bangumi/website/hooks/use-group-post';
import { useUser } from '@bangumi/website/hooks/use-user';

import styles from './edit.module.less';

const EditReplyPage = () => {
const { id } = useParams();
if (!id || Number.isNaN(parseInt(id))) {
throw new Error('参数错误:post ID');
}
const postId = parseInt(id);

const { user } = useUser();
if (!user) {
throw new Error('抱歉,当前操作需要登录后才能继续进行');
}

const { data, mutate } = useGroupPost(postId);
if (data.creator.id !== user.id) {
throw new Error('抱歉,你只能修改自己发表的帖子。');
}

const { mutate: mutateTopic } = useSWRConfig();
const navigate = useNavigate();

const [sending, setSending] = useState(false);
const [content, setContent] = useState(data.text);

const handleSubmit = async (text: string) => {
if (!text) {
toast('请填写回复内容', { type: 'error' });
return;
}
setSending(true);
const response = await ozaClient.editGroupPost(postId, { text });
if (response.status === 200) {
const topicPath = `/group/topic/${data.topicID}`;
// 确保再次回到此页面时内容是最新的,不需要向后端请求数据,因此将 revalidate 设置为 false
mutate({ ...data, text }, { revalidate: false });
// 乐观更新回复内容
await mutateTopic(topicPath, (topic?: TopicDetail) => {
if (!topic) {
return topic;
}
const reply = topic.replies.find((reply) => reply.id === postId);
if (reply) {
reply.text = text;
}
return topic;
});
navigate(topicPath);
} else {
console.error(response);
toast(response.data.message, { type: 'error' });
}
setSending(false);
};

return (
<>
<Typography.Text type='secondary' className={styles.tipText}>
修改主题
<Typography.Link
to={`/group/topic/${data.topicID}`}
fontWeight='bold'
className={styles.topicLink}
>
{data.topicTitle}
</Typography.Link>
的回复
</Typography.Text>
<div className={styles.form}>
<EditorForm
placeholder='回复内容…'
hideCancel
value={content}
onChange={setContent}
onConfirm={handleSubmit}
// TODO: use loading state
confirmText={sending ? '...' : undefined}
rows={15}
/>
</div>
{/* TODO: add right column */}
</>
);
};

export default EditReplyPage;

0 comments on commit facb65f

Please sign in to comment.