refactor(slugTitle): Switch to use the slug title returned by the server

This commit is contained in:
haitao(lj)
2022-12-16 17:39:48 +08:00
parent 96a7b47923
commit e5717ba856
25 changed files with 75 additions and 48 deletions
+4
View File
@@ -54,6 +54,7 @@ export interface TagInfo extends TagBase {
}
export interface QuestionParams {
title: string;
url_title?: string;
content: string;
html: string;
tags: Tag[];
@@ -396,6 +397,7 @@ export interface SearchParams {
export interface SearchResItem {
object_type: string;
object: {
url_title?: string;
id: string;
question_id?: string;
title: string;
@@ -455,6 +457,7 @@ export interface TimelineItem {
export interface TimelineObject {
title: string;
url_title?: string;
object_type: string;
question_id: string;
answer_id: string;
@@ -470,6 +473,7 @@ export interface TimelineRes {
export interface ReviewItem {
type: 'question' | 'answer' | 'tag';
info: {
url_title?: string;
object_id: string;
title: string;
content: string;
+1 -1
View File
@@ -30,7 +30,7 @@ const HotQuestions: FC = () => {
<ListGroupItem
key={li.id}
as={Link}
to={pathFactory.questionLanding(li.id, li.title)}
to={pathFactory.questionLanding(li.id, li.url_title)}
action>
<div className="link-dark">{li.title}</div>
{li.answer_count > 0 ? (
+9 -1
View File
@@ -19,6 +19,7 @@ interface IProps {
qid: string;
aid?: string;
title: string;
slugTitle: string;
hasAnswer?: boolean;
isAccepted: boolean;
callback: (type: string) => void;
@@ -29,6 +30,7 @@ const Index: FC<IProps> = ({
qid,
aid = '',
title,
slugTitle,
isAccepted = false,
hasAnswer = false,
memberActions = [],
@@ -159,7 +161,13 @@ const Index: FC<IProps> = ({
return (
<div className="d-flex align-items-center">
<Share type={type} qid={qid} aid={aid} title={title} />
<Share
type={type}
qid={qid}
aid={aid}
title={title}
slugTitle={slugTitle}
/>
{memberActions?.map((item) => {
if (item.action === 'edit') {
return (
+1 -1
View File
@@ -123,7 +123,7 @@ const QuestionList: FC<Props> = ({ source }) => {
<ListGroup.Item key={li.id} className="border-bottom py-3 px-0">
<h5 className="text-wrap text-break">
<NavLink
to={pathFactory.questionLanding(li.id, li.title)}
to={pathFactory.questionLanding(li.id, li.url_title)}
className="link-dark">
{li.title}
{li.status === 2 ? ` [${t('closed')}]` : ''}
+8 -4
View File
@@ -13,21 +13,25 @@ interface IProps {
qid: any;
aid?: any;
title: string;
slugTitle: string;
}
const Index: FC<IProps> = ({ type, qid, aid, title }) => {
const Index: FC<IProps> = ({ type, qid, aid, title, slugTitle = '' }) => {
const user = loggedUserInfoStore((state) => state.user);
const [show, setShow] = useState(false);
const [showTip, setShowTip] = useState(false);
const [canSystemShare, setSystemShareState] = useState(false);
const { t } = useTranslation();
// FIXME: pathFactory
let baseUrl =
type === 'question'
? `${window.location.origin}${pathFactory.questionLanding(qid, title)}`
? `${window.location.origin}${pathFactory.questionLanding(
qid,
slugTitle,
)}`
: `${window.location.origin}${pathFactory.answerLanding({
questionId: qid,
questionTitle: title,
slugTitle,
answerId: aid,
})}`;
if (user.id) {
+1 -1
View File
@@ -130,7 +130,7 @@ const Answers: FC = () => {
<a
href={pathFactory.answerLanding({
questionId: li.question_id,
questionTitle: li.question_info.title,
slugTitle: li.question_info.url_title,
answerId: li.id,
})}
target="_blank"
+1 -1
View File
@@ -102,7 +102,7 @@ const Flags: FC = () => {
<a
href={pathFactory.questionLanding(
li.question_id,
li.title,
li.url_title,
)}
target="_blank"
className="text-wrap text-break mt-2"
+1 -1
View File
@@ -137,7 +137,7 @@ const Questions: FC = () => {
<tr key={li.id}>
<td>
<a
href={pathFactory.questionLanding(li.id, li.title)}
href={pathFactory.questionLanding(li.id, li.url_title)}
target="_blank"
className="text-break text-wrap"
rel="noreferrer">
@@ -29,7 +29,7 @@ const SearchQuestion = ({ similarQuestions }) => {
as="a"
className="link-dark"
key={item.id}
href={pathFactory.questionLanding(item.id, item.title)}
href={pathFactory.questionLanding(item.id, item.url_title)}
target="_blank">
<span className="text-wrap text-break">
{item.title}
+3 -3
View File
@@ -237,7 +237,7 @@ const Ask = () => {
edit_summary: formData.edit_summary.value,
})
.then((res) => {
navigate(pathFactory.questionLanding(qid, params.title), {
navigate(pathFactory.questionLanding(qid, params.url_title), {
state: { isReview: res?.wait_for_review },
});
})
@@ -264,7 +264,7 @@ const Ask = () => {
html: editorRef2.current.getHtml(),
})
.then(() => {
navigate(pathFactory.questionLanding(id, params.title));
navigate(pathFactory.questionLanding(id, params.url_title));
})
.catch((err) => {
if (err.isError) {
@@ -273,7 +273,7 @@ const Ask = () => {
}
});
} else {
navigate(pathFactory.questionLanding(id, params.title));
navigate(pathFactory.questionLanding(id));
}
}
}
@@ -23,6 +23,7 @@ interface Props {
/** is author */
isAuthor: boolean;
questionTitle: string;
slugTitle: string;
isLogged: boolean;
callback: (type: string) => void;
}
@@ -32,6 +33,7 @@ const Index: FC<Props> = ({
isAuthor,
isLogged,
questionTitle = '',
slugTitle,
callback,
}) => {
const { t } = useTranslation('translation', {
@@ -114,6 +116,7 @@ const Index: FC<Props> = ({
type="answer"
isAccepted={data.adopted === 2}
title={questionTitle}
slugTitle={slugTitle}
callback={callback}
/>
</Col>
@@ -65,7 +65,7 @@ const Index: FC<Props> = ({ data, initPage, hasAnswer, isLogged }) => {
<Link
className="link-dark"
reloadDocument
to={pathFactory.questionLanding(data.id, data.title)}>
to={pathFactory.questionLanding(data.id, data.url_title)}>
{data.title}
{data.status === 2
? ` [${t('closed', { keyPrefix: 'question' })}]`
@@ -129,6 +129,7 @@ const Index: FC<Props> = ({ data, initPage, hasAnswer, isLogged }) => {
type="question"
memberActions={data?.member_actions}
title={data.title}
slugTitle={data.url_title}
hasAnswer={hasAnswer}
isAccepted={Boolean(data?.accepted_answer_id)}
callback={initPage}
@@ -32,7 +32,7 @@ const Index: FC<Props> = ({ id }) => {
action
key={item.id}
as={Link}
to={pathFactory.questionLanding(item.id, item.title)}>
to={pathFactory.questionLanding(item.id, item.url_title)}>
<div className="link-dark">{item.title}</div>
{item.answer_count > 0 && (
<div
+1
View File
@@ -178,6 +178,7 @@ const Index = () => {
key={item?.id}
data={item}
questionTitle={question?.title || ''}
slugTitle={question?.url_title}
isAuthor={isAuthor}
callback={initPage}
isLogged={isLogged}
+2 -2
View File
@@ -115,7 +115,7 @@ const Index = () => {
navigate(
pathFactory.answerLanding({
questionId: qid,
questionTitle: data?.question?.title,
slugTitle: data?.question?.url_title,
answerId: aid,
}),
{
@@ -147,7 +147,7 @@ const Index = () => {
<Row className="justify-content-center">
<Col xxl={7} lg={8} sm={12} className="mb-4 mb-md-0">
<a
href={pathFactory.questionLanding(qid, data?.question.title)}
href={pathFactory.questionLanding(qid, data?.question.url_title)}
target="_blank"
rel="noreferrer">
<h5 className="mb-3">{data?.question.title}</h5>
+2 -2
View File
@@ -95,7 +95,7 @@ const Index: FC = () => {
const editor = unreviewed_info?.user_info;
const editTime = unreviewed_info?.create_at;
if (type === 'question') {
itemLink = pathFactory.questionLanding(info?.object_id, info?.title);
itemLink = pathFactory.questionLanding(info?.object_id, info?.url_title);
itemTitle = info?.title;
editBadge = t('question_edit');
editSummary ||= t('edit_question');
@@ -103,7 +103,7 @@ const Index: FC = () => {
itemLink = pathFactory.answerLanding({
// @ts-ignore
questionId: unreviewed_info.content.question_id,
questionTitle: info?.title,
slugTitle: info?.url_title,
answerId: unreviewed_info.object_id,
});
itemTitle = info?.title;
@@ -15,11 +15,14 @@ const Index: FC<Props> = ({ data }) => {
if (!data?.object_type) {
return null;
}
let itemUrl = pathFactory.questionLanding(data.object.id, data.object.title);
let itemUrl = pathFactory.questionLanding(
data.object.id,
data.object.url_title,
);
if (data.object_type === 'answer' && data.object.question_id) {
itemUrl = pathFactory.answerLanding({
questionId: data.object.question_id,
questionTitle: data.object.title,
slugTitle: data.object.url_title,
answerId: data.object.id,
});
}
+2 -2
View File
@@ -48,7 +48,7 @@ const Index: FC = () => {
if (timelineData?.object_info.object_type === 'question') {
linkUrl = pathFactory.questionLanding(
timelineData?.object_info.question_id,
timelineData?.object_info.title,
timelineData?.object_info.url_title,
);
pageTitle = `${t('title_for_question')} ${timelineData?.object_info.title}`;
}
@@ -56,7 +56,7 @@ const Index: FC = () => {
if (timelineData?.object_info.object_type === 'answer') {
linkUrl = pathFactory.answerLanding({
questionId: timelineData?.object_info.question_id,
questionTitle: timelineData?.object_info.title,
slugTitle: timelineData?.object_info.url_title,
answerId: timelineData?.object_info.answer_id,
});
pageTitle = `${t('title_for_answer', {
@@ -23,7 +23,7 @@ const Index: FC<Props> = ({ visible, data }) => {
<a
href={pathFactory.answerLanding({
questionId: item.question_id,
questionTitle: item.question_info?.title,
slugTitle: item.question_info?.url_title,
answerId: item.answer_id,
})}
className="text-break">
@@ -22,10 +22,10 @@ const Index: FC<Props> = ({ visible, data }) => {
className="text-break"
href={
item.object_type === 'question'
? pathFactory.questionLanding(item.object_id, item.title)
? pathFactory.questionLanding(item.object_id, item.url_title)
: pathFactory.answerLanding({
questionId: item.question_id,
questionTitle: item.title,
slugTitle: item.url_title,
answerId: item.object_id,
})
}>
@@ -29,7 +29,7 @@ const Index: FC<Props> = ({ visible, tabName, data }) => {
className="text-break"
href={pathFactory.questionLanding(
tabName === 'questions' ? item.question_id : item.id,
item.title,
item.url_title,
)}>
{item.title}
{tabName === 'questions' && item.status === 'closed'
@@ -33,10 +33,13 @@ const Index: FC<Props> = ({ visible, data }) => {
className="text-break"
href={
item.object_type === 'question'
? pathFactory.questionLanding(item.object_id, item.title)
? pathFactory.questionLanding(
item.object_id,
item.url_title,
)
: pathFactory.answerLanding({
questionId: item.question_id,
questionTitle: item.title,
slugTitle: item.url_title,
answerId: item.object_id,
})
}>
@@ -23,10 +23,13 @@ const Index: FC<Props> = ({ data, type }) => {
type === 'answer'
? pathFactory.answerLanding({
questionId: item.question_id,
questionTitle: item.question_info?.title,
slugTitle: item.question_info?.url_title,
answerId: item.answer_id,
})
: pathFactory.questionLanding(item.question_id, item.title)
: pathFactory.questionLanding(
item.question_id,
item.url_title,
)
}>
{type === 'answer' ? item.question_info.title : item.title}
</a>
@@ -29,10 +29,13 @@ const Index: FC<Props> = ({ visible, data }) => {
className="text-break"
href={
item.object_type === 'question'
? pathFactory.questionLanding(item.question_id, item.title)
? pathFactory.questionLanding(
item.question_id,
item.url_title,
)
: pathFactory.answerLanding({
questionId: item.question_id,
questionTitle: item.title,
slugTitle: item.url_title,
answerId: item.answer_id,
})
}>
+8 -14
View File
@@ -1,6 +1,5 @@
import urlcat from 'urlcat';
import Pattern from '@/common/pattern';
import { seoSettingStore } from '@/stores';
const tagLanding = (slugName: string) => {
@@ -20,30 +19,25 @@ const tagInfo = (slugName: string) => {
const tagEdit = (tagId: string) => {
return urlcat('/tags/:tagId/edit', { tagId });
};
const questionLanding = (questionId: string, title: string = '') => {
const questionLanding = (questionId: string, slugTitle: string = '') => {
const { seo } = seoSettingStore.getState();
if (seo.permalink === 1) {
title = title.toLowerCase();
title = title.trim().replace(/\s+/g, '-');
title = title.replace(Pattern.emoji, '');
if (title) {
return urlcat('/questions/:questionId/:slugPermalink', {
questionId,
slugPermalink: title,
});
}
if (seo.permalink === 1 && slugTitle) {
return urlcat('/questions/:questionId/:slugPermalink', {
questionId,
slugPermalink: slugTitle,
});
}
return urlcat('/questions/:questionId', { questionId });
};
const answerLanding = (params: {
questionId: string;
questionTitle?: string;
slugTitle?: string;
answerId: string;
}) => {
const questionLandingUrl = questionLanding(
params.questionId,
params.questionTitle,
params.slugTitle,
);
return urlcat(`${questionLandingUrl}/:answerId`, {
answerId: params.answerId,