@@ -0,0 +1,78 @@
|
||||
import { apiClient } from "@/shared/api/axios.instance";
|
||||
import type {
|
||||
AgentInfo,
|
||||
TokenCreate,
|
||||
TokenUser,
|
||||
LogEntry,
|
||||
LogFilters,
|
||||
InsertLogRequest,
|
||||
InsertLogsRequest,
|
||||
} from "../types/agent.types";
|
||||
|
||||
class AgentApiService {
|
||||
private readonly basePath = "/agents";
|
||||
private readonly authBasePath = "/auth";
|
||||
private readonly logsBasePath = "/logs";
|
||||
|
||||
async getAgents(): Promise<AgentInfo[]> {
|
||||
const response = await apiClient.get<AgentInfo[]>(this.basePath);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
async getUsers(): Promise<TokenUser[]> {
|
||||
const response = await apiClient.get<TokenUser[]>(`${this.authBasePath}/tokens`);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
async createUser(data: TokenCreate): Promise<void> {
|
||||
await apiClient.post(`${this.authBasePath}/token`, data);
|
||||
}
|
||||
|
||||
async deleteUser(login: string): Promise<void> {
|
||||
await apiClient.delete(`${this.authBasePath}/tokens/${login}`);
|
||||
}
|
||||
|
||||
async deleteMyAccount(): Promise<void> {
|
||||
await apiClient.delete(`${this.authBasePath}/token`);
|
||||
}
|
||||
|
||||
async searchLogs(filters?: LogFilters): Promise<LogEntry[]> {
|
||||
const response = await apiClient.get<LogEntry[]>(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;
|
||||
}
|
||||
|
||||
async insertLog(entry: InsertLogRequest): Promise<void> {
|
||||
await apiClient.post(this.logsBasePath, entry);
|
||||
}
|
||||
|
||||
async insertLogsBatch(data: InsertLogsRequest): Promise<void> {
|
||||
await apiClient.post(`${this.logsBasePath}/batch`, data);
|
||||
}
|
||||
|
||||
async getDistinctAgents(): Promise<string[]> {
|
||||
const response = await apiClient.get<string[]>(`${this.logsBasePath}/agents`);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
async getDistinctLevels(): Promise<string[]> {
|
||||
const response = await apiClient.get<string[]>(`${this.logsBasePath}/levels`);
|
||||
return response.data;
|
||||
}
|
||||
|
||||
async getDistinctServices(): Promise<string[]> {
|
||||
const response = await apiClient.get<string[]>(`${this.logsBasePath}/services`);
|
||||
return response.data;
|
||||
}
|
||||
}
|
||||
|
||||
export const agentApiService = new AgentApiService();
|
||||
@@ -0,0 +1,36 @@
|
||||
import { useState, useEffect, useCallback } from "react";
|
||||
import { agentApiService } from "../api/agent.api.service";
|
||||
import type { AgentInfo } from "../types/agent.types";
|
||||
|
||||
interface UseAgentsResult {
|
||||
agents: AgentInfo[];
|
||||
isLoading: boolean;
|
||||
error: string | null;
|
||||
refetch: () => Promise<void>;
|
||||
}
|
||||
|
||||
export function useAgents(): UseAgentsResult {
|
||||
const [agents, setAgents] = useState<AgentInfo[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
const fetchAgents = useCallback(async () => {
|
||||
setIsLoading(true);
|
||||
setError(null);
|
||||
try {
|
||||
const data = await agentApiService.getAgents();
|
||||
setAgents(data);
|
||||
} catch (err) {
|
||||
const message = err instanceof Error ? err.message : "Failed to fetch agents";
|
||||
setError(message);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
fetchAgents();
|
||||
}, [fetchAgents]);
|
||||
|
||||
return { agents, isLoading, error, refetch: fetchAgents };
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
export { SSHAgentForm } from "./ui/SSHAgentForm";
|
||||
export type { SSHAgentConfig, ExtraField } from "./ui/SSHAgentForm";
|
||||
|
||||
export { useAgents } from "./hooks/useAgents.hook";
|
||||
|
||||
export { agentApiService } from "./api/agent.api.service";
|
||||
|
||||
export type {
|
||||
AgentInfo,
|
||||
LoginRequest,
|
||||
LoginResponse,
|
||||
TokenCreate,
|
||||
TokenUser,
|
||||
LogEntry,
|
||||
InsertLogRequest,
|
||||
InsertLogsRequest,
|
||||
LogFilters,
|
||||
} from "./types/agent.types";
|
||||
@@ -0,0 +1,71 @@
|
||||
export interface AgentInfo {
|
||||
label: string;
|
||||
services: string[];
|
||||
token: string;
|
||||
}
|
||||
|
||||
export interface LoginRequest {
|
||||
login: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
export interface LoginResponse {
|
||||
last_name: string;
|
||||
login: string;
|
||||
name: string;
|
||||
permission_admin: boolean;
|
||||
permission_manage_agent: boolean;
|
||||
permission_view: boolean;
|
||||
token: string;
|
||||
}
|
||||
|
||||
export interface TokenCreate {
|
||||
login: string;
|
||||
name: string;
|
||||
last_name: string;
|
||||
password: string;
|
||||
permission_admin?: boolean;
|
||||
permission_manage_agent?: boolean;
|
||||
permission_view?: boolean;
|
||||
}
|
||||
|
||||
export interface TokenUser {
|
||||
id: number;
|
||||
login: string;
|
||||
name: string;
|
||||
last_name: string;
|
||||
permission_admin: boolean;
|
||||
permission_manage_agent: boolean;
|
||||
permission_view: boolean;
|
||||
token: string;
|
||||
}
|
||||
|
||||
export interface LogEntry {
|
||||
agent: string;
|
||||
level: string;
|
||||
message: string;
|
||||
service: string;
|
||||
timestamp: string;
|
||||
}
|
||||
|
||||
export interface InsertLogRequest {
|
||||
agent: string;
|
||||
level: string;
|
||||
message: string;
|
||||
service: string;
|
||||
timestamp?: string;
|
||||
}
|
||||
|
||||
export interface InsertLogsRequest {
|
||||
logs: InsertLogRequest[];
|
||||
}
|
||||
|
||||
export interface LogFilters {
|
||||
level?: string;
|
||||
service?: string;
|
||||
agent?: string;
|
||||
date_from?: string;
|
||||
date_to?: string;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { useState } from "react";
|
||||
import { SSHAgentForm } from "../modules/agent/ui/SSHAgentForm";
|
||||
import { agentApiService } from "../modules/agent/api/agent.api.service";
|
||||
import { FiPlusCircle, FiSend } from "react-icons/fi";
|
||||
|
||||
interface SSHAgentConfig {
|
||||
@@ -66,18 +67,22 @@ export const AddAgentsPage: React.FC = () => {
|
||||
setSubmitError(null);
|
||||
|
||||
try {
|
||||
// Получаем текущих агентов для проверки подключения
|
||||
const currentAgents = await agentApiService.getAgents();
|
||||
console.log("Current agents:", currentAgents);
|
||||
|
||||
// TODO: Реальный API вызов для развертывания агентов
|
||||
console.log("Deploying agents:", agents);
|
||||
|
||||
// Имитация задержки API
|
||||
await new Promise((resolve) => setTimeout(resolve, 1500));
|
||||
|
||||
// Пока выводим список подключенных агентов
|
||||
setSubmitMessage(
|
||||
`Успешно отправлено ${agents.length} сервер(ов) на развертывание`,
|
||||
`Успешно подключено ${currentAgents.length} агент(ов). Серверы: ${agents.length}`,
|
||||
);
|
||||
setAgents([createEmptyAgentConfig()]);
|
||||
} catch (error) {
|
||||
setSubmitError("Ошибка при развертывании на серверах");
|
||||
setSubmitError(
|
||||
error instanceof Error
|
||||
? error.message
|
||||
: "Ошибка при подключении к серверам",
|
||||
);
|
||||
} finally {
|
||||
setIsSubmitting(false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user