add process with node API key added
This commit is contained in:
92
frontend/src/components/admin/AddServiceDialog.tsx
Normal file
92
frontend/src/components/admin/AddServiceDialog.tsx
Normal file
@ -0,0 +1,92 @@
|
||||
import { useState } from 'react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { Plus, Terminal } from 'lucide-react';
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
DialogFooter,
|
||||
} from '@/components/ui/dialog';
|
||||
|
||||
interface AddServiceDialogProps {
|
||||
onAdd: (name: string, command: string) => void;
|
||||
}
|
||||
|
||||
export function AddServiceDialog({ onAdd }: AddServiceDialogProps) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const [name, setName] = useState('');
|
||||
const [command, setCommand] = useState('');
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
if (name.trim() && command.trim()) {
|
||||
onAdd(name.trim(), command.trim());
|
||||
setName('');
|
||||
setCommand('');
|
||||
setOpen(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogTrigger asChild>
|
||||
<Button size="sm" className="w-full sm:w-auto">
|
||||
<Plus className="w-4 h-4 mr-2" />
|
||||
Ajouter un service
|
||||
</Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent className="sm:max-w-lg">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="flex items-center gap-2">
|
||||
<Terminal className="w-5 h-5" />
|
||||
Ajouter un service
|
||||
</DialogTitle>
|
||||
</DialogHeader>
|
||||
<form onSubmit={handleSubmit} className="space-y-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="dialog-service-name">Nom du service</Label>
|
||||
<Input
|
||||
id="dialog-service-name"
|
||||
placeholder="ex: API Gateway"
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
className="bg-background"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="dialog-service-command">Script Bash</Label>
|
||||
<div className="relative">
|
||||
<div className="absolute left-0 top-0 p-3 text-muted-foreground font-mono text-xs select-none border-r border-border bg-muted/50 rounded-l-md h-full flex items-start">
|
||||
<span>$</span>
|
||||
</div>
|
||||
<textarea
|
||||
id="dialog-service-command"
|
||||
placeholder={`#!/bin/bash\nsystemctl status nginx\nexit $?`}
|
||||
value={command}
|
||||
onChange={(e) => setCommand(e.target.value)}
|
||||
className="w-full min-h-[200px] pl-10 pr-4 py-3 rounded-md border border-input bg-[#1a1a2e] text-green-400 font-mono text-sm resize-y focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 focus:ring-offset-background placeholder:text-muted-foreground/50"
|
||||
spellCheck={false}
|
||||
/>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Entrez le script bash qui sera exécuté pour vérifier l'état du service.
|
||||
</p>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
<Button type="button" variant="outline" onClick={() => setOpen(false)}>
|
||||
Annuler
|
||||
</Button>
|
||||
<Button type="submit" disabled={!name.trim() || !command.trim()}>
|
||||
<Plus className="w-4 h-4 mr-2" />
|
||||
Ajouter
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
@ -1,18 +1,30 @@
|
||||
import { useState } from 'react';
|
||||
import { Node, Service } from '@/types/monitoring';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { StatusIndicator } from '@/components/StatusIndicator';
|
||||
import { AddServiceForm } from './AddServiceForm';
|
||||
import { Server, Trash2, Terminal } from 'lucide-react';
|
||||
import { AddServiceDialog } from './AddServiceDialog';
|
||||
import { Server, Trash2, Terminal, Key } from 'lucide-react';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
interface NodeAdminCardProps {
|
||||
node: Node;
|
||||
onAddService: (nodeId: number, name: string, command: string) => void;
|
||||
onAddService: (nodeId: number, name: string, command: string, apiKey: string) => void;
|
||||
onRemoveService: (nodeId: number, serviceId: number) => void;
|
||||
onApiKeyChange?: (nodeId: number, apiKey: string) => void;
|
||||
apiKey?: string;
|
||||
}
|
||||
|
||||
export function NodeAdminCard({ node, onAddService, onRemoveService }: NodeAdminCardProps) {
|
||||
export function NodeAdminCard({ node, onAddService, onRemoveService, onApiKeyChange, apiKey = '' }: NodeAdminCardProps) {
|
||||
const [localApiKey, setLocalApiKey] = useState(apiKey);
|
||||
|
||||
const handleApiKeyChange = (value: string) => {
|
||||
setLocalApiKey(value);
|
||||
onApiKeyChange?.(node.id, value);
|
||||
};
|
||||
|
||||
return (
|
||||
<Card className="glass-card animate-fade-in">
|
||||
<CardHeader className="p-3 sm:p-6">
|
||||
@ -30,6 +42,22 @@ export function NodeAdminCard({ node, onAddService, onRemoveService }: NodeAdmin
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
{/* API Key Field */}
|
||||
<div className="space-y-2 p-3 rounded-lg bg-muted/30 border border-border/50">
|
||||
<Label htmlFor={`api-key-${node.id}`} className="text-sm font-medium flex items-center gap-2">
|
||||
<Key className="w-4 h-4" />
|
||||
Clé API du node
|
||||
</Label>
|
||||
<Input
|
||||
id={`api-key-${node.id}`}
|
||||
type="password"
|
||||
placeholder="Entrez la clé API pour ce node..."
|
||||
value={localApiKey}
|
||||
onChange={(e) => handleApiKeyChange(e.target.value)}
|
||||
className="bg-background/50 font-mono text-sm"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Services List */}
|
||||
<div className="space-y-2">
|
||||
<h4 className="text-sm font-medium text-muted-foreground">
|
||||
@ -74,8 +102,8 @@ export function NodeAdminCard({ node, onAddService, onRemoveService }: NodeAdmin
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Add Service Form */}
|
||||
<AddServiceForm onAdd={(name, command) => onAddService(node.id, name, command)} />
|
||||
{/* Add Service Dialog */}
|
||||
<AddServiceDialog onAdd={(name, command) => onAddService(node.id, name, command, localApiKey)} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
|
||||
@ -2,7 +2,7 @@ import { useState, useEffect } from 'react';
|
||||
import { Layout } from '@/components/Layout';
|
||||
import { NodeAdminCard } from '@/components/admin/NodeAdminCard';
|
||||
import { mockNodes, useNodeUpdater } from '@/data/mockData';
|
||||
import { Node, Service, NodeDeleteRequest } from '@/types/monitoring';
|
||||
import { Node, Service, NodeDeleteRequest,AddServiceRequest } from '@/types/monitoring';
|
||||
import { useToast } from '@/hooks/use-toast';
|
||||
import api from '@/lib/axios';
|
||||
|
||||
@ -12,31 +12,48 @@ const Admin = () => {
|
||||
|
||||
const { toast } = useToast();
|
||||
|
||||
const handleAddService = (nodeId: number, name: string, command: string) => {
|
||||
const newService: Service = {
|
||||
id: 0,
|
||||
name: `svc-${Date.now()}`,
|
||||
command,
|
||||
status: 'operational',
|
||||
history: {
|
||||
minute: [],
|
||||
hour: [],
|
||||
day: [],
|
||||
},
|
||||
};
|
||||
const handleAddService = (nodeId: number, name: string, command: string, apiKey: string) => {
|
||||
|
||||
setNodes(prevNodes =>
|
||||
prevNodes.map(node =>
|
||||
node.id === nodeId
|
||||
? { ...node, services: [...node.services, newService] }
|
||||
: node
|
||||
)
|
||||
);
|
||||
const addService = async () => {
|
||||
try {
|
||||
const response = await api.post<void>(`/addProcess`, {
|
||||
node_id: nodeId,
|
||||
name: name,
|
||||
command: command,
|
||||
node_api_key: apiKey,
|
||||
});
|
||||
|
||||
toast({
|
||||
title: 'Service ajouté',
|
||||
description: `Le service "${name}" a été ajouté avec succès.`,
|
||||
});
|
||||
const newService: Service = {
|
||||
id: 0,
|
||||
name: name,
|
||||
command: command,
|
||||
status: 'operational',
|
||||
history: {
|
||||
minute: [],
|
||||
hour: [],
|
||||
day: [],
|
||||
},
|
||||
};
|
||||
|
||||
setNodes(prevNodes =>
|
||||
prevNodes.map(node =>
|
||||
node.id === nodeId
|
||||
? { ...node, services: [...node.services, newService] }
|
||||
: node
|
||||
)
|
||||
);
|
||||
|
||||
toast({
|
||||
title: 'Service ajouté',
|
||||
description: `Le service "${response.status.toString()}" a été ajouté avec succès.`,
|
||||
});
|
||||
|
||||
} catch (err: any) {
|
||||
console.error("Erreur lors de l'ajout d'un service", err);
|
||||
}
|
||||
}
|
||||
|
||||
addService();
|
||||
};
|
||||
|
||||
const handleRemoveService = (nodeId: number, serviceId: number) => {
|
||||
|
||||
@ -17,6 +17,13 @@ export interface Service {
|
||||
};
|
||||
}
|
||||
|
||||
export interface AddServiceRequest {
|
||||
node_id: number;
|
||||
name: string;
|
||||
command: string;
|
||||
node_api_key: string;
|
||||
}
|
||||
|
||||
export interface Node {
|
||||
id: number;
|
||||
name: string;
|
||||
|
||||
Reference in New Issue
Block a user