upgrade design
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { useState } from 'react';
|
||||
import { Folder, ExternalLink, Play, Maximize2, Lock } from 'lucide-react';
|
||||
import { Folder, ExternalLink, Play, Maximize2, Lock, Copy, Check } from 'lucide-react';
|
||||
|
||||
export default function VpsManager({ details, orderId, onRefresh, onAlert }) {
|
||||
const [showTerminal, setShowTerminal] = useState(false);
|
||||
@@ -7,11 +7,18 @@ export default function VpsManager({ details, orderId, onRefresh, onAlert }) {
|
||||
const [newDomain, setNewDomain] = useState(details.domain);
|
||||
const [isUpdating, setIsUpdating] = useState(false);
|
||||
const [sslStatus, setSslStatus] = useState(null);
|
||||
const [copiedField, setCopiedField] = useState(null);
|
||||
|
||||
const isInternal = details.domain && details.domain.endsWith('.gise.be');
|
||||
const fileManagerUrl = isInternal ? `https://file-${details.domain}` : `http://${details.domain}:8080`;
|
||||
const terminalUrl = isInternal ? `https://terminal-${details.domain}` : `http://${details.domain}:8081`;
|
||||
|
||||
const handleCopy = (text, field) => {
|
||||
navigator.clipboard.writeText(text);
|
||||
setCopiedField(field);
|
||||
setTimeout(() => setCopiedField(null), 2000);
|
||||
};
|
||||
|
||||
const handleUpdateDomain = async () => {
|
||||
if (!newDomain || newDomain === details.domain) return;
|
||||
setIsUpdating(true);
|
||||
@@ -62,7 +69,44 @@ export default function VpsManager({ details, orderId, onRefresh, onAlert }) {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
|
||||
|
||||
{/* ENCART DES IDENTIFIANTS */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6">
|
||||
<div className="bg-black/60 border border-gray-800 rounded p-3">
|
||||
<span className="text-gray-500 font-bold uppercase tracking-wider block mb-2 text-[10px] flex items-center gap-1">
|
||||
<Folder className="w-3 h-3" /> Accès Explorateur
|
||||
</span>
|
||||
<div className="flex justify-between items-center mb-1">
|
||||
<span className="text-xs font-mono text-gray-400">User: <strong className="text-cyan-400">root</strong></span>
|
||||
<button onClick={() => handleCopy('root', 'fileUser')} className="text-gray-500 hover:text-cyan-400 p-1">
|
||||
{copiedField === 'fileUser' ? <Check className="w-3 h-3 text-cyan-400" /> : <Copy className="w-3 h-3" />}
|
||||
</button>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-xs font-mono text-gray-400">Pass: <strong className="text-cyan-400">NexusGise2026!</strong></span>
|
||||
<button onClick={() => handleCopy('NexusGise2026!', 'filePass')} className="text-gray-500 hover:text-cyan-400 p-1">
|
||||
{copiedField === 'filePass' ? <Check className="w-3 h-3 text-cyan-400" /> : <Copy className="w-3 h-3" />}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-black/60 border border-gray-800 rounded p-3">
|
||||
<span className="text-gray-500 font-bold uppercase tracking-wider block mb-2 text-[10px] flex items-center gap-1">
|
||||
<Play className="w-3 h-3" /> Accès Console / SSH
|
||||
</span>
|
||||
<div className="flex justify-between items-center mb-1">
|
||||
<span className="text-xs font-mono text-gray-400">User: <strong className="text-cyan-400">root</strong></span>
|
||||
<button onClick={() => handleCopy('root', 'sshUser')} className="text-gray-500 hover:text-cyan-400 p-1">
|
||||
{copiedField === 'sshUser' ? <Check className="w-3 h-3 text-cyan-400" /> : <Copy className="w-3 h-3" />}
|
||||
</button>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-xs font-mono text-gray-400">Pass: <span className="text-gray-600 italic">Défini à l'installation</span></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* BOUTONS D'ACTIONS */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 mb-2">
|
||||
<button onClick={() => window.open(fileManagerUrl, '_blank')} className="bg-gray-950 hover:bg-gray-900 border border-gray-800 hover:border-cyan-500/50 rounded p-3 flex justify-between items-center transition group">
|
||||
<span className="font-mono text-gray-300 text-sm flex items-center gap-2"><Folder className="w-4 h-4 text-cyan-500" /> Explorateur</span><ExternalLink className="w-4 h-4 text-gray-600 group-hover:text-cyan-400" />
|
||||
</button>
|
||||
|
||||
@@ -1,17 +1,28 @@
|
||||
import { useState } from 'react';
|
||||
import { Globe, ExternalLink, Lock, Loader } from 'lucide-react';
|
||||
import { Globe, ExternalLink, Lock, Loader, Copy, Check } from 'lucide-react';
|
||||
import { resetHostingPassword } from '../../services/api';
|
||||
|
||||
export default function WebManager({ details, orderId, onRefresh, onOpenSso, onAlert }) {
|
||||
export default function WebManager({ details, orderId, onRefresh, onAlert }) {
|
||||
const [isEditingDomain, setIsEditingDomain] = useState(false);
|
||||
const [newDomain, setNewDomain] = useState(details.domain);
|
||||
const [isUpdating, setIsUpdating] = useState(false);
|
||||
const [sslStatus, setSslStatus] = useState(null);
|
||||
|
||||
// Nouveaux états pour gérer les accès localement
|
||||
const [isGeneratingSso, setIsGeneratingSso] = useState(false);
|
||||
const [ssoData, setSsoData] = useState(null);
|
||||
const [copiedField, setCopiedField] = useState(null);
|
||||
|
||||
const isCustomDomain = details.domain && !details.domain.endsWith('.gise.be');
|
||||
const siteUrl = (isCustomDomain && sslStatus !== 'success') ? `http://${details.domain}` : `https://${details.domain}`;
|
||||
|
||||
// Fonction utilitaire pour copier
|
||||
const handleCopy = (text, field) => {
|
||||
navigator.clipboard.writeText(text);
|
||||
setCopiedField(field);
|
||||
setTimeout(() => setCopiedField(null), 2000);
|
||||
};
|
||||
|
||||
const handleUpdateDomain = async () => {
|
||||
if (!newDomain || newDomain === details.domain) return;
|
||||
setIsUpdating(true);
|
||||
@@ -39,9 +50,12 @@ export default function WebManager({ details, orderId, onRefresh, onOpenSso, onA
|
||||
const secureHash = Math.random().toString(36).slice(-8) + Math.random().toString(36).slice(-4).toUpperCase();
|
||||
const rollingPassword = `Nx${secureHash}`;
|
||||
await resetHostingPassword(orderId, rollingPassword);
|
||||
onOpenSso({ username: details.username, password: rollingPassword, url: 'https://panel.gise.be/login/' });
|
||||
} catch (err) { onAlert("Erreur Métal", "Erreur lors de la génération du SSO HestiaCP.", "error"); }
|
||||
finally { setIsGeneratingSso(false); }
|
||||
setSsoData({ username: details.username, password: rollingPassword, url: 'https://panel.gise.be/login/' });
|
||||
} catch (err) {
|
||||
onAlert("Erreur Métal", "Erreur lors de la génération du SSO HestiaCP.", "error");
|
||||
} finally {
|
||||
setIsGeneratingSso(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -50,7 +64,9 @@ export default function WebManager({ details, orderId, onRefresh, onOpenSso, onA
|
||||
<label className="block text-xs uppercase tracking-widest text-emerald-500 mb-2">Domaine du Site Web</label>
|
||||
{!isEditingDomain ? (
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="font-mono text-xl text-emerald-400 font-bold flex items-center gap-2"><span className="h-3 w-3 rounded-full bg-emerald-500 shadow-[0_0_10px_#10b981]"></span>{details.domain}</span>
|
||||
<span className="font-mono text-xl text-emerald-400 font-bold flex items-center gap-2">
|
||||
<span className="h-3 w-3 rounded-full bg-emerald-500 shadow-[0_0_10px_#10b981]"></span>{details.domain}
|
||||
</span>
|
||||
<button onClick={() => setIsEditingDomain(true)} className="text-xs border border-gray-700 hover:border-emerald-500 text-gray-400 hover:text-emerald-400 px-3 py-1.5 rounded transition">MODIFIER</button>
|
||||
</div>
|
||||
) : (
|
||||
@@ -60,6 +76,7 @@ export default function WebManager({ details, orderId, onRefresh, onOpenSso, onA
|
||||
<button onClick={() => setIsEditingDomain(false)} className="bg-gray-800 text-white px-3 py-1.5 rounded text-xs hover:bg-gray-700">ANNULER</button>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{isCustomDomain && (
|
||||
<div className="mt-4 border-t border-gray-900 pt-3 flex justify-between items-center">
|
||||
<p className="text-[11px] text-gray-500">Domaine personnalisé détecté.</p>
|
||||
@@ -69,13 +86,48 @@ export default function WebManager({ details, orderId, onRefresh, onOpenSso, onA
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
|
||||
|
||||
<div className="grid grid-cols-1 gap-6 mb-6">
|
||||
<button onClick={() => window.open(siteUrl, '_blank')} className="bg-gray-950 hover:bg-gray-900 border border-gray-800 hover:border-emerald-500/50 rounded p-3 flex justify-between items-center transition group">
|
||||
<span className="font-mono text-gray-300 text-sm flex items-center gap-2"><Globe className="w-4 h-4 text-emerald-500" /> Ouvrir Site</span><ExternalLink className="w-4 h-4 text-gray-600 group-hover:text-emerald-400" />
|
||||
</button>
|
||||
<button onClick={handleOpenPanel} disabled={isGeneratingSso} className="bg-emerald-900/20 hover:bg-emerald-900/40 border border-emerald-800/50 hover:border-emerald-500 rounded p-3 flex justify-between items-center transition group disabled:opacity-50">
|
||||
{isGeneratingSso ? <span className="font-mono text-emerald-400 text-sm flex items-center gap-2"><Loader className="w-4 h-4 animate-spin" /> SSO...</span> : <><span className="font-mono text-emerald-400 text-sm flex items-center gap-2"><Lock className="w-4 h-4" /> Panel</span><ExternalLink className="w-4 h-4 text-emerald-600 group-hover:text-emerald-400" /></>}
|
||||
<span className="font-mono text-gray-300 text-sm flex items-center gap-2"><Globe className="w-4 h-4 text-emerald-500" /> Ouvrir le Site</span><ExternalLink className="w-4 h-4 text-gray-600 group-hover:text-emerald-400" />
|
||||
</button>
|
||||
|
||||
{/* ZONE DES ACCÈS PANEL */}
|
||||
{!ssoData ? (
|
||||
<button onClick={handleOpenPanel} disabled={isGeneratingSso} className="bg-emerald-900/20 hover:bg-emerald-900/40 border border-emerald-800/50 hover:border-emerald-500 rounded p-3 flex justify-between items-center transition group disabled:opacity-50">
|
||||
{isGeneratingSso ? (
|
||||
<span className="font-mono text-emerald-400 text-sm flex items-center gap-2"><Loader className="w-4 h-4 animate-spin" /> GÉNÉRATION DU MOT DE PASSE...</span>
|
||||
) : (
|
||||
<><span className="font-mono text-emerald-400 text-sm flex items-center gap-2"><Lock className="w-4 h-4" /> Obtenir les accès Panel</span><ExternalLink className="w-4 h-4 text-emerald-600 group-hover:text-emerald-400" /></>
|
||||
)}
|
||||
</button>
|
||||
) : (
|
||||
<div className="bg-emerald-900/10 border border-emerald-500/30 rounded p-4">
|
||||
<p className="text-[11px] text-emerald-400/80 uppercase tracking-widest mb-3 flex items-center gap-2">
|
||||
<Lock className="w-3 h-3" /> Accès Panel Généré
|
||||
</p>
|
||||
|
||||
<div className="space-y-2 mb-4">
|
||||
<div className="flex justify-between items-center bg-black/50 border border-gray-800 rounded p-2">
|
||||
<span className="text-gray-400 text-xs font-mono">User: <strong className="text-white ml-1">{ssoData.username}</strong></span>
|
||||
<button onClick={() => handleCopy(ssoData.username, 'webUser')} className="text-emerald-400 hover:text-emerald-300 transition-colors p-1">
|
||||
{copiedField === 'webUser' ? <Check className="w-4 h-4 text-emerald-500" /> : <Copy className="w-4 h-4" />}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="flex justify-between items-center bg-black/50 border border-gray-800 rounded p-2">
|
||||
<span className="text-gray-400 text-xs font-mono">Pass: <strong className="text-emerald-400 ml-1">{ssoData.password}</strong></span>
|
||||
<button onClick={() => handleCopy(ssoData.password, 'webPass')} className="text-emerald-400 hover:text-emerald-300 transition-colors p-1">
|
||||
{copiedField === 'webPass' ? <Check className="w-4 h-4 text-emerald-500" /> : <Copy className="w-4 h-4" />}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button onClick={() => window.open(ssoData.url, '_blank')} className="w-full bg-emerald-500 hover:bg-emerald-400 text-black font-bold font-mono tracking-widest uppercase py-2.5 rounded transition shadow-[0_0_15px_rgba(16,185,129,0.2)]">
|
||||
Ouvrir le Panel
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user