Anche se Laravel Pulse mette a disposizione un endpoint da raggiungere tramite un semplice link ed utilizzare la dashboard di pulse come applicazione standalone ho avuto l'esigenza di integrare la visualizzazione direttamente nella dashboard di laravel per creare una migliore esperienza utente.
Obiettivo
Qui vi indico il risultato che otterremo con questa integrazione, nella versione standard ho riscontrato questi problemi, la versione dark se attivata su Laravel Nova bisognava anche selezionarla su pulse o il contrario, avendo a disposizione un menu per laravel nova sullo stato di diverse applicazioni quando veniva richiamata la dashboard di pulse bisognava sempre tornare indietro per scegliere altra opzione.
L'idea è quella di creare una "custom route" in laravel nova che crei un elemento iframe ad una versione modificata della dashboard pulse, quindi senza usare l'endpoint originale, in questo modo possiamo personalizzare il layout originale e integrare un solo stato di tema dark/light e personalizzare il CSS.
Creazione delle "custom route"
Per prima cosa creiamo un file per la definizione delle "route" o modifichiamo quello esistente se già avete delle "route" personalizzate. Io ho creato un file in app/Nova/Routes/tools.php.
Route::get('status/pulse')
->uses('App\Nova\Controllers\Tools\Status\PulseController@index')
->name('tools.status.pulse');
Route::get('status/pulse/iframe')
->uses('App\Nova\Controllers\Tools\Status\PulseController@iframe')
->name('tools.status.pulse.iframe');
Ho creato una "route" per la pagina laravel nova principale e una per eseguire "embed" tramite "iframe" di una copia della dashboard di laravel pulse modificata in base alle nostre necessità. In seguito andremmo anche a definire il controller per l'esecuzione di queste due funzioni. Ovviamente potete cambiare il valore del "path" come desiderate in base alle vostre preferenze.
Creazione del controller
Personalmente preferisco avere tutto l'ambiente Nova nella directory app\Nova
e lasciare le directory standard per le funzione dell'applicazione operativa, quindi creo il controller necessario nella directory app/Nova/Controllers/Tools/Status
come indicato nella definizione delle "route".
namespace App\Nova\Controllers\Tools\Status;
use App\Http\Controllers\Controller;
class PulseController extends Controller
{
/**
* Application nova function
*/
public function index()
{
return inertia('StatusPulse');
}
/**
* Application nova function
*/
public function iframe()
{
return view('admin::tools.status.pulse.index');
}
}
Il primo metodo è usato per richiamare la pagina principale tramite un componente Vue, dato che Nova esegue il rendering iniziale lato client, mentre il metodo "iframe" sarà elaborato lato server e quindi elaborerà una vista blade con la copia originale della dashboard di laravel pulse però modificata.
Creazione componente Vue
Per rendere funzionante il path /status/pulse
relativo al path di laravel nova dobbiamo creare un componente Vue quindi dobbiamo implementare uno javascript e caricarlo durante l'inizializzazione di laravel nova, io ad esempio uso questa tecnica anche per caricare livewire che uso insieme a Nova.
import StatusPulse from './pages/Status/Pulse.vue'
Nova.booting((app, store) => {
Nova.inertia('StatusPulse', StatusPulse)
})
Creiamo un file nova.js
dove avete l'ambiente per la creazione degli assets, io uso ViteJS però sono sicuro che potete implementarlo anche con altri strumenti. Nella stessa directory di nova.js creiamo una directory con il template "vue" ./pages/Status/Pulse.vue
indicando questo codice.
<template>
<div>
<iframe src="/nova/status/pulse/iframe?period=24_hours"
width="100%" style="min-height:100vw"></iframe>
</div>
</template>
Creazione vista Blade
Adesso l'ambiente dovrebbe essere pronto per visualizzare una pagina che esegue il rendering della vista blade associata al controller definito in precedenza tramite il metodo "iframe". Quindi basta copiare al momento solo per testare il funzionamento (dopo faremo le personalizzazioni) il file presente nel pacchetto di laravel pulse. app\vendor\laravel\pulse\resources
nella nostra vista blade.
Attenzione alla variabile {{slot}}
che dovrà essere sostituita con la lista dei widgets di laravel pulse che vogliamo visualizzare nella nostra dashboard quindi modifichiamo il codice come segue:
<main class="py-4">
<div {{ $attributes->merge(['class' => "mx-auto grid default:grid-cols-{$cols} default:gap-6"]) }}>
<livewire:pulse.servers cols="full"/>
<livewire:pulse.usage cols="4" rows="2" />
<livewire:pulse.queues cols="4" />
<livewire:pulse.cache cols="4" />
<livewire:pulse.slow-queries cols="8" />
<livewire:pulse.exceptions cols="6" />
<livewire:pulse.slow-requests cols="6" />
<livewire:pulse.slow-jobs cols="6" />
<livewire:pulse.slow-outgoing-requests cols="6" />
</div>
</main>
Adesso siamo pronti per fare una prova, se la dashboard viene visualizzata senza problemi possiamo passare alla fase di personalizzazione codice, altrimenti ripetere con attenzione i passi precedenti. In questa dimostrazione sto usando il codice originale con cui uso l'implementazione tutti i giorni quindi dovrebbe essere abbastanza affidabile dal punto di vista del funzionamento.
Personalizzazione Dashboard
Per rendere la pagina di pulse più coerente dobbiamo eseguire alcune modifiche, la prima è quella di eliminare il componete theme-switcher dal codice copiato e sostituire il cambio di tema basandosi su quello impostato in laravel nova. Quindi per prima cosa eliminiamo la riga dello switch.
Eliminare il componete indicato dal codice che abbiamo copiato precedentemente nella nostra vista blade e aggiungiamo un codice javascript nella sezione HEAD che attivi o disattivi il tema dark in base allo stato del tema di laravel nova che in questo caso esegue la funzione di contenitore.
@livewireScriptConfig
<script>
function updateTheme() {
if (window.parent.document.documentElement.classList.contains('dark')) {
this.theme = 'dark'
localStorage.theme = 'dark'
document.documentElement.classList.add('dark')
} else {
this.theme = 'light'
localStorage.theme = 'light'
document.documentElement.classList.remove('dark')
}
}
const observer = new MutationObserver(function(mutationsList) {
for (let mutation of mutationsList) {
if (mutation.attributeName === 'class') {
updateTheme();
}
}
});
observer.observe(window.parent.document.documentElement, {
attributes: true
});
updateTheme();
</script>
Inserite questo codice subito dopo l'istruzione @livewireScriptConfig
che vi indico come riferimento, a questo punto dovremmo aver ottenuto lo switch del tema pulse usando lo switch di laravel nova. Oltre alla personalizzazione di javascript possiamo anche cambiare il CSS in modo da renderlo più idoneo al nostro ambiente o alle nostre personalizzazioni eseguite in ambiente di laravel nova.
<style>
html.dark .dark\:bg-gray-900
{
background-color: #101521 !important;
}
*, :before, :after {
--tw-gradient-to-position: 0;
}
</style>
Io ad esempio ho cambiato il "background color" nella versione "dark-mode" per renderlo più visibile rispetto al background di default di laravel nova, ho anche eliminato dei background legati all sezione header per ottenere una sensazione di integrazione più diretta con il tema di laravel nova.
Risultato finale
Spero che questa esperienza vi torni utile per il vostro lavoro, ci vediamo nella prossima pubblicazione, qualsiasi miglioramento alla soluzione è ben accetto, usate i commenti per scrivermi. Grazie.