mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-08 20:42:30 +08:00
### What problem does this PR solve? Feat: Filter the agent list by owner and category #9869 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
@ -1,3 +1,4 @@
|
|||||||
|
import { AgentCategory } from '@/constants/agent';
|
||||||
import { useTranslate } from '@/hooks/common-hooks';
|
import { useTranslate } from '@/hooks/common-hooks';
|
||||||
import { useFetchAgentList } from '@/hooks/use-agent-request';
|
import { useFetchAgentList } from '@/hooks/use-agent-request';
|
||||||
import { buildSelectOptions } from '@/utils/component-util';
|
import { buildSelectOptions } from '@/utils/component-util';
|
||||||
@ -33,8 +34,8 @@ export function DataFlowSelect(props: IProps) {
|
|||||||
const toDataPipLine = () => {
|
const toDataPipLine = () => {
|
||||||
toDataPipeline?.();
|
toDataPipeline?.();
|
||||||
};
|
};
|
||||||
const { data: dataPipelineOptions, loading } = useFetchAgentList({
|
const { data: dataPipelineOptions } = useFetchAgentList({
|
||||||
canvas_category: 'dataflow_canvas',
|
canvas_category: AgentCategory.DataflowCanvas,
|
||||||
});
|
});
|
||||||
const options = useMemo(() => {
|
const options = useMemo(() => {
|
||||||
const option = buildSelectOptions(
|
const option = buildSelectOptions(
|
||||||
|
|||||||
@ -47,3 +47,8 @@ export const initialLlmBaseValues = {
|
|||||||
presence_penalty: 0.4,
|
presence_penalty: 0.4,
|
||||||
max_tokens: 256,
|
max_tokens: 256,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export enum AgentCategory {
|
||||||
|
AgentCanvas = 'agent_canvas',
|
||||||
|
DataflowCanvas = 'dataflow_canvas',
|
||||||
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { FileUploadProps } from '@/components/file-upload';
|
import { FileUploadProps } from '@/components/file-upload';
|
||||||
|
import { useHandleFilterSubmit } from '@/components/list-filter-bar/use-handle-filter-submit';
|
||||||
import message from '@/components/ui/message';
|
import message from '@/components/ui/message';
|
||||||
import { AgentGlobals } from '@/constants/agent';
|
import { AgentGlobals } from '@/constants/agent';
|
||||||
import {
|
import {
|
||||||
@ -33,6 +34,7 @@ import {
|
|||||||
} from './logic-hooks';
|
} from './logic-hooks';
|
||||||
|
|
||||||
export const enum AgentApiAction {
|
export const enum AgentApiAction {
|
||||||
|
FetchAgentListByPage = 'fetchAgentListByPage',
|
||||||
FetchAgentList = 'fetchAgentList',
|
FetchAgentList = 'fetchAgentList',
|
||||||
UpdateAgentSetting = 'updateAgentSetting',
|
UpdateAgentSetting = 'updateAgentSetting',
|
||||||
DeleteAgent = 'deleteAgent',
|
DeleteAgent = 'deleteAgent',
|
||||||
@ -114,16 +116,36 @@ export const useFetchAgentListByPage = () => {
|
|||||||
const { searchString, handleInputChange } = useHandleSearchChange();
|
const { searchString, handleInputChange } = useHandleSearchChange();
|
||||||
const { pagination, setPagination } = useGetPaginationWithRouter();
|
const { pagination, setPagination } = useGetPaginationWithRouter();
|
||||||
const debouncedSearchString = useDebounce(searchString, { wait: 500 });
|
const debouncedSearchString = useDebounce(searchString, { wait: 500 });
|
||||||
|
const { filterValue, handleFilterSubmit } = useHandleFilterSubmit();
|
||||||
|
const canvasCategory = Array.isArray(filterValue.canvasCategory)
|
||||||
|
? filterValue.canvasCategory
|
||||||
|
: [];
|
||||||
|
const owner = filterValue.owner;
|
||||||
|
|
||||||
|
const requestParams = {
|
||||||
|
keywords: debouncedSearchString,
|
||||||
|
page_size: pagination.pageSize,
|
||||||
|
page: pagination.current,
|
||||||
|
canvas_category:
|
||||||
|
canvasCategory.length === 1 ? canvasCategory[0] : undefined,
|
||||||
|
owner_ids: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
if (Array.isArray(owner) && owner.length > 0) {
|
||||||
|
requestParams.owner_ids =
|
||||||
|
`${owner[0]}` + owner.slice(1).map((id) => `&owner_ids=${id}`);
|
||||||
|
}
|
||||||
|
|
||||||
const { data, isFetching: loading } = useQuery<{
|
const { data, isFetching: loading } = useQuery<{
|
||||||
canvas: IFlow[];
|
canvas: IFlow[];
|
||||||
total: number;
|
total: number;
|
||||||
}>({
|
}>({
|
||||||
queryKey: [
|
queryKey: [
|
||||||
AgentApiAction.FetchAgentList,
|
AgentApiAction.FetchAgentListByPage,
|
||||||
{
|
{
|
||||||
debouncedSearchString,
|
debouncedSearchString,
|
||||||
...pagination,
|
...pagination,
|
||||||
|
filterValue,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
placeholderData: (previousData) => {
|
placeholderData: (previousData) => {
|
||||||
@ -134,13 +156,9 @@ export const useFetchAgentListByPage = () => {
|
|||||||
},
|
},
|
||||||
gcTime: 0,
|
gcTime: 0,
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const { data } = await agentService.listCanvasTeam(
|
const { data } = await agentService.listCanvas(
|
||||||
{
|
{
|
||||||
params: {
|
params: requestParams,
|
||||||
keywords: debouncedSearchString,
|
|
||||||
page_size: pagination.pageSize,
|
|
||||||
page: pagination.current,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
@ -164,6 +182,8 @@ export const useFetchAgentListByPage = () => {
|
|||||||
handleInputChange: onInputChange,
|
handleInputChange: onInputChange,
|
||||||
pagination: { ...pagination, total: data?.total },
|
pagination: { ...pagination, total: data?.total },
|
||||||
setPagination,
|
setPagination,
|
||||||
|
filterValue,
|
||||||
|
handleFilterSubmit,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -181,7 +201,7 @@ export const useUpdateAgentSetting = () => {
|
|||||||
if (ret?.data?.code === 0) {
|
if (ret?.data?.code === 0) {
|
||||||
message.success('success');
|
message.success('success');
|
||||||
queryClient.invalidateQueries({
|
queryClient.invalidateQueries({
|
||||||
queryKey: [AgentApiAction.FetchAgentList],
|
queryKey: [AgentApiAction.FetchAgentListByPage],
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
message.error(ret?.data?.data);
|
message.error(ret?.data?.data);
|
||||||
@ -205,7 +225,7 @@ export const useDeleteAgent = () => {
|
|||||||
const { data } = await agentService.removeCanvas({ canvasIds });
|
const { data } = await agentService.removeCanvas({ canvasIds });
|
||||||
if (data.code === 0) {
|
if (data.code === 0) {
|
||||||
queryClient.invalidateQueries({
|
queryClient.invalidateQueries({
|
||||||
queryKey: [AgentApiAction.FetchAgentList],
|
queryKey: [AgentApiAction.FetchAgentListByPage],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return data?.data ?? [];
|
return data?.data ?? [];
|
||||||
@ -289,7 +309,7 @@ export const useSetAgent = (showMessage: boolean = true) => {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
queryClient.invalidateQueries({
|
queryClient.invalidateQueries({
|
||||||
queryKey: [AgentApiAction.FetchAgentList],
|
queryKey: [AgentApiAction.FetchAgentListByPage],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
@ -657,17 +677,14 @@ export const useFetchPrompt = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const useFetchAgentList = ({
|
export const useFetchAgentList = ({
|
||||||
canvas_category = 'agent_canvas',
|
canvas_category,
|
||||||
}: IPipeLineListRequest): {
|
}: IPipeLineListRequest) => {
|
||||||
data: {
|
const { data, isFetching: loading } = useQuery<{
|
||||||
canvas: IFlow[];
|
canvas: IFlow[];
|
||||||
total: number;
|
total: number;
|
||||||
};
|
}>({
|
||||||
loading: boolean;
|
queryKey: [AgentApiAction.FetchAgentList],
|
||||||
} => {
|
initialData: { canvas: [], total: 0 },
|
||||||
const { data, isFetching: loading } = useQuery({
|
|
||||||
queryKey: ['fetchPipeLineList'],
|
|
||||||
initialData: [],
|
|
||||||
gcTime: 0,
|
gcTime: 0,
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const { data } = await fetchPipeLineList({ canvas_category });
|
const { data } = await fetchPipeLineList({ canvas_category });
|
||||||
@ -699,3 +716,18 @@ export const useCancelDataflow = () => {
|
|||||||
|
|
||||||
return { data, loading, cancelDataflow: mutateAsync };
|
return { data, loading, cancelDataflow: mutateAsync };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// export const useFetchKnowledgeList = () => {
|
||||||
|
// const { data, isFetching: loading } = useQuery<IFlow[]>({
|
||||||
|
// queryKey: [AgentApiAction.FetchAgentList],
|
||||||
|
// initialData: [],
|
||||||
|
// gcTime: 0, // https://tanstack.com/query/latest/docs/framework/react/guides/caching?from=reactQueryV3
|
||||||
|
// queryFn: async () => {
|
||||||
|
// const { data } = await agentService.listCanvas();
|
||||||
|
|
||||||
|
// return data?.data ?? [];
|
||||||
|
// },
|
||||||
|
// });
|
||||||
|
|
||||||
|
// return { list: data, loading };
|
||||||
|
// };
|
||||||
|
|||||||
@ -30,6 +30,7 @@ export const enum KnowledgeApiAction {
|
|||||||
FetchKnowledgeDetail = 'fetchKnowledgeDetail',
|
FetchKnowledgeDetail = 'fetchKnowledgeDetail',
|
||||||
FetchKnowledgeGraph = 'fetchKnowledgeGraph',
|
FetchKnowledgeGraph = 'fetchKnowledgeGraph',
|
||||||
FetchMetadata = 'fetchMetadata',
|
FetchMetadata = 'fetchMetadata',
|
||||||
|
FetchKnowledgeList = 'fetchKnowledgeList',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useKnowledgeBaseId = (): string => {
|
export const useKnowledgeBaseId = (): string => {
|
||||||
@ -304,3 +305,25 @@ export function useFetchKnowledgeMetadata(kbIds: string[] = []) {
|
|||||||
|
|
||||||
return { data, loading };
|
return { data, loading };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const useFetchKnowledgeList = (
|
||||||
|
shouldFilterListWithoutDocument: boolean = false,
|
||||||
|
): {
|
||||||
|
list: IKnowledge[];
|
||||||
|
loading: boolean;
|
||||||
|
} => {
|
||||||
|
const { data, isFetching: loading } = useQuery({
|
||||||
|
queryKey: [KnowledgeApiAction.FetchKnowledgeList],
|
||||||
|
initialData: [],
|
||||||
|
gcTime: 0, // https://tanstack.com/query/latest/docs/framework/react/guides/caching?from=reactQueryV3
|
||||||
|
queryFn: async () => {
|
||||||
|
const { data } = await listDataset();
|
||||||
|
const list = data?.data?.kbs ?? [];
|
||||||
|
return shouldFilterListWithoutDocument
|
||||||
|
? list.filter((x: IKnowledge) => x.chunk_num > 0)
|
||||||
|
: list;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return { list: data, loading };
|
||||||
|
};
|
||||||
|
|||||||
@ -30,6 +30,7 @@ export interface ISwitchForm {
|
|||||||
no: string;
|
no: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
import { AgentCategory } from '@/constants/agent';
|
||||||
import { Edge, Node } from '@xyflow/react';
|
import { Edge, Node } from '@xyflow/react';
|
||||||
import { IReference, Message } from './chat';
|
import { IReference, Message } from './chat';
|
||||||
|
|
||||||
@ -273,5 +274,5 @@ export interface IPipeLineListRequest {
|
|||||||
keywords?: string;
|
keywords?: string;
|
||||||
orderby?: string;
|
orderby?: string;
|
||||||
desc?: boolean;
|
desc?: boolean;
|
||||||
canvas_category?: 'agent_canvas' | 'dataflow_canvas';
|
canvas_category?: AgentCategory;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -924,8 +924,3 @@ export enum AgentExceptionMethod {
|
|||||||
Comment = 'comment',
|
Comment = 'comment',
|
||||||
Goto = 'goto',
|
Goto = 'goto',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum AgentCategory {
|
|
||||||
AgentCanvas = 'agent_canvas',
|
|
||||||
DataflowCanvas = 'dataflow_canvas',
|
|
||||||
}
|
|
||||||
|
|||||||
@ -2,10 +2,10 @@ import { HomeCard } from '@/components/home-card';
|
|||||||
import { MoreButton } from '@/components/more-button';
|
import { MoreButton } from '@/components/more-button';
|
||||||
import { SharedBadge } from '@/components/shared-badge';
|
import { SharedBadge } from '@/components/shared-badge';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
|
import { AgentCategory } from '@/constants/agent';
|
||||||
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
||||||
import { IFlow } from '@/interfaces/database/agent';
|
import { IFlow } from '@/interfaces/database/agent';
|
||||||
import { DatabaseZap } from 'lucide-react';
|
import { Route } from 'lucide-react';
|
||||||
import { AgentCategory } from '../agent/constant';
|
|
||||||
import { AgentDropdown } from './agent-dropdown';
|
import { AgentDropdown } from './agent-dropdown';
|
||||||
import { useRenameAgent } from './use-rename-agent';
|
import { useRenameAgent } from './use-rename-agent';
|
||||||
|
|
||||||
@ -33,7 +33,7 @@ export function AgentCard({ data, showAgentRenameModal }: DatasetCardProps) {
|
|||||||
icon={
|
icon={
|
||||||
data.canvas_category === AgentCategory.DataflowCanvas && (
|
data.canvas_category === AgentCategory.DataflowCanvas && (
|
||||||
<Button variant={'ghost'} size={'sm'}>
|
<Button variant={'ghost'} size={'sm'}>
|
||||||
<DatabaseZap />
|
<Route />
|
||||||
</Button>
|
</Button>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
|
import { AgentCategory } from '@/constants/agent';
|
||||||
import { useSetModalState } from '@/hooks/common-hooks';
|
import { useSetModalState } from '@/hooks/common-hooks';
|
||||||
import { EmptyDsl, useSetAgent } from '@/hooks/use-agent-request';
|
import { EmptyDsl, useSetAgent } from '@/hooks/use-agent-request';
|
||||||
import { DSL } from '@/interfaces/database/agent';
|
import { DSL } from '@/interfaces/database/agent';
|
||||||
import { AgentCategory } from '@/pages/agent/constant';
|
|
||||||
import {
|
import {
|
||||||
BeginId,
|
BeginId,
|
||||||
Operator,
|
Operator,
|
||||||
|
|||||||
23
web/src/pages/agents/hooks/use-selelct-filters.ts
Normal file
23
web/src/pages/agents/hooks/use-selelct-filters.ts
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import { FilterCollection } from '@/components/list-filter-bar/interface';
|
||||||
|
import { useFetchAgentList } from '@/hooks/use-agent-request';
|
||||||
|
import { buildOwnersFilter, groupListByType } from '@/utils/list-filter-util';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
|
export function useSelectFilters() {
|
||||||
|
const { data } = useFetchAgentList({});
|
||||||
|
|
||||||
|
const canvasCategory = useMemo(() => {
|
||||||
|
return groupListByType(data.canvas, 'canvas_category', 'canvas_category');
|
||||||
|
}, [data.canvas]);
|
||||||
|
|
||||||
|
const filters: FilterCollection[] = [
|
||||||
|
buildOwnersFilter(data.canvas),
|
||||||
|
{
|
||||||
|
field: 'canvasCategory',
|
||||||
|
list: canvasCategory,
|
||||||
|
label: 'Canvas category',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return filters;
|
||||||
|
}
|
||||||
@ -17,13 +17,21 @@ import { useCallback } from 'react';
|
|||||||
import { AgentCard } from './agent-card';
|
import { AgentCard } from './agent-card';
|
||||||
import { CreateAgentDialog } from './create-agent-dialog';
|
import { CreateAgentDialog } from './create-agent-dialog';
|
||||||
import { useCreateAgentOrPipeline } from './hooks/use-create-agent';
|
import { useCreateAgentOrPipeline } from './hooks/use-create-agent';
|
||||||
|
import { useSelectFilters } from './hooks/use-selelct-filters';
|
||||||
import { UploadAgentDialog } from './upload-agent-dialog';
|
import { UploadAgentDialog } from './upload-agent-dialog';
|
||||||
import { useHandleImportJsonFile } from './use-import-json';
|
import { useHandleImportJsonFile } from './use-import-json';
|
||||||
import { useRenameAgent } from './use-rename-agent';
|
import { useRenameAgent } from './use-rename-agent';
|
||||||
|
|
||||||
export default function Agents() {
|
export default function Agents() {
|
||||||
const { data, pagination, setPagination, searchString, handleInputChange } =
|
const {
|
||||||
useFetchAgentListByPage();
|
data,
|
||||||
|
pagination,
|
||||||
|
setPagination,
|
||||||
|
searchString,
|
||||||
|
handleInputChange,
|
||||||
|
filterValue,
|
||||||
|
handleFilterSubmit,
|
||||||
|
} = useFetchAgentListByPage();
|
||||||
const { navigateToAgentTemplates } = useNavigatePage();
|
const { navigateToAgentTemplates } = useNavigatePage();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@ -50,6 +58,8 @@ export default function Agents() {
|
|||||||
hideFileUploadModal,
|
hideFileUploadModal,
|
||||||
} = useHandleImportJsonFile();
|
} = useHandleImportJsonFile();
|
||||||
|
|
||||||
|
const filters = useSelectFilters();
|
||||||
|
|
||||||
const handlePageChange = useCallback(
|
const handlePageChange = useCallback(
|
||||||
(page: number, pageSize?: number) => {
|
(page: number, pageSize?: number) => {
|
||||||
setPagination({ page, pageSize });
|
setPagination({ page, pageSize });
|
||||||
@ -65,6 +75,9 @@ export default function Agents() {
|
|||||||
searchString={searchString}
|
searchString={searchString}
|
||||||
onSearchChange={handleInputChange}
|
onSearchChange={handleInputChange}
|
||||||
icon="agent"
|
icon="agent"
|
||||||
|
filters={filters}
|
||||||
|
onChange={handleFilterSubmit}
|
||||||
|
value={filterValue}
|
||||||
>
|
>
|
||||||
<DropdownMenu>
|
<DropdownMenu>
|
||||||
<DropdownMenuTrigger>
|
<DropdownMenuTrigger>
|
||||||
|
|||||||
@ -1,18 +1,11 @@
|
|||||||
import { FilterCollection } from '@/components/list-filter-bar/interface';
|
import { FilterCollection } from '@/components/list-filter-bar/interface';
|
||||||
import { useFetchKnowledgeList } from '@/hooks/knowledge-hooks';
|
import { useFetchKnowledgeList } from '@/hooks/use-knowledge-request';
|
||||||
import { groupListByType } from '@/utils/dataset-util';
|
import { buildOwnersFilter } from '@/utils/list-filter-util';
|
||||||
import { useMemo } from 'react';
|
|
||||||
|
|
||||||
export function useSelectOwners() {
|
export function useSelectOwners() {
|
||||||
const { list } = useFetchKnowledgeList();
|
const { list } = useFetchKnowledgeList();
|
||||||
|
|
||||||
const owners = useMemo(() => {
|
const filters: FilterCollection[] = [buildOwnersFilter(list)];
|
||||||
return groupListByType(list, 'tenant_id', 'nickname');
|
|
||||||
}, [list]);
|
|
||||||
|
|
||||||
const filters: FilterCollection[] = [
|
|
||||||
{ field: 'owner', list: owners, label: 'Owner' },
|
|
||||||
];
|
|
||||||
|
|
||||||
return filters;
|
return filters;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,7 +17,6 @@ const {
|
|||||||
testDbConnect,
|
testDbConnect,
|
||||||
getInputElements,
|
getInputElements,
|
||||||
debug,
|
debug,
|
||||||
listCanvasTeam,
|
|
||||||
settingCanvas,
|
settingCanvas,
|
||||||
uploadCanvasFile,
|
uploadCanvasFile,
|
||||||
trace,
|
trace,
|
||||||
@ -85,10 +84,6 @@ const methods = {
|
|||||||
url: debug,
|
url: debug,
|
||||||
method: 'post',
|
method: 'post',
|
||||||
},
|
},
|
||||||
listCanvasTeam: {
|
|
||||||
url: listCanvasTeam,
|
|
||||||
method: 'get',
|
|
||||||
},
|
|
||||||
settingCanvas: {
|
settingCanvas: {
|
||||||
url: settingCanvas,
|
url: settingCanvas,
|
||||||
method: 'post',
|
method: 'post',
|
||||||
|
|||||||
@ -147,7 +147,6 @@ export default {
|
|||||||
// flow
|
// flow
|
||||||
listTemplates: `${api_host}/canvas/templates`,
|
listTemplates: `${api_host}/canvas/templates`,
|
||||||
listCanvas: `${api_host}/canvas/list`,
|
listCanvas: `${api_host}/canvas/list`,
|
||||||
listCanvasTeam: `${api_host}/canvas/list`,
|
|
||||||
getCanvas: `${api_host}/canvas/get`,
|
getCanvas: `${api_host}/canvas/get`,
|
||||||
getCanvasSSE: `${api_host}/canvas/getsse`,
|
getCanvasSSE: `${api_host}/canvas/getsse`,
|
||||||
removeCanvas: `${api_host}/canvas/rm`,
|
removeCanvas: `${api_host}/canvas/rm`,
|
||||||
|
|||||||
@ -7,27 +7,3 @@ export function isKnowledgeGraphParser(parserId: DocumentParserType) {
|
|||||||
export function isNaiveParser(parserId: DocumentParserType) {
|
export function isNaiveParser(parserId: DocumentParserType) {
|
||||||
return parserId === DocumentParserType.Naive;
|
return parserId === DocumentParserType.Naive;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type FilterType = {
|
|
||||||
id: string;
|
|
||||||
label: string;
|
|
||||||
count: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function groupListByType<T extends Record<string, any>>(
|
|
||||||
list: T[],
|
|
||||||
idField: string,
|
|
||||||
labelField: string,
|
|
||||||
) {
|
|
||||||
const fileTypeList: FilterType[] = [];
|
|
||||||
list.forEach((x) => {
|
|
||||||
const item = fileTypeList.find((y) => y.id === x[idField]);
|
|
||||||
if (!item) {
|
|
||||||
fileTypeList.push({ id: x[idField], label: x[labelField], count: 1 });
|
|
||||||
} else {
|
|
||||||
item.count += 1;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return fileTypeList;
|
|
||||||
}
|
|
||||||
|
|||||||
29
web/src/utils/list-filter-util.ts
Normal file
29
web/src/utils/list-filter-util.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
export type FilterType = {
|
||||||
|
id: string;
|
||||||
|
label: string;
|
||||||
|
count: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function groupListByType<T extends Record<string, any>>(
|
||||||
|
list: T[],
|
||||||
|
idField: string,
|
||||||
|
labelField: string,
|
||||||
|
) {
|
||||||
|
const fileTypeList: FilterType[] = [];
|
||||||
|
list.forEach((x) => {
|
||||||
|
const item = fileTypeList.find((y) => y.id === x[idField]);
|
||||||
|
if (!item) {
|
||||||
|
fileTypeList.push({ id: x[idField], label: x[labelField], count: 1 });
|
||||||
|
} else {
|
||||||
|
item.count += 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return fileTypeList;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function buildOwnersFilter<T extends Record<string, any>>(list: T[]) {
|
||||||
|
const owners = groupListByType(list, 'tenant_id', 'nickname');
|
||||||
|
|
||||||
|
return { field: 'owner', list: owners, label: 'Owner' };
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user