mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-01-19 11:45:10 +08:00
Fix: Issues and style fixes related to the 'Memory' page (#12469)
### What problem does this PR solve? Fix: Some bugs - Issues and style fixes related to the 'Memory' page - Data source icon replacement - Build optimization ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)
This commit is contained in:
@ -1,3 +0,0 @@
|
||||
<svg width="1024" height="1024" viewBox="0 0 1024 1024" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8C0 11.54 2.29 14.53 5.47 15.59C5.87 15.66 6.02 15.42 6.02 15.21C6.02 15.02 6.01 14.39 6.01 13.72C4 14.09 3.48 13.23 3.32 12.78C3.23 12.55 2.84 11.84 2.5 11.65C2.22 11.5 1.82 11.13 2.49 11.12C3.12 11.11 3.57 11.7 3.72 11.94C4.44 13.15 5.59 12.81 6.05 12.6C6.12 12.08 6.33 11.73 6.56 11.53C4.78 11.33 2.92 10.64 2.92 7.58C2.92 6.71 3.23 5.99 3.74 5.43C3.66 5.23 3.38 4.41 3.82 3.31C3.82 3.31 4.49 3.1 6.02 4.13C6.66 3.95 7.34 3.86 8.02 3.86C8.7 3.86 9.38 3.95 10.02 4.13C11.55 3.09 12.22 3.31 12.22 3.31C12.66 4.41 12.38 5.23 12.3 5.43C12.81 5.99 13.12 6.7 13.12 7.58C13.12 10.65 11.25 11.33 9.47 11.53C9.76 11.78 10.01 12.26 10.01 13.01C10.01 14.08 10 14.94 10 15.21C10 15.42 10.15 15.67 10.55 15.59C13.71 14.53 16 11.53 16 8C16 3.58 12.42 0 8 0Z" transform="scale(64)" fill="#1B1F23"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 968 B |
@ -1,7 +0,0 @@
|
||||
<svg stroke="currentColor" fill="none" stroke-width="2" viewBox="0 0 24 24"
|
||||
stroke-linecap="round" stroke-linejoin="round"
|
||||
class="text-text-04" height="32" width="32"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path>
|
||||
<polyline points="22,6 12,13 2,6"></polyline>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 360 B |
@ -97,6 +97,7 @@ export interface FormFieldConfig {
|
||||
schema?: ZodSchema;
|
||||
shouldRender?: (formValues: any) => boolean;
|
||||
labelClassName?: string;
|
||||
className?: string;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
|
||||
@ -10,7 +10,10 @@ export const MoreButton = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
ref={ref}
|
||||
variant="ghost"
|
||||
size={size || 'icon'}
|
||||
className={cn('invisible group-hover:visible size-3.5', className)}
|
||||
className={cn(
|
||||
'invisible group-hover:visible size-3.5 bg-transparent group-hover:bg-transparent',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<Ellipsis />
|
||||
|
||||
@ -45,7 +45,7 @@ export function RAGFlowFormItem({
|
||||
<FormItem
|
||||
className={cn(
|
||||
{
|
||||
'flex items-center w-full': horizontal,
|
||||
'flex items-center w-full space-y-0': horizontal,
|
||||
},
|
||||
className,
|
||||
)}
|
||||
|
||||
@ -3,9 +3,12 @@ import * as React from 'react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { Eye, EyeOff, Search } from 'lucide-react';
|
||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export interface InputProps
|
||||
extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'prefix'> {
|
||||
export interface InputProps extends Omit<
|
||||
React.InputHTMLAttributes<HTMLInputElement>,
|
||||
'prefix'
|
||||
> {
|
||||
value?: string | number | readonly string[] | undefined;
|
||||
prefix?: React.ReactNode;
|
||||
suffix?: React.ReactNode;
|
||||
@ -157,8 +160,13 @@ export interface ExpandedInputProps extends InputProps {}
|
||||
const ExpandedInput = Input;
|
||||
|
||||
const SearchInput = (props: InputProps) => {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<Input {...props} prefix={<Search className="ml-2 mr-1 size-[1em]" />} />
|
||||
<Input
|
||||
placeholder={t('common.search')}
|
||||
{...props}
|
||||
prefix={<Search className="ml-2 mr-1 size-[1em]" />}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -129,6 +129,7 @@ Procedural Memory: Learned skills, habits, and automated procedures.`,
|
||||
},
|
||||
memory: {
|
||||
messages: {
|
||||
forget: 'Forget',
|
||||
forgetMessageTip: 'Are you sure you want to forget?',
|
||||
messageDescription:
|
||||
'Memory extract is configured with Prompts and Temperature from Advanced Settings.',
|
||||
|
||||
@ -101,7 +101,7 @@ export default {
|
||||
embeddingModelTooltip:
|
||||
'将文本转换为数值向量,用于语义相似度搜索和记忆检索。',
|
||||
embeddingModelError: '记忆类型为必填项,且"原始"类型不可删除。',
|
||||
memoryTypeTooltip: `原始: 用户与代理之间的原始对话内容(默认必需)。
|
||||
memoryTypeTooltip: `原始: 用户与智能体之间的原始对话内容(默认必需)。
|
||||
语义记忆: 关于用户和世界的通用知识和事实。
|
||||
情景记忆: 带时间戳的特定事件和经历记录。
|
||||
程序记忆: 学习的技能、习惯和自动化程序。`,
|
||||
@ -118,15 +118,16 @@ export default {
|
||||
embeddingModel: '嵌入模型',
|
||||
selectModel: '选择模型',
|
||||
llm: '大语言模型',
|
||||
delMemoryWarn: `删除后,此记忆中的所有消息都将被删除,代理将无法检索。`,
|
||||
delMemoryWarn: `删除后,此记忆中的所有消息都将被删除,智能体将无法检索。`,
|
||||
},
|
||||
memory: {
|
||||
messages: {
|
||||
forget: '遗忘',
|
||||
forgetMessageTip: '确定遗忘吗?',
|
||||
messageDescription: '记忆提取使用高级设置中的提示词和温度值进行配置。',
|
||||
copied: '已复制!',
|
||||
content: '内容',
|
||||
delMessageWarn: `遗忘后,代理将无法检索此消息。`,
|
||||
delMessageWarn: `遗忘后,智能体将无法检索此消息。`,
|
||||
forgetMessage: '遗忘消息',
|
||||
sessionId: '会话ID',
|
||||
agent: '智能体',
|
||||
@ -2138,6 +2139,7 @@ Tokenizer 会根据所选方式将内容存储为对应的数据结构。`,
|
||||
delFilesContent: '已选择 {{count}} 个文件',
|
||||
delChat: '删除聊天',
|
||||
delMember: '删除成员',
|
||||
delMemory: '删除记忆',
|
||||
},
|
||||
|
||||
empty: {
|
||||
|
||||
@ -109,7 +109,7 @@ export default function Agents() {
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger>
|
||||
<Button>
|
||||
<Plus className="mr-2 h-4 w-4" />
|
||||
<Plus className="h-4 w-4" />
|
||||
{t('flow.createGraph')}
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
|
||||
@ -515,7 +515,6 @@ export function LLMModelItem({ line = 1, isEdit, label, name }: IProps) {
|
||||
})}
|
||||
>
|
||||
<FormLabel
|
||||
required
|
||||
tooltip={t('globalIndexModelTip')}
|
||||
className={cn('text-sm whitespace-wrap ', {
|
||||
'w-1/4': line === 1,
|
||||
|
||||
@ -96,7 +96,7 @@ export const formSchema = z
|
||||
)
|
||||
.optional(),
|
||||
enable_metadata: z.boolean().optional(),
|
||||
llm_id: z.string().min(1, { message: 'Indexing model is required' }),
|
||||
llm_id: z.string().optional(),
|
||||
})
|
||||
.optional(),
|
||||
pagerank: z.number(),
|
||||
|
||||
@ -95,7 +95,7 @@ export default function Datasets() {
|
||||
icon={'datasets'}
|
||||
>
|
||||
<Button onClick={showModal}>
|
||||
<Plus className=" size-2.5" />
|
||||
<Plus className="h-4 w-4" />
|
||||
{t('knowledgeList.createKnowledgeBase')}
|
||||
</Button>
|
||||
</ListFilterBar>
|
||||
|
||||
@ -1,14 +1,21 @@
|
||||
// src/pages/next-memoryes/hooks.ts
|
||||
|
||||
import { FilterCollection } from '@/components/list-filter-bar/interface';
|
||||
import { useHandleFilterSubmit } from '@/components/list-filter-bar/use-handle-filter-submit';
|
||||
import message from '@/components/ui/message';
|
||||
import { useSetModalState } from '@/hooks/common-hooks';
|
||||
import { useHandleSearchChange } from '@/hooks/logic-hooks';
|
||||
import { useFetchTenantInfo } from '@/hooks/use-user-setting-request';
|
||||
import memoryService, { updateMemoryById } from '@/services/memory-service';
|
||||
import {
|
||||
buildOwnersFilter,
|
||||
groupListByArray,
|
||||
groupListByType,
|
||||
} from '@/utils/list-filter-util';
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import { useDebounce } from 'ahooks';
|
||||
import { omit } from 'lodash';
|
||||
import { useCallback, useState } from 'react';
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useParams, useSearchParams } from 'react-router';
|
||||
import {
|
||||
@ -45,7 +52,27 @@ export const useCreateMemory = () => {
|
||||
export const useFetchMemoryList = () => {
|
||||
const { handleInputChange, searchString, pagination, setPagination } =
|
||||
useHandleSearchChange();
|
||||
const { filterValue, handleFilterSubmit } = useHandleFilterSubmit();
|
||||
const debouncedSearchString = useDebounce(searchString, { wait: 500 });
|
||||
|
||||
const memoryType = Array.isArray(filterValue.memoryType)
|
||||
? filterValue.memoryType
|
||||
: [];
|
||||
const storageType = Array.isArray(filterValue.storageType)
|
||||
? filterValue.storageType
|
||||
: [];
|
||||
const owner = filterValue.owner;
|
||||
const requestParams: Record<string, any> = {
|
||||
keywords: debouncedSearchString,
|
||||
page_size: pagination.pageSize,
|
||||
page: pagination.current,
|
||||
memory_type: memoryType.length > 0 ? memoryType.join(',') : undefined,
|
||||
storage_type: storageType.length === 1 ? storageType[0] : undefined,
|
||||
};
|
||||
|
||||
if (Array.isArray(owner) && owner.length > 0) {
|
||||
requestParams.owner_ids = owner.join(',');
|
||||
}
|
||||
const { data, isLoading, isError, refetch } = useQuery<
|
||||
MemoryListResponse,
|
||||
Error
|
||||
@ -56,16 +83,13 @@ export const useFetchMemoryList = () => {
|
||||
debouncedSearchString,
|
||||
...pagination,
|
||||
},
|
||||
filterValue,
|
||||
],
|
||||
queryFn: async () => {
|
||||
const { data: response } = await memoryService.getMemoryList(
|
||||
{
|
||||
params: {
|
||||
keywords: debouncedSearchString,
|
||||
page_size: pagination.pageSize,
|
||||
page: pagination.current,
|
||||
},
|
||||
data: {},
|
||||
params: requestParams,
|
||||
data: { memory_type: memoryType },
|
||||
},
|
||||
true,
|
||||
);
|
||||
@ -93,6 +117,8 @@ export const useFetchMemoryList = () => {
|
||||
handleInputChange,
|
||||
setPagination,
|
||||
refetch,
|
||||
filterValue,
|
||||
handleFilterSubmit,
|
||||
};
|
||||
};
|
||||
|
||||
@ -275,3 +301,35 @@ export const useRenameMemory = () => {
|
||||
showMemoryRenameModal: handleShowChatRenameModal,
|
||||
};
|
||||
};
|
||||
|
||||
export function useSelectFilters() {
|
||||
const { data: res } = useFetchMemoryList();
|
||||
const data = res?.data;
|
||||
|
||||
const memoryType = useMemo(() => {
|
||||
return groupListByArray(data?.memory_list ?? [], 'memory_type');
|
||||
}, [data?.memory_list]);
|
||||
const storageType = useMemo(() => {
|
||||
return groupListByType(
|
||||
data?.memory_list ?? [],
|
||||
'storage_type',
|
||||
'storage_type',
|
||||
);
|
||||
}, [data?.memory_list]);
|
||||
|
||||
const filters: FilterCollection[] = [
|
||||
buildOwnersFilter(data?.memory_list ?? [], 'owner_name'),
|
||||
{
|
||||
field: 'memoryType',
|
||||
list: memoryType,
|
||||
label: 'Memory Type',
|
||||
},
|
||||
{
|
||||
field: 'storageType',
|
||||
list: storageType,
|
||||
label: 'Storage Type',
|
||||
},
|
||||
];
|
||||
|
||||
return { filters };
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@ import { useCallback, useEffect, useState } from 'react';
|
||||
import { useSearchParams } from 'react-router';
|
||||
import { AddOrEditModal } from './add-or-edit-modal';
|
||||
import { defaultMemoryFields } from './constants';
|
||||
import { useFetchMemoryList, useRenameMemory } from './hooks';
|
||||
import { useFetchMemoryList, useRenameMemory, useSelectFilters } from './hooks';
|
||||
import { ICreateMemoryProps, IMemory } from './interface';
|
||||
import { MemoryCard } from './memory-card';
|
||||
|
||||
@ -27,6 +27,8 @@ export default function MemoryList() {
|
||||
handleInputChange,
|
||||
setPagination,
|
||||
refetch: refetchList,
|
||||
filterValue,
|
||||
handleFilterSubmit,
|
||||
} = useFetchMemoryList();
|
||||
|
||||
const {
|
||||
@ -56,6 +58,7 @@ export default function MemoryList() {
|
||||
);
|
||||
|
||||
const [searchUrl, setMemoryUrl] = useSearchParams();
|
||||
const { filters } = useSelectFilters();
|
||||
const isCreate = searchUrl.get('isCreate') === 'true';
|
||||
useEffect(() => {
|
||||
if (isCreate) {
|
||||
@ -87,9 +90,11 @@ export default function MemoryList() {
|
||||
<ListFilterBar
|
||||
icon="memory"
|
||||
title={t('memory')}
|
||||
showFilter={false}
|
||||
onSearchChange={handleInputChange}
|
||||
searchString={searchString}
|
||||
filters={filters}
|
||||
onChange={handleFilterSubmit}
|
||||
value={filterValue}
|
||||
>
|
||||
<Button
|
||||
variant={'default'}
|
||||
@ -97,7 +102,7 @@ export default function MemoryList() {
|
||||
openCreateModalFun();
|
||||
}}
|
||||
>
|
||||
<Plus className="mr-2 h-4 w-4" />
|
||||
<Plus className=" h-4 w-4" />
|
||||
{t('createMemory')}
|
||||
</Button>
|
||||
</ListFilterBar>
|
||||
|
||||
@ -4,7 +4,7 @@ import { SideBar } from './sidebar';
|
||||
|
||||
export default function DatasetWrapper() {
|
||||
return (
|
||||
<section className="flex h-full flex-col w-full">
|
||||
<section className="flex h-full flex-col w-full pt-3">
|
||||
<div className="flex flex-1 min-h-0">
|
||||
<SideBar></SideBar>
|
||||
<div className=" relative flex-1 overflow-auto border-[0.5px] border-border-button p-5 rounded-md mr-5 mb-5">
|
||||
|
||||
@ -1,9 +1,12 @@
|
||||
import { FilterCollection } from '@/components/list-filter-bar/interface';
|
||||
import { useHandleFilterSubmit } from '@/components/list-filter-bar/use-handle-filter-submit';
|
||||
import message from '@/components/ui/message';
|
||||
import { useHandleSearchChange } from '@/hooks/logic-hooks';
|
||||
import memoryService, { getMemoryDetailById } from '@/services/memory-service';
|
||||
import { groupListByType } from '@/utils/list-filter-util';
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import { t } from 'i18next';
|
||||
import { useCallback, useState } from 'react';
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import { useParams, useSearchParams } from 'react-router';
|
||||
import { MemoryApiAction } from '../constant';
|
||||
import {
|
||||
@ -18,13 +21,15 @@ export const useFetchMemoryMessageList = () => {
|
||||
const memoryBaseId = searchParams.get('id') || id;
|
||||
const { handleInputChange, searchString, pagination, setPagination } =
|
||||
useHandleSearchChange();
|
||||
|
||||
const { filterValue, handleFilterSubmit } = useHandleFilterSubmit();
|
||||
let queryKey: (MemoryApiAction | number)[] = [
|
||||
MemoryApiAction.FetchMemoryMessage,
|
||||
];
|
||||
|
||||
const agentIds = Array.isArray(filterValue.agentId)
|
||||
? filterValue.agentId
|
||||
: [];
|
||||
const { data, isFetching: loading } = useQuery<IMessageTableProps>({
|
||||
queryKey: [...queryKey, searchString, pagination],
|
||||
queryKey: [...queryKey, searchString, pagination, filterValue],
|
||||
initialData: {} as IMessageTableProps,
|
||||
gcTime: 0,
|
||||
queryFn: async () => {
|
||||
@ -33,6 +38,7 @@ export const useFetchMemoryMessageList = () => {
|
||||
keywords: searchString,
|
||||
page: pagination.current,
|
||||
page_size: pagination.pageSize,
|
||||
agentId: agentIds.length > 0 ? agentIds.join(',') : undefined,
|
||||
});
|
||||
return data?.data ?? {};
|
||||
} else {
|
||||
@ -48,6 +54,8 @@ export const useFetchMemoryMessageList = () => {
|
||||
searchString,
|
||||
pagination,
|
||||
setPagination,
|
||||
filterValue,
|
||||
handleFilterSubmit,
|
||||
};
|
||||
};
|
||||
|
||||
@ -164,3 +172,24 @@ export const useMessageAction = () => {
|
||||
handleClickUpdateMessageState,
|
||||
};
|
||||
};
|
||||
|
||||
export function useSelectFilters() {
|
||||
const { data } = useFetchMemoryMessageList();
|
||||
const agentId = useMemo(() => {
|
||||
return groupListByType(
|
||||
data?.messages?.message_list ?? [],
|
||||
'agent_id',
|
||||
'agent_name',
|
||||
);
|
||||
}, [data?.messages?.message_list]);
|
||||
|
||||
const filters: FilterCollection[] = [
|
||||
{
|
||||
field: 'agentId',
|
||||
list: agentId,
|
||||
label: 'Agent',
|
||||
},
|
||||
];
|
||||
|
||||
return { filters };
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import ListFilterBar from '@/components/list-filter-bar';
|
||||
import { t } from 'i18next';
|
||||
import { useFetchMemoryMessageList } from './hook';
|
||||
import { useFetchMemoryMessageList, useSelectFilters } from './hook';
|
||||
import { MemoryTable } from './message-table';
|
||||
|
||||
export default function MemoryMessage() {
|
||||
@ -11,25 +11,29 @@ export default function MemoryMessage() {
|
||||
pagination,
|
||||
handleInputChange,
|
||||
setPagination,
|
||||
// filterValue,
|
||||
// handleFilterSubmit,
|
||||
filterValue,
|
||||
handleFilterSubmit,
|
||||
loading,
|
||||
} = useFetchMemoryMessageList();
|
||||
const { filters } = useSelectFilters();
|
||||
return (
|
||||
<div className="flex flex-col gap-2">
|
||||
<ListFilterBar
|
||||
title="Dataset"
|
||||
onSearchChange={handleInputChange}
|
||||
searchString={searchString}
|
||||
showFilter={false}
|
||||
// showFilter={false}
|
||||
// value={filterValue}
|
||||
// onChange={handleFilterSubmit}
|
||||
// onOpenChange={onOpenChange}
|
||||
// filters={filters}
|
||||
filters={filters}
|
||||
onChange={handleFilterSubmit}
|
||||
value={filterValue}
|
||||
leftPanel={
|
||||
<div className="items-start">
|
||||
<div className="pb-1">{t('memory.sideBar.messages')}</div>
|
||||
<div className="text-text-secondary text-sm">
|
||||
<div className="text-text-secondary text-sm font-normal">
|
||||
{t('memory.messages.messageDescription')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -210,7 +210,7 @@ export function MemoryTable({
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
<Table rootClassName="max-h-[calc(100vh-282px)]">
|
||||
<Table rootClassName="max-h-[calc(100vh-292px)]">
|
||||
<TableHeader>
|
||||
{table.getHeaderGroups().map((headerGroup) => (
|
||||
<TableRow key={headerGroup.id}>
|
||||
@ -257,7 +257,7 @@ export function MemoryTable({
|
||||
title={t('memory.messages.forgetMessage')}
|
||||
open={showDeleteDialog}
|
||||
onOpenChange={setShowDeleteDialog}
|
||||
okButtonText={t('common.confirm')}
|
||||
okButtonText={t('memory.messages.forget')}
|
||||
content={{
|
||||
title: t('memory.messages.forgetMessageTip'),
|
||||
node: (
|
||||
|
||||
@ -30,7 +30,9 @@ export const AdvancedSettingsForm = () => {
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className="flex items-center gap-1 w-full cursor-pointer"
|
||||
className={cn('flex items-center gap-1 w-full cursor-pointer', {
|
||||
'text-primary': showAdvancedSettings,
|
||||
})}
|
||||
onClick={() => setShowAdvancedSettings(!showAdvancedSettings)}
|
||||
>
|
||||
{showAdvancedSettings ? (
|
||||
@ -134,6 +136,7 @@ export const AdvancedSettingsForm = () => {
|
||||
/>
|
||||
<RenderField
|
||||
field={{
|
||||
className: '!items-start',
|
||||
name: 'system_prompt',
|
||||
label: t('memory.config.systemPrompt'),
|
||||
type: FormFieldType.Textarea,
|
||||
@ -144,6 +147,7 @@ export const AdvancedSettingsForm = () => {
|
||||
/>
|
||||
<RenderField
|
||||
field={{
|
||||
className: '!items-start',
|
||||
name: 'user_prompt',
|
||||
label: t('memory.config.userPrompt'),
|
||||
type: FormFieldType.Textarea,
|
||||
|
||||
@ -41,6 +41,7 @@ export const BasicInfo = () => {
|
||||
label={t('memory.config.description')}
|
||||
required={false}
|
||||
horizontal={true}
|
||||
className="!items-start"
|
||||
// tooltip={field.tooltip}
|
||||
// labelClassName={labelClassName || field.labelClassName}
|
||||
>
|
||||
|
||||
@ -72,7 +72,7 @@ export default function ChatList() {
|
||||
searchString={searchString}
|
||||
>
|
||||
<Button onClick={handleShowCreateModal}>
|
||||
<Plus className="size-2.5" />
|
||||
<Plus className="h-4 w-4" />
|
||||
{t('chat.createChat')}
|
||||
</Button>
|
||||
</ListFilterBar>
|
||||
|
||||
@ -96,7 +96,7 @@ export default function SearchList() {
|
||||
openCreateModalFun();
|
||||
}}
|
||||
>
|
||||
<Plus className="mr-2 h-4 w-4" />
|
||||
<Plus className="h-4 w-4" />
|
||||
{t('createSearch')}
|
||||
</Button>
|
||||
</ListFilterBar>
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import { FormFieldType } from '@/components/dynamic-form';
|
||||
import { IconFontFill } from '@/components/icon-font';
|
||||
import SvgIcon from '@/components/svg-icon';
|
||||
import { t, TFunction } from 'i18next';
|
||||
import { Mail } from 'lucide-react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import BoxTokenField from '../component/box-token-field';
|
||||
@ -130,12 +132,18 @@ export const generateDataSourceInfo = (t: TFunction) => {
|
||||
[DataSourceKey.GITHUB]: {
|
||||
name: 'GitHub',
|
||||
description: t(`setting.${DataSourceKey.GITHUB}Description`),
|
||||
icon: <SvgIcon name={'data-source/github'} width={38} />,
|
||||
icon: (
|
||||
<IconFontFill
|
||||
// name="a-DiscordIconSVGVectorIcon"
|
||||
name="GitHub"
|
||||
className="text-text-primary size-6"
|
||||
></IconFontFill>
|
||||
),
|
||||
},
|
||||
[DataSourceKey.IMAP]: {
|
||||
name: 'IMAP',
|
||||
description: t(`setting.${DataSourceKey.IMAP}Description`),
|
||||
icon: <SvgIcon name={'data-source/imap'} width={38} />,
|
||||
icon: <Mail className="text-text-primary" size={22} />,
|
||||
},
|
||||
[DataSourceKey.BITBUCKET]: {
|
||||
name: 'Bitbucket',
|
||||
|
||||
@ -22,8 +22,32 @@ export function groupListByType<T extends Record<string, any>>(
|
||||
return fileTypeList;
|
||||
}
|
||||
|
||||
export function buildOwnersFilter<T extends Record<string, any>>(list: T[]) {
|
||||
const owners = groupListByType(list, 'tenant_id', 'nickname');
|
||||
export function groupListByArray<T extends Record<string, any>>(
|
||||
list: T[],
|
||||
idField: string,
|
||||
) {
|
||||
const fileTypeList: FilterType[] = [];
|
||||
list.forEach((x) => {
|
||||
if (Array.isArray(x[idField])) {
|
||||
x[idField].forEach((j) => {
|
||||
const item = fileTypeList.find((i) => i.id === j);
|
||||
if (!item) {
|
||||
fileTypeList.push({ id: j, label: j, count: 1 });
|
||||
} else {
|
||||
item.count += 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return fileTypeList;
|
||||
}
|
||||
|
||||
export function buildOwnersFilter<T extends Record<string, any>>(
|
||||
list: T[],
|
||||
nickName?: string,
|
||||
) {
|
||||
const owners = groupListByType(list, 'tenant_id', nickName || 'nickname');
|
||||
|
||||
return { field: 'owner', list: owners, label: 'Owner' };
|
||||
}
|
||||
|
||||
@ -61,6 +61,9 @@ export default defineConfig(({ mode, command }) => {
|
||||
server: {
|
||||
port: 9222,
|
||||
strictPort: false,
|
||||
hmr: {
|
||||
overlay: false,
|
||||
},
|
||||
proxy: {
|
||||
'/api/v1/admin': {
|
||||
target: 'http://127.0.0.1:9381/',
|
||||
@ -77,18 +80,63 @@ export default defineConfig(({ mode, command }) => {
|
||||
assetsInclude: ['**/*.md'],
|
||||
base: env.VITE_BASE_URL,
|
||||
publicDir: 'public',
|
||||
cacheDir: './node_modules/.vite-cache',
|
||||
optimizeDeps: {
|
||||
include: [
|
||||
'react',
|
||||
'react-dom',
|
||||
'react-router',
|
||||
'antd',
|
||||
'axios',
|
||||
'lodash',
|
||||
'dayjs',
|
||||
],
|
||||
exclude: [],
|
||||
force: false,
|
||||
},
|
||||
build: {
|
||||
outDir: 'dist',
|
||||
assetsDir: 'assets',
|
||||
assetsInlineLimit: 4096,
|
||||
experimentalMinChunkSize: 30 * 1024,
|
||||
chunkSizeWarningLimit: 1000,
|
||||
rollupOptions: {
|
||||
output: {
|
||||
manualChunks(id) {
|
||||
// if (id.includes('src/components')) {
|
||||
// return 'components';
|
||||
// }
|
||||
|
||||
if (id.includes('node_modules')) {
|
||||
if (id.includes('node_modules/d3')) {
|
||||
return 'd3';
|
||||
}
|
||||
if (id.includes('node_modules/ajv')) {
|
||||
return 'ajv';
|
||||
}
|
||||
if (id.includes('node_modules/@antv')) {
|
||||
return 'antv';
|
||||
}
|
||||
const name = id
|
||||
.toString()
|
||||
.split('node_modules/')[1]
|
||||
.split('/')[0]
|
||||
.toString();
|
||||
if (['lodash', 'dayjs', 'date-fns', 'axios'].includes(name)) {
|
||||
return 'utils';
|
||||
}
|
||||
if (['@xmldom', 'xmlbuilder '].includes(name)) {
|
||||
return 'xml-js';
|
||||
}
|
||||
return name;
|
||||
}
|
||||
},
|
||||
chunkFileNames: 'chunk/js/[name]-[hash].js',
|
||||
entryFileNames: 'entry/js/[name]-[hash].js',
|
||||
assetFileNames: 'assets/[ext]/[name]-[hash].[ext]',
|
||||
},
|
||||
plugins: [],
|
||||
treeshake: true,
|
||||
},
|
||||
minify: 'terser',
|
||||
terserOptions: {
|
||||
@ -108,6 +156,8 @@ export default defineConfig(({ mode, command }) => {
|
||||
},
|
||||
},
|
||||
sourcemap: true,
|
||||
cssCodeSplit: true,
|
||||
target: 'es2015',
|
||||
},
|
||||
esbuild: {
|
||||
tsconfigRaw: {
|
||||
@ -118,5 +168,6 @@ export default defineConfig(({ mode, command }) => {
|
||||
},
|
||||
},
|
||||
},
|
||||
entries: ['./src/main.tsx'],
|
||||
};
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user