feat: Toastra-Plugin eingebunden + DKIM-Regenerierung fix
- Toastra als Toast-System integriert (ersetzt GlassToastra) - CSS auf var(--mw-*) Dark-Theme angepasst, keine Klassen entfernt - Livewire-Adapter mappt done/warn/error/info auf Toastra-Typen - DnsDkim: doppelter sudo-install-dkim entfernt (DkimService macht es bereits) - dkimReady() prüft Storage-Pfad statt sudo-Test (kein Sudoers-Eintrag nötig) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>main v1.1.376
parent
f375ea0215
commit
486166c05a
|
|
@ -4,7 +4,6 @@ namespace App\Livewire\Ui\Nx\Domain;
|
|||
|
||||
use App\Models\Domain;
|
||||
use App\Services\DkimService;
|
||||
use Illuminate\Support\Facades\Process;
|
||||
use Livewire\Attributes\Layout;
|
||||
use Livewire\Attributes\On;
|
||||
use Livewire\Attributes\Title;
|
||||
|
|
@ -44,22 +43,7 @@ class DnsDkim extends Component
|
|||
try {
|
||||
/** @var DkimService $svc */
|
||||
$svc = app(DkimService::class);
|
||||
$res = $svc->generateForDomain($domain, 2048, $selector);
|
||||
$priv = $res['priv_path'] ?? storage_path("app/private/dkim/{$domain->domain}/{$selector}.private");
|
||||
$txt = storage_path("app/private/dkim/{$domain->domain}/{$selector}.txt");
|
||||
|
||||
if (!is_readable($txt) && !empty($res['dns_txt'])) {
|
||||
file_put_contents($txt, $res['dns_txt']);
|
||||
}
|
||||
|
||||
$proc = Process::run(['sudo', '-n', '/usr/local/sbin/mailwolt-install-dkim',
|
||||
$domain->domain, $selector, $priv, $txt]);
|
||||
|
||||
if (!$proc->successful()) {
|
||||
throw new \RuntimeException($proc->errorOutput());
|
||||
}
|
||||
|
||||
Process::run(['sudo', '-n', '/usr/bin/systemctl', 'reload', 'opendkim']);
|
||||
$svc->generateForDomain($domain, 2048, $selector);
|
||||
|
||||
$this->dispatch('toast', type: 'done', badge: 'DKIM',
|
||||
title: 'DKIM erneuert', text: "Schlüssel für <b>{$domain->domain}</b> wurde neu generiert.", duration: 5000);
|
||||
|
|
@ -71,8 +55,8 @@ class DnsDkim extends Component
|
|||
|
||||
private function dkimReady(string $domain, string $selector): bool
|
||||
{
|
||||
return Process::run(['sudo', '-n', '/usr/bin/test', '-s',
|
||||
"/etc/opendkim/keys/{$domain}/{$selector}.private"])->successful();
|
||||
$path = storage_path("app/private/dkim/{$domain}/{$selector}.private");
|
||||
return is_file($path) && filesize($path) > 0;
|
||||
}
|
||||
|
||||
public function render()
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
@import 'tailwindcss';
|
||||
@import '../js/plugins/GlassToastra/style.css';
|
||||
@import '../js/plugins/Toastra/src/message.css';
|
||||
|
||||
@import "../fonts/BaiJamjuree/font.css";
|
||||
@import "../fonts/Space/font.css";
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import "@phosphor-icons/web/regular";
|
|||
import "@phosphor-icons/web/bold";
|
||||
import './components/sidebar.js';
|
||||
|
||||
import './plugins/GlassToastra/toastra.glass.js'
|
||||
import './plugins/GlassToastra/livewire-adapter';
|
||||
import './plugins/Toastra/index.js';
|
||||
import './plugins/Toastra/livewire-adapter';
|
||||
|
||||
import './utils/events.js';
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
// Maps Livewire `toast` events → window.toastra.notify()
|
||||
const TYPE_MAP = {
|
||||
done: 'success',
|
||||
warn: 'warning',
|
||||
warning: 'warning',
|
||||
error: 'error',
|
||||
info: 'info',
|
||||
default: 'default',
|
||||
update: 'update',
|
||||
};
|
||||
|
||||
function dispatchToast(detail) {
|
||||
if (!window.toastra) return;
|
||||
|
||||
const { type = 'info', badge, title, text, duration } = detail || {};
|
||||
|
||||
window.toastra.notify({
|
||||
type: TYPE_MAP[type] ?? 'info',
|
||||
badge: badge ?? '',
|
||||
title: title ?? '',
|
||||
text: text ?? '',
|
||||
duration: duration !== undefined ? duration : 4000,
|
||||
close: true,
|
||||
progressbar: true,
|
||||
icon: true,
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('livewire:init', () => {
|
||||
window.addEventListener('toast', (e) => dispatchToast(e?.detail || {}));
|
||||
window.addEventListener('toast.clear', () => { /* Toastra hat kein clear-API */ });
|
||||
window.addEventListener('toast.reload',(e) => setTimeout(() => window.location.reload(), e?.detail?.delay || 0));
|
||||
});
|
||||
|
||||
window.showToast = dispatchToast;
|
||||
|
|
@ -603,13 +603,13 @@
|
|||
/* background: linear-gradient(180deg, var(--accent), rgba(var(--toast-red), .6));*/
|
||||
/* border-radius: 3px 0 0 3px;*/
|
||||
/*}*/
|
||||
/* ===== Toast · Glass v2 (Badge) ===== */
|
||||
/* ===== Toast · Glass v2 – mw dark theme ===== */
|
||||
.notification.glass-mode .notification-container {
|
||||
backdrop-filter: blur(14px);
|
||||
background: rgba(17, 24, 39, .52); /* dunkleres Glas */
|
||||
border: 1px solid rgba(255,255,255,.09);
|
||||
background: color-mix(in srgb, var(--mw-bg3, #111420) 88%, transparent);
|
||||
border: 1px solid var(--mw-b1, #1c2035);
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 12px 40px rgba(0,0,0,.28);
|
||||
box-shadow: 0 12px 40px rgba(0,0,0,.40);
|
||||
}
|
||||
|
||||
.notification.glass-mode .notification-block {
|
||||
|
|
@ -634,10 +634,10 @@
|
|||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding-right: 36px; /* Platz für Close */
|
||||
padding-right: 36px;
|
||||
font-weight: 700;
|
||||
letter-spacing: .2px;
|
||||
color: #e5e7eb; /* text-gray-200 */
|
||||
color: var(--mw-t1, #edf0fc);
|
||||
}
|
||||
|
||||
/* Badge aus data-badge rendern */
|
||||
|
|
@ -648,17 +648,17 @@
|
|||
letter-spacing: .6px;
|
||||
padding: 4px 8px;
|
||||
border-radius: 9px;
|
||||
border: 1px solid rgba(255,255,255,.10);
|
||||
background: rgba(31,41,55,.55); /* dunkles Glas */
|
||||
color: #cbd5e1; /* text-gray-300 */
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,.08);
|
||||
border: 1px solid var(--mw-b2, #242840);
|
||||
background: var(--mw-bg4, #161a28);
|
||||
color: var(--mw-t3, #737b96);
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,.06);
|
||||
}
|
||||
|
||||
/* Subtext */
|
||||
.notification.glass-mode .notification-message {
|
||||
margin-top: 6px;
|
||||
line-height: 1.35;
|
||||
color: #cbd5e1; /* text-gray-300 */
|
||||
color: var(--mw-t2, #9aa3be);
|
||||
}
|
||||
|
||||
/* Close-Button dezenter */
|
||||
|
|
@ -666,12 +666,12 @@
|
|||
top: 10px; right: 10px;
|
||||
width: 30px; height: 30px;
|
||||
display: grid; place-items: center;
|
||||
background: rgba(255,255,255,.06);
|
||||
border: 1px solid rgba(255,255,255,.10);
|
||||
box-shadow: 0 6px 20px rgba(0,0,0,.25);
|
||||
background: var(--mw-bg4, #161a28);
|
||||
border: 1px solid var(--mw-b2, #242840);
|
||||
box-shadow: 0 4px 12px rgba(0,0,0,.30);
|
||||
}
|
||||
.notification.glass-mode .notification-dismiss-btn:hover {
|
||||
background: rgba(255,255,255,.12);
|
||||
background: var(--mw-b1, #1c2035);
|
||||
}
|
||||
|
||||
/* Progressbar dünn & soft */
|
||||
|
|
@ -747,15 +747,15 @@
|
|||
letter-spacing: .6px;
|
||||
padding: 4px 8px;
|
||||
border-radius: 9px;
|
||||
border: 1px solid rgba(255,255,255,.10);
|
||||
background: rgba(31,41,55,.55);
|
||||
color: #cbd5e1; /* gray-300 */
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,.08);
|
||||
border: 1px solid var(--mw-b2, #242840);
|
||||
background: var(--mw-bg4, #161a28);
|
||||
color: var(--mw-t3, #737b96);
|
||||
box-shadow: inset 0 1px 0 rgba(255,255,255,.06);
|
||||
}
|
||||
|
||||
/* keep your bold style on the title text itself */
|
||||
.notification-title-text b {
|
||||
color: #e5e7eb; /* gray-200 */
|
||||
color: var(--mw-t1, #edf0fc);
|
||||
font-weight: 800;
|
||||
letter-spacing: .3px;
|
||||
}
|
||||
|
|
@ -764,14 +764,7 @@
|
|||
.notification-subtitle {
|
||||
margin-top: .25rem;
|
||||
font-weight: 700;
|
||||
color: #e5e7eb; /* gray-200 */
|
||||
color: var(--mw-t1, #edf0fc);
|
||||
}
|
||||
|
||||
/* Glass container (you already had this, listing again for completeness) */
|
||||
.notification.glass-mode .notification-container {
|
||||
backdrop-filter: blur(10px);
|
||||
background: rgba(31,41,55,.45);
|
||||
border: 1px solid rgba(255,255,255,.08);
|
||||
border-radius: 14px;
|
||||
box-shadow: 0 8px 30px rgba(0,0,0,.25);
|
||||
}
|
||||
/* Glass container duplicate removed – see above */
|
||||
|
|
|
|||
Loading…
Reference in New Issue