mirror of https://gitee.com/answerdev/answer.git
232 lines
6.9 KiB
TypeScript
232 lines
6.9 KiB
TypeScript
import { FC, useEffect, useState } from 'react';
|
|
import {
|
|
Container,
|
|
Row,
|
|
Col,
|
|
Alert,
|
|
Badge,
|
|
Stack,
|
|
Button,
|
|
} from 'react-bootstrap';
|
|
import { Link } from 'react-router-dom';
|
|
import { useTranslation } from 'react-i18next';
|
|
|
|
import { BaseUserCard, FormatTime, Empty, DiffContent } from '@/components';
|
|
import { useReviewList, revisionAudit } from '@/services';
|
|
import { pathFactory } from '@/router/pathFactory';
|
|
import type * as Type from '@/common/interface';
|
|
|
|
const Index: FC = () => {
|
|
const { t } = useTranslation('translation', { keyPrefix: 'page_review' });
|
|
const [isLoading, setIsLoading] = useState(false);
|
|
const [noTasks, setNoTasks] = useState(false);
|
|
const [page, setPage] = useState(1);
|
|
const { data: reviewResp, mutate: mutateList } = useReviewList(page);
|
|
const ro = reviewResp?.list[0];
|
|
const { info, type, unreviewed_info } = ro || {
|
|
info: null,
|
|
type: '',
|
|
unreviewed_info: null,
|
|
};
|
|
const reviewInfo = unreviewed_info?.content;
|
|
const mutateNextPage = () => {
|
|
const count = reviewResp?.count;
|
|
if (count && page < count) {
|
|
setPage(page + 1);
|
|
} else {
|
|
setNoTasks(true);
|
|
}
|
|
};
|
|
const handlingSkip = () => {
|
|
mutateNextPage();
|
|
};
|
|
const handlingApprove = () => {
|
|
if (!unreviewed_info) {
|
|
return;
|
|
}
|
|
setIsLoading(true);
|
|
revisionAudit(unreviewed_info.id, 'approve')
|
|
.then(() => {
|
|
mutateList();
|
|
})
|
|
.catch((ex) => {
|
|
console.log('ex: ', ex);
|
|
})
|
|
.finally(() => {
|
|
setIsLoading(false);
|
|
});
|
|
};
|
|
const handlingReject = () => {
|
|
if (!unreviewed_info) {
|
|
return;
|
|
}
|
|
setIsLoading(true);
|
|
revisionAudit(unreviewed_info.id, 'reject')
|
|
.then(() => {
|
|
mutateList();
|
|
})
|
|
.catch((ex) => {
|
|
console.log('ex: ', ex);
|
|
})
|
|
.finally(() => {
|
|
setIsLoading(false);
|
|
});
|
|
};
|
|
|
|
let itemLink = '';
|
|
let itemTitle = '';
|
|
let editBadge = '';
|
|
let editSummary = unreviewed_info?.reason;
|
|
const editor = unreviewed_info?.user_info;
|
|
const editTime = unreviewed_info?.create_at;
|
|
if (type === 'question') {
|
|
itemLink = pathFactory.questionLanding(info?.object_id);
|
|
itemTitle = info?.title;
|
|
editBadge = t('question_edit');
|
|
editSummary ||= t('edit_question');
|
|
} else if (type === 'answer') {
|
|
itemLink = pathFactory.answerLanding(
|
|
// @ts-ignore
|
|
unreviewed_info.content.question_id,
|
|
unreviewed_info.object_id,
|
|
);
|
|
itemTitle = info?.title;
|
|
editBadge = t('answer_edit');
|
|
editSummary ||= t('edit_answer');
|
|
} else if (type === 'tag') {
|
|
const tagInfo = unreviewed_info.content as Type.Tag;
|
|
itemLink = pathFactory.tagLanding(tagInfo);
|
|
itemTitle = tagInfo.display_name;
|
|
editBadge = t('tag_edit');
|
|
editSummary ||= t('edit_tag');
|
|
}
|
|
useEffect(() => {
|
|
if (!reviewResp) {
|
|
return;
|
|
}
|
|
window.scrollTo({ top: 0 });
|
|
if (!reviewResp.list || !reviewResp.list.length) {
|
|
setNoTasks(true);
|
|
}
|
|
}, [reviewResp]);
|
|
return (
|
|
<Container className="pt-2 mt-4 mb-5">
|
|
<Row>
|
|
<Col lg={{ span: 7, offset: 1 }}>
|
|
<h3 className="mb-4">{t('review')}</h3>
|
|
</Col>
|
|
{!noTasks && ro && (
|
|
<>
|
|
<Col lg={{ span: 7, offset: 1 }}>
|
|
<Alert variant="secondary">
|
|
<Stack className="align-items-start">
|
|
<Badge bg="secondary" className="mb-2">
|
|
{editBadge}
|
|
</Badge>
|
|
<Link to={itemLink} target="_blank">
|
|
{itemTitle}
|
|
</Link>
|
|
<p className="mb-0">
|
|
{t('edit_summary')}: {editSummary}
|
|
</p>
|
|
</Stack>
|
|
<Stack
|
|
direction="horizontal"
|
|
gap={1}
|
|
className="align-items-baseline mt-2">
|
|
<BaseUserCard data={editor} avatarSize="24" />
|
|
{editTime && (
|
|
<FormatTime
|
|
time={editTime}
|
|
className="small text-secondary"
|
|
preFix={t('proposed')}
|
|
/>
|
|
)}
|
|
</Stack>
|
|
</Alert>
|
|
</Col>
|
|
<Col lg={{ span: 7, offset: 1 }}>
|
|
{type === 'question' &&
|
|
info &&
|
|
reviewInfo &&
|
|
'content' in reviewInfo && (
|
|
<DiffContent
|
|
className="mt-2"
|
|
objectType={type}
|
|
oldData={{
|
|
title: info.title,
|
|
original_text: info.content,
|
|
tags: info.tags,
|
|
}}
|
|
newData={{
|
|
title: reviewInfo.title,
|
|
original_text: reviewInfo.content,
|
|
tags: reviewInfo.tags,
|
|
}}
|
|
/>
|
|
)}
|
|
{type === 'answer' &&
|
|
info &&
|
|
reviewInfo &&
|
|
'content' in reviewInfo && (
|
|
<DiffContent
|
|
className="mt-2"
|
|
objectType={type}
|
|
newData={{
|
|
original_text: reviewInfo.content,
|
|
}}
|
|
oldData={{
|
|
original_text: info.content,
|
|
}}
|
|
/>
|
|
)}
|
|
{type === 'tag' && info && reviewInfo && (
|
|
<DiffContent
|
|
className="mt-2"
|
|
objectType={type}
|
|
newData={{
|
|
original_text: reviewInfo.original_text,
|
|
}}
|
|
oldData={{
|
|
original_text: info.content,
|
|
}}
|
|
opts={{ showTitle: false, showTagUrlSlug: false }}
|
|
/>
|
|
)}
|
|
</Col>
|
|
<Col lg={{ span: 7, offset: 1 }}>
|
|
<Stack direction="horizontal" gap={2} className="mt-4">
|
|
<Button
|
|
variant="outline-primary"
|
|
disabled={isLoading}
|
|
onClick={handlingApprove}>
|
|
{t('approve', { keyPrefix: 'btns' })}
|
|
</Button>
|
|
<Button
|
|
variant="outline-primary"
|
|
disabled={isLoading}
|
|
onClick={handlingReject}>
|
|
{t('reject', { keyPrefix: 'btns' })}
|
|
</Button>
|
|
<Button
|
|
variant="outline-primary"
|
|
disabled={isLoading}
|
|
onClick={handlingSkip}>
|
|
{t('skip', { keyPrefix: 'btns' })}
|
|
</Button>
|
|
</Stack>
|
|
</Col>
|
|
</>
|
|
)}
|
|
{noTasks && (
|
|
<Col lg={{ span: 7, offset: 1 }}>
|
|
<Empty>{t('empty')}</Empty>
|
|
</Col>
|
|
)}
|
|
</Row>
|
|
</Container>
|
|
);
|
|
};
|
|
|
|
export default Index;
|