mirror of https://gitee.com/answerdev/answer.git
Merge branch 'ui-v0.3' of git.backyard.segmentfault.com:opensource/answer into ui-v0.3
This commit is contained in:
commit
787193cf55
|
@ -228,6 +228,7 @@ export type AdminContentsFilterBy = 'normal' | 'closed' | 'deleted';
|
|||
|
||||
export interface AdminContentsReq extends Paging {
|
||||
status: AdminContentsFilterBy;
|
||||
query?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -263,6 +264,7 @@ export interface AdminSettingsInterface {
|
|||
logo: string;
|
||||
language: string;
|
||||
theme: string;
|
||||
time_zone: string;
|
||||
}
|
||||
|
||||
export interface AdminSettingsSmtp {
|
||||
|
|
|
@ -759,7 +759,30 @@
|
|||
"dashboard": {
|
||||
"title": "Dashboard",
|
||||
"welcome": "Welcome to Answer Admin !",
|
||||
"version": "Version"
|
||||
"site_statistics": "Site Statistics",
|
||||
"questions": "Questions:",
|
||||
"answers": "Answers:",
|
||||
"comments": "Comments:",
|
||||
"votes": "Votes:",
|
||||
"active_users": "Active users:",
|
||||
"flags": "Flags:",
|
||||
"site_health_status": "Site Health Status",
|
||||
"version": "Version:",
|
||||
"https": "HTTPS:",
|
||||
"uploading_files": "Uploading files:",
|
||||
"smtp": "SMTP:",
|
||||
"timezone": "Timezone:",
|
||||
"system_info": "System Info",
|
||||
"storage_used": "Storage used:",
|
||||
"uptime": "Uptime:",
|
||||
"answer_links": "Answer Links",
|
||||
"documents": "Documents",
|
||||
"feedback": "Feedback",
|
||||
"review": "Review",
|
||||
"config": "Config",
|
||||
"update_to": "Update to",
|
||||
"latest": "Latest",
|
||||
"check_failed": "Check failed"
|
||||
},
|
||||
"flags": {
|
||||
"title": "Flags",
|
||||
|
@ -816,7 +839,10 @@
|
|||
"inactive": "Inactive",
|
||||
"suspended": "Suspended",
|
||||
"deleted": "Deleted",
|
||||
"normal": "Normal"
|
||||
"normal": "Normal",
|
||||
"filter": {
|
||||
"placeholder": "Filter by name, user:id"
|
||||
}
|
||||
},
|
||||
"questions": {
|
||||
"page_title": "Questions",
|
||||
|
@ -829,7 +855,10 @@
|
|||
"created": "Created",
|
||||
"status": "Status",
|
||||
"action": "Action",
|
||||
"change": "Change"
|
||||
"change": "Change",
|
||||
"filter": {
|
||||
"placeholder": "Filter by title, question:id"
|
||||
}
|
||||
},
|
||||
"answers": {
|
||||
"page_title": "Answers",
|
||||
|
@ -840,7 +869,10 @@
|
|||
"created": "Created",
|
||||
"status": "Status",
|
||||
"action": "Action",
|
||||
"change": "Change"
|
||||
"change": "Change",
|
||||
"filter": {
|
||||
"placeholder": "Filter by title, answer:id"
|
||||
}
|
||||
},
|
||||
"general": {
|
||||
"page_title": "General",
|
||||
|
@ -876,6 +908,11 @@
|
|||
"label": "Interface Language",
|
||||
"msg": "Interface language cannot be empty.",
|
||||
"text": "User interface language. It will change when you refresh the page."
|
||||
},
|
||||
"timezone": {
|
||||
"label": "Timezone",
|
||||
"msg": "Timezone cannot be empty.",
|
||||
"text": "Choose a UTC (Coordinated Universal Time) time offset."
|
||||
}
|
||||
},
|
||||
"smtp": {
|
||||
|
|
|
@ -22,10 +22,12 @@ import '../index.scss';
|
|||
const answerFilterItems: Type.AdminContentsFilterBy[] = ['normal', 'deleted'];
|
||||
|
||||
const Answers: FC = () => {
|
||||
const [urlSearchParams] = useSearchParams();
|
||||
const [urlSearchParams, setUrlSearchParams] = useSearchParams();
|
||||
const curFilter = urlSearchParams.get('status') || answerFilterItems[0];
|
||||
const PAGE_SIZE = 20;
|
||||
const curPage = Number(urlSearchParams.get('page')) || 1;
|
||||
const curQuery = urlSearchParams.get('query') || '';
|
||||
const questionId = urlSearchParams.get('questionId') || '';
|
||||
const { t } = useTranslation('translation', { keyPrefix: 'admin.answers' });
|
||||
|
||||
const {
|
||||
|
@ -36,6 +38,8 @@ const Answers: FC = () => {
|
|||
page_size: PAGE_SIZE,
|
||||
page: curPage,
|
||||
status: curFilter as Type.AdminContentsFilterBy,
|
||||
query: curQuery,
|
||||
question_id: questionId,
|
||||
});
|
||||
const count = listData?.count || 0;
|
||||
|
||||
|
@ -77,6 +81,11 @@ const Answers: FC = () => {
|
|||
});
|
||||
};
|
||||
|
||||
const handleFilter = (e) => {
|
||||
urlSearchParams.set('query', e.target.value);
|
||||
urlSearchParams.delete('page');
|
||||
setUrlSearchParams(urlSearchParams);
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<h3 className="mb-4">{t('page_title')}</h3>
|
||||
|
@ -89,19 +98,20 @@ const Answers: FC = () => {
|
|||
/>
|
||||
|
||||
<Form.Control
|
||||
value={curQuery}
|
||||
onChange={handleFilter}
|
||||
size="sm"
|
||||
type="input"
|
||||
placeholder="Filter by title"
|
||||
className="d-none"
|
||||
placeholder={t('filter.placeholder')}
|
||||
style={{ width: '12.25rem' }}
|
||||
/>
|
||||
</div>
|
||||
<Table>
|
||||
<Table responsive>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style={{ width: '45%' }}>{t('post')}</th>
|
||||
<th>{t('post')}</th>
|
||||
<th>{t('votes')}</th>
|
||||
<th style={{ width: '20%' }}>{t('created')}</th>
|
||||
<th>{t('created')}</th>
|
||||
<th>{t('status')}</th>
|
||||
{curFilter !== 'deleted' && <th>{t('action')}</th>}
|
||||
</tr>
|
||||
|
@ -132,6 +142,7 @@ const Answers: FC = () => {
|
|||
__html: li.description,
|
||||
}}
|
||||
className="last-p text-truncate-2 fs-14"
|
||||
style={{ maxWidth: '30rem' }}
|
||||
/>
|
||||
</Stack>
|
||||
</td>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { FC } from 'react';
|
||||
import { Button, Form, Table, Stack, Badge } from 'react-bootstrap';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { Link, useSearchParams } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import {
|
||||
|
@ -31,9 +31,10 @@ const questionFilterItems: Type.AdminContentsFilterBy[] = [
|
|||
|
||||
const PAGE_SIZE = 20;
|
||||
const Questions: FC = () => {
|
||||
const [urlSearchParams] = useSearchParams();
|
||||
const [urlSearchParams, setUrlSearchParams] = useSearchParams();
|
||||
const curFilter = urlSearchParams.get('status') || questionFilterItems[0];
|
||||
const curPage = Number(urlSearchParams.get('page')) || 1;
|
||||
const curQuery = urlSearchParams.get('query') || '';
|
||||
const { t } = useTranslation('translation', { keyPrefix: 'admin.questions' });
|
||||
|
||||
const {
|
||||
|
@ -44,6 +45,7 @@ const Questions: FC = () => {
|
|||
page_size: PAGE_SIZE,
|
||||
page: curPage,
|
||||
status: curFilter as Type.AdminContentsFilterBy,
|
||||
query: curQuery,
|
||||
});
|
||||
const count = listData?.count || 0;
|
||||
|
||||
|
@ -96,6 +98,11 @@ const Questions: FC = () => {
|
|||
});
|
||||
};
|
||||
|
||||
const handleFilter = (e) => {
|
||||
urlSearchParams.set('query', e.target.value);
|
||||
urlSearchParams.delete('page');
|
||||
setUrlSearchParams(urlSearchParams);
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<h3 className="mb-4">{t('page_title')}</h3>
|
||||
|
@ -108,10 +115,11 @@ const Questions: FC = () => {
|
|||
/>
|
||||
|
||||
<Form.Control
|
||||
value={curQuery}
|
||||
size="sm"
|
||||
type="input"
|
||||
placeholder="Filter by title"
|
||||
className="d-none"
|
||||
placeholder={t('filter.placeholder')}
|
||||
onChange={handleFilter}
|
||||
style={{ width: '12.25rem' }}
|
||||
/>
|
||||
</div>
|
||||
|
@ -147,12 +155,11 @@ const Questions: FC = () => {
|
|||
</td>
|
||||
<td>{li.vote_count}</td>
|
||||
<td>
|
||||
<a
|
||||
href={`/questions/${li.id}`}
|
||||
target="_blank"
|
||||
<Link
|
||||
to={`/admin/answers?questionId=${li.id}`}
|
||||
rel="noreferrer">
|
||||
{li.answer_count}
|
||||
</a>
|
||||
</Link>
|
||||
</td>
|
||||
<td>
|
||||
<Stack>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { FC, useState } from 'react';
|
||||
import { FC } from 'react';
|
||||
import { Button, Form, Table, Badge } from 'react-bootstrap';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
@ -33,11 +33,11 @@ const bgMap = {
|
|||
const PAGE_SIZE = 10;
|
||||
const Users: FC = () => {
|
||||
const { t } = useTranslation('translation', { keyPrefix: 'admin.users' });
|
||||
const [userName, setUserName] = useState('');
|
||||
|
||||
const [urlSearchParams] = useSearchParams();
|
||||
const [urlSearchParams, setUrlSearchParams] = useSearchParams();
|
||||
const curFilter = urlSearchParams.get('filter') || UserFilterKeys[0];
|
||||
const curPage = Number(urlSearchParams.get('page') || '1');
|
||||
const curQuery = urlSearchParams.get('query') || '';
|
||||
const {
|
||||
data,
|
||||
isLoading,
|
||||
|
@ -45,7 +45,7 @@ const Users: FC = () => {
|
|||
} = useQueryUsers({
|
||||
page: curPage,
|
||||
page_size: PAGE_SIZE,
|
||||
...(userName ? { username: userName } : {}),
|
||||
query: curQuery,
|
||||
...(curFilter === 'all' ? {} : { status: curFilter }),
|
||||
});
|
||||
const changeModal = useChangeModal({
|
||||
|
@ -59,6 +59,11 @@ const Users: FC = () => {
|
|||
});
|
||||
};
|
||||
|
||||
const handleFilter = (e) => {
|
||||
urlSearchParams.set('query', e.target.value);
|
||||
urlSearchParams.delete('page');
|
||||
setUrlSearchParams(urlSearchParams);
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<h3 className="mb-4">{t('title')}</h3>
|
||||
|
@ -71,11 +76,10 @@ const Users: FC = () => {
|
|||
/>
|
||||
|
||||
<Form.Control
|
||||
className="d-none"
|
||||
size="sm"
|
||||
value={userName}
|
||||
onChange={(e) => setUserName(e.target.value)}
|
||||
placeholder="Filter by name"
|
||||
value={curQuery}
|
||||
onChange={handleFilter}
|
||||
placeholder={t('filter.placeholder')}
|
||||
style={{ width: '12.25rem' }}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -4,7 +4,9 @@ import qs from 'qs';
|
|||
import request from '@/utils/request';
|
||||
import type * as Type from '@/common/interface';
|
||||
|
||||
export const useAnswerSearch = (params: Type.AdminContentsReq) => {
|
||||
export const useAnswerSearch = (
|
||||
params: Type.AdminContentsReq & { question_id?: string },
|
||||
) => {
|
||||
const apiUrl = `/answer/admin/api/answer/page?${qs.stringify(params)}`;
|
||||
const { data, error, mutate } = useSWR<Type.ListResult, Error>(
|
||||
[apiUrl],
|
||||
|
|
Loading…
Reference in New Issue