Files
HellreigN/frontend/src/pages/add-agents.page.tsx
T
nikitaa_ts 57f12f792c
ci-front / build (push) Successful in 2m8s
feat: add create agents
2026-04-04 01:24:45 +03:00

225 lines
7.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React, { useState } from "react";
import { SSHAgentForm } from "../modules/agent/ui/SSHAgentForm";
import { FiPlusCircle, FiSend } from "react-icons/fi";
interface SSHAgentConfig {
user: string;
ip: string;
authMethod: string;
sshKey?: string;
password?: string;
extraFields: { key: string; value: string }[];
deployType: string;
}
const createEmptyAgentConfig = (): SSHAgentConfig => ({
user: "",
ip: "",
authMethod: "key",
sshKey: "",
password: "",
extraFields: [],
deployType: "docker",
});
export const AddAgentsPage: React.FC = () => {
const [agents, setAgents] = useState<SSHAgentConfig[]>([
createEmptyAgentConfig(),
]);
const [isSubmitting, setIsSubmitting] = useState(false);
const [submitMessage, setSubmitMessage] = useState<string | null>(null);
const [submitError, setSubmitError] = useState<string | null>(null);
const handleAgentChange = (index: number, config: SSHAgentConfig) => {
const newAgents = [...agents];
newAgents[index] = config;
setAgents(newAgents);
};
const handleAgentRemove = (index: number) => {
const newAgents = agents.filter((_, i) => i !== index);
setAgents(newAgents);
};
const handleAddAgent = () => {
setAgents([...agents, createEmptyAgentConfig()]);
};
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
// Валидация
const isValid = agents.every((agent) => {
if (!agent.user || !agent.ip) return false;
if (agent.authMethod === "key" && !agent.sshKey) return false;
if (agent.authMethod === "password" && !agent.password) return false;
return true;
});
if (!isValid) {
setSubmitError("Пожалуйста, заполните все обязательные поля");
return;
}
setIsSubmitting(true);
setSubmitMessage(null);
setSubmitError(null);
try {
// TODO: Реальный API вызов для развертывания агентов
console.log("Deploying agents:", agents);
// Имитация задержки API
await new Promise((resolve) => setTimeout(resolve, 1500));
setSubmitMessage(
`Успешно отправлено ${agents.length} сервер(ов) на развертывание`,
);
setAgents([createEmptyAgentConfig()]);
} catch (error) {
setSubmitError("Ошибка при развертывании на серверах");
} finally {
setIsSubmitting(false);
}
};
return (
<div
className="min-h-screen py-8 px-4"
style={{ backgroundColor: "var(--bg-primary)" }}
>
<div style={{ maxWidth: "900px", margin: "0 auto" }}>
{/* Header */}
<div className="mb-8">
<div className="flex items-center gap-4 mb-4">
<div
className="w-14 h-14 rounded-xl flex items-center justify-center"
style={{ backgroundColor: "var(--bg-secondary)" }}
>
<FiSend className="w-7 h-7" style={{ color: "var(--accent)" }} />
</div>
<div>
<h1
className="text-3xl font-bold mb-1"
style={{ color: "var(--text-primary)" }}
>
Развертывание агентов по SSH
</h1>
<p style={{ color: "var(--text-secondary)", fontSize: "16px" }}>
Настройте SSH-серверы и разверните агенты
</p>
</div>
</div>
</div>
<form onSubmit={handleSubmit}>
{/* Agent Forms */}
<div className="space-y-5">
{agents.map((agent, index) => (
<SSHAgentForm
key={index}
index={index}
config={agent}
onChange={handleAgentChange}
onRemove={handleAgentRemove}
canRemove={agents.length > 1}
/>
))}
</div>
{/* Add Agent Button */}
<button
type="button"
onClick={handleAddAgent}
className="w-full flex items-center justify-center gap-2 py-3.5 px-4 rounded-xl border-2 border-dashed transition-all mb-6 font-medium"
style={{
borderColor: "var(--border)",
backgroundColor: "transparent",
color: "var(--accent)",
fontSize: "15px",
cursor: "pointer",
}}
onMouseEnter={(e) => {
e.currentTarget.style.borderColor = "var(--accent)";
e.currentTarget.style.backgroundColor = "var(--accent)10";
}}
onMouseLeave={(e) => {
e.currentTarget.style.borderColor = "var(--border)";
e.currentTarget.style.backgroundColor = "transparent";
}}
>
<FiPlusCircle size={18} />
Добавить ещё один сервер
</button>
{/* Messages */}
{submitMessage && (
<div
className="mb-6 p-4 rounded-lg border text-sm"
style={{
backgroundColor: "var(--success-bg)",
borderColor: "var(--success-border)",
color: "var(--success-text)",
}}
>
{submitMessage}
</div>
)}
{submitError && (
<div
className="mb-6 p-4 rounded-lg border text-sm"
style={{
backgroundColor: "var(--error-bg)",
borderColor: "var(--error-border)",
color: "var(--error-text)",
}}
>
{submitError}
</div>
)}
{/* Submit Button */}
<button
type="submit"
disabled={isSubmitting}
className="w-full flex items-center justify-center gap-2 px-4 py-3.5 rounded-xl transition-all disabled:opacity-50 disabled:cursor-not-allowed font-medium text-base"
style={{
backgroundColor: isSubmitting
? "var(--bg-secondary)"
: "var(--button-primary)",
color: "var(--button-primary-text)",
boxShadow: isSubmitting
? "none"
: "0 4px 14px var(--shadow-color)",
}}
onMouseEnter={(e) => {
if (!isSubmitting) {
e.currentTarget.style.backgroundColor =
"var(--button-primary-hover)";
}
}}
onMouseLeave={(e) => {
e.currentTarget.style.backgroundColor = isSubmitting
? "var(--bg-secondary)"
: "var(--button-primary)";
}}
>
{isSubmitting ? (
<>
<div className="w-5 h-5 border-2 border-current border-t-transparent rounded-full animate-spin" />
Подключение к серверам...
</>
) : (
<>
<FiSend size={18} />
Развернуть на {agents.length} сервер(ах)
</>
)}
</button>
</form>
</div>
</div>
);
};