From 13a7bffc7401ec3f3149c9e5841945eeda613ca4 Mon Sep 17 00:00:00 2001 From: shuai Date: Sun, 9 Oct 2022 18:20:19 +0800 Subject: [PATCH] fix: add QueryGroup component --- ui/src/components/QueryGroup/index.tsx | 62 +++++++++++++++++++ ui/src/components/Questions/index.tsx | 43 +++++-------- ui/src/components/index.ts | 2 + ui/src/pages/Admin/Answers/index.tsx | 41 +++--------- ui/src/pages/Admin/Flags/index.tsx | 33 +++------- ui/src/pages/Admin/Questions/index.tsx | 42 +++---------- ui/src/pages/Admin/Users/index.tsx | 37 ++++------- .../Detail/components/AnswerHead/index.tsx | 39 ++++++------ .../Search/components/SearchHead/index.tsx | 56 +++-------------- .../Search/components/SearchItem/index.tsx | 7 +-- ui/src/pages/Tags/index.tsx | 51 ++++----------- .../Personal/components/DefaultList/index.tsx | 4 +- .../Personal/components/ListHead/index.tsx | 49 +++------------ .../Personal/components/Reputation/index.tsx | 2 +- 14 files changed, 178 insertions(+), 290 deletions(-) create mode 100644 ui/src/components/QueryGroup/index.tsx diff --git a/ui/src/components/QueryGroup/index.tsx b/ui/src/components/QueryGroup/index.tsx new file mode 100644 index 00000000..05ee51c8 --- /dev/null +++ b/ui/src/components/QueryGroup/index.tsx @@ -0,0 +1,62 @@ +import { FC, memo } from 'react'; +import { ButtonGroup, Button } from 'react-bootstrap'; +import { useSearchParams } from 'react-router-dom'; +import { useTranslation } from 'react-i18next'; + +interface Props { + data: string[] | Array<{ name: string; sort: string }>; + i18nkeyPrefix: string; + currentSort: string; + sortKey?: string; + className?: string; +} + +const Index: FC = ({ + data, + currentSort = '', + sortKey = 'order', + i18nkeyPrefix = '', + className = '', +}) => { + const [searchParams, setUrlSearchParams] = useSearchParams(); + + const { t } = useTranslation('translation', { + keyPrefix: i18nkeyPrefix, + }); + + const handleParams = (order): string => { + searchParams.delete('page'); + searchParams.set(sortKey, order); + const searchStr = searchParams.toString(); + return `?${searchStr}`; + }; + + const handleClick = (e, type) => { + e.preventDefault(); + const str = handleParams(type); + setUrlSearchParams(str); + }; + + return ( + + {data.map((btn) => { + const key = typeof btn === 'string' ? btn : btn.sort; + const name = typeof btn === 'string' ? btn : btn.name; + return ( + + ); + })} + + ); +}; + +export default memo(Index); diff --git a/ui/src/components/Questions/index.tsx b/ui/src/components/Questions/index.tsx index b104a91a..6dc89f8a 100644 --- a/ui/src/components/Questions/index.tsx +++ b/ui/src/components/Questions/index.tsx @@ -1,5 +1,5 @@ import { FC } from 'react'; -import { Row, Col, ButtonGroup, Button, ListGroup } from 'react-bootstrap'; +import { Row, Col, ListGroup } from 'react-bootstrap'; import { NavLink, useParams, useSearchParams } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; @@ -12,6 +12,7 @@ import { FormatTime, Empty, BaseUserCard, + QueryGroup, } from '@answer/components'; const QuestionOrderKeys: Type.QuestionOrderBy[] = [ @@ -83,7 +84,7 @@ const QuestionLastUpdate = ({ q }) => { const QuestionList: FC = ({ source }) => { const { t } = useTranslation('translation', { keyPrefix: 'question' }); const { tagName = '' } = useParams(); - const [urlSearchParams, setUrlSearchParams] = useSearchParams(); + const [urlSearchParams] = useSearchParams(); const curOrder = urlSearchParams.get('order') || QuestionOrderKeys[0]; const curPage = Number(urlSearchParams.get('page')) || 1; const pageSize = 20; @@ -99,15 +100,15 @@ const QuestionList: FC = ({ source }) => { } const { data: listData, isLoading } = useQuestionList(reqParams); const count = listData?.count || 0; - const onOrderChange = (evt, order) => { - evt.preventDefault(); - if (order === curOrder) { - return; - } - urlSearchParams.set('page', '1'); - urlSearchParams.set('order', order); - setUrlSearchParams(urlSearchParams); - }; + // const onOrderChange = (evt, order) => { + // evt.preventDefault(); + // if (order === curOrder) { + // return; + // } + // urlSearchParams.set('page', '1'); + // urlSearchParams.set('order', order); + // setUrlSearchParams(urlSearchParams); + // }; return (
@@ -120,21 +121,11 @@ const QuestionList: FC = ({ source }) => { - - {QuestionOrderKeys.map((k) => { - return ( - - ); - })} - + diff --git a/ui/src/components/index.ts b/ui/src/components/index.ts index 99cd527d..25bdefa7 100644 --- a/ui/src/components/index.ts +++ b/ui/src/components/index.ts @@ -24,6 +24,7 @@ import PageTitle from './PageTitle'; import Empty from './Empty'; import BaseUserCard from './BaseUserCard'; import FollowingTags from './FollowingTags'; +import QueryGroup from './QueryGroup'; export { Avatar, @@ -53,5 +54,6 @@ export { BaseUserCard, FollowingTags, htmlRender, + QueryGroup, }; export type { EditorRef }; diff --git a/ui/src/pages/Admin/Answers/index.tsx b/ui/src/pages/Admin/Answers/index.tsx index 5bca3f13..0ea39a66 100644 --- a/ui/src/pages/Admin/Answers/index.tsx +++ b/ui/src/pages/Admin/Answers/index.tsx @@ -1,12 +1,5 @@ import { FC } from 'react'; -import { - ButtonGroup, - Button, - Form, - Table, - Stack, - Badge, -} from 'react-bootstrap'; +import { Button, Form, Table, Stack, Badge } from 'react-bootstrap'; import { useSearchParams } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; @@ -17,6 +10,7 @@ import { Modal, BaseUserCard, Empty, + QueryGroup, } from '@answer/components'; import { ADMIN_LIST_STATUS } from '@answer/common/constants'; import { useEditStatusModal } from '@answer/hooks'; @@ -28,7 +22,7 @@ import '../index.scss'; const answerFilterItems: Type.AdminContentsFilterBy[] = ['normal', 'deleted']; const Answers: FC = () => { - const [urlSearchParams, setUrlSearchParams] = useSearchParams(); + const [urlSearchParams] = useSearchParams(); const curFilter = urlSearchParams.get('status') || answerFilterItems[0]; const PAGE_SIZE = 20; const curPage = Number(urlSearchParams.get('page')) || 1; @@ -44,14 +38,6 @@ const Answers: FC = () => { status: curFilter as Type.AdminContentsFilterBy, }); const count = listData?.count || 0; - const onFilterChange = (filter) => { - if (filter === curFilter) { - return; - } - urlSearchParams.set('page', '1'); - urlSearchParams.set('status', filter); - setUrlSearchParams(urlSearchParams); - }; const handleCallback = (id, type) => { if (type === 'normal') { @@ -95,20 +81,13 @@ const Answers: FC = () => { <>

{t('page_title')}

- - {answerFilterItems.map((li) => { - return ( - - ); - })} - + + { const reportModal = useReportModal(refreshList); const count = listData?.count || 0; - const onFilterChange = (filter) => { - if (filter === curFilter) { - return; - } - urlSearchParams.set('page', '1'); - urlSearchParams.set('status', filter); - setUrlSearchParams(urlSearchParams); - }; + const onTypeChange = (evt) => { urlSearchParams.set('type', evt.target.value); setUrlSearchParams(urlSearchParams); @@ -64,20 +58,13 @@ const Flags: FC = () => { <>

{t('title')}

- - {flagFilterKeys.map((k) => { - return ( - - ); - })} - + + { - const [urlSearchParams, setUrlSearchParams] = useSearchParams(); + const [urlSearchParams] = useSearchParams(); const curFilter = urlSearchParams.get('status') || questionFilterItems[0]; const curPage = Number(urlSearchParams.get('page')) || 1; const { t } = useTranslation('translation', { keyPrefix: 'admin.questions' }); @@ -55,15 +49,6 @@ const Questions: FC = () => { const closeModal = useReportModal(refreshList); - const onFilterChange = (filter) => { - if (filter === curFilter) { - return; - } - urlSearchParams.set('page', '1'); - urlSearchParams.set('status', filter); - setUrlSearchParams(urlSearchParams); - }; - const handleCallback = (id, type) => { if (type === 'normal') { changeQuestionStatus(id, 'available').then(() => { @@ -115,20 +100,13 @@ const Questions: FC = () => { <>

{t('page_title')}

- - {questionFilterItems.map((li) => { - return ( - - ); - })} - + + { const { t } = useTranslation('translation', { keyPrefix: 'admin.users' }); const [userName, setUserName] = useState(''); - const [urlSearchParams, setUrlSearchParams] = useSearchParams(); + const [urlSearchParams] = useSearchParams(); const curFilter = urlSearchParams.get('filter') || UserFilterKeys[0]; const curPage = Number(urlSearchParams.get('page') || '1'); const { @@ -51,15 +52,6 @@ const Users: FC = () => { callback: refreshUsers, }); - const onFilterChange = (filter) => { - if (filter === urlSearchParams.get('filter')) { - return; - } - urlSearchParams.set('page', '1'); - urlSearchParams.set('filter', filter); - setUrlSearchParams(urlSearchParams); - }; - const handleClick = ({ user_id, status }) => { changeModal.onShow({ id: user_id, @@ -71,20 +63,13 @@ const Users: FC = () => { <>

{t('title')}

- - {UserFilterKeys.map((k) => { - return ( - - ); - })} - + + = ({ count = 0, order = 'default' }) => { const { t } = useTranslation('translation', { keyPrefix: 'question_detail.answers', }); - const location = useLocation(); + return (
= ({ count = 0, order = 'default' }) => {
{count} {t('title')}
- - - {t('score')} - - - {t('newest')} - - +
); }; diff --git a/ui/src/pages/Search/components/SearchHead/index.tsx b/ui/src/pages/Search/components/SearchHead/index.tsx index ffb20ae9..4cd420bb 100644 --- a/ui/src/pages/Search/components/SearchHead/index.tsx +++ b/ui/src/pages/Search/components/SearchHead/index.tsx @@ -1,65 +1,29 @@ import { FC, memo } from 'react'; -import { ListGroupItem, ButtonGroup, Button } from 'react-bootstrap'; -import { useSearchParams, useNavigate, useLocation } from 'react-router-dom'; +import { ListGroupItem } from 'react-bootstrap'; import { useTranslation } from 'react-i18next'; -const sortBtns = [ - { - name: 'newest', - }, - { - name: 'active', - }, - { - name: 'score', - }, -]; +import { QueryGroup } from '@answer/components'; + +const sortBtns = ['newest', 'active', 'score']; interface Props { count: number; sort: string; } const Index: FC = ({ sort, count = 0 }) => { - const [searchParams] = useSearchParams(); - const location = useLocation(); - const navigate = useNavigate(); - const { t } = useTranslation('translation', { keyPrefix: 'search.sort_btns', }); - const handleParams = (order): string => { - const basePath = location.pathname; - searchParams.delete('page'); - searchParams.set('order', order); - const searchStr = searchParams.toString(); - return `${basePath}?${searchStr}`; - }; - - const handleClick = (e, type) => { - e.preventDefault(); - const str = handleParams(type); - navigate(str); - }; - return (
{t('counts', { count, keyPrefix: 'search' })}
- - {sortBtns.map((item) => { - return ( - - ); - })} - +
); }; diff --git a/ui/src/pages/Search/components/SearchItem/index.tsx b/ui/src/pages/Search/components/SearchItem/index.tsx index 6855d1cf..d1bf5ddd 100644 --- a/ui/src/pages/Search/components/SearchItem/index.tsx +++ b/ui/src/pages/Search/components/SearchItem/index.tsx @@ -60,10 +60,9 @@ const Index: FC = ({ data }) => {
{data.object?.excerpt && ( -

+

+ {data.object.excerpt} +

)} {data.object?.tags?.map((item) => { diff --git a/ui/src/pages/Tags/index.tsx b/ui/src/pages/Tags/index.tsx index acd5a019..e8326951 100644 --- a/ui/src/pages/Tags/index.tsx +++ b/ui/src/pages/Tags/index.tsx @@ -1,25 +1,18 @@ import { useState } from 'react'; -import { - Container, - Row, - Col, - Card, - ButtonGroup, - Button, - Form, -} from 'react-bootstrap'; -import { useSearchParams, useNavigate } from 'react-router-dom'; +import { Container, Row, Col, Card, Button, Form } from 'react-bootstrap'; +import { useSearchParams } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { useQueryTags, following } from '@answer/api'; -import { Tag, Pagination, PageTitle } from '@answer/components'; +import { Tag, Pagination, PageTitle, QueryGroup } from '@answer/components'; import { formatCount } from '@answer/utils'; +const sortBtns = ['popular', 'name', 'newest']; + const Tags = () => { const [urlSearch] = useSearchParams(); const { t } = useTranslation('translation', { keyPrefix: 'tags' }); const [searchTag, setSearchTag] = useState(''); - const navigate = useNavigate(); const page = Number(urlSearch.get('page')) || 1; const sort = urlSearch.get('sort'); @@ -36,10 +29,6 @@ const Tags = () => { setSearchTag(e.target.value); }; - const handleSort = (param) => { - navigate(`/tags?sort=${param}`); - }; - const handleFollow = (tag) => { following({ object_id: tag.tag_id, @@ -67,30 +56,12 @@ const Tags = () => { /> - - - - - +
diff --git a/ui/src/pages/Users/Personal/components/DefaultList/index.tsx b/ui/src/pages/Users/Personal/components/DefaultList/index.tsx index f0d69b62..7eb67525 100644 --- a/ui/src/pages/Users/Personal/components/DefaultList/index.tsx +++ b/ui/src/pages/Users/Personal/components/DefaultList/index.tsx @@ -19,7 +19,9 @@ const Index: FC = ({ visible, tabName, data }) => { {data.map((item) => { return ( - +
= ({ sort, count = 0, }) => { - const [searchParams] = useSearchParams(); - const navigate = useNavigate(); - const location = useLocation(); const { t } = useTranslation('translation', { keyPrefix: 'personal' }); - const handleParams = (order): string => { - const basePath = location.pathname; - searchParams.delete('page'); - searchParams.set('order', order); - const searchStr = searchParams.toString(); - return `${basePath}?${searchStr}`; - }; - - const handleClick = (e, type) => { - e.preventDefault(); - const str = handleParams(type); - navigate(str); - }; - if (!visible) { return null; } @@ -53,20 +29,11 @@ const Index: FC = ({ {count} {t(tabName)}
{(tabName === 'answers' || tabName === 'questions') && ( - - {sortBtns.map((item) => { - return ( - - ); - })} - + )}
); diff --git a/ui/src/pages/Users/Personal/components/Reputation/index.tsx b/ui/src/pages/Users/Personal/components/Reputation/index.tsx index d95b57e3..fa1cb3db 100644 --- a/ui/src/pages/Users/Personal/components/Reputation/index.tsx +++ b/ui/src/pages/Users/Personal/components/Reputation/index.tsx @@ -18,7 +18,7 @@ const Index: FC = ({ visible, data }) => { {data.map((item) => { return ( - +
0 ? 'text-success' : 'text-danger'