From 0615e0969d49707fe4d4c084252d337296c3547c Mon Sep 17 00:00:00 2001 From: Boban Blaskovic Date: Mon, 1 Jun 2026 00:24:30 +0200 Subject: [PATCH] =?UTF-8?q?Site=20Details:=203=20high-value=20tabs=20?= =?UTF-8?q?=E2=80=94=20Plugins=20/=20Redirects=20/=20Staging?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit User accepted top-3 from brainstorm. Tab bar now 12 tabs (wraps cleanly). Plugins tab: - 4 metrics: total / updates-pending / auto-update count / themes count. - Plugins table with favicon-letter, name + slug, version pill (green current, orange 'x.y → x.z' on update available), active/inactive health label, per-row auto-update toggle, row actions (update + activate/deactivate + delete). - Themes table (Storefront parent, Storefront Child active, TT4 inactive). - Update-Policy card with 5 toggle-rows: security-only / minor / major auto, pre-update snapshot, staging-test-first. - Bulk-update CTA banner when any update is pending. Redirects tab: - 4 metrics: active rules / 24h hits / 404 sources / loop count. - 'Neue Regel' card with source + target input, status-code segmented (301/302/307/410), match-type select, query-string + case-insensitive toggles. CSV import button. - Active rules table with from → to, code pill, hits, last-hit, edit/ test/delete actions. Sorted by hits. Staging tab: - Subdomain input with .domain suffix, server select. - 5 toggle-rows: HTTP-Basic-Auth (default on), robots.txt block, exclude media on sync, email-sandbox, payment-gateways-test-mode. - Two big action cards: 'Production → Staging Clone' and 'Staging → Production Push' (push uses clu-btn-danger gradient, includes table-include pills + auto-snapshot note). - Recent sync operations feed with success/info/warning icons. Volt state additions: stagingActive, stagingSubdomain, stagingPasswordProtect, stagingExcludeMedia, stagingLastSync. Mocked plugins/themes/redirects via computed properties (no DB yet, would come from WP-API/Redirect model in prod). 5/5 SiteDetailsTest still green. --- .../views/livewire/pages/sites/show.blade.php | 409 +++++++++++++++++- 1 file changed, 408 insertions(+), 1 deletion(-) diff --git a/app/resources/views/livewire/pages/sites/show.blade.php b/app/resources/views/livewire/pages/sites/show.blade.php index 9a2a6f1..13c58f9 100644 --- a/app/resources/views/livewire/pages/sites/show.blade.php +++ b/app/resources/views/livewire/pages/sites/show.blade.php @@ -27,6 +27,49 @@ new #[Layout('layouts.app')] class extends Component { public string $tlsMin = '1.3'; public string $sslProvider = 'letsencrypt'; // letsencrypt | custom | cloudflare + /** Staging environment state. */ + public bool $stagingActive = true; + public string $stagingSubdomain = 'staging'; + public bool $stagingPasswordProtect = true; + public bool $stagingExcludeMedia = false; + public string $stagingLastSync = '2026-05-31 14:22'; + + /** Plugin / theme registry — mocked, would come from WP-API in prod. */ + public function getPluginsProperty(): array + { + return [ + ['name' => 'Yoast SEO', 'slug' => 'wordpress-seo', 'version' => '22.5', 'latest' => '22.5', 'status' => 'active', 'auto' => true, 'updates' => false], + ['name' => 'WooCommerce', 'slug' => 'woocommerce', 'version' => '8.9.2', 'latest' => '9.0.1', 'status' => 'active', 'auto' => false, 'updates' => true], + ['name' => 'WP Rocket', 'slug' => 'wp-rocket', 'version' => '3.16.0', 'latest' => '3.16.0', 'status' => 'active', 'auto' => true, 'updates' => false], + ['name' => 'Wordfence Security', 'slug' => 'wordfence', 'version' => '7.11.4', 'latest' => '7.11.6', 'status' => 'active', 'auto' => true, 'updates' => true], + ['name' => 'Advanced Custom Fields', 'slug' => 'advanced-custom-fields', 'version' => '6.2.10', 'latest' => '6.3.1', 'status' => 'active', 'auto' => false, 'updates' => true], + ['name' => 'Contact Form 7', 'slug' => 'contact-form-7', 'version' => '5.9.6', 'latest' => '5.9.6', 'status' => 'inactive', 'auto' => true, 'updates' => false], + ['name' => 'Akismet Anti-Spam', 'slug' => 'akismet', 'version' => '5.3.2', 'latest' => '5.3.3', 'status' => 'active', 'auto' => true, 'updates' => true], + ['name' => 'UpdraftPlus', 'slug' => 'updraftplus', 'version' => '1.24.0', 'latest' => '1.24.0', 'status' => 'inactive', 'auto' => false, 'updates' => false], + ]; + } + + public function getThemesProperty(): array + { + return [ + ['name' => 'Storefront', 'version' => '4.6.0', 'latest' => '4.6.0', 'status' => 'parent'], + ['name' => 'Storefront Child', 'version' => '1.2.1', 'latest' => '1.2.1', 'status' => 'active'], + ['name' => 'Twenty Twenty-Four','version' => '1.2', 'latest' => '1.2', 'status' => 'inactive'], + ]; + } + + public function getRedirectsProperty(): array + { + return [ + ['from' => '/alte-kategorie/', 'to' => '/produkte/kaffee/', 'code' => 301, 'hits' => 4218, 'last' => 'vor 12 min'], + ['from' => '/2024-aktion', 'to' => '/aktuelle-angebote/', 'code' => 301, 'hits' => 2104, 'last' => 'vor 38 min'], + ['from' => '/sale', 'to' => '/aktuelle-angebote/', 'code' => 302, 'hits' => 18642,'last' => 'vor 2 min'], + ['from' => '/checkout-old', 'to' => '/warenkorb/', 'code' => 301, 'hits' => 12, 'last' => 'gestern'], + ['from' => '/feed/atom', 'to' => '/feed/', 'code' => 301, 'hits' => 891, 'last' => 'vor 7 min'], + ['from' => '/wp-content/uploads/2022/(.*)', 'to' => '/wp-content/uploads/legacy/$1', 'code' => 301, 'hits' => 56, 'last' => 'vor 4 std'], + ]; + } + public function mount(Site $site): void { $this->site = $site->load(['server', 'certificate', 'crons']); @@ -329,7 +372,7 @@ new #[Layout('layouts.app')] class extends Component { {{-- ── Tab bar ── --}}
- @foreach (['overview' => ['Übersicht', ''], 'wp' => ['WordPress', ''], 'vhost' => ['vHost', ''], 'ssl' => ['SSL / TLS', ''], 'access' => ['SSH / FTP', ''], 'php' => ['PHP / ini', ''], 'files' => ['Datei-Manager', ''], 'cron' => ['Cronjobs', ''], 'logs' => ['Logs', '']] as $key => [$label, $svg]) + @foreach (['overview' => ['Übersicht', ''], 'wp' => ['WordPress', ''], 'plugins' => ['Plugins', ''], 'redirects' => ['Redirects', ''], 'staging' => ['Staging', ''], 'vhost' => ['vHost', ''], 'ssl' => ['SSL / TLS', ''], 'access' => ['SSH / FTP', ''], 'php' => ['PHP / ini', ''], 'files' => ['Datei-Manager', ''], 'cron' => ['Cronjobs', ''], 'logs' => ['Logs', '']] as $key => [$label, $svg])
@endif + {{-- ────── PLUGINS (Plugin- + Theme-Manager) ────── --}} + @if ($tab === 'plugins') +
+
+ @php + $totalPlugins = count($this->plugins); + $activePlugins = count(array_filter($this->plugins, fn($p) => $p['status'] === 'active')); + $updatesPending = count(array_filter($this->plugins, fn($p) => $p['updates'])); + $autoUpdate = count(array_filter($this->plugins, fn($p) => $p['auto'])); + @endphp +
Plugins gesamt
{{ $totalPlugins }}
{{ $activePlugins }} aktiv
+
Updates verfügbar
{{ $updatesPending }}
{{ $updatesPending > 0 ? 'jetzt aktualisieren' : 'alles aktuell' }}
+
Auto-Update aktiv
{{ $autoUpdate }}/{{ $totalPlugins }}
automatisch gepflegt
+
Themes
{{ count($this->themes) }}
1 aktiv (child)
+
+ +
+
+

+ + Plugins +

+
+ + +
+
+
+ + + + @foreach ($this->plugins as $p) + + + + + + + + @endforeach + +
PluginVersionStatusAuto-Update
+
+
{{ mb_strtoupper(mb_substr($p['name'], 0, 1)) }}
+
+ {{ $p['name'] }} + {{ $p['slug'] }} +
+
+
+ @if ($p['updates']) + {{ $p['version'] }} → {{ $p['latest'] }} + @else + {{ $p['version'] }} + @endif + + @if ($p['status'] === 'active')aktiv + @else inaktiv@endif + + + +
+ @if ($p['updates']) + + @endif + + +
+
+
+ @if ($updatesPending > 0) +
+ {{ $updatesPending }} Updates verfügbar. Bulk-Update führt vorher automatisch einen Snapshot durch. + +
+ @endif +
+ +
+
+

Themes

+ +
+
+ + + + @foreach ($this->themes as $t) + + + + + + + @endforeach + +
ThemeVersionStatus
{{ $t['name'] }}{{ $t['version'] }} + @if ($t['status'] === 'active')aktiv + @elseif ($t['status'] === 'parent')parent + @else inaktiv@endif + +
+ + +
+
+
+
+ +
+

Update-Policy

+
+
+
Auto-Update: Security-Patches
kritische sicherheits-updates automatisch einspielen
+ +
+
+
Auto-Update: Minor-Versionen
8.9.2 → 8.9.4 automatisch (gleiche major)
+ +
+
+
Auto-Update: Major-Versionen
8.x → 9.x — manuell empfohlen, breaking changes möglich
+ +
+
+
Snapshot vor jedem Update
automatisches backup vor plugin-update, rollback bei fehler
+ +
+
+
Staging-Test vor Production
update zuerst auf staging, smoke-test, dann auf prod
+ +
+
+
+
+ @endif + + {{-- ────── REDIRECTS ────── --}} + @if ($tab === 'redirects') +
+
+ @php + $totalRedirects = count($this->redirects); + $totalHits = array_sum(array_column($this->redirects, 'hits')); + @endphp +
Aktive Regeln
{{ $totalRedirects }}
301 + 302
+
Treffer / 24h
{{ number_format($totalHits, 0, ',', '.') }}
erfolgreich weitergeleitet
+
404-Quellen
7
potenzielle redirect-targets
+
Loop-Detection
0
keine zirkelschlüsse
+
+ +
+
+

+ + Neue Redirect-Regel +

+
+
+
+
+ +
+ Regex erlaubt mit Capture-Groups ($1, $2). +
+
+ +
+ Externe URLs (https://...) erlaubt. +
+
+ +
+ + + + +
+
+
+ + +
+
+
+
+
Query-String beibehalten
?utm_source=… überträgt sich auf target
+ +
+
+
Case-insensitive Match
/PRODUKT und /produkt matchen gleich
+ +
+
+
+
+ + +
+
+ +
+
+

Aktive Regeln {{ $totalRedirects }}

+ nach hits sortiert +
+
+ + + + @foreach ($this->redirects as $r) + + + + + + + + + + @endforeach + +
VonNachCodeHits 24hLetzter Treffer
{{ $r['from'] }}{{ $r['to'] }}{{ $r['code'] }}{{ number_format($r['hits'], 0, ',', '.') }}{{ $r['last'] }} +
+ + + +
+
+
+
+
+ @endif + + {{-- ────── STAGING ────── --}} + @if ($tab === 'staging') +
+
+
+

+ + Staging-Environment +

+ @if ($stagingActive) + aktiv + @else + nicht angelegt + @endif +
+
+
+
+ +
+ + .{{ $site->domain }} +
+ URL: {{ $stagingSubdomain }}.{{ $site->domain }} +
+
+ + + Staging auf gleichem Server spart Ressourcen — Lasttests ggf. eigenen Server. +
+
+ +
+
+
+ +
+
+
+ +
+
+
HTTP-Basic-Auth
staging-zugriff per username + passwort schützen (verhindert google-indexierung)
+ +
+
+
robots.txt blockt alle Crawler
User-agent: * / Disallow: /
+ +
+
+
Media-Dateien beim Sync ausschließen
spart bandwidth, lädt /uploads lazy on-demand
+ +
+
+
Email-Sandbox (DISALLOW_OUTGOING_MAIL)
keine kunden-mails von staging versenden
+ +
+
+
Payment-Gateways auf Test-Mode
stripe + paypal automatisch im sandbox-mode
+ +
+
+
+
+ @if ($stagingActive) + + @endif + +
+
+ + {{-- Sync actions --}} +
+
+

Production → Staging

CLONE
+
+

Vollständiger Clone von Production: DB + Files + Uploads. URLs werden automatisch auf staging.{{ $site->domain }} umgeschrieben.

+
Schätzung~4 min · 2.8 GB
+
Letzter Lauf{{ $stagingLastSync }}
+ +
+
+
+

Staging → Production

PUSH
+
+

Selektive Übernahme: Code, DB-Tabellen oder beides. Auto-Snapshot von Production vor dem Push.

+
+ ✓ Plugins + ✓ Themes + ✓ wp_options + ✗ wp_posts + ✗ wp_users +
+ +
+
+
+ + {{-- Recent activity --}} +
+

Letzte Sync-Operationen

+
+
+
Push: Plugins + Themes nach Production · 142 MB übertragen
heute, 14:22 · Marie Weber · 3m 18s
+
Clone: Production → Staging · 2.8 GB · automatisch
heute, 06:00 · Scheduler · 4m 02s
+
Push abgebrochen: WP-Version-Mismatch (6.6 ↔ 6.4)
gestern, 18:14 · Marie Weber
+
Clone: Production → Staging · WooCommerce-Update testen
gestern, 11:42 · Marie Weber · 3m 56s
+
+
+
+
+ @endif + {{-- ────── VHOST ────── --}} @if ($tab === 'vhost')