|
@@ -0,0 +1,273 @@
|
|
|
|
|
+<!-- resources/views/livewire/vpn-management.blade.php -->
|
|
|
|
|
+<div>
|
|
|
|
|
+ <!-- Content Header -->
|
|
|
|
|
+ <div class="content-header">
|
|
|
|
|
+ <div class="container-fluid">
|
|
|
|
|
+ <div class="row mb-2">
|
|
|
|
|
+ <div class="col-sm-6">
|
|
|
|
|
+ <h1 class="m-0">Gestione Connessione VPN</h1>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="col-sm-6">
|
|
|
|
|
+ <ol class="breadcrumb float-sm-right">
|
|
|
|
|
+ <li class="breadcrumb-item"><a href="/dashboard">Home</a></li>
|
|
|
|
|
+ <li class="breadcrumb-item active">VPN</li>
|
|
|
|
|
+ </ol>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- Main content -->
|
|
|
|
|
+ <div class="row">
|
|
|
|
|
+ <!-- Stato VPN -->
|
|
|
|
|
+ <div class="col-md-6">
|
|
|
|
|
+ <div class="card card-primary">
|
|
|
|
|
+ <div class="card-header">
|
|
|
|
|
+ <h3 class="card-title">
|
|
|
|
|
+ <i class="fas fa-shield-alt"></i> Stato Connessione VPN
|
|
|
|
|
+ </h3>
|
|
|
|
|
+ <div class="card-tools">
|
|
|
|
|
+ <button type="button" class="btn btn-tool" wire:click="refreshStatus">
|
|
|
|
|
+ <i class="fas fa-sync"></i>
|
|
|
|
|
+ </button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="card-body">
|
|
|
|
|
+ <div class="row">
|
|
|
|
|
+ <div class="col-md-6">
|
|
|
|
|
+ <div class="info-box">
|
|
|
|
|
+ <span class="{{ $this->getStatusIconClass() }}">
|
|
|
|
|
+ <i class="{{ $this->getStatusIcon() }}"></i>
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <div class="info-box-content">
|
|
|
|
|
+ <span class="info-box-text">Stato VPN</span>
|
|
|
|
|
+ <span class="info-box-number">{{ $this->getStatusText() }}</span>
|
|
|
|
|
+ <span class="info-box-more">
|
|
|
|
|
+ @if($lastUpdate)
|
|
|
|
|
+ Ultimo aggiornamento: {{ \Carbon\Carbon::parse($lastUpdate)->format('d/m/Y H:i:s') }}
|
|
|
|
|
+ @else
|
|
|
|
|
+ Nessun aggiornamento disponibile
|
|
|
|
|
+ @endif
|
|
|
|
|
+ </span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="col-md-6">
|
|
|
|
|
+ <div class="text-center">
|
|
|
|
|
+ <button type="button"
|
|
|
|
|
+ class="btn btn-success btn-lg"
|
|
|
|
|
+ wire:click="connectVpn"
|
|
|
|
|
+ wire:loading.attr="disabled"
|
|
|
|
|
+ wire:target="connectVpn">
|
|
|
|
|
+ <span wire:loading.remove wire:target="connectVpn">
|
|
|
|
|
+ <i class="fas fa-play"></i> Connetti VPN
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <span wire:loading wire:target="connectVpn">
|
|
|
|
|
+ <i class="fas fa-spinner fa-spin"></i> Connettendo...
|
|
|
|
|
+ </span>
|
|
|
|
|
+ </button>
|
|
|
|
|
+ <br><br>
|
|
|
|
|
+ <button type="button"
|
|
|
|
|
+ class="btn btn-warning btn-lg"
|
|
|
|
|
+ wire:click="disconnectVpn"
|
|
|
|
|
+ wire:loading.attr="disabled"
|
|
|
|
|
+ wire:target="disconnectVpn">
|
|
|
|
|
+ <span wire:loading.remove wire:target="disconnectVpn">
|
|
|
|
|
+ <i class="fas fa-stop"></i> Disconnetti VPN
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <span wire:loading wire:target="disconnectVpn">
|
|
|
|
|
+ <i class="fas fa-spinner fa-spin"></i> Disconnettendo...
|
|
|
|
|
+ </span>
|
|
|
|
|
+ </button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- Configurazione Credenziali -->
|
|
|
|
|
+ <div class="col-md-6">
|
|
|
|
|
+ <div class="card card-warning">
|
|
|
|
|
+ <div class="card-header">
|
|
|
|
|
+ <h3 class="card-title">
|
|
|
|
|
+ <i class="fas fa-cog"></i> Configurazione Credenziali
|
|
|
|
|
+ </h3>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="card-body">
|
|
|
|
|
+ @if($successMessage)
|
|
|
|
|
+ <div class="alert alert-success alert-dismissible">
|
|
|
|
|
+ <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
|
|
|
|
|
+ {{ $successMessage }}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ @endif
|
|
|
|
|
+
|
|
|
|
|
+ @if($errorMessage)
|
|
|
|
|
+ <div class="alert alert-danger alert-dismissible">
|
|
|
|
|
+ <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
|
|
|
|
|
+ {{ $errorMessage }}
|
|
|
|
|
+ </div>
|
|
|
|
|
+ @endif
|
|
|
|
|
+
|
|
|
|
|
+ <form wire:submit.prevent="updateCredentials">
|
|
|
|
|
+ <div class="form-group">
|
|
|
|
|
+ <label for="username">Username</label>
|
|
|
|
|
+ <input type="text"
|
|
|
|
|
+ class="form-control @error('username') is-invalid @enderror"
|
|
|
|
|
+ wire:model="username"
|
|
|
|
|
+ required>
|
|
|
|
|
+ @error('username')
|
|
|
|
|
+ <div class="invalid-feedback">{{ $message }}</div>
|
|
|
|
|
+ @enderror
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="form-group">
|
|
|
|
|
+ <label for="password">Password</label>
|
|
|
|
|
+ <input type="password"
|
|
|
|
|
+ class="form-control @error('password') is-invalid @enderror"
|
|
|
|
|
+ wire:model="password"
|
|
|
|
|
+ placeholder="Inserisci la password"
|
|
|
|
|
+ required>
|
|
|
|
|
+ @error('password')
|
|
|
|
|
+ <div class="invalid-feedback">{{ $message }}</div>
|
|
|
|
|
+ @enderror
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <div class="form-group">
|
|
|
|
|
+ <label for="server">Server VPN</label>
|
|
|
|
|
+ <input type="text"
|
|
|
|
|
+ class="form-control @error('server') is-invalid @enderror"
|
|
|
|
|
+ wire:model="server"
|
|
|
|
|
+ required>
|
|
|
|
|
+ @error('server')
|
|
|
|
|
+ <div class="invalid-feedback">{{ $message }}</div>
|
|
|
|
|
+ @enderror
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <button type="submit"
|
|
|
|
|
+ class="btn btn-primary"
|
|
|
|
|
+ wire:loading.attr="disabled"
|
|
|
|
|
+ wire:target="updateCredentials">
|
|
|
|
|
+ <span wire:loading.remove wire:target="updateCredentials">
|
|
|
|
|
+ <i class="fas fa-save"></i> Salva Credenziali
|
|
|
|
|
+ </span>
|
|
|
|
|
+ <span wire:loading wire:target="updateCredentials">
|
|
|
|
|
+ <i class="fas fa-spinner fa-spin"></i> Salvando...
|
|
|
|
|
+ </span>
|
|
|
|
|
+ </button>
|
|
|
|
|
+ </form>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
|
|
+ <!-- Log VPN -->
|
|
|
|
|
+ <div class="row mt-4">
|
|
|
|
|
+ <div class="col-md-12">
|
|
|
|
|
+ <div class="card card-info">
|
|
|
|
|
+ <div class="card-header">
|
|
|
|
|
+ <h3 class="card-title">
|
|
|
|
|
+ <i class="fas fa-file-alt"></i> Informazioni VPN
|
|
|
|
|
+ </h3>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="card-body">
|
|
|
|
|
+ <div class="table-responsive">
|
|
|
|
|
+ <table class="table table-striped">
|
|
|
|
|
+ <thead>
|
|
|
|
|
+ <tr>
|
|
|
|
|
+ <th>Proprietà</th>
|
|
|
|
|
+ <th>Valore</th>
|
|
|
|
|
+ </tr>
|
|
|
|
|
+ </thead>
|
|
|
|
|
+ <tbody>
|
|
|
|
|
+ <tr>
|
|
|
|
|
+ <td><strong>Stato Attuale</strong></td>
|
|
|
|
|
+ <td>
|
|
|
|
|
+ <span class="{{ $this->getStatusBadgeClass() }}">
|
|
|
|
|
+ {{ $this->getStatusBadgeText() }}
|
|
|
|
|
+ </span>
|
|
|
|
|
+ {{ $this->getStatusText() }}
|
|
|
|
|
+ </td>
|
|
|
|
|
+ </tr>
|
|
|
|
|
+ <tr>
|
|
|
|
|
+ <td><strong>Server Configurato</strong></td>
|
|
|
|
|
+ <td>{{ $server }}</td>
|
|
|
|
|
+ </tr>
|
|
|
|
|
+ <tr>
|
|
|
|
|
+ <td><strong>Username Configurato</strong></td>
|
|
|
|
|
+ <td>{{ $username }}</td>
|
|
|
|
|
+ </tr>
|
|
|
|
|
+ <tr>
|
|
|
|
|
+ <td><strong>Ultimo Aggiornamento</strong></td>
|
|
|
|
|
+ <td>
|
|
|
|
|
+ @if($lastUpdate)
|
|
|
|
|
+ {{ \Carbon\Carbon::parse($lastUpdate)->format('d/m/Y H:i:s') }}
|
|
|
|
|
+ @else
|
|
|
|
|
+ Non disponibile
|
|
|
|
|
+ @endif
|
|
|
|
|
+ </td>
|
|
|
|
|
+ </tr>
|
|
|
|
|
+ </tbody>
|
|
|
|
|
+ </table>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+</div>
|
|
|
|
|
+
|
|
|
|
|
+@push('css')
|
|
|
|
|
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css">
|
|
|
|
|
+@endpush
|
|
|
|
|
+
|
|
|
|
|
+@push('scripts')
|
|
|
|
|
+<script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js"></script>
|
|
|
|
|
+<script>
|
|
|
|
|
+ // Listen for Livewire events
|
|
|
|
|
+ document.addEventListener('livewire:load', function () {
|
|
|
|
|
+ // Auto-refresh status every 30 seconds
|
|
|
|
|
+ setInterval(function() {
|
|
|
|
|
+ @this.call('refreshStatus');
|
|
|
|
|
+ }, 30000);
|
|
|
|
|
+
|
|
|
|
|
+ // Update sidebar badge when status changes
|
|
|
|
|
+ Livewire.on('vpnStatusUpdated', status => {
|
|
|
|
|
+ updateSidebarBadge(status);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // Show toast notifications
|
|
|
|
|
+ Livewire.on('showToast', (type, message) => {
|
|
|
|
|
+ if (typeof toastr !== 'undefined') {
|
|
|
|
|
+ toastr[type](message);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // Refresh status with delay (after connect/disconnect commands)
|
|
|
|
|
+ Livewire.on('refreshStatusDelayed', () => {
|
|
|
|
|
+ setTimeout(function() {
|
|
|
|
|
+ @this.call('refreshStatus');
|
|
|
|
|
+ }, 3000);
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ function updateSidebarBadge(status) {
|
|
|
|
|
+ const badge = document.getElementById('vpn-status-badge');
|
|
|
|
|
+ if (badge) {
|
|
|
|
|
+ badge.className = ''; // Clear existing classes
|
|
|
|
|
+ if (status === 'connected') {
|
|
|
|
|
+ badge.className = 'badge badge-success right';
|
|
|
|
|
+ badge.textContent = 'ON';
|
|
|
|
|
+ } else if (status === 'disconnected') {
|
|
|
|
|
+ badge.className = 'badge badge-danger right';
|
|
|
|
|
+ badge.textContent = 'OFF';
|
|
|
|
|
+ } else if (status === 'error') {
|
|
|
|
|
+ badge.className = 'badge badge-danger right';
|
|
|
|
|
+ badge.textContent = 'ERR';
|
|
|
|
|
+ } else {
|
|
|
|
|
+ badge.className = 'badge badge-warning right';
|
|
|
|
|
+ badge.textContent = '?';
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+</script>
|
|
|
|
|
+@endpush
|