This commit is contained in:
@@ -134,9 +134,8 @@ export default function AppLayout() {
|
|||||||
fontSize: '0.7rem',
|
fontSize: '0.7rem',
|
||||||
letterSpacing: '1px',
|
letterSpacing: '1px',
|
||||||
fontWeight: 'normal',
|
fontWeight: 'normal',
|
||||||
textTransform: 'lowercase'
|
|
||||||
}}>
|
}}>
|
||||||
by gise
|
by GISE
|
||||||
</span>
|
</span>
|
||||||
</h1>
|
</h1>
|
||||||
<p style={{ color: '#555', fontSize: '0.7rem', margin: '8px 0 0 0' }}>
|
<p style={{ color: '#555', fontSize: '0.7rem', margin: '8px 0 0 0' }}>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ export default function PublicLayout() {
|
|||||||
<nav style={{ padding: '20px', borderBottom: '1px solid #242424', display: 'flex', gap: '15px', alignItems: 'center' }}>
|
<nav style={{ padding: '20px', borderBottom: '1px solid #242424', display: 'flex', gap: '15px', alignItems: 'center' }}>
|
||||||
<Link to="/" style={{ display: 'flex', alignItems: 'baseline', gap: '6px', textDecoration: 'none' }}>
|
<Link to="/" style={{ display: 'flex', alignItems: 'baseline', gap: '6px', textDecoration: 'none' }}>
|
||||||
<span style={{ color: '#FFF', fontSize: '1.2rem', letterSpacing: '2px', fontWeight: 'bold' }}>NEXUS</span>
|
<span style={{ color: '#FFF', fontSize: '1.2rem', letterSpacing: '2px', fontWeight: 'bold' }}>NEXUS</span>
|
||||||
<span style={{ color: '#00E5FF', fontSize: '0.65rem', letterSpacing: '1px', fontWeight: 'normal', textTransform: 'lowercase' }}>by gise</span>
|
<span style={{ color: '#00E5FF', fontSize: '0.65rem', letterSpacing: '1px', fontWeight: 'normal'}}>by GISE</span>
|
||||||
</Link>
|
</Link>
|
||||||
<Link to="/offres" style={{ color: '#E0E0E0', textDecoration: 'none', marginLeft: '20px' }}>Catalogue</Link>
|
<Link to="/offres" style={{ color: '#E0E0E0', textDecoration: 'none', marginLeft: '20px' }}>Catalogue</Link>
|
||||||
|
|
||||||
|
|||||||
@@ -71,9 +71,7 @@ export default function Dashboard() {
|
|||||||
<div className="w-full max-w-6xl p-6 mx-auto">
|
<div className="w-full max-w-6xl p-6 mx-auto">
|
||||||
|
|
||||||
<header className="mb-8">
|
<header className="mb-8">
|
||||||
<h1 className="text-3xl font-bold text-white tracking-widest">
|
<h1 className="text-3xl font-black text-white tracking-wider">TABLEAU DE <span className="text-cyan-400">BORD</span></h1>
|
||||||
TERMINAL <span className="text-cyan-400">NEXUS</span>
|
|
||||||
</h1>
|
|
||||||
<p className="text-gray-400 mt-2">Aperçu de vos accréditations réseau et infrastructures.</p>
|
<p className="text-gray-400 mt-2">Aperçu de vos accréditations réseau et infrastructures.</p>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
|
|||||||
+30
-13
@@ -1,7 +1,7 @@
|
|||||||
import { useState, useEffect, useCallback } from 'react';
|
import { useState, useEffect, useCallback } from 'react';
|
||||||
import { getMyServices, getServiceDetails, getHostingServiceDetails, resetHostingPassword } from '../../services/api';
|
import { getMyServices, getServiceDetails, getHostingServiceDetails, resetHostingPassword } from '../../services/api';
|
||||||
import { useVPC } from '../../services/useVPC';
|
import { useVPC } from '../../services/useVPC';
|
||||||
import { Server, Database, Cloud, Globe, Folder, Trash2, ExternalLink, Loader, Plus, Play, Lock, Maximize2 } from 'lucide-react';
|
import { Server, Database, Cloud, Globe, Folder, Trash2, ExternalLink, Loader, Plus, Play, Lock, Maximize2, AlertCircle } from 'lucide-react'; // Ajout de AlertCircle
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// COMPOSANT 0 : MODAL DE NOTIFICATION (Remplace les alert() natifs)
|
// COMPOSANT 0 : MODAL DE NOTIFICATION (Remplace les alert() natifs)
|
||||||
@@ -290,7 +290,6 @@ const VpsManager = ({ details, orderId, onRefresh, onAlert }) => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* ACCÈS DE FAUT REMIS À JOUR */}
|
|
||||||
<div className="mt-4 bg-black/60 border border-gray-900 rounded p-3 text-[11px] space-y-1">
|
<div className="mt-4 bg-black/60 border border-gray-900 rounded p-3 text-[11px] space-y-1">
|
||||||
<span className="text-gray-500 font-bold uppercase tracking-wider block mb-1 text-[10px]">Identifiants d'usine :</span>
|
<span className="text-gray-500 font-bold uppercase tracking-wider block mb-1 text-[10px]">Identifiants d'usine :</span>
|
||||||
<p className="text-gray-400 font-mono">Console SSH : <span className="text-cyan-400 font-bold">root</span> / <span className="text-gray-500 italic">Clé choisie à l'initialisation</span></p>
|
<p className="text-gray-400 font-mono">Console SSH : <span className="text-cyan-400 font-bold">root</span> / <span className="text-gray-500 italic">Clé choisie à l'initialisation</span></p>
|
||||||
@@ -320,7 +319,6 @@ const VpsManager = ({ details, orderId, onRefresh, onAlert }) => {
|
|||||||
<div className="flex justify-between items-center mb-4 border-b border-gray-800 pb-2">
|
<div className="flex justify-between items-center mb-4 border-b border-gray-800 pb-2">
|
||||||
<span className="text-cyan-400 font-mono text-sm tracking-widest">NEXUS TERMINAL ({details.domain})</span>
|
<span className="text-cyan-400 font-mono text-sm tracking-widest">NEXUS TERMINAL ({details.domain})</span>
|
||||||
<div className="flex items-center space-x-2">
|
<div className="flex items-center space-x-2">
|
||||||
{/* OPTION AJOUTÉE : OUVRIR EN PLEIN ÉCRAN DANS UN NOUVEL ONGLET */}
|
|
||||||
<button onClick={() => { window.open(terminalUrl, '_blank'); setShowTerminal(false); }} className="text-xs bg-cyan-600/30 text-cyan-400 hover:bg-cyan-600 hover:text-white border border-cyan-500/30 px-3 py-1 rounded transition flex items-center gap-1">
|
<button onClick={() => { window.open(terminalUrl, '_blank'); setShowTerminal(false); }} className="text-xs bg-cyan-600/30 text-cyan-400 hover:bg-cyan-600 hover:text-white border border-cyan-500/30 px-3 py-1 rounded transition flex items-center gap-1">
|
||||||
<Maximize2 className="w-3 h-3" /> Plein Écran ↗
|
<Maximize2 className="w-3 h-3" /> Plein Écran ↗
|
||||||
</button>
|
</button>
|
||||||
@@ -471,7 +469,7 @@ export default function Services() {
|
|||||||
const [isConnecting, setIsConnecting] = useState(null);
|
const [isConnecting, setIsConnecting] = useState(null);
|
||||||
const [ssoVault, setSsoVault] = useState(null);
|
const [ssoVault, setSsoVault] = useState(null);
|
||||||
const [activeServiceModal, setActiveServiceModal] = useState(null);
|
const [activeServiceModal, setActiveServiceModal] = useState(null);
|
||||||
const [customAlert, setCustomAlert] = useState(null); // Gère les pop-ups personnalisés
|
const [customAlert, setCustomAlert] = useState(null);
|
||||||
|
|
||||||
const { vpcs, createVPC, deleteVPC, assignToVPC, removeFromVPC } = useVPC();
|
const { vpcs, createVPC, deleteVPC, assignToVPC, removeFromVPC } = useVPC();
|
||||||
|
|
||||||
@@ -544,14 +542,16 @@ export default function Services() {
|
|||||||
const assignedServiceIds = vpcs.flatMap(vpc => vpc.services);
|
const assignedServiceIds = vpcs.flatMap(vpc => vpc.services);
|
||||||
const freeServices = services.filter(s => !assignedServiceIds.includes(s.id));
|
const freeServices = services.filter(s => !assignedServiceIds.includes(s.id));
|
||||||
|
|
||||||
if (isLoading) return <div className="text-center mt-20 text-cyan-400 animate-pulse font-mono tracking-widest">ANALYSE DU RÉSEAU...</div>;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="max-w-7xl mx-auto mt-8 p-6">
|
<div className="w-full max-w-6xl p-6 mx-auto"> {/* Alignement avec le Dashboard */}
|
||||||
<div className="flex flex-col md:flex-row justify-between items-start md:items-end mb-10 gap-4">
|
<div className="flex flex-col md:flex-row justify-between items-start md:items-end mb-8 gap-4">
|
||||||
<div>
|
<div>
|
||||||
<h1 className="text-3xl font-black text-white tracking-wider">INVENTAIRE RÉSEAU</h1>
|
<header>
|
||||||
<p className="text-gray-400 mt-1">Orchestration des environnements et des Virtual Private Clouds.</p>
|
<h1 className="text-3xl font-black text-white tracking-wider"> {/* Typographie Dashboard */}
|
||||||
|
TERMINAL <span className="text-cyan-400">NEXUS</span>
|
||||||
|
</h1>
|
||||||
|
<p className="text-gray-400 mt-2">Orchestration des environnements et des Virtual Private Clouds.</p>
|
||||||
|
</header>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex space-x-2 bg-gray-900 p-2 rounded-xl border border-gray-800">
|
<div className="flex space-x-2 bg-gray-900 p-2 rounded-xl border border-gray-800">
|
||||||
@@ -562,8 +562,25 @@ export default function Services() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{error && <div className="text-red-400 bg-red-400/10 p-4 rounded-xl border border-red-500/20 mb-6">{error}</div>}
|
{/* GESTION DU CHARGEMENT IDENTIQUE AU DASHBOARD */}
|
||||||
|
{isLoading && (
|
||||||
|
<div className="flex items-center space-x-3 text-cyan-400 mb-8">
|
||||||
|
<Loader className="w-6 h-6 animate-spin" />
|
||||||
|
<span>Analyse du réseau et des instances en cours...</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* GESTION DES ERREURS IDENTIQUE AU DASHBOARD */}
|
||||||
|
{error && (
|
||||||
|
<div className="flex items-center space-x-3 text-red-400 bg-red-400/10 border border-red-400 p-4 rounded-lg mb-8">
|
||||||
|
<AlertCircle className="w-6 h-6" />
|
||||||
|
<span>{error}</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* CONTENU (Caché pendant le chargement pour rester propre) */}
|
||||||
|
{!isLoading && !error && (
|
||||||
|
<>
|
||||||
<div className="space-y-8 mb-12">
|
<div className="space-y-8 mb-12">
|
||||||
{vpcs.map(vpc => {
|
{vpcs.map(vpc => {
|
||||||
const vpcServices = services.filter(s => vpc.services.includes(s.id));
|
const vpcServices = services.filter(s => vpc.services.includes(s.id));
|
||||||
@@ -619,6 +636,8 @@ export default function Services() {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* MODAL 1 : HESTIACP SSO VAULT */}
|
{/* MODAL 1 : HESTIACP SSO VAULT */}
|
||||||
{ssoVault && (
|
{ssoVault && (
|
||||||
@@ -626,7 +645,6 @@ export default function Services() {
|
|||||||
<div className="bg-gray-900 border border-emerald-500/50 rounded-lg shadow-2xl shadow-emerald-500/20 max-w-md w-full p-6 text-gray-200">
|
<div className="bg-gray-900 border border-emerald-500/50 rounded-lg shadow-2xl shadow-emerald-500/20 max-w-md w-full p-6 text-gray-200">
|
||||||
<div className="flex justify-between items-center mb-6">
|
<div className="flex justify-between items-center mb-6">
|
||||||
<h3 className="text-xl font-bold text-emerald-400 font-mono tracking-wider">ACCÈS AUTORISÉ</h3>
|
<h3 className="text-xl font-bold text-emerald-400 font-mono tracking-wider">ACCÈS AUTORISÉ</h3>
|
||||||
{/* La croix permet de fermer manuellement le modal après copie */}
|
|
||||||
<button onClick={() => setSsoVault(null)} className="text-gray-400 hover:text-white transition text-lg">✖</button>
|
<button onClick={() => setSsoVault(null)} className="text-gray-400 hover:text-white transition text-lg">✖</button>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm text-gray-400 mb-6">Le pare-feu HestiaCP bloque les injections directes. Un mot de passe <strong>jetable</strong> a été généré. Copiez-le et connectez-vous.</p>
|
<p className="text-sm text-gray-400 mb-6">Le pare-feu HestiaCP bloque les injections directes. Un mot de passe <strong>jetable</strong> a été généré. Copiez-le et connectez-vous.</p>
|
||||||
@@ -646,7 +664,6 @@ export default function Services() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/* REFIXÉ : Pas de setSsoVault(null) ici pour garder le modal ouvert au retour de l'onglet */}
|
|
||||||
<a href={ssoVault.url} target="_blank" rel="noopener noreferrer" className="block w-full bg-emerald-500 hover:bg-emerald-400 text-gray-950 font-bold py-3 text-center rounded transition font-mono tracking-widest uppercase">
|
<a href={ssoVault.url} target="_blank" rel="noopener noreferrer" className="block w-full bg-emerald-500 hover:bg-emerald-400 text-gray-950 font-bold py-3 text-center rounded transition font-mono tracking-widest uppercase">
|
||||||
Ouvrir le Panel Web ↗
|
Ouvrir le Panel Web ↗
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -19,10 +19,9 @@ export default function Home() {
|
|||||||
color: '#00E5FF',
|
color: '#00E5FF',
|
||||||
fontSize: '1.4rem',
|
fontSize: '1.4rem',
|
||||||
letterSpacing: '2px',
|
letterSpacing: '2px',
|
||||||
fontWeight: 'normal',
|
fontWeight: 'normal'
|
||||||
textTransform: 'lowercase'
|
|
||||||
}}>
|
}}>
|
||||||
by gise
|
by GISE
|
||||||
</span>
|
</span>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user