diff --git a/dbgpt/_private/config.py b/dbgpt/_private/config.py index 10b3f1684..cd7936a60 100644 --- a/dbgpt/_private/config.py +++ b/dbgpt/_private/config.py @@ -332,17 +332,6 @@ def __init__(self) -> None: os.getenv("MULTI_INSTANCE", "False").lower() == "true" ) - # file server configuration - # The host of the current file server, if None, get the host automatically - self.FILE_SERVER_HOST = os.getenv("FILE_SERVER_HOST") - self.FILE_SERVER_LOCAL_STORAGE_PATH = os.getenv( - "FILE_SERVER_LOCAL_STORAGE_PATH" - ) - # multi-instance flag - self.WEBSERVER_MULTI_INSTANCE = ( - os.getenv("MULTI_INSTANCE", "False").lower() == "true" - ) - @property def local_db_manager(self) -> "ConnectorManager": from dbgpt.datasource.manages import ConnectorManager diff --git a/web/.eslintignore b/web/.eslintignore new file mode 100644 index 000000000..7ee78a605 --- /dev/null +++ b/web/.eslintignore @@ -0,0 +1,3 @@ +node_modules/ +build/ +dist/ \ No newline at end of file diff --git a/web/.eslintrc.js b/web/.eslintrc.js new file mode 100644 index 000000000..53ea14119 --- /dev/null +++ b/web/.eslintrc.js @@ -0,0 +1,57 @@ +module.exports = { + env: { + browser: true, + es2021: true, + node: true, + commonjs: true, + }, + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:react/recommended', + 'plugin:react-hooks/recommended', + 'plugin:prettier/recommended', + 'prettier', + ], + parser: '@typescript-eslint/parser', + parserOptions: { + ecmaFeatures: { + jsx: true, + }, + ecmaVersion: 'latest', + sourceType: 'module', + }, + plugins: ['@typescript-eslint', 'prettier'], + rules: { + 'prettier/prettier': 'error', + 'react/react-in-jsx-scope': 'off', + 'react/prop-types': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-unused-expressions': ['error', { allowShortCircuit: true, allowTernary: true }], + '@typescript-eslint/no-unused-vars': [ + 'error', + { + args: 'all', + argsIgnorePattern: '^_', + caughtErrors: 'all', + caughtErrorsIgnorePattern: '^_', + destructuredArrayIgnorePattern: '^_', + varsIgnorePattern: '^_', + ignoreRestSiblings: true, + }, + ], + quotes: ['error', 'single', { allowTemplateLiterals: true, avoidEscape: true }], + semi: ['error', 'always'], + }, + settings: { + react: { + version: 'detect', + }, + 'import/resolver': { + typescript: { + alwaysTryTypes: true, + project: './tsconfig.json', + }, + }, + }, +}; diff --git a/web/.prettierignore b/web/.prettierignore new file mode 100644 index 000000000..7ee78a605 --- /dev/null +++ b/web/.prettierignore @@ -0,0 +1,3 @@ +node_modules/ +build/ +dist/ \ No newline at end of file diff --git a/web/.prettierrc.js b/web/.prettierrc.js new file mode 100644 index 000000000..56a99b7ba --- /dev/null +++ b/web/.prettierrc.js @@ -0,0 +1,16 @@ +module.exports = { + printWidth: 120, + tabWidth: 2, + useTabs: false, + semi: true, + singleQuote: true, + jsxSingleQuote: true, + trailingComma: "all", + bracketSpacing: true, + jsxBracketSameLine: false, + arrowParens: "avoid", + plugins: [ + require.resolve('prettier-plugin-organize-imports'), + require.resolve('prettier-plugin-packagejson'), + ] +} \ No newline at end of file diff --git a/web/app/chat-context.tsx b/web/app/chat-context.tsx index 62827e79f..aee0f5d45 100644 --- a/web/app/chat-context.tsx +++ b/web/app/chat-context.tsx @@ -1,11 +1,11 @@ -import { apiInterceptors, getDialogueList, getUsableModels, queryAdminList } from '@/client/api'; +import { apiInterceptors, getUsableModels, queryAdminList } from '@/client/api'; import { ChatHistoryResponse, DialogueListResponse, IChatDialogueSchema } from '@/types/chat'; import { UserInfoResponse } from '@/types/userinfo'; import { getUserId } from '@/utils'; import { STORAGE_THEME_KEY } from '@/utils/constants/index'; import { useRequest } from 'ahooks'; import { useSearchParams } from 'next/navigation'; -import { createContext, useEffect, useMemo, useState } from 'react'; +import { createContext, useEffect, useState } from 'react'; type ThemeMode = 'dark' | 'light'; @@ -109,7 +109,7 @@ const ChatContextProvider = ({ children }: { children: React.ReactElement }) => return res ?? []; }, { - onSuccess: (data) => { + onSuccess: data => { setAdminList(data); }, manual: true, @@ -120,7 +120,7 @@ const ChatContextProvider = ({ children }: { children: React.ReactElement }) => if (getUserId()) { queryAdminListRun(); } - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line react-hooks/exhaustive-deps }, [queryAdminListRun, getUserId()]); useEffect(() => { @@ -128,7 +128,7 @@ const ChatContextProvider = ({ children }: { children: React.ReactElement }) => try { const dialogInfo = JSON.parse(localStorage.getItem('cur_dialog_info') || ''); setCurrentDialogInfo(dialogInfo); - } catch (error) { + } catch { setCurrentDialogInfo({ chat_scene: '', app_code: '', diff --git a/web/app/i18n.ts b/web/app/i18n.ts index da5d80bdc..072bef401 100644 --- a/web/app/i18n.ts +++ b/web/app/i18n.ts @@ -1,8 +1,7 @@ -import { Domain } from '@mui/icons-material'; -import i18n from 'i18next'; -import { initReactI18next } from 'react-i18next'; import en from '@/locales/en'; import zh from '@/locales/zh'; +import i18n from 'i18next'; +import { initReactI18next } from 'react-i18next'; export type I18nKeys = keyof typeof en; interface Resources { diff --git a/web/client/api/app/index.ts b/web/client/api/app/index.ts index bcd3377a5..bf991c5d7 100644 --- a/web/client/api/app/index.ts +++ b/web/client/api/app/index.ts @@ -32,7 +32,10 @@ export const updateApp = (data: CreateAppParams) => { * 应用列表 */ export const getAppList = (data: Record) => { - return POST, AppListResponse>(`/api/v1/app/list?page=${data.page || 1}&page_size=${data.page_size || 12}`, data); + return POST, AppListResponse>( + `/api/v1/app/list?page=${data.page || 1}&page_size=${data.page_size || 12}`, + data, + ); }; /** * 获取创建应用agents @@ -52,9 +55,7 @@ export const getAppStrategy = () => { * 获取资源参数 */ export const getResource = (data: Record) => { - return GET, Record[]>( - `/api/v1/app/resources/list?type=${data.type}` - ); + return GET, Record[]>(`/api/v1/app/resources/list?type=${data.type}`); }; /** * 创建native_app应用 @@ -80,12 +81,6 @@ export const getAppAdmins = (appCode: string) => { /** * 更新应用权限 */ -export const updateAppAdmins = (data: { - app_code: string; - admins: string[]; -}) => { - return POST<{ app_code: string; admins: string[] }, null>( - `/api/v1/app/admins/update`, - data - ); +export const updateAppAdmins = (data: { app_code: string; admins: string[] }) => { + return POST<{ app_code: string; admins: string[] }, null>(`/api/v1/app/admins/update`, data); }; diff --git a/web/client/api/chat/index.ts b/web/client/api/chat/index.ts index 940a6845d..a4ac732f1 100644 --- a/web/client/api/chat/index.ts +++ b/web/client/api/chat/index.ts @@ -36,5 +36,8 @@ export const cancelFeedback = (data: CancelFeedbackAddParams) => { * 终止话题 */ export const stopTopic = (data: StopTopicParams) => { - return POST(`/api/v1/chat/topic/terminate?conv_id=${data.conv_id}&round_index=${data.round_index}`, data); + return POST( + `/api/v1/chat/topic/terminate?conv_id=${data.conv_id}&round_index=${data.round_index}`, + data, + ); }; diff --git a/web/client/api/evaluate/index.ts b/web/client/api/evaluate/index.ts index 80224d512..cc51ca662 100644 --- a/web/client/api/evaluate/index.ts +++ b/web/client/api/evaluate/index.ts @@ -1,16 +1,16 @@ -import { getUserId } from '@/utils'; -import { GET, POST, DELETE } from '../index'; import type { - getDataSetsRequest, - getEvaluationsRequest, + createEvaluationsRequest, delDataSetRequest, delEvaluationRequest, - uploadDataSetsRequest, - createEvaluationsRequest, + downloadEvaluationRequest, + getDataSetsRequest, + getEvaluationsRequest, getMetricsRequest, updateDataSetRequest, - downloadEvaluationRequest, + uploadDataSetsRequest, } from '@/types/evaluate'; +import { getUserId } from '@/utils'; +import { DELETE, GET, POST } from '../index'; export const getTestAuth = () => { return GET(`/api/v1/evaluate/test_auth`); @@ -100,11 +100,15 @@ export const getMetrics = (data: getMetricsRequest) => { }); }; export const showEvaluation = (data: Partial) => { - return GET, Record[]>(`/api/v1/evaluate/evaluation/detail/show`, data, { - headers: { - 'user-id': userId, + return GET, Record[]>( + `/api/v1/evaluate/evaluation/detail/show`, + data, + { + headers: { + 'user-id': userId, + }, }, - }); + ); }; export const getStorageTypes = () => { return GET>(`/api/v1/evaluate/storage/types`, undefined, { diff --git a/web/client/api/flow/index.ts b/web/client/api/flow/index.ts index 96bc73095..7f32ac1d9 100644 --- a/web/client/api/flow/index.ts +++ b/web/client/api/flow/index.ts @@ -1,11 +1,11 @@ import { IFlow, + IFlowExportParams, + IFlowImportParams, IFlowNode, + IFlowRefreshParams, IFlowResponse, IFlowUpdateParam, - IFlowRefreshParams, - IFlowExportParams, - IFlowImportParams, IUploadFileRequestParams, IUploadFileResponse, } from '@/types/flow'; @@ -16,7 +16,7 @@ export const addFlow = (data: IFlowUpdateParam) => { return POST('/api/v2/serve/awel/flows', data); }; -export const getFlows = (page?: number, page_size?: number) => { +export const getFlows = ({ page, page_size }: { page?: number; page_size?: number }) => { return GET('/api/v2/serve/awel/flows', { page, page_size, @@ -40,10 +40,7 @@ export const getFlowNodes = () => { }; export const refreshFlowNodeById = (data: IFlowRefreshParams) => { - return POST( - '/api/v2/serve/awel/nodes/refresh', - data - ); + return POST('/api/v2/serve/awel/nodes/refresh', data); }; export const debugFlow = (data: any) => { @@ -51,10 +48,7 @@ export const debugFlow = (data: any) => { }; export const exportFlow = (data: IFlowExportParams) => { - return GET( - `/api/v2/serve/awel/flow/export/${data.uid}`, - data - ); + return GET(`/api/v2/serve/awel/flow/export/${data.uid}`, data); }; export const importFlow = (data: IFlowImportParams) => { @@ -62,10 +56,7 @@ export const importFlow = (data: IFlowImportParams) => { }; export const uploadFile = (data: IUploadFileRequestParams) => { - return POST>( - '/api/v2/serve/file/files/dbgpt', - data - ); + return POST>('/api/v2/serve/file/files/dbgpt', data); }; export const downloadFile = (fileId: string) => { diff --git a/web/client/api/index.ts b/web/client/api/index.ts index 7936755c1..8f477afd8 100644 --- a/web/client/api/index.ts +++ b/web/client/api/index.ts @@ -1,6 +1,6 @@ import { getUserId } from '@/utils'; import { HEADER_USER_ID_KEY } from '@/utils/constants/index'; -import axios, { AxiosRequestConfig, AxiosError, AxiosResponse } from 'axios'; +import axios, { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios'; export type ResponseType = { data: T; @@ -38,8 +38,8 @@ const LONG_TIME_API: string[] = [ '/personal/agent/upload', ]; -ins.interceptors.request.use((request) => { - const isLongTimeApi = LONG_TIME_API.some((item) => request.url && request.url.indexOf(item) >= 0); +ins.interceptors.request.use(request => { + const isLongTimeApi = LONG_TIME_API.some(item => request.url && request.url.indexOf(item) >= 0); if (!request.timeout) { request.timeout = isLongTimeApi ? 60000 : 100000; } @@ -47,7 +47,11 @@ ins.interceptors.request.use((request) => { return request; }); -export const GET = (url: string, params?: Params, config?: AxiosRequestConfig) => { +export const GET = ( + url: string, + params?: Params, + config?: AxiosRequestConfig, +) => { return ins.get>(url, { params, ...config }); }; @@ -55,7 +59,11 @@ export const POST = (url: string, data?: Da return ins.post>(url, data, config); }; -export const PATCH = (url: string, data?: Data, config?: AxiosRequestConfig) => { +export const PATCH = ( + url: string, + data?: Data, + config?: AxiosRequestConfig, +) => { return ins.patch>(url, data, config); }; @@ -63,16 +71,20 @@ export const PUT = (url: string, data?: Dat return ins.put>(url, data, config); }; -export const DELETE = (url: string, params?: Params, config?: AxiosRequestConfig) => { +export const DELETE = ( + url: string, + params?: Params, + config?: AxiosRequestConfig, +) => { return ins.delete>(url, { params, ...config }); }; -export * from './tools'; -export * from './request'; +export * from './app'; export * from './chat'; +export * from './evaluate'; export * from './flow'; -export * from './app'; export * from './knowledge'; -export * from './user'; export * from './prompt'; -export * from './evaluate'; +export * from './request'; +export * from './tools'; +export * from './user'; diff --git a/web/client/api/knowledge/index.ts b/web/client/api/knowledge/index.ts index cb59396d0..ef515cb04 100644 --- a/web/client/api/knowledge/index.ts +++ b/web/client/api/knowledge/index.ts @@ -1,12 +1,14 @@ -import { AddYuqueProps, RecallTestChunk, RecallTestProps } from '@/types/knowledge'; +import { AddYuqueProps, RecallTestChunk, RecallTestProps, SearchDocumentParams } from '@/types/knowledge'; import { GET, POST } from '../index'; -import { SearchDocumentParams } from '@/types/knowledge'; /** * 知识库编辑搜索 */ export const searchDocumentList = (spaceName: string, data: SearchDocumentParams) => { - return POST(`/knowledge/${spaceName}/document/list`, data); + return POST( + `/knowledge/${spaceName}/document/list`, + data, + ); }; /** @@ -19,8 +21,14 @@ export const addYuque = (data: AddYuqueProps) => { /** * 编辑知识库切片 */ -export const editChunk = (knowledgeName: string, data: { questions: string[]; doc_id: string | number; doc_name: string }) => { - return POST<{ questions: string[]; doc_id: string | number; doc_name: string }, null>(`/knowledge/${knowledgeName}/document/edit`, data); +export const editChunk = ( + knowledgeName: string, + data: { questions: string[]; doc_id: string | number; doc_name: string }, +) => { + return POST<{ questions: string[]; doc_id: string | number; doc_name: string }, null>( + `/knowledge/${knowledgeName}/document/edit`, + data, + ); }; /** * 召回测试推荐问题 diff --git a/web/client/api/prompt/index.ts b/web/client/api/prompt/index.ts index 84c1e128b..c6e03ae96 100644 --- a/web/client/api/prompt/index.ts +++ b/web/client/api/prompt/index.ts @@ -49,7 +49,10 @@ export const deletePrompt = (data: OperatePromptParams) => { * prompt列表 */ export const getPromptList = (data: Record) => { - return POST, PromptListResponse>(`/prompt/query_page?page=${data.page}&page_size=${data.page_size}`, data); + return POST, PromptListResponse>( + `/prompt/query_page?page=${data.page}&page_size=${data.page_size}`, + data, + ); }; /** diff --git a/web/client/api/request.ts b/web/client/api/request.ts index 3cd74ed9a..d710b8611 100644 --- a/web/client/api/request.ts +++ b/web/client/api/request.ts @@ -5,8 +5,8 @@ import { PostAgentPluginResponse, PostAgentQueryParams, PostDbgptMyQueryParams, -} from "@/types/agent"; -import { GetAppInfoParams, IApp, IAgent, IAppData } from "@/types/app"; +} from '@/types/agent'; +import { GetAppInfoParams, IApp } from '@/types/app'; import { ChatHistoryResponse, DialogueListResponse, @@ -17,14 +17,14 @@ import { SceneResponse, UserParam, UserParamResponse, -} from "@/types/chat"; +} from '@/types/chat'; import { ChatFeedBackSchema, DbListResponse, DbSupportTypeResponse, PostDbParams, PostDbRefreshParams, -} from "@/types/db"; +} from '@/types/db'; import { GetEditorSQLRoundRequest, GetEditorySqlParams, @@ -38,9 +38,9 @@ import { ArgumentsParams, ChunkListParams, DocumentParams, + GraphVisResult, IArguments, IChunkList, - GraphVisResult, IChunkStrategyResponse, IDocumentResponse, ISpace, @@ -48,26 +48,9 @@ import { ISyncBatchResponse, SpaceConfig, } from '@/types/knowledge'; -import { - BaseModelParams, - IModelData, - StartModelParams, - SupportModel, -} from '@/types/model'; +import { BaseModelParams, IModelData, StartModelParams, SupportModel } from '@/types/model'; import { AxiosRequestConfig } from 'axios'; -import { DELETE, GET, POST, PUT } from "."; -import { UpdatePromptParams, IPrompt, PromptParams } from "@/types/prompt"; -import { - IFlow, - IFlowNode, - IFlowResponse, - IFlowUpdateParam, - IFlowRefreshParams, - IFlowExportParams, - IFlowImportParams, - IUploadFileRequestParams, - IUploadFileResponse, -} from "@/types/flow"; +import { GET, POST } from '.'; /** App */ export const postScenes = () => { @@ -76,7 +59,7 @@ export const postScenes = () => { export const newDialogue = (data: NewDialogueParam) => { return POST( `/api/v1/chat/dialogue/new?chat_mode=${data.chat_mode}&model_name=${data.model}`, - data + data, ); }; @@ -115,19 +98,13 @@ export const getUsableModels = () => { return GET>('/api/v1/model/types'); }; export const postChatModeParamsList = (chatMode: string) => { - return POST( - `/api/v1/chat/mode/params/list?chat_mode=${chatMode}` - ); + return POST(`/api/v1/chat/mode/params/list?chat_mode=${chatMode}`); }; export const postChatModeParamsInfoList = (chatMode: string) => { - return POST>( - `/api/v1/chat/mode/params/info?chat_mode=${chatMode}` - ); + return POST>(`/api/v1/chat/mode/params/info?chat_mode=${chatMode}`); }; export const getChatHistory = (convId: string) => { - return GET( - `/api/v1/chat/dialogue/messages/history?con_uid=${convId}` - ); + return GET(`/api/v1/chat/dialogue/messages/history?con_uid=${convId}`); }; export const postChatModeParamsFileLoad = ({ convUid, @@ -154,14 +131,12 @@ export const postChatModeParamsFileLoad = ({ 'Content-Type': 'multipart/form-data', }, ...config, - } + }, ); }; export const clearChatHistory = (conUid: string) => { - return POST>( - `/api/v1/chat/dialogue/clear?con_uid=${conUid}` - ); + return POST>(`/api/v1/chat/dialogue/clear?con_uid=${conUid}`); }; /** Menu */ @@ -171,18 +146,13 @@ export const delDialogue = (conv_uid: string) => { /** Editor */ export const getEditorSqlRounds = (id: string) => { - return GET( - `/api/v1/editor/sql/rounds?con_uid=${id}` - ); + return GET(`/api/v1/editor/sql/rounds?con_uid=${id}`); }; export const postEditorSqlRun = (data: PostEditorSQLRunParams) => { return POST(`/api/v1/editor/sql/run`, data); }; export const postEditorChartRun = (data: PostEditorChartRunParams) => { - return POST( - `/api/v1/editor/chart/run`, - data - ); + return POST(`/api/v1/editor/chart/run`, data); }; export const postSqlEditorSubmit = (data: PostSQLEditorSubmitParams) => { return POST(`/api/v1/sql/editor/submit`, data); @@ -199,36 +169,21 @@ export const getArguments = (knowledgeName: string) => { return POST(`/knowledge/${knowledgeName}/arguments`, {}); }; export const saveArguments = (knowledgeName: string, data: ArgumentsParams) => { - return POST( - `/knowledge/${knowledgeName}/argument/save`, - data - ); + return POST(`/knowledge/${knowledgeName}/argument/save`, data); }; -export const getSpaceList = (data: any) => { +export const getSpaceList = (data?: any) => { return POST>('/knowledge/space/list', data); }; -export const getDocumentList = ( - spaceName: string, - data: Record> -) => { - return POST>, IDocumentResponse>( - `/knowledge/${spaceName}/document/list`, - data - ); +export const getDocumentList = (spaceName: string, data: Record>) => { + return POST>, IDocumentResponse>(`/knowledge/${spaceName}/document/list`, data); }; export const getGraphVis = (spaceName: string, data: { limit: number }) => { - return POST, GraphVisResult>( - `/knowledge/${spaceName}/graphvis`, - data - ); + return POST, GraphVisResult>(`/knowledge/${spaceName}/graphvis`, data); }; export const addDocument = (knowledgeName: string, data: DocumentParams) => { - return POST( - `/knowledge/${knowledgeName}/document/add`, - data - ); + return POST(`/knowledge/${knowledgeName}/document/add`, data); }; export const addSpace = (data: AddKnowledgeParams) => { @@ -236,53 +191,27 @@ export const addSpace = (data: AddKnowledgeParams) => { }; export const getChunkStrategies = () => { - return GET>( - "/knowledge/document/chunkstrategies" - ); + return GET>('/knowledge/document/chunkstrategies'); }; -export const syncDocument = ( - spaceName: string, - data: Record> -) => { - return POST>, string | null>( - `/knowledge/${spaceName}/document/sync`, - data - ); +export const syncDocument = (spaceName: string, data: Record>) => { + return POST>, string | null>(`/knowledge/${spaceName}/document/sync`, data); }; -export const syncBatchDocument = ( - spaceName: string, - data: Array -) => { - return POST, ISyncBatchResponse>( - `/knowledge/${spaceName}/document/sync_batch`, - data - ); +export const syncBatchDocument = (spaceName: string, data: Array) => { + return POST, ISyncBatchResponse>(`/knowledge/${spaceName}/document/sync_batch`, data); }; export const uploadDocument = (knowLedgeName: string, data: FormData) => { - return POST( - `/knowledge/${knowLedgeName}/document/upload`, - data - ); + return POST(`/knowledge/${knowLedgeName}/document/upload`, data); }; export const getChunkList = (spaceName: string, data: ChunkListParams) => { - return POST( - `/knowledge/${spaceName}/chunk/list`, - data - ); + return POST(`/knowledge/${spaceName}/chunk/list`, data); }; -export const delDocument = ( - spaceName: string, - data: Record -) => { - return POST, null>( - `/knowledge/${spaceName}/document/delete`, - data - ); +export const delDocument = (spaceName: string, data: Record) => { + return POST, null>(`/knowledge/${spaceName}/document/delete`, data); }; export const delSpace = (data: Record) => { @@ -308,72 +237,61 @@ export const getSupportModels = () => { /** Agent */ export const postAgentQuery = (data: PostAgentQueryParams) => { - return POST( - "/api/v1/agent/query", - data - ); + return POST('/api/v1/agent/query', data); }; export const postDbgptsQuery = (data: PostAgentQueryParams) => { return POST( `/api/v1/serve/dbgpts/hub/query_page?page=${data?.page_index}&page_size=${data?.page_size}`, - data + data, ); }; export const postAgentHubUpdate = (data?: PostAgentHubUpdateParams) => { return POST( - "/api/v1/agent/hub/update", - data ?? { channel: "", url: "", branch: "", authorization: "" } + '/api/v1/agent/hub/update', + data ?? { channel: '', url: '', branch: '', authorization: '' }, ); }; export const postDbgptsHubUpdate = (data?: PostAgentHubUpdateParams) => { return POST( - "/api/v1/serve/dbgpts/hub/source/refresh", - data ?? { channel: "", url: "", branch: "", authorization: "" } + '/api/v1/serve/dbgpts/hub/source/refresh', + data ?? { channel: '', url: '', branch: '', authorization: '' }, ); }; export const postAgentMy = (user?: string) => { - return POST( - "/api/v1/agent/my", - undefined, - { params: { user } } - ); + return POST('/api/v1/agent/my', undefined, { params: { user } }); }; export const postDbgptsMy = (data?: PostDbgptMyQueryParams) => { return POST( `/api/v1/serve/dbgpts/my/query_page?page=${data?.page_index}&page_size=${data?.page_size}`, - data + data, ); }; export const postAgentInstall = (pluginName: string, user?: string) => { - return POST("/api/v1/agent/install", undefined, { + return POST('/api/v1/agent/install', undefined, { params: { plugin_name: pluginName, user }, timeout: 60000, }); }; export const postDbgptsInstall = (data: object, user?: string) => { - return POST("/api/v1/serve/dbgpts/hub/install", data, { + return POST('/api/v1/serve/dbgpts/hub/install', data, { params: { user }, timeout: 60000, }); }; export const postAgentUninstall = (pluginName: string, user?: string) => { - return POST("/api/v1/agent/uninstall", undefined, { + return POST('/api/v1/agent/uninstall', undefined, { params: { plugin_name: pluginName, user }, timeout: 60000, }); }; -export const postDbgptsUninstall = (data: { name: string, type: string }, user?: string) => { - return POST("/api/v1/serve/dbgpts/my/uninstall", undefined, { +export const postDbgptsUninstall = (data: { name: string; type: string }, user?: string) => { + return POST('/api/v1/serve/dbgpts/my/uninstall', undefined, { params: { ...data, user }, timeout: 60000, }); }; -export const postAgentUpload = ( - user = "", - data: FormData, - config?: Omit -) => { - return POST("/api/v1/personal/agent/upload", data, { +export const postAgentUpload = (user = '', data: FormData, config?: Omit) => { + return POST('/api/v1/personal/agent/upload', data, { params: { user }, headers: { 'Content-Type': 'multipart/form-data', @@ -392,7 +310,7 @@ export const getChatFeedBackSelect = () => { export const getChatFeedBackItme = (conv_uid: string, conv_index: number) => { return GET>( `/api/v1/feedback/find?conv_uid=${conv_uid}&conv_index=${conv_index}`, - undefined + undefined, ); }; export const postChatFeedBackForm = ({ @@ -400,7 +318,7 @@ export const postChatFeedBackForm = ({ config, }: { data: ChatFeedBackSchema; - config?: Omit; + config?: Omit; }) => { return POST(`/api/v1/feedback/commit`, data, { headers: { @@ -412,73 +330,6 @@ export const postChatFeedBackForm = ({ /** prompt */ -/** AWEL Flow */ -export const addFlow = (data: IFlowUpdateParam) => { - return POST("/api/v2/serve/awel/flows", data); -}; - -export const getFlows = ({ page, page_size }: { page?: number, page_size?: number }) => { - return GET(`/api/v2/serve/awel/flows?page=${page || 1}&page_size=${page_size || 12}`); -}; - -export const getFlowById = (id: string) => { - return GET(`/api/v2/serve/awel/flows/${id}`); -}; - -export const updateFlowById = (id: string, data: IFlowUpdateParam) => { - return PUT(`/api/v2/serve/awel/flows/${id}`, data); -}; - -export const deleteFlowById = (id: string) => { - return DELETE(`/api/v2/serve/awel/flows/${id}`); -}; - -export const getFlowNodes = () => { - return GET>(`/api/v2/serve/awel/nodes`); -}; - -export const refreshFlowNodeById = (data: IFlowRefreshParams) => { - return POST( - "/api/v2/serve/awel/nodes/refresh", - data - ); -}; - -export const debugFlow = (data: any) => { - return POST("/api/v2/serve/awel/flow/debug", data); -}; - -export const exportFlow = (data: IFlowExportParams) => { - return GET( - `/api/v2/serve/awel/flow/export/${data.uid}`, - data - ); -}; - -export const importFlow = (data: IFlowImportParams) => { - return POST("/api/v2/serve/awel/flow/import", data); -}; - -export const uploadFile = (data: IUploadFileRequestParams) => { - return POST>( - "/api/v2/serve/file/files/dbgpt", - data - ); -}; - -export const downloadFile = (fileId: string) => { - return GET(`/api/v2/serve/file/files/dbgpt/${fileId}`); -}; - -// TODO:wait for interface update -export const getFlowTemplateList = () => { - return GET>("/api/v2/serve/awel/flow/templates"); -}; - -export const getFlowTemplateById = (id: string) => { - return GET(`/api/v2/serve/awel/flow/templates/${id}`); -}; - /** app */ export const collectApp = (data: Record) => { @@ -508,10 +359,8 @@ export const getAppInfo = (data: GetAppInfoParams) => { return GET('/api/v1/app/info', data); }; -export const getSupportDBList = (db_name = "") => { - return GET>( - `/api/v1/permission/db/list?db_name=${db_name}` - ); +export const getSupportDBList = (db_name = '') => { + return GET>(`/api/v1/permission/db/list?db_name=${db_name}`); }; export const recommendApps = (data: Record) => { @@ -525,9 +374,7 @@ export const modelSearch = (data: Record) => { }; export const getKnowledgeAdmins = (spaceId: string) => { - return GET>( - `/knowledge/users/list?space_id=${spaceId}` - ); + return GET>(`/knowledge/users/list?space_id=${spaceId}`); }; export const updateKnowledgeAdmins = (data: Record) => { return POST, any[]>(`/knowledge/users/update`, data); diff --git a/web/client/api/tools/interceptors.ts b/web/client/api/tools/interceptors.ts index efe940aef..8a70f0776 100644 --- a/web/client/api/tools/interceptors.ts +++ b/web/client/api/tools/interceptors.ts @@ -1,6 +1,6 @@ -import { AxiosError } from 'axios'; -import { ApiResponse, FailedTuple, SuccessTuple, ResponseType } from '../'; import { notification } from 'antd'; +import { AxiosError } from 'axios'; +import { ApiResponse, FailedTuple, ResponseType, SuccessTuple } from '../'; /** * Response processing @@ -9,9 +9,12 @@ import { notification } from 'antd'; * @param ignoreCodes ignore error codes * @returns */ -export const apiInterceptors = (promise: Promise>, ignoreCodes?: '*' | (number | string)[]) => { +export const apiInterceptors = ( + promise: Promise>, + ignoreCodes?: '*' | (number | string)[], +) => { return promise - .then>((response) => { + .then>(response => { const { data } = response; if (!data) { throw new Error('Network Error!'); @@ -34,7 +37,9 @@ export const apiInterceptors = (promise: Promise; err_msg && (errMessage = err_msg); - } catch (e) {} + } catch { + /* empty */ + } } notification.error({ message: `Request error`, diff --git a/web/client/api/user/index.ts b/web/client/api/user/index.ts index dde420b9c..417af8cd5 100644 --- a/web/client/api/user/index.ts +++ b/web/client/api/user/index.ts @@ -1,5 +1,4 @@ -import { Role, UserInfoResponse } from '@/types/userinfo'; -import { GET } from '../index'; +import { Role } from '@/types/userinfo'; interface Props { role: Role; @@ -8,6 +7,6 @@ interface Props { /** * 查询管理员列表 */ -export const queryAdminList = (data: Props) => { +export const queryAdminList = (_data: Props) => { return []; }; diff --git a/web/components/MenuModal/index.tsx b/web/components/MenuModal/index.tsx index c52343898..c85e0af98 100644 --- a/web/components/MenuModal/index.tsx +++ b/web/components/MenuModal/index.tsx @@ -13,21 +13,21 @@ function MenuModal({ items, modal }: Props) { const [currentMenuKey, setCurrentMenuKey] = useState('edit'); return ( -
-
+
+
{ + mode='inline' + onSelect={info => { setCurrentMenuKey(info.key); }} inlineCollapsed={false} - items={items.map((item) => ({ key: item.key, label: item.label }))} + items={items.map(item => ({ key: item.key, label: item.label }))} />
-
- {items.map((item) => { +
+ {items.map(item => { if (item.key === currentMenuKey) { return {item.children}; } diff --git a/web/components/agent/market-plugins.tsx b/web/components/agent/market-plugins.tsx index 4e3ca2f89..2a7fd9a3c 100644 --- a/web/components/agent/market-plugins.tsx +++ b/web/components/agent/market-plugins.tsx @@ -1,13 +1,19 @@ -import { apiInterceptors, postAgentHubUpdate, postAgentInstall, postAgentQuery, postAgentUninstall } from '@/client/api'; -import { IAgentPlugin, PostAgentQueryParams } from '@/types/agent'; +import { + apiInterceptors, + postAgentHubUpdate, + postAgentInstall, + postAgentQuery, + postAgentUninstall, +} from '@/client/api'; +import BlurredCard, { ChatButton } from '@/new-components/common/blurredCard'; +import { PostAgentQueryParams } from '@/types/agent'; +import { ClearOutlined, DownloadOutlined, SearchOutlined, SyncOutlined } from '@ant-design/icons'; import { useRequest } from 'ahooks'; -import { Button, Card, Form, Input, Spin, Tag, Tooltip, message } from 'antd'; +import { Button, Form, Input, Spin, Tag, message } from 'antd'; +import moment from 'moment'; import { useCallback, useMemo, useState } from 'react'; -import MyEmpty from '../common/MyEmpty'; -import { ClearOutlined, DownloadOutlined, GithubOutlined, LoadingOutlined, SearchOutlined, SyncOutlined } from '@ant-design/icons'; import { useTranslation } from 'react-i18next'; -import BlurredCard, { ChatButton, InnerDropdown } from '@/new-components/common/blurredCard'; -import moment from 'moment'; +import MyEmpty from '../common/MyEmpty'; function MarketPlugins() { const { t } = useTranslation(); @@ -67,56 +73,57 @@ function MarketPlugins() { [actionIndex, refresh], ); - const renderAction = useCallback( - (agent: IAgentPlugin, index: number) => { - if (index === actionIndex) { - return ; - } - return agent.installed ? ( - -
{ - pluginAction(agent.name, index, false); - }} - > - -
-
- ) : ( - -
{ - pluginAction(agent.name, index, true); - }} - > - -
-
- ); - }, - [actionIndex, pluginAction], - ); + // const renderAction = useCallback( + // (agent: IAgentPlugin, index: number) => { + // if (index === actionIndex) { + // return ; + // } + // return agent.installed ? ( + // + //
{ + // pluginAction(agent.name, index, false); + // }} + // > + // + //
+ //
+ // ) : ( + // + //
{ + // pluginAction(agent.name, index, true); + // }} + // > + // + //
+ //
+ // ); + // }, + // [actionIndex, pluginAction], + // ); + console.log(agents); return ( -
- - + + + - - {!agents.length && !loading && } -
+
{/* } LeftBottom={ -
+
{agent.author} {agent?.gmt_created && {moment(agent?.gmt_created).fromNow() + ' ' + t('update')}} @@ -172,7 +179,7 @@ function MarketPlugins() { agent.installed ? ( } - text="Uninstall" + text='Uninstall' onClick={() => { pluginAction(agent.name, index, false); }} @@ -180,7 +187,7 @@ function MarketPlugins() { ) : ( } - text="Install" + text='Install' onClick={() => { pluginAction(agent.name, index, true); }} diff --git a/web/components/agent/my-plugins.tsx b/web/components/agent/my-plugins.tsx index d7c394d9d..c3d4301b0 100644 --- a/web/components/agent/my-plugins.tsx +++ b/web/components/agent/my-plugins.tsx @@ -1,11 +1,11 @@ import { apiInterceptors, postAgentMy, postAgentUninstall, postAgentUpload } from '@/client/api'; import { IMyPlugin } from '@/types/agent'; +import { ClearOutlined, LoadingOutlined, UploadOutlined } from '@ant-design/icons'; import { useRequest } from 'ahooks'; import { Button, Card, Spin, Tag, Tooltip, Upload, UploadProps, message } from 'antd'; import { useCallback, useState } from 'react'; -import MyEmpty from '../common/MyEmpty'; -import { ClearOutlined, LoadingOutlined, UploadOutlined } from '@ant-design/icons'; import { useTranslation } from 'react-i18next'; +import MyEmpty from '../common/MyEmpty'; function MyPlugins() { const { t } = useTranslation(); @@ -40,9 +40,9 @@ function MyPlugins() { return ; } return ( - +
{ uninstall(item.name, index); }} @@ -55,7 +55,7 @@ function MyPlugins() { [actionIndex], ); - const onChange: UploadProps['onChange'] = async (info) => { + const onChange: UploadProps['onChange'] = async info => { if (!info) { message.error('Please select the *.zip,*.rar file'); return; @@ -84,10 +84,10 @@ function MyPlugins() {
false} - name="file" - accept=".zip,.rar" + name='file' + accept='.zip,.rar' multiple={false} onChange={onChange} showUploadList={{ @@ -97,22 +97,22 @@ function MyPlugins() { }} itemRender={() => <>} > -
{!data.length && !loading && } -
+
{data.map((item, index) => ( - + -

{item.name}

+

{item.name}

{item.version && v{item.version}} {item.type && Type {item.type}} -

{item.description}

+

{item.description}

))} diff --git a/web/components/app/agent-panel.tsx b/web/components/app/agent-panel.tsx index 2a550b9e1..5d50ece0c 100644 --- a/web/components/app/agent-panel.tsx +++ b/web/components/app/agent-panel.tsx @@ -1,8 +1,8 @@ -import { apiInterceptors, getAppStrategy, getAppStrategyValues, getResource } from '@/client/api'; +import { apiInterceptors, getAppStrategy, getAppStrategyValues } from '@/client/api'; import { Button, Input, Select } from 'antd'; -import React, { useEffect, useMemo, useState } from 'react'; -import ResourceCard from './resource-card'; +import { useEffect, useMemo, useState } from 'react'; import { useTranslation } from 'react-i18next'; +import ResourceCard from './resource-card'; interface IProps { resourceTypes: any; @@ -40,14 +40,14 @@ export default function AgentPanel(props: IProps) { const getStrategy = async () => { const [_, data] = await apiInterceptors(getAppStrategy()); if (data) { - setStrategyOptions(data?.map((item) => ({ label: item.name_cn, value: item.value }))); + setStrategyOptions(data?.map(item => ({ label: item.name_cn, value: item.value }))); } }; const getStrategyValues = async (type: string) => { const [_, data] = await apiInterceptors(getAppStrategyValues(type)); if (data) { - setStrategyValueOptions(data.map((item) => ({ label: item, value: item })) ?? []); + setStrategyValueOptions(data.map(item => ({ label: item, value: item })) ?? []); } }; @@ -88,35 +88,35 @@ export default function AgentPanel(props: IProps) { return (
-
-
{t('Prompt')}:
+
+
{t('Prompt')}:
{ + onChange={e => { updateAgent(e.target.value, 'prompt_template'); }} /> -
{t('LLM_strategy')}:
+
{t('LLM_strategy')}:
{ + onChange={value => { if (!value || value?.length === 0) { updateAgent(null, 'llm_strategy_value'); return null; @@ -136,7 +136,7 @@ export default function AgentPanel(props: IProps) { )}
-
{t('available_resources')}
+
{t('available_resources')}
{resources.map((resource: any, index: number) => { return ( ); })} -
diff --git a/web/components/app/app-card.tsx b/web/components/app/app-card.tsx index 169854221..02bf729ec 100644 --- a/web/components/app/app-card.tsx +++ b/web/components/app/app-card.tsx @@ -4,7 +4,7 @@ import { IApp } from '@/types/app'; import { DeleteFilled, MessageFilled, StarFilled, WarningOutlined } from '@ant-design/icons'; import { Modal, Popconfirm, Tooltip, message } from 'antd'; import { useRouter } from 'next/router'; -import React, { useContext, useEffect, useMemo, useState } from 'react'; +import React, { useContext, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import IconFont from '@/new-components/common/Icon'; @@ -92,7 +92,7 @@ export default function AppCard(props: IProps) { }, { manual: true, - onSuccess: (data) => { + onSuccess: data => { if (data[2]?.success) { if (app.published === 'true') { message.success(t('cancel_success')); @@ -122,10 +122,10 @@ export default function AppCard(props: IProps) { operate(); }} > - + {published == 'true' ? ( ) : ( { + const teamModalOptions = data.map(item => { return { value: item, label: item }; }); setTeamModal(teamModalOptions); @@ -113,7 +113,7 @@ export default function AppModal(props: IProps) { setDropItems( data - .map((agent) => { + .map(agent => { return { label: agent.name, key: agent.name, @@ -123,7 +123,7 @@ export default function AppModal(props: IProps) { agent, }; }) - .filter((item) => { + .filter(item => { if (!app.details || app.details?.length === 0) { return item; } @@ -182,7 +182,13 @@ export default function AppModal(props: IProps) { label: newActiveKey, children: ( @@ -192,8 +198,8 @@ export default function AppModal(props: IProps) { ]; }); - setDropItems((items) => { - return items.filter((item) => item.key !== tabBar.name); + setDropItems(items => { + return items.filter(item => item.key !== tabBar.name); }); }; @@ -211,7 +217,7 @@ export default function AppModal(props: IProps) { } }); - const newPanes = agents.filter((item) => item.key !== targetKey); + const newPanes = agents.filter(item => item.key !== targetKey); if (newPanes.length && newActiveKey === targetKey) { if (lastIndex >= 0) { newActiveKey = newPanes[lastIndex].key; @@ -274,7 +280,7 @@ export default function AppModal(props: IProps) { try { await createApp(data); - } catch (error) { + } catch { return; } @@ -289,7 +295,7 @@ export default function AppModal(props: IProps) { const renderAddIcon = () => { return ( - e.preventDefault()}> + e.preventDefault()}> @@ -313,10 +319,10 @@ export default function AppModal(props: IProps) {
- label={'App Name'} name="app_name" rules={[{ required: true, message: t('Please_input_the_name') }]}> + + label={'App Name'} + name='app_name' + rules={[{ required: true, message: t('Please_input_the_name') }]} + > label={t('Description')} - name="app_describe" + name='app_describe' rules={[{ required: true, message: t('Please_input_the_description') }]} > -
- labelCol={{ span: 7 }} label={t('language')} name="language" className="w-1/2" rules={[{ required: true }]}> - - label={t('team_modal')} name="team_mode" className="w-1/2" labelCol={{ span: 6 }} rules={[{ required: true }]}> + + label={t('team_modal')} + name='team_mode' + className='w-1/2' + labelCol={{ span: 6 }} + rules={[{ required: true }]} + > - +
+
Flows:
+
+ ) => { updateResource(e.target.value, 'name'); }} /> -
-
{t('resource_dynamic')}
+
+
{t('resource_dynamic')}
{ + onChange={value => { updateResource(value, 'is_dynamic'); }} />
-
-
{t('resource_type')}:
+
+
{t('resource_type')}:
{ + onChange={value => { updateResource(value, 'value'); }} /> ) : ( ) => { updateResource(e.target.value, 'value'); diff --git a/web/components/chart/autoChart/advisor/pipeline.ts b/web/components/chart/autoChart/advisor/pipeline.ts index 892a40f8a..db87b3bfd 100644 --- a/web/components/chart/autoChart/advisor/pipeline.ts +++ b/web/components/chart/autoChart/advisor/pipeline.ts @@ -1,7 +1,7 @@ -import { Advisor, CkbConfig, DataFrame } from '@antv/ava'; import type { Advice, AdviseParams, AdvisorConfig, ChartKnowledgeBase, Datum, FieldInfo } from '@antv/ava'; -import type { CustomAdvisorConfig, RuleConfig, Specification } from '../types'; +import { Advisor, CkbConfig, DataFrame } from '@antv/ava'; import { size } from 'lodash'; +import type { CustomAdvisorConfig, RuleConfig, Specification } from '../types'; export type CustomRecommendConfig = { customCKB?: Partial; @@ -12,10 +12,10 @@ export const customizeAdvisor = (props: CustomAdvisorConfig): Advisor => { const { charts, scopeOfCharts: CKBCfg, ruleConfig: ruleCfg } = props; const customCKB: ChartKnowledgeBase = {}; - charts?.forEach((chart) => { + charts?.forEach(chart => { /** 若用户自定义的图表 id 与内置图表 id 相同,内置图表将被覆盖 */ if (!chart.chartKnowledge.toSpec) { - chart.chartKnowledge.toSpec = (data: any, dataProps: any) => { + chart.chartKnowledge.toSpec = (_: any, dataProps: any) => { return { dataProps } as Specification; }; } else { @@ -65,25 +65,29 @@ export const customizeAdvisor = (props: CustomAdvisorConfig): Advisor => { }; /** 主推荐流程 */ -export const getVisAdvices = (props: { data: Datum[]; myChartAdvisor: Advisor; dataMetaMap?: Record }): Advice[] => { +export const getVisAdvices = (props: { + data: Datum[]; + myChartAdvisor: Advisor; + dataMetaMap?: Record; +}): Advice[] => { const { data, dataMetaMap, myChartAdvisor } = props; /** * 若输入中有信息能够获取列的类型( Interval, Nominal, Time ),则将这个 信息传给 Advisor * 主要是读取 levelOfMeasureMents 这个字段,即 dataMetaMap[item].levelOfMeasurements */ const customDataProps = dataMetaMap - ? Object.keys(dataMetaMap).map((item) => { + ? Object.keys(dataMetaMap).map(item => { return { name: item, ...dataMetaMap[item] }; }) : null; - + // 可根据需要选择是否使用全部 fields 进行推荐 const useAllFields = false; // 挑选出维值不只有一个的字段 const allFieldsInfo = new DataFrame(data).info(); const selectedFields = size(allFieldsInfo) > 2 - ? allFieldsInfo?.filter((field) => { + ? allFieldsInfo?.filter(field => { if (field.recommendation === 'string' || field.recommendation === 'date') { return field.distinct && field.distinct > 1; } @@ -95,7 +99,7 @@ export const getVisAdvices = (props: { data: Datum[]; myChartAdvisor: Advisor; d data, dataProps: customDataProps as AdviseParams['dataProps'], // 不传 fields 参数,内部默认使用全部 fields,否则使用业务选择的字段 - fields: useAllFields ? undefined : selectedFields?.map((field) => field.name), + fields: useAllFields ? undefined : selectedFields?.map(field => field.name), }); return allAdvices?.advices ?? []; }; diff --git a/web/components/chart/autoChart/advisor/utils.ts b/web/components/chart/autoChart/advisor/utils.ts index 76cfb1cd6..1b67df66b 100644 --- a/web/components/chart/autoChart/advisor/utils.ts +++ b/web/components/chart/autoChart/advisor/utils.ts @@ -1,5 +1,5 @@ -import { isNull } from 'lodash'; import type { Advice } from '@antv/ava'; +import { isNull } from 'lodash'; export function defaultAdvicesFilter(props: { advices: Advice[] }) { const { advices } = props; @@ -19,11 +19,11 @@ export const compare = (f1: any, f2: any) => { }; export function hasSubset(array1: any[], array2: any[]): boolean { - return array2.every((e) => array1.includes(e)); + return array2.every(e => array1.includes(e)); } export function intersects(array1: any[], array2: any[]): boolean { - return array2.some((e) => array1.includes(e)); + return array2.some(e => array1.includes(e)); } export function LOM2EncodingType(lom: string) { diff --git a/web/components/chart/autoChart/charts/index.ts b/web/components/chart/autoChart/charts/index.ts index 499c9b11c..eb27467d0 100644 --- a/web/components/chart/autoChart/charts/index.ts +++ b/web/components/chart/autoChart/charts/index.ts @@ -1,7 +1,7 @@ +import type { CustomChart } from '../types'; import multi_line_chart from './multi-line-chart'; import multi_measure_column_chart from './multi-measure-column-chart'; import multi_measure_line_chart from './multi-measure-line-chart'; -import type { CustomChart } from '../types'; export const customCharts: CustomChart[] = [multi_line_chart, multi_measure_column_chart, multi_measure_line_chart]; diff --git a/web/components/chart/autoChart/charts/multi-line-chart.ts b/web/components/chart/autoChart/charts/multi-line-chart.ts index 192fea123..fa608a674 100644 --- a/web/components/chart/autoChart/charts/multi-line-chart.ts +++ b/web/components/chart/autoChart/charts/multi-line-chart.ts @@ -1,20 +1,22 @@ +import type { Datum } from '@antv/ava'; import { hasSubset } from '../advisor/utils'; -import { processDateEncode, findOrdinalField, findNominalField, getLineSize, sortData } from './util'; import type { ChartKnowledge, CustomChart, GetChartConfigProps, Specification } from '../types'; -import type { Datum } from '@antv/ava'; +import { findNominalField, findOrdinalField, getLineSize, processDateEncode, sortData } from './util'; -const MULTI_LINE_CHART = 'multi_line_chart' +const MULTI_LINE_CHART = 'multi_line_chart'; const getChartSpec = (data: GetChartConfigProps['data'], dataProps: GetChartConfigProps['dataProps']) => { const ordinalField = findOrdinalField(dataProps); const nominalField = findNominalField(dataProps); // 放宽折线图的 x 轴条件,优先选择 time, ordinal, nominal 类型,没有的话使用第一个字段作兜底 const field4X = ordinalField ?? nominalField ?? dataProps[0]; - const remainFields = dataProps.filter((field) => field.name !== field4X?.name); + const remainFields = dataProps.filter(field => field.name !== field4X?.name); - const field4Y = remainFields.filter((field) => field.levelOfMeasurements && hasSubset(field.levelOfMeasurements, ['Interval'])) ?? [remainFields[0]]; - const field4Nominal = remainFields.filter(field => !field4Y.find(y => y.name === field.name)).find( - (field) => field.levelOfMeasurements && hasSubset(field.levelOfMeasurements, ['Nominal']), - ); + const field4Y = remainFields.filter( + field => field.levelOfMeasurements && hasSubset(field.levelOfMeasurements, ['Interval']), + ) ?? [remainFields[0]]; + const field4Nominal = remainFields + .filter(field => !field4Y.find(y => y.name === field.name)) + .find(field => field.levelOfMeasurements && hasSubset(field.levelOfMeasurements, ['Nominal'])); if (!field4X || !field4Y) return null; const spec: Specification = { @@ -24,7 +26,7 @@ const getChartSpec = (data: GetChartConfigProps['data'], dataProps: GetChartConf children: [], }; - field4Y.forEach((field) => { + field4Y.forEach(field => { const singleLine: Specification = { type: 'line', encode: { diff --git a/web/components/chart/autoChart/charts/multi-measure-column-chart.ts b/web/components/chart/autoChart/charts/multi-measure-column-chart.ts index a91e5f70b..2edea3b2a 100644 --- a/web/components/chart/autoChart/charts/multi-measure-column-chart.ts +++ b/web/components/chart/autoChart/charts/multi-measure-column-chart.ts @@ -5,8 +5,7 @@ import { findNominalField, findOrdinalField } from './util'; const getChartSpec = (data: GetChartConfigProps['data'], dataProps: GetChartConfigProps['dataProps']) => { try { - // @ts-ignore - const field4Y = dataProps?.filter((field) => hasSubset(field.levelOfMeasurements, ['Interval'])); + const field4Y = dataProps?.filter(field => hasSubset(field.levelOfMeasurements, ['Interval'])); const nominalField = findNominalField(dataProps); const ordinalField = findOrdinalField(dataProps); const field4X = nominalField ?? ordinalField; @@ -18,7 +17,7 @@ const getChartSpec = (data: GetChartConfigProps['data'], dataProps: GetChartConf children: [], }; - field4Y?.forEach((field) => { + field4Y?.forEach(field => { const singleLine: Specification = { type: 'interval', encode: { diff --git a/web/components/chart/autoChart/charts/multi-measure-line-chart.ts b/web/components/chart/autoChart/charts/multi-measure-line-chart.ts index 28ee2c001..a1aa130a9 100644 --- a/web/components/chart/autoChart/charts/multi-measure-line-chart.ts +++ b/web/components/chart/autoChart/charts/multi-measure-line-chart.ts @@ -1,15 +1,17 @@ +import { Datum } from '@antv/ava'; import { hasSubset } from '../advisor/utils'; -import { processDateEncode, findNominalField, findOrdinalField, getLineSize, sortData } from './util'; import type { ChartKnowledge, CustomChart, GetChartConfigProps, Specification } from '../types'; -import { Datum } from '@antv/ava'; +import { findNominalField, findOrdinalField, getLineSize, processDateEncode, sortData } from './util'; -const MULTI_MEASURE_LINE_CHART = 'multi_measure_line_chart' +const MULTI_MEASURE_LINE_CHART = 'multi_measure_line_chart'; const getChartSpec = (data: GetChartConfigProps['data'], dataProps: GetChartConfigProps['dataProps']) => { try { // 优先确认 x 轴,如果没有枚举类型字段,取第一个字段为 x 轴 const field4Nominal = findNominalField(dataProps) ?? findOrdinalField(dataProps) ?? dataProps[0]; - // @ts-ignore - const field4Y = dataProps?.filter((field) => field.name !== field4Nominal?.name && hasSubset(field.levelOfMeasurements, ['Interval'])); + + const field4Y = dataProps?.filter( + field => field.name !== field4Nominal?.name && hasSubset(field.levelOfMeasurements, ['Interval']), + ); if (!field4Nominal || !field4Y) return null; const spec: Specification = { @@ -18,7 +20,7 @@ const getChartSpec = (data: GetChartConfigProps['data'], dataProps: GetChartConf children: [], }; - field4Y?.forEach((field) => { + field4Y?.forEach(field => { const singleLine: Specification = { type: 'line', encode: { diff --git a/web/components/chart/autoChart/charts/util.ts b/web/components/chart/autoChart/charts/util.ts index 94518c2f8..4fa84d096 100644 --- a/web/components/chart/autoChart/charts/util.ts +++ b/web/components/chart/autoChart/charts/util.ts @@ -1,6 +1,6 @@ -import type { Datum, FieldInfo } from "@antv/ava"; +import type { Datum, FieldInfo } from '@antv/ava'; +import { cloneDeep, uniq } from 'lodash'; import { hasSubset, intersects } from '../advisor/utils'; -import { cloneDeep, uniq } from "lodash"; /** * Process date column to new Date(). @@ -9,7 +9,7 @@ import { cloneDeep, uniq } from "lodash"; * @returns */ export function processDateEncode(field: string, dataProps: FieldInfo[]) { - const dp = dataProps.find((dataProp) => dataProp.name === field); + const dp = dataProps.find(dataProp => dataProp.name === field); if (dp?.recommendation === 'date') { return (d: any) => new Date(d[field]); @@ -18,16 +18,16 @@ export function processDateEncode(field: string, dataProps: FieldInfo[]) { } export function findOrdinalField(fields: FieldInfo[]) { - return fields.find((field) => field.levelOfMeasurements && intersects(field.levelOfMeasurements, ['Time', 'Ordinal'])); + return fields.find(field => field.levelOfMeasurements && intersects(field.levelOfMeasurements, ['Time', 'Ordinal'])); } export function findNominalField(fields: FieldInfo[]) { - return fields.find((field) => field.levelOfMeasurements && hasSubset(field.levelOfMeasurements, ['Nominal'])); + return fields.find(field => field.levelOfMeasurements && hasSubset(field.levelOfMeasurements, ['Nominal'])); } // 识别 x 轴是否只有一条数据(绘制的折线图是否只有一个点) export const isUniqueXValue = ({ data, xField }: { xField: string; data: Datum[] }): boolean => { - const uniqXValues = uniq(data.map((datum) => datum[xField])); + const uniqXValues = uniq(data.map(datum => datum[xField])); return uniqXValues.length <= 1; }; @@ -43,40 +43,42 @@ export const getLineSize = ( const { field4Split, field4X } = fields; if (field4Split?.name && field4X?.name) { const seriesValue = datum[field4Split.name]; - const splitData = allData.filter((item) => field4Split.name && item[field4Split.name] === seriesValue); + const splitData = allData.filter(item => field4Split.name && item[field4Split.name] === seriesValue); return isUniqueXValue({ data: splitData, xField: field4X.name }) ? 5 : undefined; } return field4X?.name && isUniqueXValue({ data: allData, xField: field4X.name }) ? 5 : undefined; }; -export const sortData = ({ data, chartType, xField }: { - data: Datum[]; - xField?: FieldInfo; - chartType: string; -}) => { - const sortedData = cloneDeep(data) +export const sortData = ({ data, chartType, xField }: { data: Datum[]; xField?: FieldInfo; chartType: string }) => { + const sortedData = cloneDeep(data); try { // 折线图绘制需要将数据点按照日期从小到大的顺序排序和连线 if (chartType.includes('line') && xField?.name && xField.recommendation === 'date') { - sortedData.sort((datum1, datum2) => new Date(datum1[xField.name as string]).getTime() - new Date(datum2[xField.name as string]).getTime()) - return sortedData + sortedData.sort( + (datum1, datum2) => + new Date(datum1[xField.name as string]).getTime() - new Date(datum2[xField.name as string]).getTime(), + ); + return sortedData; } // 如果折线图横轴是数值类型,则按照数值大小排序 if (chartType.includes('line') && xField?.name && ['float', 'integer'].includes(xField.recommendation)) { - sortedData.sort((datum1, datum2) => (datum1[xField.name as string] as number) - (datum2[xField.name as string] as number)) - return sortedData + sortedData.sort( + (datum1, datum2) => (datum1[xField.name as string] as number) - (datum2[xField.name as string] as number), + ); + return sortedData; } } catch (err) { - console.error(err) + console.error(err); } - return sortedData -} + return sortedData; +}; /** 数据空值处理:后端返回的空数据为 '-', 在展示为图表时会有问题,修改为 null */ -export const processNilData = (data: Datum[], emptyValue = '-') => data.map((datum) => { - const processedDatum: Record = {}; - Object.keys(datum).forEach((key) => { - processedDatum[key] = datum[key] === emptyValue ? null : datum[key]; +export const processNilData = (data: Datum[], emptyValue = '-') => + data.map(datum => { + const processedDatum: Record = {}; + Object.keys(datum).forEach(key => { + processedDatum[key] = datum[key] === emptyValue ? null : datum[key]; + }); + return processedDatum; }); - return processedDatum; -}); diff --git a/web/components/chart/autoChart/index.tsx b/web/components/chart/autoChart/index.tsx index 35d84089d..c25e932b0 100644 --- a/web/components/chart/autoChart/index.tsx +++ b/web/components/chart/autoChart/index.tsx @@ -1,18 +1,17 @@ -import { Empty, Row, Col, Select, Tooltip, Button, Space } from 'antd'; +import { ChatContext } from '@/app/chat-context'; +import i18n, { I18nKeys } from '@/app/i18n'; +import { DownloadOutlined } from '@ant-design/icons'; import { Advice, Advisor, Datum } from '@antv/ava'; import { Chart, ChartRef } from '@berryv/g2-react'; -import i18n, { I18nKeys } from '@/app/i18n'; +import { Button, Col, Empty, Row, Select, Space, Tooltip } from 'antd'; +import { compact, concat, uniq } from 'lodash'; +import { useContext, useEffect, useMemo, useRef, useState } from 'react'; +import { downloadImage } from '../helpers/downloadChartImage'; import { customizeAdvisor, getVisAdvices } from './advisor/pipeline'; -import { useContext, useEffect, useMemo, useState, useRef } from 'react'; import { defaultAdvicesFilter } from './advisor/utils'; -import { AutoChartProps, ChartType, CustomAdvisorConfig, CustomChart, Specification } from './types'; import { customCharts } from './charts'; -import { ChatContext } from '@/app/chat-context'; -import { compact, concat, uniq } from 'lodash'; import { processNilData, sortData } from './charts/util'; -import { downloadImage } from '../helpers/downloadChartImage';; -import { DownloadOutlined } from '@ant-design/icons'; - +import { AutoChartProps, ChartType, CustomAdvisorConfig, CustomChart, Specification } from './types'; const { Option } = Select; export const AutoChart = (props: AutoChartProps) => { @@ -24,7 +23,7 @@ export const AutoChart = (props: AutoChartProps) => { const [advisor, setAdvisor] = useState(); const [advices, setAdvices] = useState([]); const [renderChartType, setRenderChartType] = useState(); - const chartRef = useRef() + const chartRef = useRef(); useEffect(() => { const input_charts: CustomChart[] = customCharts; @@ -49,13 +48,13 @@ export const AutoChart = (props: AutoChartProps) => { compact( concat( chartType, - avaAdvices.map((item) => item.type), + avaAdvices.map(item => item.type), ), ), ); const allAdvices = allChartTypes - .map((chartTypeItem) => { - const avaAdvice = filteredAdvices.find((item) => item.type === chartTypeItem); + .map(chartTypeItem => { + const avaAdvice = filteredAdvices.find(item => item.type === chartTypeItem); // 如果在 AVA 推荐列表中,直接采用推荐列表中的结果 if (avaAdvice) { return avaAdvice; @@ -71,7 +70,7 @@ export const AutoChart = (props: AutoChartProps) => { if ('advices' in specGeneratorOutput) return specGeneratorOutput.advices?.[0]; } }) - .filter((advice) => advice?.spec) as Advice[]; + .filter(advice => advice?.spec) as Advice[]; return allAdvices; }; @@ -96,14 +95,18 @@ export const AutoChart = (props: AutoChartProps) => { if (spec) { if (spec.data && ['line_chart', 'step_line_chart'].includes(chartTypeInput)) { // 处理 ava 内置折线图的排序问题 - const dataAnalyzerOutput = advisor?.dataAnalyzer.execute({ data }) + const dataAnalyzerOutput = advisor?.dataAnalyzer.execute({ data }); if (dataAnalyzerOutput && 'dataProps' in dataAnalyzerOutput) { - spec.data = sortData({ data: spec.data, xField: dataAnalyzerOutput.dataProps?.find((field: any) => field.recommendation === 'date'), chartType: chartTypeInput }); + spec.data = sortData({ + data: spec.data, + xField: dataAnalyzerOutput.dataProps?.find((field: any) => field.recommendation === 'date'), + chartType: chartTypeInput, + }); } } if (chartTypeInput === 'pie_chart' && spec?.encode?.color) { // 补充饼图的 tooltip title 展示 - spec.tooltip = { title: { field: spec.encode.color } } + spec.tooltip = { title: { field: spec.encode.color } }; } return ( { if (renderChartType) { return (
- + {i18n.t('Advices')} setQuesType(newValue ?? '')} + placeholder='Choose one…' + onChange={(_, newValue) => setQuesType(newValue ?? '')} {...(ques_type && { // display the button and remove select indicator // when user has selected a value endDecorator: ( { + size='sm' + variant='plain' + color='neutral' + onMouseDown={event => { // don't open the popup when clicking on this button event.stopPropagation(); }} @@ -170,7 +174,7 @@ const ChatFeedback = ({ conv_index, question, knowledge_space, select_param }: P sx={{ width: '100%' }} > {select_param && - Object.keys(select_param)?.map((paramItem) => ( + Object.keys(select_param)?.map(paramItem => ( @@ -185,8 +189,8 @@ const ChatFeedback = ({ conv_index, question, knowledge_space, select_param }: P
{t('feed_back_desc')}
} - variant="solid" - placement="left" + variant='solid' + placement='left' > {t('Q_A_Rating')} @@ -194,15 +198,15 @@ const ChatFeedback = ({ conv_index, question, knowledge_space, select_param }: P setScore(event.target?.value)} + onChange={event => setScore(event.target?.value)} value={score} /> @@ -210,11 +214,11 @@ const ChatFeedback = ({ conv_index, question, knowledge_space, select_param }: P