mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-25 16:26:51 +08:00
### What problem does this PR solve? Fix: Added styles for empty states on the page. ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)
This commit is contained in:
@ -1,4 +1,6 @@
|
||||
import { CardContainer } from '@/components/card-container';
|
||||
import { EmptyCardType } from '@/components/empty/constant';
|
||||
import { EmptyAppCard } from '@/components/empty/empty';
|
||||
import ListFilterBar from '@/components/list-filter-bar';
|
||||
import { RenameDialog } from '@/components/rename-dialog';
|
||||
import { Button } from '@/components/ui/button';
|
||||
@ -14,7 +16,8 @@ import { useFetchAgentListByPage } from '@/hooks/use-agent-request';
|
||||
import { t } from 'i18next';
|
||||
import { pick } from 'lodash';
|
||||
import { Clipboard, ClipboardPlus, FileInput, Plus } from 'lucide-react';
|
||||
import { useCallback } from 'react';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import { useSearchParams } from 'umi';
|
||||
import { AgentCard } from './agent-card';
|
||||
import { CreateAgentDialog } from './create-agent-dialog';
|
||||
import { useCreateAgentOrPipeline } from './hooks/use-create-agent';
|
||||
@ -67,95 +70,120 @@ export default function Agents() {
|
||||
},
|
||||
[setPagination],
|
||||
);
|
||||
|
||||
const [searchUrl, setSearchUrl] = useSearchParams();
|
||||
const isCreate = searchUrl.get('isCreate') === 'true';
|
||||
useEffect(() => {
|
||||
if (isCreate) {
|
||||
showCreatingModal();
|
||||
searchUrl.delete('isCreate');
|
||||
setSearchUrl(searchUrl);
|
||||
}
|
||||
}, [isCreate, showCreatingModal, searchUrl, setSearchUrl]);
|
||||
return (
|
||||
<section className="flex flex-col w-full flex-1">
|
||||
<div className="px-8 pt-8 ">
|
||||
<ListFilterBar
|
||||
title={t('flow.agents')}
|
||||
searchString={searchString}
|
||||
onSearchChange={handleInputChange}
|
||||
icon="agents"
|
||||
filters={filters}
|
||||
onChange={handleFilterSubmit}
|
||||
value={filterValue}
|
||||
>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger>
|
||||
<Button>
|
||||
<Plus className="mr-2 h-4 w-4" />
|
||||
{t('flow.createGraph')}
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent>
|
||||
<DropdownMenuItem
|
||||
justifyBetween={false}
|
||||
onClick={showCreatingModal}
|
||||
>
|
||||
<Clipboard />
|
||||
{t('flow.createFromBlank')}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
justifyBetween={false}
|
||||
onClick={navigateToAgentTemplates}
|
||||
>
|
||||
<ClipboardPlus />
|
||||
{t('flow.createFromTemplate')}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
justifyBetween={false}
|
||||
onClick={handleImportJson}
|
||||
>
|
||||
<FileInput />
|
||||
{t('flow.importJsonFile')}
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</ListFilterBar>
|
||||
</div>
|
||||
<div className="flex-1 overflow-auto">
|
||||
<CardContainer className="max-h-[calc(100dvh-280px)] overflow-auto px-8">
|
||||
{data.map((x) => {
|
||||
return (
|
||||
<AgentCard
|
||||
key={x.id}
|
||||
data={x}
|
||||
showAgentRenameModal={showAgentRenameModal}
|
||||
></AgentCard>
|
||||
);
|
||||
})}
|
||||
</CardContainer>
|
||||
</div>
|
||||
<div className="mt-8 px-8 pb-8">
|
||||
<RAGFlowPagination
|
||||
{...pick(pagination, 'current', 'pageSize')}
|
||||
total={pagination.total}
|
||||
onChange={handlePageChange}
|
||||
></RAGFlowPagination>
|
||||
</div>
|
||||
{agentRenameVisible && (
|
||||
<RenameDialog
|
||||
hideModal={hideAgentRenameModal}
|
||||
onOk={onAgentRenameOk}
|
||||
initialName={initialAgentName}
|
||||
loading={agentRenameLoading}
|
||||
></RenameDialog>
|
||||
<>
|
||||
{(!data?.length || data?.length <= 0) && (
|
||||
<div className="flex w-full items-center justify-center h-[calc(100vh-164px)]">
|
||||
<EmptyAppCard
|
||||
showIcon
|
||||
size="large"
|
||||
className="w-[480px] p-14"
|
||||
type={EmptyCardType.Agent}
|
||||
onClick={() => showCreatingModal()}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{creatingVisible && (
|
||||
<CreateAgentDialog
|
||||
loading={loading}
|
||||
visible={creatingVisible}
|
||||
hideModal={hideCreatingModal}
|
||||
shouldChooseAgent
|
||||
onOk={handleCreateAgentOrPipeline}
|
||||
></CreateAgentDialog>
|
||||
)}
|
||||
{fileUploadVisible && (
|
||||
<UploadAgentDialog
|
||||
hideModal={hideFileUploadModal}
|
||||
onOk={onFileUploadOk}
|
||||
></UploadAgentDialog>
|
||||
)}
|
||||
</section>
|
||||
<section className="flex flex-col w-full flex-1">
|
||||
{!!data?.length && (
|
||||
<>
|
||||
<div className="px-8 pt-8 ">
|
||||
<ListFilterBar
|
||||
title={t('flow.agents')}
|
||||
searchString={searchString}
|
||||
onSearchChange={handleInputChange}
|
||||
icon="agents"
|
||||
filters={filters}
|
||||
onChange={handleFilterSubmit}
|
||||
value={filterValue}
|
||||
>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger>
|
||||
<Button>
|
||||
<Plus className="mr-2 h-4 w-4" />
|
||||
{t('flow.createGraph')}
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent>
|
||||
<DropdownMenuItem
|
||||
justifyBetween={false}
|
||||
onClick={showCreatingModal}
|
||||
>
|
||||
<Clipboard />
|
||||
{t('flow.createFromBlank')}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
justifyBetween={false}
|
||||
onClick={navigateToAgentTemplates}
|
||||
>
|
||||
<ClipboardPlus />
|
||||
{t('flow.createFromTemplate')}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
justifyBetween={false}
|
||||
onClick={handleImportJson}
|
||||
>
|
||||
<FileInput />
|
||||
{t('flow.importJsonFile')}
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</ListFilterBar>
|
||||
</div>
|
||||
<div className="flex-1 overflow-auto">
|
||||
<CardContainer className="max-h-[calc(100dvh-280px)] overflow-auto px-8">
|
||||
{data.map((x) => {
|
||||
return (
|
||||
<AgentCard
|
||||
key={x.id}
|
||||
data={x}
|
||||
showAgentRenameModal={showAgentRenameModal}
|
||||
></AgentCard>
|
||||
);
|
||||
})}
|
||||
</CardContainer>
|
||||
</div>
|
||||
<div className="mt-8 px-8 pb-8">
|
||||
<RAGFlowPagination
|
||||
{...pick(pagination, 'current', 'pageSize')}
|
||||
total={pagination.total}
|
||||
onChange={handlePageChange}
|
||||
></RAGFlowPagination>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{agentRenameVisible && (
|
||||
<RenameDialog
|
||||
hideModal={hideAgentRenameModal}
|
||||
onOk={onAgentRenameOk}
|
||||
initialName={initialAgentName}
|
||||
loading={agentRenameLoading}
|
||||
></RenameDialog>
|
||||
)}
|
||||
{creatingVisible && (
|
||||
<CreateAgentDialog
|
||||
loading={loading}
|
||||
visible={creatingVisible}
|
||||
hideModal={hideCreatingModal}
|
||||
shouldChooseAgent
|
||||
onOk={handleCreateAgentOrPipeline}
|
||||
></CreateAgentDialog>
|
||||
)}
|
||||
{fileUploadVisible && (
|
||||
<UploadAgentDialog
|
||||
hideModal={hideFileUploadModal}
|
||||
onOk={onFileUploadOk}
|
||||
></UploadAgentDialog>
|
||||
)}
|
||||
</section>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { EmptyType } from '@/components/empty/constant';
|
||||
import Empty from '@/components/empty/empty';
|
||||
import FileStatusBadge from '@/components/file-status-badge';
|
||||
import { FileIcon, IconFontFill } from '@/components/icon-font';
|
||||
import { RAGFlowAvatar } from '@/components/ragflow-avatar';
|
||||
@ -344,6 +346,7 @@ const FileLogsTable: FC<FileLogsTableProps> = ({
|
||||
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
|
||||
const [rowSelection, setRowSelection] = useState({});
|
||||
const { t } = useTranslate('knowledgeDetails');
|
||||
const { t: tDatasetOverview } = useTranslate('datasetOverview');
|
||||
const [isModalVisible, setIsModalVisible] = useState(false);
|
||||
const { navigateToDataflowResult } = useNavigatePage();
|
||||
const [logInfo, setLogInfo] = useState<IFileLogItem>();
|
||||
@ -445,7 +448,10 @@ const FileLogsTable: FC<FileLogsTableProps> = ({
|
||||
) : (
|
||||
<TableRow>
|
||||
<TableCell colSpan={columns.length} className="h-24 text-center">
|
||||
No results.
|
||||
<Empty
|
||||
type={EmptyType.Data}
|
||||
text={tDatasetOverview('noData')}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
|
||||
@ -14,6 +14,8 @@ import {
|
||||
import * as React from 'react';
|
||||
|
||||
import { ChunkMethodDialog } from '@/components/chunk-method-dialog';
|
||||
import { EmptyType } from '@/components/empty/constant';
|
||||
import Empty from '@/components/empty/empty';
|
||||
import { RenameDialog } from '@/components/rename-dialog';
|
||||
import { RAGFlowPagination } from '@/components/ui/ragflow-pagination';
|
||||
import {
|
||||
@ -164,7 +166,7 @@ export function DatasetTable({
|
||||
) : (
|
||||
<TableRow>
|
||||
<TableCell colSpan={columns.length} className="h-24 text-center">
|
||||
No results.
|
||||
<Empty type={EmptyType.Data} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
|
||||
@ -136,7 +136,7 @@ export function useDatasetTableColumns({
|
||||
{
|
||||
DataSourceInfo[
|
||||
row.original.source_type as keyof typeof DataSourceInfo
|
||||
].icon
|
||||
]?.icon
|
||||
}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import { EmptyType } from '@/components/empty/constant';
|
||||
import Empty from '@/components/empty/empty';
|
||||
import { FormContainer } from '@/components/form-container';
|
||||
import { FilterButton } from '@/components/list-filter-bar';
|
||||
@ -101,7 +102,7 @@ export function TestingResult({
|
||||
{!data.chunks?.length && !loading && (
|
||||
<div className="flex justify-center items-center w-full h-[calc(100vh-241px)]">
|
||||
<div>
|
||||
<Empty>
|
||||
<Empty type={EmptyType.SearchData}>
|
||||
{data.isRuned && (
|
||||
<div className="text-text-secondary">
|
||||
{t('knowledgeDetails.noTestResultsForRuned')}
|
||||
|
||||
@ -1,13 +1,17 @@
|
||||
import { CardContainer } from '@/components/card-container';
|
||||
import { EmptyCardType } from '@/components/empty/constant';
|
||||
import { EmptyAppCard } from '@/components/empty/empty';
|
||||
import ListFilterBar from '@/components/list-filter-bar';
|
||||
import { RenameDialog } from '@/components/rename-dialog';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { RAGFlowPagination } from '@/components/ui/ragflow-pagination';
|
||||
import { useFetchNextKnowledgeListByPage } from '@/hooks/use-knowledge-request';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import { pick } from 'lodash';
|
||||
import { Plus } from 'lucide-react';
|
||||
import { useCallback } from 'react';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useSearchParams } from 'umi';
|
||||
import { DatasetCard } from './dataset-card';
|
||||
import { DatasetCreatingDialog } from './dataset-creating-dialog';
|
||||
import { useSaveKnowledge } from './hooks';
|
||||
@ -52,59 +56,86 @@ export default function Datasets() {
|
||||
},
|
||||
[setPagination],
|
||||
);
|
||||
|
||||
const [searchUrl, setSearchUrl] = useSearchParams();
|
||||
const isCreate = searchUrl.get('isCreate') === 'true';
|
||||
const queryClient = useQueryClient();
|
||||
useEffect(() => {
|
||||
if (isCreate) {
|
||||
queryClient.invalidateQueries({ queryKey: ['tenantInfo'] });
|
||||
showModal();
|
||||
searchUrl.delete('isCreate');
|
||||
setSearchUrl(searchUrl);
|
||||
}
|
||||
}, [isCreate, showModal, searchUrl, setSearchUrl]);
|
||||
return (
|
||||
<section className="py-4 flex-1 flex flex-col">
|
||||
<ListFilterBar
|
||||
title={t('header.dataset')}
|
||||
searchString={searchString}
|
||||
onSearchChange={handleInputChange}
|
||||
value={filterValue}
|
||||
filters={owners}
|
||||
onChange={handleFilterSubmit}
|
||||
className="px-8"
|
||||
icon={'datasets'}
|
||||
>
|
||||
<Button onClick={showModal}>
|
||||
<Plus className=" size-2.5" />
|
||||
{t('knowledgeList.createKnowledgeBase')}
|
||||
</Button>
|
||||
</ListFilterBar>
|
||||
<div className="flex-1">
|
||||
<CardContainer className="max-h-[calc(100dvh-280px)] overflow-auto px-8">
|
||||
{kbs.map((dataset) => {
|
||||
return (
|
||||
<DatasetCard
|
||||
dataset={dataset}
|
||||
key={dataset.id}
|
||||
showDatasetRenameModal={showDatasetRenameModal}
|
||||
></DatasetCard>
|
||||
);
|
||||
})}
|
||||
</CardContainer>
|
||||
</div>
|
||||
<div className="mt-8 px-8">
|
||||
<RAGFlowPagination
|
||||
{...pick(pagination, 'current', 'pageSize')}
|
||||
total={total}
|
||||
onChange={handlePageChange}
|
||||
></RAGFlowPagination>
|
||||
</div>
|
||||
{visible && (
|
||||
<DatasetCreatingDialog
|
||||
hideModal={hideModal}
|
||||
onOk={onCreateOk}
|
||||
loading={creatingLoading}
|
||||
></DatasetCreatingDialog>
|
||||
)}
|
||||
{datasetRenameVisible && (
|
||||
<RenameDialog
|
||||
hideModal={hideDatasetRenameModal}
|
||||
onOk={onDatasetRenameOk}
|
||||
initialName={initialDatasetName}
|
||||
loading={datasetRenameLoading}
|
||||
></RenameDialog>
|
||||
)}
|
||||
</section>
|
||||
<>
|
||||
<section className="py-4 flex-1 flex flex-col">
|
||||
{(!kbs?.length || kbs?.length <= 0) && (
|
||||
<div className="flex w-full items-center justify-center h-[calc(100vh-164px)]">
|
||||
<EmptyAppCard
|
||||
showIcon
|
||||
size="large"
|
||||
className="w-[480px] p-14"
|
||||
type={EmptyCardType.Dataset}
|
||||
onClick={() => showModal()}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{!!kbs?.length && (
|
||||
<>
|
||||
<ListFilterBar
|
||||
title={t('header.dataset')}
|
||||
searchString={searchString}
|
||||
onSearchChange={handleInputChange}
|
||||
value={filterValue}
|
||||
filters={owners}
|
||||
onChange={handleFilterSubmit}
|
||||
className="px-8"
|
||||
icon={'datasets'}
|
||||
>
|
||||
<Button onClick={showModal}>
|
||||
<Plus className=" size-2.5" />
|
||||
{t('knowledgeList.createKnowledgeBase')}
|
||||
</Button>
|
||||
</ListFilterBar>
|
||||
<div className="flex-1">
|
||||
<CardContainer className="max-h-[calc(100dvh-280px)] overflow-auto px-8">
|
||||
{kbs.map((dataset) => {
|
||||
return (
|
||||
<DatasetCard
|
||||
dataset={dataset}
|
||||
key={dataset.id}
|
||||
showDatasetRenameModal={showDatasetRenameModal}
|
||||
></DatasetCard>
|
||||
);
|
||||
})}
|
||||
</CardContainer>
|
||||
</div>
|
||||
<div className="mt-8 px-8">
|
||||
<RAGFlowPagination
|
||||
{...pick(pagination, 'current', 'pageSize')}
|
||||
total={total}
|
||||
onChange={handlePageChange}
|
||||
></RAGFlowPagination>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{visible && (
|
||||
<DatasetCreatingDialog
|
||||
hideModal={hideModal}
|
||||
onOk={onCreateOk}
|
||||
loading={creatingLoading}
|
||||
></DatasetCreatingDialog>
|
||||
)}
|
||||
{datasetRenameVisible && (
|
||||
<RenameDialog
|
||||
hideModal={hideDatasetRenameModal}
|
||||
onOk={onDatasetRenameOk}
|
||||
initialName={initialDatasetName}
|
||||
loading={datasetRenameLoading}
|
||||
></RenameDialog>
|
||||
)}
|
||||
</section>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@ -3,11 +3,18 @@ import { MoreButton } from '@/components/more-button';
|
||||
import { RenameDialog } from '@/components/rename-dialog';
|
||||
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
||||
import { useFetchAgentListByPage } from '@/hooks/use-agent-request';
|
||||
import { useEffect } from 'react';
|
||||
import { AgentDropdown } from '../agents/agent-dropdown';
|
||||
import { useRenameAgent } from '../agents/use-rename-agent';
|
||||
|
||||
export function Agents() {
|
||||
const { data } = useFetchAgentListByPage();
|
||||
export function Agents({
|
||||
setListLength,
|
||||
setLoading,
|
||||
}: {
|
||||
setListLength: (length: number) => void;
|
||||
setLoading?: (loading: boolean) => void;
|
||||
}) {
|
||||
const { data, loading } = useFetchAgentListByPage();
|
||||
const { navigateToAgent } = useNavigatePage();
|
||||
const {
|
||||
agentRenameLoading,
|
||||
@ -18,6 +25,11 @@ export function Agents() {
|
||||
showAgentRenameModal,
|
||||
} = useRenameAgent();
|
||||
|
||||
useEffect(() => {
|
||||
setListLength(data?.length || 0);
|
||||
setLoading?.(loading || false);
|
||||
}, [data, setListLength, loading, setLoading]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{data.slice(0, 10).map((x) => (
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
import { CardSineLineContainer } from '@/components/card-singleline-container';
|
||||
import { EmptyCardType } from '@/components/empty/constant';
|
||||
import { EmptyAppCard } from '@/components/empty/empty';
|
||||
import { HomeIcon } from '@/components/svg-icon';
|
||||
import { Segmented, SegmentedValue } from '@/components/ui/segmented';
|
||||
import { Routes } from '@/routes';
|
||||
@ -16,14 +18,29 @@ const IconMap = {
|
||||
[Routes.Agents]: 'agents',
|
||||
};
|
||||
|
||||
const EmptyTypeMap = {
|
||||
[Routes.Chats]: EmptyCardType.Chat,
|
||||
[Routes.Searches]: EmptyCardType.Search,
|
||||
[Routes.Agents]: EmptyCardType.Agent,
|
||||
};
|
||||
|
||||
export function Applications() {
|
||||
const [val, setVal] = useState(Routes.Chats);
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const [listLength, setListLength] = useState(0);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const handleNavigate = useCallback(() => {
|
||||
navigate(val);
|
||||
}, [navigate, val]);
|
||||
const handleNavigate = useCallback(
|
||||
({ isCreate }: { isCreate?: boolean }) => {
|
||||
if (isCreate) {
|
||||
navigate(val + '?isCreate=true');
|
||||
} else {
|
||||
navigate(val);
|
||||
}
|
||||
},
|
||||
[navigate, val],
|
||||
);
|
||||
|
||||
const options = useMemo(
|
||||
() => [
|
||||
@ -36,16 +53,14 @@ export function Applications() {
|
||||
|
||||
const handleChange = (path: SegmentedValue) => {
|
||||
setVal(path as Routes);
|
||||
setListLength(0);
|
||||
setLoading(true);
|
||||
};
|
||||
|
||||
return (
|
||||
<section className="mt-12">
|
||||
<div className="flex justify-between items-center mb-5">
|
||||
<h2 className="text-2xl font-semibold flex gap-2.5">
|
||||
{/* <IconFont
|
||||
name={IconMap[val as keyof typeof IconMap]}
|
||||
className="size-8"
|
||||
></IconFont> */}
|
||||
<HomeIcon
|
||||
name={`${IconMap[val as keyof typeof IconMap]}`}
|
||||
width={'32'}
|
||||
@ -63,11 +78,36 @@ export function Applications() {
|
||||
</div>
|
||||
{/* <div className="flex flex-wrap gap-4"> */}
|
||||
<CardSineLineContainer>
|
||||
{val === Routes.Agents && <Agents></Agents>}
|
||||
{val === Routes.Chats && <ChatList></ChatList>}
|
||||
{val === Routes.Searches && <SearchList></SearchList>}
|
||||
{<SeeAllAppCard click={handleNavigate}></SeeAllAppCard>}
|
||||
{val === Routes.Agents && (
|
||||
<Agents
|
||||
setListLength={(length: number) => setListLength(length)}
|
||||
setLoading={(loading: boolean) => setLoading(loading)}
|
||||
></Agents>
|
||||
)}
|
||||
{val === Routes.Chats && (
|
||||
<ChatList
|
||||
setListLength={(length: number) => setListLength(length)}
|
||||
setLoading={(loading: boolean) => setLoading(loading)}
|
||||
></ChatList>
|
||||
)}
|
||||
{val === Routes.Searches && (
|
||||
<SearchList
|
||||
setListLength={(length: number) => setListLength(length)}
|
||||
setLoading={(loading: boolean) => setLoading(loading)}
|
||||
></SearchList>
|
||||
)}
|
||||
{listLength > 0 && (
|
||||
<SeeAllAppCard
|
||||
click={() => handleNavigate({ isCreate: false })}
|
||||
></SeeAllAppCard>
|
||||
)}
|
||||
</CardSineLineContainer>
|
||||
{listLength <= 0 && !loading && (
|
||||
<EmptyAppCard
|
||||
type={EmptyTypeMap[val as keyof typeof EmptyTypeMap]}
|
||||
onClick={() => handleNavigate({ isCreate: true })}
|
||||
/>
|
||||
)}
|
||||
{/* </div> */}
|
||||
</section>
|
||||
);
|
||||
|
||||
@ -3,13 +3,20 @@ import { MoreButton } from '@/components/more-button';
|
||||
import { RenameDialog } from '@/components/rename-dialog';
|
||||
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
||||
import { useFetchDialogList } from '@/hooks/use-chat-request';
|
||||
import { useEffect } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ChatDropdown } from '../next-chats/chat-dropdown';
|
||||
import { useRenameChat } from '../next-chats/hooks/use-rename-chat';
|
||||
|
||||
export function ChatList() {
|
||||
export function ChatList({
|
||||
setListLength,
|
||||
setLoading,
|
||||
}: {
|
||||
setListLength: (length: number) => void;
|
||||
setLoading?: (loading: boolean) => void;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const { data } = useFetchDialogList();
|
||||
const { data, loading } = useFetchDialogList();
|
||||
const { navigateToChat } = useNavigatePage();
|
||||
|
||||
const {
|
||||
@ -20,7 +27,10 @@ export function ChatList() {
|
||||
onChatRenameOk,
|
||||
chatRenameLoading,
|
||||
} = useRenameChat();
|
||||
|
||||
useEffect(() => {
|
||||
setListLength(data?.dialogs?.length || 0);
|
||||
setLoading?.(loading || false);
|
||||
}, [data, setListLength, loading, setLoading]);
|
||||
return (
|
||||
<>
|
||||
{data.dialogs.slice(0, 10).map((x) => (
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
import { CardSineLineContainer } from '@/components/card-singleline-container';
|
||||
import { EmptyCardType } from '@/components/empty/constant';
|
||||
import { EmptyAppCard } from '@/components/empty/empty';
|
||||
import { RenameDialog } from '@/components/rename-dialog';
|
||||
import { HomeIcon } from '@/components/svg-icon';
|
||||
import { CardSkeleton } from '@/components/ui/skeleton';
|
||||
@ -35,18 +37,32 @@ export function Datasets() {
|
||||
<CardSkeleton />
|
||||
</div>
|
||||
) : (
|
||||
<CardSineLineContainer>
|
||||
{kbs
|
||||
?.slice(0, 6)
|
||||
.map((dataset) => (
|
||||
<DatasetCard
|
||||
key={dataset.id}
|
||||
dataset={dataset}
|
||||
showDatasetRenameModal={showDatasetRenameModal}
|
||||
></DatasetCard>
|
||||
))}
|
||||
{<SeeAllAppCard click={navigateToDatasetList}></SeeAllAppCard>}
|
||||
</CardSineLineContainer>
|
||||
<>
|
||||
{kbs?.length > 0 && (
|
||||
<CardSineLineContainer>
|
||||
{kbs
|
||||
?.slice(0, 6)
|
||||
.map((dataset) => (
|
||||
<DatasetCard
|
||||
key={dataset.id}
|
||||
dataset={dataset}
|
||||
showDatasetRenameModal={showDatasetRenameModal}
|
||||
></DatasetCard>
|
||||
))}
|
||||
{
|
||||
<SeeAllAppCard
|
||||
click={() => navigateToDatasetList({ isCreate: false })}
|
||||
></SeeAllAppCard>
|
||||
}
|
||||
</CardSineLineContainer>
|
||||
)}
|
||||
{kbs?.length <= 0 && (
|
||||
<EmptyAppCard
|
||||
type={EmptyCardType.Dataset}
|
||||
onClick={() => navigateToDatasetList({ isCreate: true })}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
// </div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@ -3,11 +3,18 @@ import { IconFont } from '@/components/icon-font';
|
||||
import { MoreButton } from '@/components/more-button';
|
||||
import { RenameDialog } from '@/components/rename-dialog';
|
||||
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
||||
import { useEffect } from 'react';
|
||||
import { useFetchSearchList, useRenameSearch } from '../next-searches/hooks';
|
||||
import { SearchDropdown } from '../next-searches/search-dropdown';
|
||||
|
||||
export function SearchList() {
|
||||
const { data, refetch: refetchList } = useFetchSearchList();
|
||||
export function SearchList({
|
||||
setListLength,
|
||||
setLoading,
|
||||
}: {
|
||||
setListLength: (length: number) => void;
|
||||
setLoading?: (loading: boolean) => void;
|
||||
}) {
|
||||
const { data, refetch: refetchList, isLoading } = useFetchSearchList();
|
||||
const { navigateToSearch } = useNavigatePage();
|
||||
const {
|
||||
openCreateModal,
|
||||
@ -22,6 +29,11 @@ export function SearchList() {
|
||||
refetchList();
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setListLength(data?.data?.search_apps?.length || 0);
|
||||
setLoading?.(isLoading || false);
|
||||
}, [data, setListLength, isLoading, setLoading]);
|
||||
return (
|
||||
<>
|
||||
{data?.data.search_apps.slice(0, 10).map((x) => (
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
import { CardContainer } from '@/components/card-container';
|
||||
import { EmptyCardType } from '@/components/empty/constant';
|
||||
import { EmptyAppCard } from '@/components/empty/empty';
|
||||
import ListFilterBar from '@/components/list-filter-bar';
|
||||
import { RenameDialog } from '@/components/rename-dialog';
|
||||
import { Button } from '@/components/ui/button';
|
||||
@ -6,8 +8,9 @@ import { RAGFlowPagination } from '@/components/ui/ragflow-pagination';
|
||||
import { useFetchDialogList } from '@/hooks/use-chat-request';
|
||||
import { pick } from 'lodash';
|
||||
import { Plus } from 'lucide-react';
|
||||
import { useCallback } from 'react';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useSearchParams } from 'umi';
|
||||
import { ChatCard } from './chat-card';
|
||||
import { useRenameChat } from './hooks/use-rename-chat';
|
||||
|
||||
@ -35,41 +38,66 @@ export default function ChatList() {
|
||||
showChatRenameModal();
|
||||
}, [showChatRenameModal]);
|
||||
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
const isCreate = searchParams.get('isCreate') === 'true';
|
||||
useEffect(() => {
|
||||
if (isCreate) {
|
||||
handleShowCreateModal();
|
||||
searchParams.delete('isCreate');
|
||||
setSearchParams(searchParams);
|
||||
}
|
||||
}, [isCreate, handleShowCreateModal, searchParams, setSearchParams]);
|
||||
|
||||
return (
|
||||
<section className="flex flex-col w-full flex-1">
|
||||
<div className="px-8 pt-8">
|
||||
<ListFilterBar
|
||||
title={t('chat.chatApps')}
|
||||
icon="chats"
|
||||
onSearchChange={handleInputChange}
|
||||
searchString={searchString}
|
||||
>
|
||||
<Button onClick={handleShowCreateModal}>
|
||||
<Plus className="size-2.5" />
|
||||
{t('chat.createChat')}
|
||||
</Button>
|
||||
</ListFilterBar>
|
||||
</div>
|
||||
<div className="flex-1 overflow-auto">
|
||||
<CardContainer className="max-h-[calc(100dvh-280px)] overflow-auto px-8">
|
||||
{data.dialogs.map((x) => {
|
||||
return (
|
||||
<ChatCard
|
||||
key={x.id}
|
||||
data={x}
|
||||
showChatRenameModal={showChatRenameModal}
|
||||
></ChatCard>
|
||||
);
|
||||
})}
|
||||
</CardContainer>
|
||||
</div>
|
||||
<div className="mt-8 px-8 pb-8">
|
||||
<RAGFlowPagination
|
||||
{...pick(pagination, 'current', 'pageSize')}
|
||||
total={pagination.total}
|
||||
onChange={handlePageChange}
|
||||
></RAGFlowPagination>
|
||||
</div>
|
||||
{data.dialogs?.length <= 0 && (
|
||||
<div className="flex w-full items-center justify-center h-[calc(100vh-164px)]">
|
||||
<EmptyAppCard
|
||||
showIcon
|
||||
size="large"
|
||||
className="w-[480px] p-14"
|
||||
type={EmptyCardType.Chat}
|
||||
onClick={() => handleShowCreateModal()}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{data.dialogs?.length > 0 && (
|
||||
<>
|
||||
<div className="px-8 pt-8">
|
||||
<ListFilterBar
|
||||
title={t('chat.chatApps')}
|
||||
icon="chats"
|
||||
onSearchChange={handleInputChange}
|
||||
searchString={searchString}
|
||||
>
|
||||
<Button onClick={handleShowCreateModal}>
|
||||
<Plus className="size-2.5" />
|
||||
{t('chat.createChat')}
|
||||
</Button>
|
||||
</ListFilterBar>
|
||||
</div>
|
||||
<div className="flex-1 overflow-auto">
|
||||
<CardContainer className="max-h-[calc(100dvh-280px)] overflow-auto px-8">
|
||||
{data.dialogs.map((x) => {
|
||||
return (
|
||||
<ChatCard
|
||||
key={x.id}
|
||||
data={x}
|
||||
showChatRenameModal={showChatRenameModal}
|
||||
></ChatCard>
|
||||
);
|
||||
})}
|
||||
</CardContainer>
|
||||
</div>
|
||||
<div className="mt-8 px-8 pb-8">
|
||||
<RAGFlowPagination
|
||||
{...pick(pagination, 'current', 'pageSize')}
|
||||
total={pagination.total}
|
||||
onChange={handlePageChange}
|
||||
></RAGFlowPagination>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{chatRenameVisible && (
|
||||
<RenameDialog
|
||||
hideModal={hideChatRenameModal}
|
||||
|
||||
@ -17,26 +17,39 @@ import {
|
||||
import { Separator } from '@/components/ui/separator';
|
||||
import {
|
||||
useAllTestingResult,
|
||||
useChunkIsTesting,
|
||||
useSelectTestingResult,
|
||||
} from '@/hooks/knowledge-hooks';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { CheckIcon, ChevronDown, Files, XIcon } from 'lucide-react';
|
||||
import { useMemo, useState } from 'react';
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
|
||||
interface IProps {
|
||||
onTesting(documentIds: string[]): void;
|
||||
setSelectedDocumentIds(documentIds: string[]): void;
|
||||
selectedDocumentIds: string[];
|
||||
setLoading?: (loading: boolean) => void;
|
||||
}
|
||||
|
||||
const RetrievalDocuments = ({
|
||||
onTesting,
|
||||
selectedDocumentIds,
|
||||
setSelectedDocumentIds,
|
||||
setLoading,
|
||||
}: IProps) => {
|
||||
const { documents: documentsAll } = useAllTestingResult();
|
||||
const { documents } = useSelectTestingResult();
|
||||
const isTesting = useChunkIsTesting();
|
||||
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (isTesting) {
|
||||
setLoading?.(true);
|
||||
} else {
|
||||
setLoading?.(false);
|
||||
}
|
||||
}, [isTesting, setLoading]);
|
||||
|
||||
const { documents: useDocuments } = {
|
||||
documents:
|
||||
documentsAll?.length > documents?.length ? documentsAll : documents,
|
||||
@ -45,6 +58,9 @@ const RetrievalDocuments = ({
|
||||
useState<string[]>(selectedDocumentIds);
|
||||
|
||||
const multiOptions = useMemo(() => {
|
||||
if (!useDocuments || !useDocuments.length) {
|
||||
return [];
|
||||
}
|
||||
return useDocuments?.map((item) => {
|
||||
return {
|
||||
label: item.doc_name,
|
||||
@ -97,36 +113,38 @@ const RetrievalDocuments = ({
|
||||
return (
|
||||
<Popover open={isPopoverOpen} onOpenChange={setIsPopoverOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
onClick={handleTogglePopover}
|
||||
className={cn(
|
||||
'flex w-full p-1 rounded-md text-base text-text-primary border min-h-10 h-auto items-center justify-between bg-inherit hover:bg-inherit [&_svg]:pointer-events-auto',
|
||||
)}
|
||||
>
|
||||
<div className="flex justify-between items-center w-full">
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<Files />
|
||||
<span>
|
||||
{selectedDocumentIds?.length ?? 0}/{useDocuments?.length ?? 0}
|
||||
</span>
|
||||
Files
|
||||
{useDocuments?.length && (
|
||||
<Button
|
||||
onClick={handleTogglePopover}
|
||||
className={cn(
|
||||
'flex w-full p-1 rounded-md text-base text-text-primary border min-h-10 h-auto items-center justify-between bg-inherit hover:bg-inherit [&_svg]:pointer-events-auto',
|
||||
)}
|
||||
>
|
||||
<div className="flex justify-between items-center w-full">
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<Files />
|
||||
<span>
|
||||
{selectedDocumentIds?.length ?? 0}/{useDocuments?.length ?? 0}
|
||||
</span>
|
||||
Files
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<XIcon
|
||||
className="h-4 mx-2 cursor-pointer text-muted-foreground"
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
handleClear();
|
||||
}}
|
||||
/>
|
||||
<Separator
|
||||
orientation="vertical"
|
||||
className="flex min-h-6 h-full"
|
||||
/>
|
||||
<ChevronDown className="h-4 mx-2 cursor-pointer text-muted-foreground" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<XIcon
|
||||
className="h-4 mx-2 cursor-pointer text-muted-foreground"
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
handleClear();
|
||||
}}
|
||||
/>
|
||||
<Separator
|
||||
orientation="vertical"
|
||||
className="flex min-h-6 h-full"
|
||||
/>
|
||||
<ChevronDown className="h-4 mx-2 cursor-pointer text-muted-foreground" />
|
||||
</div>
|
||||
</div>
|
||||
</Button>
|
||||
</Button>
|
||||
)}
|
||||
</PopoverTrigger>
|
||||
<PopoverContent
|
||||
className="w-auto p-0"
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { EmptyType } from '@/components/empty/constant';
|
||||
import Empty from '@/components/empty/empty';
|
||||
import { FileIcon } from '@/components/icon-font';
|
||||
import { ImageWithPopover } from '@/components/image';
|
||||
import { Input } from '@/components/originui/input';
|
||||
@ -65,6 +67,7 @@ export default function SearchingView({
|
||||
// changeLanguage();
|
||||
// }, [i18n]);
|
||||
const [searchtext, setSearchtext] = useState<string>('');
|
||||
const [retrievalLoading, setRetrievalLoading] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setSearchtext(searchStr);
|
||||
@ -182,6 +185,9 @@ export default function SearchingView({
|
||||
selectedDocumentIds={selectedDocumentIds}
|
||||
setSelectedDocumentIds={setSelectedDocumentIds}
|
||||
onTesting={handleTestChunk}
|
||||
setLoading={(loading: boolean) => {
|
||||
setRetrievalLoading(loading);
|
||||
}}
|
||||
></RetrievalDocuments>
|
||||
</div>
|
||||
{/* <div className="w-full border-b border-border-default/80 my-6"></div> */}
|
||||
@ -264,6 +270,17 @@ export default function SearchingView({
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
{!isSearchStrEmpty &&
|
||||
!retrievalLoading &&
|
||||
!answer.answer &&
|
||||
!sendingLoading &&
|
||||
total <= 0 &&
|
||||
chunks?.length <= 0 &&
|
||||
relatedQuestions?.length <= 0 && (
|
||||
<div className="h-2/5 flex items-center justify-center">
|
||||
<Empty type={EmptyType.SearchData} iconWidth={80} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{total > 0 && (
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
import { CardContainer } from '@/components/card-container';
|
||||
import { EmptyCardType } from '@/components/empty/constant';
|
||||
import { EmptyAppCard } from '@/components/empty/empty';
|
||||
import { IconFont } from '@/components/icon-font';
|
||||
import ListFilterBar from '@/components/list-filter-bar';
|
||||
import { RenameDialog } from '@/components/rename-dialog';
|
||||
@ -6,6 +8,8 @@ import { Button } from '@/components/ui/button';
|
||||
import { RAGFlowPagination } from '@/components/ui/ragflow-pagination';
|
||||
import { useTranslate } from '@/hooks/common-hooks';
|
||||
import { Plus } from 'lucide-react';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import { useSearchParams } from 'umi';
|
||||
import { useFetchSearchList, useRenameSearch } from './hooks';
|
||||
import { SearchCard } from './search-card';
|
||||
|
||||
@ -27,6 +31,7 @@ export default function SearchList() {
|
||||
onSearchRenameOk,
|
||||
initialSearchName,
|
||||
} = useRenameSearch();
|
||||
|
||||
const handleSearchChange = (value: string) => {
|
||||
console.log(value);
|
||||
};
|
||||
@ -35,61 +40,86 @@ export default function SearchList() {
|
||||
refetchList();
|
||||
});
|
||||
};
|
||||
const openCreateModalFun = () => {
|
||||
const openCreateModalFun = useCallback(() => {
|
||||
// setIsEdit(false);
|
||||
showSearchRenameModal();
|
||||
};
|
||||
}, [showSearchRenameModal]);
|
||||
const handlePageChange = (page: number, pageSize: number) => {
|
||||
// setIsEdit(false);
|
||||
setSearchListParams({ ...searchParams, page, page_size: pageSize });
|
||||
};
|
||||
|
||||
const [searchUrl, setSearchUrl] = useSearchParams();
|
||||
const isCreate = searchUrl.get('isCreate') === 'true';
|
||||
useEffect(() => {
|
||||
if (isCreate) {
|
||||
openCreateModalFun();
|
||||
searchUrl.delete('isCreate');
|
||||
setSearchUrl(searchUrl);
|
||||
}
|
||||
}, [isCreate, openCreateModalFun, searchUrl, setSearchUrl]);
|
||||
|
||||
return (
|
||||
<section className="w-full h-full flex flex-col">
|
||||
<div className="px-8 pt-8">
|
||||
<ListFilterBar
|
||||
icon="searches"
|
||||
title={t('searchApps')}
|
||||
showFilter={false}
|
||||
onSearchChange={(e) => handleSearchChange(e.target.value)}
|
||||
>
|
||||
<Button
|
||||
variant={'default'}
|
||||
onClick={() => {
|
||||
openCreateModalFun();
|
||||
}}
|
||||
>
|
||||
<Plus className="mr-2 h-4 w-4" />
|
||||
{t('createSearch')}
|
||||
</Button>
|
||||
</ListFilterBar>
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<CardContainer className="max-h-[calc(100dvh-280px)] overflow-auto px-8">
|
||||
{list?.data.search_apps.map((x) => {
|
||||
return (
|
||||
<SearchCard
|
||||
key={x.id}
|
||||
data={x}
|
||||
showSearchRenameModal={() => {
|
||||
showSearchRenameModal(x);
|
||||
}}
|
||||
></SearchCard>
|
||||
);
|
||||
})}
|
||||
</CardContainer>
|
||||
</div>
|
||||
{list?.data.total && list?.data.total > 0 && (
|
||||
<div className="px-8 mb-4">
|
||||
<RAGFlowPagination
|
||||
current={searchParams.page}
|
||||
pageSize={searchParams.page_size}
|
||||
total={list?.data.total}
|
||||
onChange={handlePageChange}
|
||||
{(!list?.data?.search_apps?.length ||
|
||||
list?.data?.search_apps?.length <= 0) && (
|
||||
<div className="flex w-full items-center justify-center h-[calc(100vh-164px)]">
|
||||
<EmptyAppCard
|
||||
showIcon
|
||||
size="large"
|
||||
className="w-[480px] p-14"
|
||||
type={EmptyCardType.Search}
|
||||
onClick={() => openCreateModalFun()}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!!list?.data?.search_apps?.length && (
|
||||
<>
|
||||
<div className="px-8 pt-8">
|
||||
<ListFilterBar
|
||||
icon="searches"
|
||||
title={t('searchApps')}
|
||||
showFilter={false}
|
||||
onSearchChange={(e) => handleSearchChange(e.target.value)}
|
||||
>
|
||||
<Button
|
||||
variant={'default'}
|
||||
onClick={() => {
|
||||
openCreateModalFun();
|
||||
}}
|
||||
>
|
||||
<Plus className="mr-2 h-4 w-4" />
|
||||
{t('createSearch')}
|
||||
</Button>
|
||||
</ListFilterBar>
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<CardContainer className="max-h-[calc(100dvh-280px)] overflow-auto px-8">
|
||||
{list?.data.search_apps.map((x) => {
|
||||
return (
|
||||
<SearchCard
|
||||
key={x.id}
|
||||
data={x}
|
||||
showSearchRenameModal={() => {
|
||||
showSearchRenameModal(x);
|
||||
}}
|
||||
></SearchCard>
|
||||
);
|
||||
})}
|
||||
</CardContainer>
|
||||
</div>
|
||||
{list?.data.total && list?.data.total > 0 && (
|
||||
<div className="px-8 mb-4">
|
||||
<RAGFlowPagination
|
||||
current={searchParams.page}
|
||||
pageSize={searchParams.page_size}
|
||||
total={list?.data.total}
|
||||
onChange={handlePageChange}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{openCreateModal && (
|
||||
<RenameDialog
|
||||
hideModal={hideSearchRenameModal}
|
||||
|
||||
@ -96,62 +96,77 @@ export default function McpServer() {
|
||||
</>
|
||||
}
|
||||
>
|
||||
{isSelectionMode && (
|
||||
<section className="pb-5 flex items-center">
|
||||
<Checkbox id="all" onCheckedChange={handleSelectAll} />
|
||||
<Label
|
||||
className="pl-2 text-text-primary cursor-pointer"
|
||||
htmlFor="all"
|
||||
>
|
||||
{t('common.selectAll')}
|
||||
</Label>
|
||||
<span className="text-text-secondary pr-10 pl-5">
|
||||
{t('mcp.selected')} {selectedList.length}
|
||||
</span>
|
||||
<div className="flex gap-10 items-center">
|
||||
<Button variant={'secondary'} onClick={handleExportMcp}>
|
||||
<Upload className="size-3.5"></Upload>
|
||||
{t('mcp.export')}
|
||||
</Button>
|
||||
<ConfirmDeleteDialog
|
||||
onOk={handleDelete}
|
||||
title={t('common.delete') + ' ' + t('mcp.mcpServers')}
|
||||
content={{
|
||||
title: t('common.deleteThem'),
|
||||
node: (
|
||||
<ConfirmDeleteDialogNode
|
||||
name={`${t('mcp.selected')} ${selectedList.length} ${t('mcp.mcpServers')}`}
|
||||
></ConfirmDeleteDialogNode>
|
||||
),
|
||||
}}
|
||||
>
|
||||
<Button variant={'danger'}>
|
||||
<Trash2 className="size-3.5 cursor-pointer" />
|
||||
{t('common.delete')}
|
||||
</Button>
|
||||
</ConfirmDeleteDialog>
|
||||
</div>
|
||||
</section>
|
||||
{!data.mcp_servers?.length && (
|
||||
<div
|
||||
className="flex items-center justify-between border border-dashed border-border-button rounded-md p-10 cursor-pointer w-[590px]"
|
||||
onClick={showEditModal('')}
|
||||
>
|
||||
<div className="text-text-secondary text-sm">{t('empty.noMCP')}</div>
|
||||
<Button variant={'ghost'} className="border border-border-button">
|
||||
<Plus className="size-3.5 font-medium" /> {t('empty.addNow')}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
{!!data.mcp_servers?.length && (
|
||||
<>
|
||||
{isSelectionMode && (
|
||||
<section className="pb-5 flex items-center">
|
||||
<Checkbox id="all" onCheckedChange={handleSelectAll} />
|
||||
<Label
|
||||
className="pl-2 text-text-primary cursor-pointer"
|
||||
htmlFor="all"
|
||||
>
|
||||
{t('common.selectAll')}
|
||||
</Label>
|
||||
<span className="text-text-secondary pr-10 pl-5">
|
||||
{t('mcp.selected')} {selectedList.length}
|
||||
</span>
|
||||
<div className="flex gap-10 items-center">
|
||||
<Button variant={'secondary'} onClick={handleExportMcp}>
|
||||
<Upload className="size-3.5"></Upload>
|
||||
{t('mcp.export')}
|
||||
</Button>
|
||||
<ConfirmDeleteDialog
|
||||
onOk={handleDelete}
|
||||
title={t('common.delete') + ' ' + t('mcp.mcpServers')}
|
||||
content={{
|
||||
title: t('common.deleteThem'),
|
||||
node: (
|
||||
<ConfirmDeleteDialogNode
|
||||
name={`${t('mcp.selected')} ${selectedList.length} ${t('mcp.mcpServers')}`}
|
||||
></ConfirmDeleteDialogNode>
|
||||
),
|
||||
}}
|
||||
>
|
||||
<Button variant={'danger'}>
|
||||
<Trash2 className="size-3.5 cursor-pointer" />
|
||||
{t('common.delete')}
|
||||
</Button>
|
||||
</ConfirmDeleteDialog>
|
||||
</div>
|
||||
</section>
|
||||
)}
|
||||
<CardContainer>
|
||||
{data.mcp_servers.map((item) => (
|
||||
<McpCard
|
||||
key={item.id}
|
||||
data={item}
|
||||
selectedList={selectedList}
|
||||
handleSelectChange={handleSelectChange}
|
||||
showEditModal={showEditModal}
|
||||
isSelectionMode={isSelectionMode}
|
||||
></McpCard>
|
||||
))}
|
||||
</CardContainer>
|
||||
<div className="mt-8">
|
||||
<RAGFlowPagination
|
||||
{...pick(pagination, 'current', 'pageSize')}
|
||||
total={pagination.total || 0}
|
||||
onChange={handlePageChange}
|
||||
></RAGFlowPagination>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
<CardContainer>
|
||||
{data.mcp_servers.map((item) => (
|
||||
<McpCard
|
||||
key={item.id}
|
||||
data={item}
|
||||
selectedList={selectedList}
|
||||
handleSelectChange={handleSelectChange}
|
||||
showEditModal={showEditModal}
|
||||
isSelectionMode={isSelectionMode}
|
||||
></McpCard>
|
||||
))}
|
||||
</CardContainer>
|
||||
<div className="mt-8">
|
||||
<RAGFlowPagination
|
||||
{...pick(pagination, 'current', 'pageSize')}
|
||||
total={pagination.total || 0}
|
||||
onChange={handlePageChange}
|
||||
></RAGFlowPagination>
|
||||
</div>
|
||||
{editVisible && (
|
||||
<EditMcpDialog
|
||||
hideModal={hideEditModal}
|
||||
|
||||
@ -75,7 +75,9 @@ export const ModelProviderCard: FC<IModelCardProps> = ({
|
||||
<div className="flex items-center space-x-3">
|
||||
<LlmIcon name={item.name} />
|
||||
<div>
|
||||
<div className="font-medium text-xl">{item.name}</div>
|
||||
<div className="font-medium text-xl text-text-primary">
|
||||
{item.name}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user