mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-08 20:42:30 +08:00
### What problem does this PR solve? Fix (next search): Optimize the search problem interface and related functions #3221 -Add search_id to the retrievval_test interface -Optimize handleSearchStrChange and handleSearch callbacks to determine whether to enable AI search based on search configuration ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)
This commit is contained in:
54
web/src/components/home-card.tsx
Normal file
54
web/src/components/home-card.tsx
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import { RAGFlowAvatar } from '@/components/ragflow-avatar';
|
||||||
|
import { Card, CardContent } from '@/components/ui/card';
|
||||||
|
import { formatDate } from '@/utils/date';
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
data: {
|
||||||
|
name: string;
|
||||||
|
description?: string;
|
||||||
|
avatar?: string;
|
||||||
|
update_time?: string | number;
|
||||||
|
};
|
||||||
|
onClick?: () => void;
|
||||||
|
moreDropdown: React.ReactNode;
|
||||||
|
}
|
||||||
|
export function HomeCard({ data, onClick, moreDropdown }: IProps) {
|
||||||
|
return (
|
||||||
|
<Card
|
||||||
|
className="bg-bg-card border-colors-outline-neutral-standard"
|
||||||
|
onClick={() => {
|
||||||
|
// navigateToSearch(data?.id);
|
||||||
|
onClick?.();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CardContent className="p-4 flex gap-2 items-start group h-full">
|
||||||
|
<div className="flex justify-between mb-4">
|
||||||
|
<RAGFlowAvatar
|
||||||
|
className="w-[32px] h-[32px]"
|
||||||
|
avatar={data.avatar}
|
||||||
|
name={data.name}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col justify-between gap-1 flex-1 h-full w-[calc(100%-50px)]">
|
||||||
|
<section className="flex justify-between">
|
||||||
|
<div className="text-[20px] font-bold w-80% leading-5">
|
||||||
|
{data.name}
|
||||||
|
</div>
|
||||||
|
{moreDropdown}
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section className="flex flex-col gap-1 mt-1">
|
||||||
|
<div className="whitespace-nowrap overflow-hidden text-ellipsis">
|
||||||
|
{data.description}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm opacity-80">
|
||||||
|
{formatDate(data.update_time)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -1,10 +1,7 @@
|
|||||||
|
import { HomeCard } from '@/components/home-card';
|
||||||
import { MoreButton } from '@/components/more-button';
|
import { MoreButton } from '@/components/more-button';
|
||||||
import { RAGFlowAvatar } from '@/components/ragflow-avatar';
|
|
||||||
import { SharedBadge } from '@/components/shared-badge';
|
|
||||||
import { Card, CardContent } from '@/components/ui/card';
|
|
||||||
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
||||||
import { IFlow } from '@/interfaces/database/agent';
|
import { IFlow } from '@/interfaces/database/agent';
|
||||||
import { formatDate } from '@/utils/date';
|
|
||||||
import { AgentDropdown } from './agent-dropdown';
|
import { AgentDropdown } from './agent-dropdown';
|
||||||
import { useRenameAgent } from './use-rename-agent';
|
import { useRenameAgent } from './use-rename-agent';
|
||||||
|
|
||||||
@ -16,36 +13,16 @@ export function AgentCard({ data, showAgentRenameModal }: DatasetCardProps) {
|
|||||||
const { navigateToAgent } = useNavigatePage();
|
const { navigateToAgent } = useNavigatePage();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card key={data.id} className="w-40" onClick={navigateToAgent(data.id)}>
|
<HomeCard
|
||||||
<CardContent className="p-2.5 pt-2 group">
|
data={{ ...data, name: data.title, description: data.description || '' }}
|
||||||
<section className="flex justify-between mb-2">
|
moreDropdown={
|
||||||
<div className="flex gap-2 items-center">
|
<AgentDropdown showAgentRenameModal={showAgentRenameModal} agent={data}>
|
||||||
<RAGFlowAvatar
|
|
||||||
className="size-6 rounded-lg"
|
|
||||||
avatar={data.avatar}
|
|
||||||
name={data.title || 'CN'}
|
|
||||||
></RAGFlowAvatar>
|
|
||||||
<SharedBadge>{data.nickname}</SharedBadge>
|
|
||||||
</div>
|
|
||||||
<AgentDropdown
|
|
||||||
showAgentRenameModal={showAgentRenameModal}
|
|
||||||
agent={data}
|
|
||||||
>
|
|
||||||
<MoreButton></MoreButton>
|
<MoreButton></MoreButton>
|
||||||
</AgentDropdown>
|
</AgentDropdown>
|
||||||
</section>
|
}
|
||||||
<div className="flex justify-between items-end">
|
onClick={() => {
|
||||||
<div className="w-full">
|
navigateToAgent(data?.id);
|
||||||
<h3 className="text-lg font-semibold mb-2 line-clamp-1">
|
}}
|
||||||
{data.title}
|
/>
|
||||||
</h3>
|
|
||||||
<p className="text-xs text-text-secondary">{data.description}</p>
|
|
||||||
<p className="text-xs text-text-secondary">
|
|
||||||
{formatDate(data.update_time)}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -46,7 +46,7 @@ export default function Agents() {
|
|||||||
</ListFilterBar>
|
</ListFilterBar>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1 overflow-auto">
|
<div className="flex-1 overflow-auto">
|
||||||
<div className="flex flex-wrap gap-4 px-8">
|
<div className="grid gap-6 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 max-h-[78vh] overflow-auto px-8">
|
||||||
{data.map((x) => {
|
{data.map((x) => {
|
||||||
return (
|
return (
|
||||||
<AgentCard
|
<AgentCard
|
||||||
|
|||||||
@ -1,10 +1,8 @@
|
|||||||
|
import { HomeCard } from '@/components/home-card';
|
||||||
import { MoreButton } from '@/components/more-button';
|
import { MoreButton } from '@/components/more-button';
|
||||||
import { RAGFlowAvatar } from '@/components/ragflow-avatar';
|
|
||||||
import { Badge } from '@/components/ui/badge';
|
|
||||||
import { Card, CardContent } from '@/components/ui/card';
|
import { Card, CardContent } from '@/components/ui/card';
|
||||||
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
||||||
import { IKnowledge } from '@/interfaces/database/knowledge';
|
import { IKnowledge } from '@/interfaces/database/knowledge';
|
||||||
import { formatDate } from '@/utils/date';
|
|
||||||
import { ChevronRight } from 'lucide-react';
|
import { ChevronRight } from 'lucide-react';
|
||||||
import { DatasetDropdown } from './dataset-dropdown';
|
import { DatasetDropdown } from './dataset-dropdown';
|
||||||
import { useDisplayOwnerName } from './use-display-owner';
|
import { useDisplayOwnerName } from './use-display-owner';
|
||||||
@ -24,47 +22,20 @@ export function DatasetCard({
|
|||||||
const owner = displayOwnerName(dataset.tenant_id, dataset.nickname);
|
const owner = displayOwnerName(dataset.tenant_id, dataset.nickname);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<HomeCard
|
||||||
key={dataset.id}
|
data={{ ...dataset, description: `${dataset.doc_num} files` }}
|
||||||
className="w-40"
|
moreDropdown={
|
||||||
onClick={navigateToDataset(dataset.id)}
|
|
||||||
>
|
|
||||||
<CardContent className="p-2.5 pt-2 group">
|
|
||||||
<section className="flex justify-between mb-2">
|
|
||||||
<div className="flex gap-2 items-center">
|
|
||||||
<RAGFlowAvatar
|
|
||||||
className="size-6 rounded-lg"
|
|
||||||
avatar={dataset.avatar}
|
|
||||||
name={dataset.name || 'CN'}
|
|
||||||
></RAGFlowAvatar>
|
|
||||||
{owner && (
|
|
||||||
<Badge className="h-5 rounded-sm px-1 bg-background-badge text-text-badge">
|
|
||||||
{owner}
|
|
||||||
</Badge>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
<DatasetDropdown
|
<DatasetDropdown
|
||||||
showDatasetRenameModal={showDatasetRenameModal}
|
showDatasetRenameModal={showDatasetRenameModal}
|
||||||
dataset={dataset}
|
dataset={dataset}
|
||||||
>
|
>
|
||||||
<MoreButton></MoreButton>
|
<MoreButton></MoreButton>
|
||||||
</DatasetDropdown>
|
</DatasetDropdown>
|
||||||
</section>
|
}
|
||||||
<div className="flex justify-between items-end">
|
onClick={() => {
|
||||||
<div className="w-full">
|
navigateToDataset(dataset.id);
|
||||||
<h3 className="text-lg font-semibold mb-2 line-clamp-1">
|
}}
|
||||||
{dataset.name}
|
/>
|
||||||
</h3>
|
|
||||||
<p className="text-xs text-text-secondary">
|
|
||||||
{dataset.doc_num} files
|
|
||||||
</p>
|
|
||||||
<p className="text-xs text-text-secondary">
|
|
||||||
{formatDate(dataset.update_time)}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -70,7 +70,7 @@ export default function Datasets() {
|
|||||||
</Button>
|
</Button>
|
||||||
</ListFilterBar>
|
</ListFilterBar>
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<div className="flex flex-wrap gap-4 max-h-[78vh] overflow-auto px-8">
|
<div className="grid gap-6 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 max-h-[78vh] overflow-auto px-8">
|
||||||
{kbs.map((dataset) => {
|
{kbs.map((dataset) => {
|
||||||
return (
|
return (
|
||||||
<DatasetCard
|
<DatasetCard
|
||||||
|
|||||||
@ -1,9 +1,7 @@
|
|||||||
|
import { HomeCard } from '@/components/home-card';
|
||||||
import { MoreButton } from '@/components/more-button';
|
import { MoreButton } from '@/components/more-button';
|
||||||
import { RAGFlowAvatar } from '@/components/ragflow-avatar';
|
|
||||||
import { Card, CardContent } from '@/components/ui/card';
|
|
||||||
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
||||||
import { IDialog } from '@/interfaces/database/chat';
|
import { IDialog } from '@/interfaces/database/chat';
|
||||||
import { formatDate } from '@/utils/date';
|
|
||||||
import { ChatDropdown } from './chat-dropdown';
|
import { ChatDropdown } from './chat-dropdown';
|
||||||
import { useRenameChat } from './hooks/use-rename-chat';
|
import { useRenameChat } from './hooks/use-rename-chat';
|
||||||
|
|
||||||
@ -15,32 +13,21 @@ export function ChatCard({ data, showChatRenameModal }: IProps) {
|
|||||||
const { navigateToChat } = useNavigatePage();
|
const { navigateToChat } = useNavigatePage();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card key={data.id} className="w-40" onClick={navigateToChat(data.id)}>
|
<HomeCard
|
||||||
<CardContent className="p-2.5 pt-2 group">
|
data={{
|
||||||
<section className="flex justify-between mb-2">
|
name: data.name,
|
||||||
<div className="flex gap-2 items-center">
|
description: data.description,
|
||||||
<RAGFlowAvatar
|
avatar: data.icon,
|
||||||
className="size-6 rounded-lg"
|
update_time: data.update_time,
|
||||||
avatar={data.icon}
|
}}
|
||||||
name={data.name || 'CN'}
|
moreDropdown={
|
||||||
></RAGFlowAvatar>
|
|
||||||
</div>
|
|
||||||
<ChatDropdown chat={data} showChatRenameModal={showChatRenameModal}>
|
<ChatDropdown chat={data} showChatRenameModal={showChatRenameModal}>
|
||||||
<MoreButton></MoreButton>
|
<MoreButton></MoreButton>
|
||||||
</ChatDropdown>
|
</ChatDropdown>
|
||||||
</section>
|
}
|
||||||
<div className="flex justify-between items-end">
|
onClick={() => {
|
||||||
<div className="w-full">
|
navigateToChat(data?.id);
|
||||||
<h3 className="text-lg font-semibold mb-2 line-clamp-1 truncate">
|
}}
|
||||||
{data.name}
|
/>
|
||||||
</h3>
|
|
||||||
<p className="text-xs text-text-secondary">{data.description}</p>
|
|
||||||
<p className="text-xs text-text-secondary">
|
|
||||||
{formatDate(data.update_time)}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -49,7 +49,7 @@ export default function ChatList() {
|
|||||||
</ListFilterBar>
|
</ListFilterBar>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1 overflow-auto">
|
<div className="flex-1 overflow-auto">
|
||||||
<div className="flex flex-wrap gap-4 px-8">
|
<div className="grid gap-6 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5 max-h-[84vh] overflow-auto px-8">
|
||||||
{data.dialogs.map((x) => {
|
{data.dialogs.map((x) => {
|
||||||
return (
|
return (
|
||||||
<ChatCard
|
<ChatCard
|
||||||
|
|||||||
@ -288,20 +288,23 @@ export const useSendQuestion = (
|
|||||||
const { pagination, setPagination } = useGetPaginationWithRouter();
|
const { pagination, setPagination } = useGetPaginationWithRouter();
|
||||||
|
|
||||||
const sendQuestion = useCallback(
|
const sendQuestion = useCallback(
|
||||||
(question: string) => {
|
(question: string, enableAI: boolean = true) => {
|
||||||
const q = trim(question);
|
const q = trim(question);
|
||||||
if (isEmpty(q)) return;
|
if (isEmpty(q)) return;
|
||||||
setPagination({ page: 1 });
|
setPagination({ page: 1 });
|
||||||
setIsFirstRender(false);
|
setIsFirstRender(false);
|
||||||
setCurrentAnswer({} as IAnswer);
|
setCurrentAnswer({} as IAnswer);
|
||||||
|
if (enableAI) {
|
||||||
setSendingLoading(true);
|
setSendingLoading(true);
|
||||||
send({ kb_ids: kbIds, question: q, tenantId, search_id: searchId });
|
send({ kb_ids: kbIds, question: q, tenantId, search_id: searchId });
|
||||||
|
}
|
||||||
testChunk({
|
testChunk({
|
||||||
kb_id: kbIds,
|
kb_id: kbIds,
|
||||||
highlight: true,
|
highlight: true,
|
||||||
question: q,
|
question: q,
|
||||||
page: 1,
|
page: 1,
|
||||||
size: pagination.pageSize,
|
size: pagination.pageSize,
|
||||||
|
search_id: searchId,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (related_search) {
|
if (related_search) {
|
||||||
@ -327,11 +330,12 @@ export const useSendQuestion = (
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleClickRelatedQuestion = useCallback(
|
const handleClickRelatedQuestion = useCallback(
|
||||||
(question: string) => () => {
|
(question: string, enableAI: boolean = true) =>
|
||||||
|
() => {
|
||||||
if (sendingLoading) return;
|
if (sendingLoading) return;
|
||||||
|
|
||||||
setSearchStr(question);
|
setSearchStr(question);
|
||||||
sendQuestion(question);
|
sendQuestion(question, enableAI);
|
||||||
},
|
},
|
||||||
[sendQuestion, sendingLoading],
|
[sendQuestion, sendingLoading],
|
||||||
);
|
);
|
||||||
@ -348,6 +352,7 @@ export const useSendQuestion = (
|
|||||||
doc_ids: documentIds ?? selectedDocumentIds,
|
doc_ids: documentIds ?? selectedDocumentIds,
|
||||||
page,
|
page,
|
||||||
size,
|
size,
|
||||||
|
search_id: searchId,
|
||||||
});
|
});
|
||||||
|
|
||||||
testChunkAll({
|
testChunkAll({
|
||||||
@ -357,6 +362,7 @@ export const useSendQuestion = (
|
|||||||
doc_ids: [],
|
doc_ids: [],
|
||||||
page,
|
page,
|
||||||
size,
|
size,
|
||||||
|
search_id: searchId,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
@ -366,6 +372,7 @@ export const useSendQuestion = (
|
|||||||
kbIds,
|
kbIds,
|
||||||
selectedDocumentIds,
|
selectedDocumentIds,
|
||||||
testChunkAll,
|
testChunkAll,
|
||||||
|
searchId,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -430,7 +437,6 @@ export const useSearching = ({
|
|||||||
|
|
||||||
const handleSearchStrChange = useCallback(
|
const handleSearchStrChange = useCallback(
|
||||||
(value: string) => {
|
(value: string) => {
|
||||||
console.log('handleSearchStrChange', value);
|
|
||||||
setSearchStr(value);
|
setSearchStr(value);
|
||||||
},
|
},
|
||||||
[setSearchStr],
|
[setSearchStr],
|
||||||
@ -442,10 +448,16 @@ export const useSearching = ({
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (searchText) {
|
if (searchText) {
|
||||||
setSearchStr(searchText);
|
setSearchStr(searchText);
|
||||||
sendQuestion(searchText);
|
sendQuestion(searchText, searchData.search_config.summary);
|
||||||
setSearchText?.('');
|
setSearchText?.('');
|
||||||
}
|
}
|
||||||
}, [searchText, sendQuestion, setSearchStr, setSearchText]);
|
}, [
|
||||||
|
searchText,
|
||||||
|
sendQuestion,
|
||||||
|
setSearchStr,
|
||||||
|
setSearchText,
|
||||||
|
searchData.search_config.summary,
|
||||||
|
]);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
mindMapVisible,
|
mindMapVisible,
|
||||||
@ -462,11 +474,16 @@ export const useSearching = ({
|
|||||||
|
|
||||||
const handleSearch = useCallback(
|
const handleSearch = useCallback(
|
||||||
(value: string) => {
|
(value: string) => {
|
||||||
sendQuestion(value);
|
sendQuestion(value, searchData.search_config.summary);
|
||||||
setSearchStr?.(value);
|
setSearchStr?.(value);
|
||||||
hideMindMapModal();
|
hideMindMapModal();
|
||||||
},
|
},
|
||||||
[setSearchStr, sendQuestion, hideMindMapModal],
|
[
|
||||||
|
setSearchStr,
|
||||||
|
sendQuestion,
|
||||||
|
hideMindMapModal,
|
||||||
|
searchData.search_config.summary,
|
||||||
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
const { pagination, setPagination } = useGetPaginationWithRouter();
|
const { pagination, setPagination } = useGetPaginationWithRouter();
|
||||||
|
|||||||
@ -252,7 +252,10 @@ export default function SearchingView({
|
|||||||
key={idx}
|
key={idx}
|
||||||
variant="transparent"
|
variant="transparent"
|
||||||
className="bg-bg-card text-text-secondary"
|
className="bg-bg-card text-text-secondary"
|
||||||
onClick={handleClickRelatedQuestion(x)}
|
onClick={handleClickRelatedQuestion(
|
||||||
|
x,
|
||||||
|
searchData.search_config.summary,
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{x}
|
{x}
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@ -1,8 +1,6 @@
|
|||||||
|
import { HomeCard } from '@/components/home-card';
|
||||||
import { MoreButton } from '@/components/more-button';
|
import { MoreButton } from '@/components/more-button';
|
||||||
import { RAGFlowAvatar } from '@/components/ragflow-avatar';
|
|
||||||
import { Card, CardContent } from '@/components/ui/card';
|
|
||||||
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
||||||
import { formatDate } from '@/utils/date';
|
|
||||||
import { ISearchAppProps } from './hooks';
|
import { ISearchAppProps } from './hooks';
|
||||||
import { SearchDropdown } from './search-dropdown';
|
import { SearchDropdown } from './search-dropdown';
|
||||||
|
|
||||||
@ -14,43 +12,19 @@ export function SearchCard({ data, showSearchRenameModal }: IProps) {
|
|||||||
const { navigateToSearch } = useNavigatePage();
|
const { navigateToSearch } = useNavigatePage();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<HomeCard
|
||||||
className="bg-bg-card border-colors-outline-neutral-standard"
|
data={data}
|
||||||
onClick={() => {
|
moreDropdown={
|
||||||
navigateToSearch(data?.id);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<CardContent className="p-4 flex gap-2 items-start group h-full">
|
|
||||||
<div className="flex justify-between mb-4">
|
|
||||||
<RAGFlowAvatar
|
|
||||||
className="w-[32px] h-[32px]"
|
|
||||||
avatar={data.avatar}
|
|
||||||
name={data.name}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-col justify-between gap-1 flex-1 h-full">
|
|
||||||
<section className="flex justify-between">
|
|
||||||
<div className="text-[20px] font-bold w-80% leading-5">
|
|
||||||
{data.name}
|
|
||||||
</div>
|
|
||||||
<SearchDropdown
|
<SearchDropdown
|
||||||
dataset={data}
|
dataset={data}
|
||||||
showSearchRenameModal={showSearchRenameModal}
|
showSearchRenameModal={showSearchRenameModal}
|
||||||
>
|
>
|
||||||
<MoreButton></MoreButton>
|
<MoreButton></MoreButton>
|
||||||
</SearchDropdown>
|
</SearchDropdown>
|
||||||
</section>
|
}
|
||||||
|
onClick={() => {
|
||||||
<section className="flex flex-col gap-1 mt-1">
|
navigateToSearch(data?.id);
|
||||||
<div>{data.description}</div>
|
}}
|
||||||
<div>
|
/>
|
||||||
<p className="text-sm opacity-80">
|
|
||||||
{formatDate(data.update_time)}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user