mirror of
https://github.com/dyzulk/trustlab.git
synced 2026-01-26 05:25:36 +07:00
docs: redesign Linux guide to show all CLI snippets simultaneously
This commit is contained in:
@@ -91,22 +91,45 @@ function TabButton({ id, label, active, onClick, icon }: { id: string, label: st
|
||||
);
|
||||
}
|
||||
|
||||
function OsGuideContent({ title, steps, selectedOs, certificates, t }: { title: string, steps: string[], selectedOs: string, certificates: CaCertificate[], t: any }) {
|
||||
const [guideCertSerial, setGuideCertSerial] = useState(certificates[0]?.serial);
|
||||
function CliSnippet({ label, command, t }: { label: string, command: string, t: any }) {
|
||||
const [copied, setCopied] = useState(false);
|
||||
|
||||
const activeCert = certificates.find(c => c.serial === guideCertSerial) || certificates[0];
|
||||
const linuxCli = activeCert?.linux_cdn_url ? `curl -sL ${activeCert.linux_cdn_url} | sudo bash` : '';
|
||||
|
||||
const copyCli = () => {
|
||||
if (!linuxCli) return;
|
||||
navigator.clipboard.writeText(linuxCli);
|
||||
if (!command) return;
|
||||
navigator.clipboard.writeText(command);
|
||||
setCopied(true);
|
||||
setTimeout(() => setCopied(false), 2000);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="p-8 bg-white dark:bg-gray-800 rounded-[2rem] border border-gray-100 dark:border-gray-700 shadow-sm space-y-8 animate-in fade-in slide-in-from-bottom-2 duration-500">
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center justify-between gap-4">
|
||||
<span className="text-[10px] font-bold text-gray-500 dark:text-gray-400 uppercase tracking-widest">{label}</span>
|
||||
</div>
|
||||
<div className="relative group">
|
||||
<div className="font-mono text-[11px] bg-gray-950 text-brand-400 p-4 rounded-2xl border border-gray-800 break-all pr-12 shadow-inner">
|
||||
<span className="text-gray-600 mr-2 select-none">$</span>
|
||||
{command || 'No script available.'}
|
||||
</div>
|
||||
<button
|
||||
onClick={copyCli}
|
||||
className={`absolute right-3 top-1/2 -translate-y-1/2 p-2 rounded-xl transition-all duration-300 active:scale-90 border ${
|
||||
copied
|
||||
? 'bg-green-500 text-white border-green-500 shadow-lg shadow-green-500/20'
|
||||
: 'bg-gray-900 text-gray-400 hover:text-white border-gray-800 hover:bg-gray-800'
|
||||
}`}
|
||||
title="Copy Command"
|
||||
>
|
||||
{copied ? <CheckIcon className="w-3.5 h-3.5" /> : <CopyIcon className="w-3.5 h-3.5" />}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function OsGuideContent({ title, steps, selectedOs, certificates, t }: { title: string, steps: string[], selectedOs: string, certificates: CaCertificate[], t: any }) {
|
||||
return (
|
||||
<div className="p-8 bg-white dark:bg-gray-800 rounded-[2rem] border border-gray-100 dark:border-gray-700 shadow-sm space-y-10 animate-in fade-in slide-in-from-bottom-2 duration-500">
|
||||
<div>
|
||||
<h4 className="text-lg font-bold text-gray-900 dark:text-white mb-6 flex items-center gap-2">
|
||||
<div className="w-1.5 h-6 bg-brand-500 rounded-full"></div>
|
||||
@@ -127,49 +150,35 @@ function OsGuideContent({ title, steps, selectedOs, certificates, t }: { title:
|
||||
</div>
|
||||
|
||||
{selectedOs === 'linux' && (
|
||||
<div className="pt-8 border-t border-gray-100 dark:border-gray-700 space-y-4">
|
||||
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4">
|
||||
<div>
|
||||
<h5 className="font-bold text-gray-900 dark:text-white flex items-center gap-2">
|
||||
<span className="w-2 h-2 rounded-full bg-green-500 animate-pulse"></span>
|
||||
{t('guide_linux_shortcut_title')}
|
||||
</h5>
|
||||
<p className="text-xs text-gray-500 dark:text-gray-400 mt-1">{t('guide_linux_shortcut_desc')}</p>
|
||||
</div>
|
||||
|
||||
{/* Cert Selector */}
|
||||
<div className="relative group min-w-[200px]">
|
||||
<select
|
||||
value={guideCertSerial}
|
||||
onChange={(e) => setGuideCertSerial(e.target.value)}
|
||||
className="w-full appearance-none bg-gray-50 dark:bg-gray-900 border border-gray-200 dark:border-gray-700 rounded-xl px-4 py-2 pr-10 text-xs font-bold text-gray-700 dark:text-gray-300 focus:outline-none focus:ring-2 focus:ring-brand-500/20 transition-all cursor-pointer"
|
||||
>
|
||||
{certificates.map(c => (
|
||||
<option key={c.serial} value={c.serial}>{c.name}</option>
|
||||
))}
|
||||
</select>
|
||||
<div className="absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none text-gray-400">
|
||||
<ChevronDownIcon className="w-4 h-4" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="pt-10 border-t border-gray-100 dark:border-gray-700 space-y-6">
|
||||
<div>
|
||||
<h5 className="font-bold text-gray-900 dark:text-white flex items-center gap-2">
|
||||
<span className="w-2 h-2 rounded-full bg-green-500 animate-pulse"></span>
|
||||
{t('guide_linux_shortcut_title')}
|
||||
</h5>
|
||||
<p className="text-xs text-gray-500 dark:text-gray-400 mt-1">{t('guide_linux_shortcut_desc')}</p>
|
||||
</div>
|
||||
|
||||
<div className="relative group">
|
||||
<div className="font-mono text-xs bg-gray-950 text-brand-400 p-4 rounded-2xl border border-gray-800 break-all pr-12">
|
||||
<span className="text-gray-500 mr-2">$</span>
|
||||
{linuxCli || 'No Linux script available for this certificate.'}
|
||||
</div>
|
||||
<button
|
||||
onClick={copyCli}
|
||||
className={`absolute right-3 top-1/2 -translate-y-1/2 p-2 rounded-xl transition-all duration-300 active:scale-90 ${
|
||||
copied
|
||||
? 'bg-green-500 text-white'
|
||||
: 'bg-gray-800 text-gray-400 hover:text-white hover:bg-gray-700'
|
||||
}`}
|
||||
title="Copy Command"
|
||||
>
|
||||
{copied ? <CheckIcon className="w-3.5 h-3.5" /> : <CopyIcon className="w-3.5 h-3.5" />}
|
||||
</button>
|
||||
<div className="grid grid-cols-1 gap-6">
|
||||
{/* Root CAs */}
|
||||
{certificates.filter(c => c.type === 'root').map(c => (
|
||||
<CliSnippet
|
||||
key={c.serial}
|
||||
label={`${t('root_ca')}: ${c.name}`}
|
||||
command={c.linux_cdn_url ? `curl -sL ${c.linux_cdn_url} | sudo bash` : ''}
|
||||
t={t}
|
||||
/>
|
||||
))}
|
||||
|
||||
{/* Intermediate CAs */}
|
||||
{certificates.filter(c => c.type !== 'root').map(c => (
|
||||
<CliSnippet
|
||||
key={c.serial}
|
||||
label={`${t('intermediate_ca')}: ${c.name}`}
|
||||
command={c.linux_cdn_url ? `curl -sL ${c.linux_cdn_url} | sudo bash` : ''}
|
||||
t={t}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -216,9 +216,8 @@
|
||||
"Open terminal and run: sudo bash install-*.sh",
|
||||
"The script will automatically detect and update your CA store."
|
||||
],
|
||||
"guide_linux_shortcut_title": "One-liner Shortcut (Recommended)",
|
||||
"guide_linux_shortcut_desc": "Copy and paste this command to your terminal for instant installation:",
|
||||
"guide_linux_select_cert": "Select Certificate to install:",
|
||||
"guide_linux_shortcut_title": "Instant Installation (CLI)",
|
||||
"guide_linux_shortcut_desc": "Run the corresponding command for the certificate you wish to trust:",
|
||||
"guide_steps_mobile": [
|
||||
"Android: Settings > Security > Install from storage > CA Certificate.",
|
||||
"iOS: Install the profile, then Settings > General > About > Certificate Trust Settings."
|
||||
|
||||
@@ -216,9 +216,8 @@
|
||||
"Buka terminal dan jalankan: sudo bash install-*.sh",
|
||||
"Skrip akan secara otomatis mendeteksi distro dan memperbarui penyimpanan CA Anda."
|
||||
],
|
||||
"guide_linux_shortcut_title": "Pintas Satu-Baris (Disarankan)",
|
||||
"guide_linux_shortcut_desc": "Salin dan tempel perintah ini ke terminal Anda untuk instalasi instan:",
|
||||
"guide_linux_select_cert": "Pilih Sertifikat untuk diinstal:",
|
||||
"guide_linux_shortcut_title": "Instalasi Instan (CLI)",
|
||||
"guide_linux_shortcut_desc": "Jalankan perintah yang sesuai untuk sertifikat yang ingin Anda percayai:",
|
||||
"guide_steps_mobile": [
|
||||
"Android: Pengaturan > Keamanan > Instal dari penyimpanan > Sertifikat CA.",
|
||||
"iOS: Instal profil, lalu Pengaturan > Umum > Mengenai > Pengaturan Kepercayaan Sertifikat."
|
||||
|
||||
Reference in New Issue
Block a user