refactor(ui): adjust dataset page styles (#13452)

### What problem does this PR solve?

- Adjust UI styles in **Dataset** pages.
- Adjust several shared components styles
- Modify files and directory structure in `src/layouts`

### Type of change

- [x] Refactoring
This commit is contained in:
Jimmy Ben Klieve
2026-03-06 21:13:14 +08:00
committed by GitHub
parent 7166a7e50e
commit 094eae3cf5
44 changed files with 589 additions and 543 deletions

View File

@@ -1,56 +0,0 @@
import { useIsDarkTheme, useTheme } from '@/components/theme-provider';
import { ThemeEnum } from '@/constants/common';
import { cn } from '@/lib/utils';
import { Root, Thumb } from '@radix-ui/react-switch';
import { LucideMoon, LucideSun } from 'lucide-react';
import { forwardRef } from 'react';
const ThemeSwitch = forwardRef<
React.ElementRef<typeof Root>,
React.ComponentPropsWithoutRef<typeof Root>
>(({ className, ...props }, ref) => {
const { setTheme } = useTheme();
const isDark = useIsDarkTheme();
return (
<Root
ref={ref}
className={cn(
'group/theme-switch relative rounded-full outline-none self-center focus-visible:ring-1 focus-visible:ring-accent-primary',
className,
)}
{...props}
checked={isDark}
onCheckedChange={(value) =>
setTheme(value ? ThemeEnum.Dark : ThemeEnum.Light)
}
>
<div className="self-center p-3 py-2 rounded-full bg-bg-card transition-[background-color]">
<div className="h-full flex items-center justify-between gap-4 relative z-[1] text-text-disabled transition-[text-color]">
<LucideSun
className={cn('size-[1em]', !isDark && 'text-text-primary')}
/>
<LucideMoon
className={cn('size-[1em]', isDark && 'text-text-primary')}
/>
</div>
</div>
<Thumb
className={cn(
'absolute top-0 left-0 w-[calc(50%+.25rem)] p-0.5 h-full rounded-full overflow-hidden',
'transition-all ease-out',
'group-hover/theme-switch:w-[calc(50%+.66rem)] group-focus-visible/theme-switch:w-[calc(50%+.66rem)]',
{
'left-[calc(50%-.25rem)] group-hover/theme-switch:left-[calc(50%-.66rem)] group-focus-visible/theme-switch:left-[calc(50%-.66rem)]':
isDark,
},
)}
>
<div className="size-full rounded-full bg-bg-base shadow-md transition-colors ease-out" />
</Thumb>
</Root>
);
});
export default ThemeSwitch;

View File

@@ -20,7 +20,7 @@ import { getSystemVersion, logout } from '@/services/admin-service';
import authorizationUtil from '@/utils/authorization-util';
import ThemeSwitch from '../components/theme-switch';
import ThemeSwitch from '../../../components/theme-switch';
import { IS_ENTERPRISE } from '../utils';
import { CurrentUserInfoContext } from './root-layout';

View File

@@ -33,8 +33,8 @@ import authorizationUtil from '@/utils/authorization-util';
import { login } from '@/services/admin-service';
import ThemeSwitch from '../../components/theme-switch';
import { BgSvg } from '../login-next/bg';
import ThemeSwitch from './components/theme-switch';
import { CurrentUserInfoContext } from './layouts/root-layout';

View File

@@ -50,25 +50,23 @@ export function DatasetActionCell({
}, [record, showRenameModal]);
return (
<section className="flex gap-4 items-center text-text-sub-title-invert opacity-0 group-hover:opacity-100 transition-opacity">
<div
className="
flex gap-2 items-center opacity-0
transition-opacity group-hover:opacity-100 group-focus-within:opacity-100"
>
<Button
variant="transparent"
className="border-none hover:bg-bg-card text-text-primary"
size={'sm'}
size="icon-xs"
variant="ghost"
disabled={isRunning}
onClick={handleRename}
>
<PenLine />
<PenLine className="size-[1em]" />
</Button>
<HoverCard>
<HoverCardTrigger>
<Button
variant="transparent"
className="border-none hover:bg-bg-card text-text-primary"
disabled={isRunning}
size={'sm'}
>
<Eye />
<Button size="icon-xs" variant="ghost" disabled={isRunning}>
<Eye className="size-[1em]" />
</Button>
</HoverCardTrigger>
<HoverCardContent className="w-[40vw] max-h-[40vh] overflow-auto">
@@ -94,26 +92,24 @@ export function DatasetActionCell({
{isVirtualDocument || (
<Button
variant="transparent"
className="border-none hover:bg-bg-card text-text-primary"
size="icon-xs"
variant="ghost"
onClick={onDownloadDocument}
disabled={isRunning}
size={'sm'}
>
<Download />
<Download className="size-[1em]" />
</Button>
)}
<ConfirmDeleteDialog onOk={handleRemove}>
<Button
data-testid="document-delete"
variant="transparent"
className="border-none hover:bg-bg-card text-text-primary"
size={'sm'}
size="icon-xs"
variant="ghost"
disabled={isRunning}
>
<Trash2 />
<Trash2 className="size-[1em]" />
</Button>
</ConfirmDeleteDialog>
</section>
</div>
);
}

View File

@@ -199,25 +199,27 @@ const Generate: React.FC<GenerateProps> = (props) => {
return (
<DropdownMenu open={open} onOpenChange={handleOpenChange}>
<DropdownMenuTrigger asChild disabled={disabled}>
<Tooltip>
<TooltipTrigger asChild>
<Button
disabled={disabled}
className={cn(disabled && '!cursor-not-allowed')}
variant="transparent"
size="icon"
onClick={() => {
if (!disabled) {
handleOpenChange(!open);
}
}}
>
<WandSparkles />
</Button>
</TooltipTrigger>
<div>
<Tooltip>
<TooltipTrigger asChild>
<Button
disabled={disabled}
className={cn(disabled && '!cursor-not-allowed')}
variant="transparent"
size="icon"
onClick={() => {
if (!disabled) {
handleOpenChange(!open);
}
}}
>
<WandSparkles />
</Button>
</TooltipTrigger>
<TooltipContent>{t('knowledgeDetails.generate')}</TooltipContent>
</Tooltip>
<TooltipContent>{t('knowledgeDetails.generate')}</TooltipContent>
</Tooltip>
</div>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-[380px] p-5 flex flex-col gap-2 ">
{Object.values(GenerateType).map((name) => {

View File

@@ -6,6 +6,7 @@ import { FileUploadDialog } from '@/components/file-upload-dialog';
import ListFilterBar from '@/components/list-filter-bar';
import { RenameDialog } from '@/components/rename-dialog';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader } from '@/components/ui/card';
import {
DropdownMenu,
DropdownMenuContent,
@@ -16,7 +17,7 @@ import {
import { useRowSelection } from '@/hooks/logic-hooks/use-row-selection';
import { useFetchDocumentList } from '@/hooks/use-document-request';
import { useFetchKnowledgeBaseConfiguration } from '@/hooks/use-knowledge-request';
import { Upload } from 'lucide-react';
import { LucidePlus } from 'lucide-react';
import { useEffect, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { MetadataType } from '../components/metedata/constant';
@@ -136,10 +137,12 @@ export default function Dataset() {
});
return (
<>
<section className="p-5 min-w-[880px]">
<Card
as="article"
className="mb-5 mr-5 min-w-[880px] bg-transparent shadow-none"
>
<CardHeader as="header" className="p-5 space-y-0">
<ListFilterBar
title={t('header.dataset')}
onSearchChange={handleInputChange}
searchString={searchString}
value={filterValue}
@@ -147,12 +150,15 @@ export default function Dataset() {
onChange={handleFilterSubmit}
onOpenChange={onOpenChange}
filters={filters}
className="items-end"
leftPanel={
<div className="items-start">
<div className="pb-1">{t('knowledgeDetails.subbarFiles')}</div>
<div className="text-text-secondary text-sm">
<div>
<h1 className="leading-normal font-medium">
{t('knowledgeDetails.subbarFiles')}
</h1>
<p className="text-text-secondary text-sm font-normal">
{t('knowledgeDetails.datasetDescription')}
</div>
</p>
</div>
}
preChildren={<Generate disabled={!(dataSetData.chunk_num > 0)} />}
@@ -190,12 +196,12 @@ export default function Dataset() {
>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button size={'sm'}>
<Upload />
<Button size="default">
<LucidePlus />
{t('knowledgeDetails.addFile')}
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-56">
<DropdownMenuContent className="w-auto min-w-40" align="end">
<DropdownMenuItem onClick={showDocumentUploadModal}>
{t('fileManager.uploadFile')}
</DropdownMenuItem>
@@ -206,12 +212,17 @@ export default function Dataset() {
</DropdownMenuContent>
</DropdownMenu>
</ListFilterBar>
{rowSelectionIsEmpty || (
<BulkOperateBar
className="!mt-2.5 !-mb-2.5"
list={updatedList as BulkOperateItemType[]}
count={selectedCount}
></BulkOperateBar>
/>
)}
</CardHeader>
<CardContent className="px-5 py-0">
<DatasetTable
documents={documents}
pagination={pagination}
@@ -220,7 +231,8 @@ export default function Dataset() {
setRowSelection={setRowSelection}
showManageMetadataModal={showManageMetadataModal}
loading={loading}
></DatasetTable>
/>
{documentUploadVisible && (
<FileUploadDialog
hideModal={hideDocumentUploadModal}
@@ -282,7 +294,7 @@ export default function Dataset() {
hideModal={hideReparseDialogModal}
></ReparseDialog>
)}
</section>
</>
</CardContent>
</Card>
);
}

View File

@@ -84,9 +84,8 @@ export const PopoverContent = ({ record }: IProps) => {
export function ParsingCard({ record, handleShowLog }: IProps) {
return (
<Button
variant={'transparent'}
className="border-none"
size={'sm'}
variant="ghost"
size="icon-xs"
onClick={() => handleShowLog?.(record)}
>
<Dot run={record.run}></Dot>

View File

@@ -1,4 +1,5 @@
import { IconFontFill } from '@/components/icon-font';
import { Button } from '@/components/ui/button';
import {
DropdownMenu,
DropdownMenuContent,
@@ -24,10 +25,10 @@ import { useHandleRunDocumentByIds } from './use-run-document';
import { isParserRunning } from './utils';
const IconMap = {
[RunningStatus.UNSTART]: (
<IconFontFill name="play" className="text-accent-primary" />
<IconFontFill name="play" className="text-accent-primary size-[1em]" />
),
[RunningStatus.RUNNING]: (
<CircleX size={14} color="rgba(var(--state-error))" />
<CircleX color="rgba(var(--state-error))" className="size-[1em]" />
),
[RunningStatus.CANCEL]: (
<IconFontFill name="reparse" className="text-accent-primary" />
@@ -49,25 +50,63 @@ const ParseStatusStateMap = {
[RunningStatus.SCHEDULE]: 'running',
} as const;
export function ParsingStatusCell({
export function ParseDropdownButton({
record,
showChangeParserModal,
// showSetMetaModal,
}: {
record: IDocumentInfo;
} & UseChangeDocumentParserShowType) {
const { t } = useTranslation();
const { pipeline_id, pipeline_name, parser_id } = record;
const handleShowChangeParserModal = useCallback(() => {
showChangeParserModal(record);
}, [record, showChangeParserModal]);
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<div>
<Tooltip>
<TooltipTrigger asChild>
<Button variant="static" size="auto" className="capitalize">
{pipeline_id
? pipeline_name || pipeline_id
: parser_id === 'naive'
? 'general'
: parser_id}
</Button>
</TooltipTrigger>
<TooltipContent>
<p className="capitalize">
{pipeline_id
? pipeline_name || pipeline_id
: parser_id === 'naive'
? 'general'
: parser_id}
</p>
</TooltipContent>
</Tooltip>
</div>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem onClick={handleShowChangeParserModal}>
{t('knowledgeDetails.dataPipeline')}
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}
export function ParsingStatusCell({
record,
showLog,
}: {
record: IDocumentInfo;
showLog: (record: IDocumentInfo) => void;
} & UseChangeDocumentParserShowType) {
const { t } = useTranslation();
const {
run,
parser_id,
pipeline_id,
pipeline_name,
progress,
chunk_num,
id,
} = record;
const { run, progress, chunk_num, id } = record;
const operationIcon = IconMap[run];
const p = Number((progress * 100).toFixed(2));
const {
@@ -86,10 +125,6 @@ export function ParsingStatusCell({
handleRunDocumentByIds(record.id, isRunning, option);
};
const handleShowChangeParserModal = useCallback(() => {
showChangeParserModal(record);
}, [record, showChangeParserModal]);
const showParse = useMemo(() => {
return record.type !== DocumentType.Virtual;
}, [record]);
@@ -103,71 +138,25 @@ export function ParsingStatusCell({
data-testid="document-parse-status"
data-state={ParseStatusStateMap[run] ?? 'unknown'}
>
<div className="text-ellipsis w-[100px] flex items-center justify-between">
<DropdownMenu>
<DropdownMenuTrigger>
<Tooltip>
<TooltipTrigger asChild>
<div className="border-none truncate max-w-32 cursor-pointer px-2 py-1 rounded-sm hover:bg-bg-card">
{pipeline_id
? pipeline_name || pipeline_id
: parser_id === 'naive'
? 'general'
: parser_id}
</div>
</TooltipTrigger>
<TooltipContent>
<p>
{pipeline_id
? pipeline_name || pipeline_id
: parser_id === 'naive'
? 'general'
: parser_id}
</p>
</TooltipContent>
</Tooltip>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem onClick={handleShowChangeParserModal}>
{t('knowledgeDetails.dataPipeline')}
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
{showParse && (
<div className="flex items-center gap-3">
<Separator orientation="vertical" className="h-2.5" />
{!isParserRunning(run) && (
// <ReparseDialog
// hidden={isZeroChunk || isRunning}
// handleOperationIconClick={handleOperationIconClick}
// chunk_num={chunk_num}
// >
<div
className="cursor-pointer flex items-center gap-3"
onClick={() => {
showReparseDialogModal();
}}
>
{!isParserRunning(run) && operationIcon}
</div>
// {/* </ReparseDialog> */}
)}
<div className="flex items-center gap-2">
<Separator orientation="vertical" className="h-[1em]" />
{isParserRunning(run) ? (
<>
<div
className="flex items-center gap-1 cursor-pointer"
<Button
size="auto"
variant="static"
onClick={() => handleShowLog(record)}
>
<Progress value={p} className="h-1 flex-1 min-w-10" />
{p}%
</div>
<div
className="cursor-pointer flex items-center gap-3"
onClick={() => {
showReparseDialogModal();
}}
</Button>
<Button
variant="ghost"
size="icon-xs"
onClick={() => showReparseDialogModal()}
// onClick={
// isZeroChunk || isRunning
// ? handleOperationIconClick(false)
@@ -175,13 +164,22 @@ export function ParsingStatusCell({
// }
>
{operationIcon}
</div>
</Button>
</>
) : (
<ParsingCard
record={record}
handleShowLog={handleShowLog}
></ParsingCard>
<>
<Button
variant="ghost"
size="icon-xs"
onClick={() => {
showReparseDialogModal();
}}
>
{operationIcon}
</Button>
<ParsingCard record={record} handleShowLog={handleShowLog} />
</>
)}
</div>
)}

View File

@@ -10,12 +10,12 @@ import {
} from '@/hooks/use-document-request';
import { IDocumentInfo } from '@/interfaces/database/document';
import {
Ban,
CircleCheck,
CircleX,
Cylinder,
Play,
Trash2,
LucideCircleX,
LucideCylinder,
LucidePlayCircle,
LucideToggleLeft,
LucideToggleRight,
LucideTrash2,
} from 'lucide-react';
import { useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
@@ -117,36 +117,36 @@ export function useBulkOperateDataset({
{
id: 'enabled',
label: t('knowledgeDetails.enabled'),
icon: <CircleCheck />,
icon: <LucideToggleRight />,
onClick: handleEnableClick,
},
{
id: 'disabled',
label: t('knowledgeDetails.disabled'),
icon: <Ban />,
icon: <LucideToggleLeft />,
onClick: handleDisableClick,
},
{
id: 'run',
label: t('knowledgeDetails.run'),
icon: <Play />,
icon: <LucidePlayCircle />,
onClick: () => showModal(),
},
{
id: 'cancel',
label: t('knowledgeDetails.cancel'),
icon: <CircleX />,
icon: <LucideCircleX />,
onClick: handleCancelClick,
},
{
id: 'batch-metadata',
label: t('knowledgeDetails.metadata.metadata'),
icon: <Cylinder />,
icon: <LucideCylinder />,
},
{
id: 'delete',
label: t('common.delete'),
icon: <Trash2 />,
icon: <LucideTrash2 />,
onClick: async () => {
const code = await handleDelete();
if (code === 0) {

View File

@@ -11,15 +11,14 @@ import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
import { useSetDocumentStatus } from '@/hooks/use-document-request';
import { IDocumentInfo } from '@/interfaces/database/document';
import { cn } from '@/lib/utils';
import { useDataSourceInfo } from '@/pages/user-setting/data-source/constant';
import { formatDate } from '@/utils/date';
import { ColumnDef } from '@tanstack/table-core';
import { ArrowUpDown, MonitorUp } from 'lucide-react';
import { ArrowUpDown } from 'lucide-react';
import { useTranslation } from 'react-i18next';
import { MetadataType } from '../components/metedata/constant';
import { ShowManageMetadataModalProps } from '../components/metedata/interface';
import { DatasetActionCell } from './dataset-action-cell';
import { ParsingStatusCell } from './parsing-status-cell';
import { ParseDropdownButton, ParsingStatusCell } from './parsing-status-cell';
import { UseChangeDocumentParserShowType } from './use-change-document-parser';
import { UseRenameDocumentShowType } from './use-rename-document';
@@ -38,7 +37,7 @@ export function useDatasetTableColumns({
const { t } = useTranslation('translation', {
keyPrefix: 'knowledgeDetails',
});
const { dataSourceInfo } = useDataSourceInfo();
// const { dataSourceInfo } = useDataSourceInfo();
const { navigateToChunkParsedResult } = useNavigatePage();
const { setDocumentStatus } = useSetDocumentStatus();
@@ -47,6 +46,7 @@ export function useDatasetTableColumns({
id: 'select',
header: ({ table }) => (
<Checkbox
className="size-3"
checked={
table.getIsAllPageRowsSelected() ||
(table.getIsSomePageRowsSelected() && 'indeterminate')
@@ -57,6 +57,7 @@ export function useDatasetTableColumns({
),
cell: ({ row }) => (
<Checkbox
className="size-3"
checked={row.getIsSelected()}
onCheckedChange={(value) => row.toggleSelected(!!value)}
aria-label="Select row"
@@ -69,14 +70,19 @@ export function useDatasetTableColumns({
accessorKey: 'name',
header: ({ column }) => {
return (
<Button
variant="transparent"
className="border-none"
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
>
<div className="flex items-center gap-1">
{t('name')}
<ArrowUpDown />
</Button>
<Button
variant="ghost"
size="icon-xs"
onClick={() =>
column.toggleSorting(column.getIsSorted() === 'asc')
}
>
<ArrowUpDown />
</Button>
</div>
);
},
meta: { cellClassName: 'max-w-[20vw]' },
@@ -87,7 +93,7 @@ export function useDatasetTableColumns({
<Tooltip>
<TooltipTrigger asChild>
<div
className="flex gap-2 cursor-pointer"
className="flex items-center gap-2 cursor-pointer"
onClick={navigateToChunkParsedResult(
row.original.id,
row.original.kb_id,
@@ -108,22 +114,31 @@ export function useDatasetTableColumns({
accessorKey: 'create_time',
header: ({ column }) => {
return (
<Button
variant="transparent"
className="border-none"
onClick={() => column.toggleSorting(column.getIsSorted() === 'asc')}
>
<div className="flex items-center gap-1">
{t('uploadDate')}
<ArrowUpDown />
</Button>
<Button
variant="ghost"
size="icon-xs"
onClick={() =>
column.toggleSorting(column.getIsSorted() === 'asc')
}
>
<ArrowUpDown />
</Button>
</div>
);
},
cell: ({ row }) => (
<div className="lowercase">
<time
className="lowercase"
dateTime={new Date(row.getValue('create_time')).toISOString()}
>
{formatDate(row.getValue('create_time'))}
</div>
</time>
),
},
/*
{
accessorKey: 'source_from',
header: t('source'),
@@ -146,6 +161,7 @@ export function useDatasetTableColumns({
</div>
),
},
*/
{
accessorKey: 'status',
header: t('enabled'),
@@ -174,8 +190,9 @@ export function useDatasetTableColumns({
cell: ({ row }) => {
const length = Object.keys(row.getValue('meta_fields') || {}).length;
return (
<div
className="capitalize cursor-pointer"
<Button
variant="static"
size="auto"
onClick={() => {
showManageMetadataModal({
// metadata: util.JSONToMetaDataTableData(
@@ -209,7 +226,7 @@ export function useDatasetTableColumns({
}}
>
{length + ' fields'}
</div>
</Button>
);
},
},
@@ -217,13 +234,25 @@ export function useDatasetTableColumns({
accessorKey: 'run',
header: t('Parse'),
// meta: { cellClassName: 'min-w-[20vw]' },
cell: ({ row }) => {
return (
<ParseDropdownButton
record={row.original}
showChangeParserModal={showChangeParserModal}
/>
);
},
},
{
id: 'run-status',
header: '',
cell: ({ row }) => {
return (
<ParsingStatusCell
record={row.original}
showChangeParserModal={showChangeParserModal}
showLog={showLog}
></ParsingStatusCell>
/>
);
},
},
@@ -238,7 +267,7 @@ export function useDatasetTableColumns({
<DatasetActionCell
record={record}
showRenameModal={showRenameModal}
></DatasetActionCell>
/>
);
},
},

View File

@@ -45,7 +45,7 @@ export function SeeAllCard() {
return (
<Card
className="w-full flex-none h-full cursor-pointer"
onClick={navigateToDatasetList}
onClick={() => navigateToDatasetList({ isCreate: false })}
>
<CardContent className="p-2.5 pt-1 w-full h-full flex items-center justify-center gap-1.5 text-text-secondary">
{t('common.seeAll')} <ChevronRight className="size-4" />

View File

@@ -20,14 +20,16 @@ export function ApplicationCard({
moreDropdown,
}: ApplicationCardProps) {
return (
<Card className="w-[264px]" onClick={onClick}>
<CardContent className="p-2.5 group flex justify-between w-full">
<Card className="w-[264px]" onClick={onClick} as="article">
<CardContent className="p-2.5 group flex justify-between w-full">
<div className="flex items-center gap-2.5 w-full">
<RAGFlowAvatar
className="size-14 rounded-lg"
avatar={app.avatar}
name={app.title || 'CN'}
></RAGFlowAvatar>
aria-hidden="true"
/>
<div className="flex-1">
<h3 className="text-sm font-normal line-clamp-1 mb-1 text-ellipsis w-[160px] overflow-hidden">
{app.title}
@@ -37,6 +39,7 @@ export function ApplicationCard({
</p>
</div>
</div>
{moreDropdown}
</CardContent>
</Card>
@@ -49,7 +52,11 @@ export type SeeAllAppCardProps = {
export function SeeAllAppCard({ click }: SeeAllAppCardProps) {
return (
<Card className="w-full min-h-[76px] cursor-pointer" onClick={click}>
<Card
className="w-full min-h-[76px] cursor-pointer"
onClick={click}
tabIndex={0}
>
<CardContent className="p-2.5 pt-1 w-full h-full flex items-center justify-center gap-1.5 text-text-secondary">
{t('common.seeAll')} <ChevronRight className="size-4" />
</CardContent>

View File

@@ -47,10 +47,10 @@ export function Applications() {
const options = useMemo(
() => [
{ value: Routes.Chats, label: t('chat.chatApps') },
{ value: Routes.Searches, label: t('search.searchApps') },
{ value: Routes.Chats, label: t('header.chat') },
{ value: Routes.Searches, label: t('header.search') },
{ value: Routes.Agents, label: t('header.flow') },
{ value: Routes.Memories, label: t('memories.memory') },
{ value: Routes.Memories, label: t('header.memories') },
],
[t],
);
@@ -63,55 +63,57 @@ export function Applications() {
return (
<section className="mt-12">
<div className="flex justify-between items-center mb-5">
<h2 className="text-2xl font-semibold flex gap-2.5">
<header className="flex justify-between items-center mb-2.5">
<h2 className="text-2xl font-semibold">
<HomeIcon
imgClass="me-2.5"
name={`${IconMap[val as keyof typeof IconMap]}`}
width={'32'}
width={24}
/>
{options.find((x) => x.value === val)?.label}
</h2>
<Segmented
buttonSize="sm"
options={options}
value={val}
onChange={handleChange}
buttonSize="xl"
// className="bg-bg-card border border-border-button rounded-lg"
// activeClassName="bg-text-primary border-none rounded-lg"
></Segmented>
</div>
/>
</header>
{/* <div className="flex flex-wrap gap-4"> */}
<CardSineLineContainer>
{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>
/>
)}
{val === Routes.Memories && (
<MemoryList
setListLength={(length: number) => setListLength(length)}
setLoading={(loading: boolean) => setLoading(loading)}
></MemoryList>
/>
)}
{listLength > 0 && (
<SeeAllAppCard
click={() => handleNavigate({ isCreate: false })}
></SeeAllAppCard>
<SeeAllAppCard click={() => handleNavigate({ isCreate: false })} />
)}
</CardSineLineContainer>
{listLength <= 0 && !loading && (
<EmptyAppCard
type={EmptyTypeMap[val as keyof typeof EmptyTypeMap]}

View File

@@ -42,9 +42,11 @@ export function Banner() {
export function NextBanner() {
const { t } = useTranslation();
return (
<h1 className="text-5xl font-bold leading-normal">
<span className="text-text-primary">{t('header.welcome')} </span>
<span className="text-transparent bg-clip-text bg-gradient-to-l from-[#40EBE3] to-[#4A51FF]">
<h1 className="text-5xl leading-normal">
<span className="font-semibold text-text-primary">
{t('header.welcome')}{' '}
</span>
<span className="font-bold text-transparent bg-clip-text bg-gradient-to-l from-[#40EBE3] to-[#4A51FF]">
RAGFlow
</span>
</h1>

View File

@@ -26,12 +26,15 @@ export function Datasets() {
return (
<section>
<h2 className="text-2xl font-semibold mb-6 flex gap-2.5 items-center">
{/* <IconFont name="data" className="size-8"></IconFont> */}
<HomeIcon name="datasets" width={'32'} />
{t('header.dataset')}
</h2>
<div className="">
<header>
<h2 className="leading-8 text-2xl font-semibold mb-2.5">
{/* <IconFont name="data" className="size-8"></IconFont> */}
<HomeIcon imgClass="me-2.5" name="datasets" width={24} />
{t('header.dataset')}
</h2>
</header>
<div>
{loading ? (
<div className="flex-1">
<CardSkeleton />
@@ -40,15 +43,13 @@ export function Datasets() {
<>
{kbs?.length > 0 && (
<CardSineLineContainer>
{kbs
?.slice(0, 6)
.map((dataset) => (
<DatasetCard
key={dataset.id}
dataset={dataset}
showDatasetRenameModal={showDatasetRenameModal}
></DatasetCard>
))}
{kbs?.slice(0, 6).map((dataset) => (
<DatasetCard
key={dataset.id}
dataset={dataset}
showDatasetRenameModal={showDatasetRenameModal}
></DatasetCard>
))}
{
<SeeAllAppCard
click={() => navigateToDatasetList({ isCreate: false })}
@@ -66,13 +67,14 @@ export function Datasets() {
// </div>
)}
</div>
{datasetRenameVisible && (
<RenameDialog
hideModal={hideDatasetRenameModal}
onOk={onDatasetRenameOk}
initialName={initialDatasetName}
loading={datasetRenameLoading}
></RenameDialog>
/>
)}
</section>
);

View File

@@ -1,4 +1,4 @@
import { PageContainer } from '@/layouts/page-container';
import { PageContainer } from '@/layouts/components/page-container';
import { Applications } from './applications';
import { NextBanner } from './banner';
import { Datasets } from './datasets';
@@ -6,12 +6,14 @@ import { Datasets } from './datasets';
const Home = () => {
return (
<PageContainer>
<header className="mb-8">
<NextBanner />
</header>
<article>
<header className="mb-8">
<NextBanner />
</header>
<Datasets />
<Applications />
<Datasets />
<Applications />
</article>
</PageContainer>
);
};

View File

@@ -6,7 +6,7 @@ import {
useGetChatSearchParams,
} from '@/hooks/use-chat-request';
import { IClientConversation } from '@/interfaces/database/chat';
import { NextLayoutContainer } from '@/layouts/next';
import { RootLayoutContainer } from '@/layouts/root-layout';
import { cn } from '@/lib/utils';
import { useMount } from 'ahooks';
import { isEmpty } from 'lodash';
@@ -106,7 +106,7 @@ export default function Chat() {
}
return (
<NextLayoutContainer>
<RootLayoutContainer>
<section className="h-full flex flex-col" data-testid="chat-detail">
<article className="flex flex-1 min-h-0 pb-9">
<Sessions handleConversationCardClick={handleSessionClick}></Sessions>
@@ -146,6 +146,6 @@ export default function Chat() {
</Card>
</article>
</section>
</NextLayoutContainer>
</RootLayoutContainer>
);
}

View File

@@ -1,6 +1,6 @@
import { IconFontFill } from '@/components/icon-font';
import { RAGFlowAvatar } from '@/components/ragflow-avatar';
import ThemeToggle from '@/components/theme-toggle';
import ThemeSwitch from '@/components/theme-switch';
import { Button } from '@/components/ui/button';
import { Domain } from '@/constants/common';
import { useSecondPathName } from '@/hooks/route-hook';
@@ -103,15 +103,10 @@ export function SideBar() {
<div className="mr-2 px-2 text-accent-primary rounded-md">
{version}
</div>
<ThemeToggle />
<ThemeSwitch />
</div>
<Button
variant="ghost"
className="w-full gap-3 bg-bg-base border border-border-button"
onClick={() => {
logout();
}}
>
<Button block size="lg" variant="transparent" onClick={() => logout()}>
{t('setting.logout')}
</Button>
</div>