From 400ceab47cfa316e683ffb74cb9096967fcef842 Mon Sep 17 00:00:00 2001 From: NikitaTorbenko <2015nekitciti@gmail.com> Date: Sat, 4 Apr 2026 20:05:25 +0300 Subject: [PATCH 1/2] fix: for crush --- .../modules/agent/api/agent.api.service.ts | 23 +++---- frontend/src/pages/logs.page.tsx | 63 +++++++++++++++---- 2 files changed, 62 insertions(+), 24 deletions(-) diff --git a/frontend/src/modules/agent/api/agent.api.service.ts b/frontend/src/modules/agent/api/agent.api.service.ts index 14aacd2..db258e8 100644 --- a/frontend/src/modules/agent/api/agent.api.service.ts +++ b/frontend/src/modules/agent/api/agent.api.service.ts @@ -45,20 +45,17 @@ class AgentApiService { } async searchLogs(filters?: LogFilters): Promise { - const response = await apiClient.get( - `${this.logsBasePath}/mock`, - { - params: { - level: filters?.level, - service: filters?.service, - agent: filters?.agent, - date_from: filters?.date_from, - date_to: filters?.date_to, - limit: filters?.limit ?? 100, - offset: filters?.offset ?? 0, - }, + const response = await apiClient.get(this.logsBasePath, { + params: { + level: filters?.level, + service: filters?.service, + agent: filters?.agent, + date_from: filters?.date_from, + date_to: filters?.date_to, + limit: filters?.limit ?? 100, + offset: filters?.offset ?? 0, }, - ); + }); return response.data; } diff --git a/frontend/src/pages/logs.page.tsx b/frontend/src/pages/logs.page.tsx index 6b2b824..0ec9256 100644 --- a/frontend/src/pages/logs.page.tsx +++ b/frontend/src/pages/logs.page.tsx @@ -63,12 +63,20 @@ export const LogsPage: React.FC = () => { try { const filters = getFilters(); const data = await agentApiService.searchLogs(filters); + if (!Array.isArray(data)) { + console.error("[Logs] Expected array, got:", typeof data); + setLogs([]); + setTotalLogs(0); + return; + } setLogs(data); setTotalLogs(data.length); } catch (err) { setError( err instanceof Error ? err.message : "Ошибка при загрузке логов", ); + setLogs([]); + setTotalLogs(0); } finally { setIsLoading(false); } @@ -76,14 +84,44 @@ export const LogsPage: React.FC = () => { const fetchDistinctData = useCallback(async () => { try { - const [services, agents] = await Promise.all([ + const [servicesResult, agentsResult] = await Promise.allSettled([ agentApiService.getDistinctServices(), agentApiService.getDistinctAgents(), ]); - setAvailableServices(services); - setAvailableAgents(agents); + + if ( + servicesResult.status === "fulfilled" && + Array.isArray(servicesResult.value) + ) { + setAvailableServices(servicesResult.value); + } else { + console.error( + "[Logs] Failed to fetch services:", + servicesResult.status === "rejected" + ? servicesResult.reason + : "non-array response", + ); + setAvailableServices([]); + } + + if ( + agentsResult.status === "fulfilled" && + Array.isArray(agentsResult.value) + ) { + setAvailableAgents(agentsResult.value); + } else { + console.error( + "[Logs] Failed to fetch agents:", + agentsResult.status === "rejected" + ? agentsResult.reason + : "non-array response", + ); + setAvailableAgents([]); + } } catch (err) { - console.error("Failed to fetch distinct data:", err); + console.error("[Logs] Failed to fetch distinct data:", err); + setAvailableServices([]); + setAvailableAgents([]); } }, []); @@ -108,8 +146,10 @@ export const LogsPage: React.FC = () => { setOffset(Math.max(0, offset - limit)); }; - const formatTimestamp = (timestamp: string) => { + const formatTimestamp = (timestamp: string | undefined | null) => { + if (!timestamp) return "—"; const date = new Date(timestamp); + if (isNaN(date.getTime())) return "—"; return date.toLocaleString("ru-RU", { year: "numeric", month: "2-digit", @@ -266,8 +306,9 @@ export const LogsPage: React.FC = () => { {logs.map((log, index) => { + const level = log.level || "INFO"; const colors = - logLevelColors[log.level] || logLevelColors.INFO; + logLevelColors[level] || logLevelColors.INFO; return ( { borderColor: colors.border, }} > - {logLevelIcons[log.level]} - {log.level} + {logLevelIcons[level]} + {level} - {log.service} + {log.service || "—"} - {log.agent} + {log.agent || "—"} - {log.message} + {log.message || "—"} ); From bcca8fa2986ad843ab8d6eddf504f66bb9ba7c46 Mon Sep 17 00:00:00 2001 From: NikitaTorbenko <2015nekitciti@gmail.com> Date: Sat, 4 Apr 2026 21:38:25 +0300 Subject: [PATCH 2/2] fix: 401 --- .../modules/agent/api/agent.api.service.ts | 35 +++++++++++++------ frontend/src/shared/api/axios.instance.ts | 2 +- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/frontend/src/modules/agent/api/agent.api.service.ts b/frontend/src/modules/agent/api/agent.api.service.ts index db258e8..906371e 100644 --- a/frontend/src/modules/agent/api/agent.api.service.ts +++ b/frontend/src/modules/agent/api/agent.api.service.ts @@ -22,14 +22,14 @@ class AgentApiService { async getAgents(): Promise { const response = await apiClient.get(this.basePath); - return response.data; + return Array.isArray(response.data) ? response.data : []; } async getUsers(): Promise { const response = await apiClient.get( `${this.authBasePath}/tokens`, ); - return response.data; + return Array.isArray(response.data) ? response.data : []; } async createUser(data: TokenCreate): Promise { @@ -47,15 +47,25 @@ class AgentApiService { async searchLogs(filters?: LogFilters): Promise { const response = await apiClient.get(this.logsBasePath, { params: { - level: filters?.level, - service: filters?.service, - agent: filters?.agent, - date_from: filters?.date_from, - date_to: filters?.date_to, + level: filters?.level || undefined, + service: filters?.service || undefined, + agent: filters?.agent || undefined, + date_from: filters?.date_from || undefined, + date_to: filters?.date_to || undefined, limit: filters?.limit ?? 100, offset: filters?.offset ?? 0, }, }); + + if (!Array.isArray(response.data)) { + console.error( + "[Logs] Unexpected response format:", + typeof response.data, + response.data, + ); + return []; + } + return response.data; } @@ -71,21 +81,21 @@ class AgentApiService { const response = await apiClient.get( `${this.logsBasePath}/agents`, ); - return response.data; + return Array.isArray(response.data) ? response.data : []; } async getDistinctLevels(): Promise { const response = await apiClient.get( `${this.logsBasePath}/levels`, ); - return response.data; + return Array.isArray(response.data) ? response.data : []; } async getDistinctServices(): Promise { const response = await apiClient.get( `${this.logsBasePath}/services`, ); - return response.data; + return Array.isArray(response.data) ? response.data : []; } // User management methods @@ -93,6 +103,9 @@ class AgentApiService { const response = await apiClient.get( `${this.authBasePath}/users/${login}`, ); + if (!response.data || typeof response.data !== "object") { + throw new Error(`User not found: ${login}`); + } return response.data; } @@ -100,7 +113,7 @@ class AgentApiService { const response = await apiClient.get( `${this.authBasePath}/users/inactive`, ); - return response.data; + return Array.isArray(response.data) ? response.data : []; } async updateUser(login: string, data: TokenUpdate): Promise { diff --git a/frontend/src/shared/api/axios.instance.ts b/frontend/src/shared/api/axios.instance.ts index d61f9fe..afd5aa1 100644 --- a/frontend/src/shared/api/axios.instance.ts +++ b/frontend/src/shared/api/axios.instance.ts @@ -22,7 +22,7 @@ class ApiClient { "Content-Type": "application/json", }, validateStatus: (status) => { - return status >= 200 && status < 500; + return status >= 200 && status < 400; }, });