This is an automated email from the ASF dual-hosted git repository.
shuai pushed a commit to branch feat/1.4.0/personal
in repository https://gitbox.apache.org/repos/asf/incubator-answer.git
The following commit(s) were added to refs/heads/feat/1.4.0/personal by this
push:
new 48f9546f fix: bages detail add userCard conponent
48f9546f is described below
commit 48f9546fb6dc1ef19858f0b7d4ae1b56af3747ce
Author: shuai <[email protected]>
AuthorDate: Mon Aug 12 16:26:31 2024 +0800
fix: bages detail add userCard conponent
---
ui/src/common/interface.ts | 14 +++-
.../Detail/components/HeaderLoader/index.tsx | 16 ++--
.../Badges/Detail/components/UserCard/index.tsx | 97 ++++++++++++++++++++++
ui/src/pages/Badges/Detail/index.tsx | 28 ++-----
ui/src/pages/Badges/index.tsx | 1 -
ui/src/services/client/badges.ts | 4 +-
ui/src/services/client/personal.ts | 8 +-
7 files changed, 134 insertions(+), 34 deletions(-)
diff --git a/ui/src/common/interface.ts b/ui/src/common/interface.ts
index 789109d2..45f957c2 100644
--- a/ui/src/common/interface.ts
+++ b/ui/src/common/interface.ts
@@ -761,9 +761,21 @@ export interface BadgeDetailListReq {
page: number;
page_size: number;
badge_id: string;
+ username?: string | null;
+}
+
+export interface BadgeDetailListItem {
+ created_at: number;
+ author_user_info: UserInfoBase;
+ object_type: string;
+ object_id: string;
+ url_title: string;
+ question_id: string;
+ answer_id: string;
+ comment_id: string;
}
export interface BadgeDetailListRes {
count: number;
- list: BadgeInfo[];
+ list: BadgeDetailListItem[];
}
diff --git a/ui/src/pages/Badges/Detail/components/HeaderLoader/index.tsx
b/ui/src/pages/Badges/Detail/components/HeaderLoader/index.tsx
index df0c9204..d56432e8 100644
--- a/ui/src/pages/Badges/Detail/components/HeaderLoader/index.tsx
+++ b/ui/src/pages/Badges/Detail/components/HeaderLoader/index.tsx
@@ -22,23 +22,23 @@ import { Card } from 'react-bootstrap';
const Index = () => {
return (
<Card className="mb-4 placeholder-glow">
- <Card.Body className="d-flex">
+ <Card.Body className="d-block d-sm-flex">
<div
- className="placeholder me-3"
+ className="placeholder me-3 flex-shrink-0"
style={{ width: '96px', height: '96px' }}
/>
- <div>
- <div className="placeholder h5" />
- <div className="placeholder" />
- <div className="placeholder" />
+ <div className="w-100 mt-3 mt-sm-0">
+ <div className="placeholder h5 w-25" />
+ <div className="placeholder w-100" />
+ <div className="placeholder w-75" />
<div className="placeholder mt-2 w-50" />
<div className="small mt-2">
- <span className="placeholder" style={{ width: '100px' }} />
+ <span className="placeholder" style={{ width: '80px' }} />
- <span className="placeholder ms-2" style={{ width: '100px' }} />
+ <span className="placeholder ms-2" style={{ width: '80px' }} />
</div>
</div>
</Card.Body>
diff --git a/ui/src/pages/Badges/Detail/components/UserCard/index.tsx
b/ui/src/pages/Badges/Detail/components/UserCard/index.tsx
new file mode 100644
index 00000000..d874ceb9
--- /dev/null
+++ b/ui/src/pages/Badges/Detail/components/UserCard/index.tsx
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { memo, FC } from 'react';
+import { Link } from 'react-router-dom';
+import { useTranslation } from 'react-i18next';
+
+import classnames from 'classnames';
+
+import { Avatar } from '@/components';
+import { formatCount } from '@/utils';
+
+interface Props {
+ data: any;
+ className?: string;
+}
+
+const Index: FC<Props> = ({ data, className = '' }) => {
+ const { t } = useTranslation('translation', { keyPrefix: 'badges' });
+ return (
+ <div className={classnames('d-flex', className)}>
+ {data?.status !== 'deleted' ? (
+ <Link to={`/users/${data?.username}`}>
+ <Avatar
+ avatar={data?.avatar}
+ size="40px"
+ className="me-2 d-none d-md-block"
+ searchStr="s=96"
+ alt={data?.display_name}
+ />
+
+ <Avatar
+ avatar={data?.avatar}
+ size="24px"
+ className="me-2 d-block d-md-none"
+ searchStr="s=48"
+ alt={data?.display_name}
+ />
+ </Link>
+ ) : (
+ <>
+ <Avatar
+ avatar={data?.avatar}
+ size="40px"
+ className="me-2 d-none d-md-block"
+ searchStr="s=96"
+ alt={data?.display_name}
+ />
+
+ <Avatar
+ avatar={data?.avatar}
+ size="24px"
+ className="me-2 d-block d-md-none"
+ searchStr="s=48"
+ alt={data?.display_name}
+ />
+ </>
+ )}
+ <div className="small text-secondary d-flex flex-row flex-md-column
align-items-center align-items-md-start">
+ <div className="me-1 me-md-0 d-flex align-items-center">
+ {data?.status !== 'deleted' ? (
+ <Link
+ to={`/users/${data?.username}`}
+ className="me-1 text-break name-ellipsis"
+ style={{ maxWidth: '100px' }}>
+ {data?.display_name}
+ </Link>
+ ) : (
+ <span className="me-1 text-break">{data?.display_name}</span>
+ )}
+ </div>
+ <div className="text-secondary">
+ {formatCount(data?.rank)}{' '}
+ {t('x_reputation', { keyPrefix: 'personal' })}
+ </div>
+ </div>
+ </div>
+ );
+};
+
+export default memo(Index);
diff --git a/ui/src/pages/Badges/Detail/index.tsx
b/ui/src/pages/Badges/Detail/index.tsx
index 3e8513ae..42487db3 100644
--- a/ui/src/pages/Badges/Detail/index.tsx
+++ b/ui/src/pages/Badges/Detail/index.tsx
@@ -23,7 +23,7 @@ import { Link, useParams, useSearchParams } from
'react-router-dom';
// import classnames from 'classnames';
-import { Avatar, FormatTime, Pagination, Empty } from '@/components';
+import { FormatTime, Pagination, Empty } from '@/components';
import { usePageTags, useSkeletonControl } from '@/hooks';
// import { formatCount } from '@/utils';
import { useGetBadgeInfo, useBadgeDetailList } from '@/services';
@@ -31,6 +31,7 @@ import { useGetBadgeInfo, useBadgeDetailList } from
'@/services';
import BadgeDetail from './components/Badge';
import Loader from './components/Loader';
import HeaderLoader from './components/HeaderLoader';
+import UserCard from './components/UserCard';
const Index = () => {
const { t } = useTranslation('translation', { keyPrefix: 'badges' });
@@ -46,6 +47,7 @@ const Index = () => {
badge_id,
page,
page_size: pageSize,
+ username: urlSearchParams.get('username') || null,
});
const { isSkeletonShow } = useSkeletonControl(isDetailLoading);
@@ -65,36 +67,20 @@ const Index = () => {
<h3 className="mb-4">{t('title')}</h3>
{isHeaderLoading ? <HeaderLoader /> : <BadgeDetail data={badgeInfo} />}
<Row>
- <Loader />
{isSkeletonShow ? (
<Loader />
) : (
badges?.list?.map((item) => {
return (
- <Col sm={12} md={6} lg={3} key={item.id} className="mb-4">
+ <Col sm={12} md={6} lg={3} key={item.object_id} className="mb-4">
<FormatTime
- time={1722397094672}
+ time={item.created_at}
preFix={t('awarded')}
className="small mb-1 d-block"
/>
- <div className="d-flex align-items-center">
- <Link to="/user">
- <Avatar size="40px" avatar="" alt="" />
- </Link>
- <div className="small ms-2">
- <Link
- to="/user"
- className="lh-1 name-ellipsis"
- style={{ maxWidth: '200px' }}>
- username
- </Link>
- <div className="text-secondary">
- 980 {t('x_reputation', { keyPrefix: 'personal' })}
- </div>
- </div>
- </div>
+ <UserCard data={item.author_user_info} />
<Link to="/question" className="mt-1 d-block">
- How to `go test` all tests in my project?
+ {item.url_title}
</Link>
</Col>
);
diff --git a/ui/src/pages/Badges/index.tsx b/ui/src/pages/Badges/index.tsx
index 39628062..d37f5d9a 100644
--- a/ui/src/pages/Badges/index.tsx
+++ b/ui/src/pages/Badges/index.tsx
@@ -16,7 +16,6 @@
* specific language governing permissions and limitations
* under the License.
*/
-
import { useTranslation } from 'react-i18next';
import { CardBadge } from '@/components';
diff --git a/ui/src/services/client/badges.ts b/ui/src/services/client/badges.ts
index c3a7bba2..476f85d1 100644
--- a/ui/src/services/client/badges.ts
+++ b/ui/src/services/client/badges.ts
@@ -52,7 +52,9 @@ export const useGetBadgeInfo = (id: string) => {
export const useBadgeDetailList = (params: Type.BadgeDetailListReq) => {
const { data, error, mutate } = useSWR<Type.BadgeDetailListRes, Error>(
- `/answer/api/v1/badge/awards/page?${qs.stringify(params)}`,
+ `/answer/api/v1/badge/awards/page?${qs.stringify(params, {
+ skipNulls: true,
+ })}`,
request.instance.get,
);
return {
diff --git a/ui/src/services/client/personal.ts
b/ui/src/services/client/personal.ts
index 339f1e60..fbf38938 100644
--- a/ui/src/services/client/personal.ts
+++ b/ui/src/services/client/personal.ts
@@ -66,7 +66,7 @@ export const usePersonalTop = (username: string, tabName:
string) => {
};
export const usePersonalListByTabName = (params: ListReq, tabName: string) => {
- let apiUrl = '';
+ let apiUrl: string | null = '';
if (tabName === 'answers') {
apiUrl = '/answer/api/v1/personal/answer/page';
}
@@ -89,10 +89,14 @@ export const usePersonalListByTabName = (params: ListReq,
tabName: string) => {
delete params.username;
apiUrl = '/answer/api/v1/personal/vote/page';
}
+ if (tabName === 'badges') {
+ delete params.order;
+ apiUrl = '/answer/api/v1/badge/user/awards';
+ }
const queryParams = qs.stringify(params, { skipNulls: true });
const { data, error, mutate } = useSWR<ListRes, Error>(
- tabName !== 'overview' ? `${apiUrl}?${queryParams}` : null,
+ tabName !== 'review' ? `${apiUrl}?${queryParams}` : null,
request.instance.get,
);