130 lines
7.8 KiB
PHP
130 lines
7.8 KiB
PHP
<x-app-layout>
|
||
<x-slot name="header">
|
||
<div class="flex items-center space-x-2">
|
||
<a href="{{ route('network.segments.index') }}" class="text-gray-500 hover:text-gray-700">Segmente</a>
|
||
<span class="text-gray-400">/</span>
|
||
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200">Neues Segment</h2>
|
||
</div>
|
||
</x-slot>
|
||
|
||
<div class="py-8">
|
||
<div class="max-w-xl mx-auto sm:px-6 lg:px-8">
|
||
<div class="bg-white dark:bg-gray-800 shadow-sm rounded-lg p-6">
|
||
<form method="POST" action="{{ route('network.segments.store') }}" class="space-y-5">
|
||
@csrf
|
||
|
||
<div>
|
||
<x-input-label for="name" value="Name *" />
|
||
<x-text-input id="name" name="name" type="text" class="mt-1 block w-full"
|
||
value="{{ old('name') }}" placeholder="z.B. Büro, Server-VLAN, Produktion" required />
|
||
<x-input-error :messages="$errors->get('name')" class="mt-1" />
|
||
</div>
|
||
|
||
<div>
|
||
<x-input-label for="subnet" value="Subnetz *" />
|
||
<div class="flex gap-2 mt-1">
|
||
<x-text-input id="subnet" name="subnet" type="text" class="block w-full font-mono"
|
||
value="{{ old('subnet') }}" placeholder="z.B. 192.168.1.0/24 oder 10.0.0.0/8" required />
|
||
<button type="button" id="detect-subnet-btn"
|
||
class="shrink-0 px-3 py-2 text-sm font-medium rounded-md border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 transition">
|
||
🔍 Erkennen
|
||
</button>
|
||
</div>
|
||
<x-input-error :messages="$errors->get('subnet')" class="mt-1" />
|
||
<div id="subnet-suggestions" class="mt-1 hidden"></div>
|
||
</div>
|
||
|
||
<div>
|
||
<x-input-label for="vlan_id" value="VLAN-ID (optional)" />
|
||
<x-text-input id="vlan_id" name="vlan_id" type="number" class="mt-1 block w-full"
|
||
value="{{ old('vlan_id') }}" placeholder="z.B. 10" min="1" max="4094" />
|
||
<x-input-error :messages="$errors->get('vlan_id')" class="mt-1" />
|
||
</div>
|
||
|
||
<div>
|
||
<x-input-label for="description" value="Beschreibung (optional)" />
|
||
<textarea id="description" name="description" rows="2"
|
||
class="mt-1 block w-full border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200 rounded-md shadow-sm text-sm focus:ring-indigo-500 focus:border-indigo-500"
|
||
placeholder="Kurze Beschreibung dieses Segments...">{{ old('description') }}</textarea>
|
||
</div>
|
||
|
||
<div>
|
||
<x-input-label for="scan_interval_minutes" value="Scan-Zyklus (automatisch)" />
|
||
<select id="scan_interval_minutes" name="scan_interval_minutes"
|
||
class="mt-1 block w-full border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-gray-200 rounded-md shadow-sm text-sm focus:ring-indigo-500 focus:border-indigo-500">
|
||
<option value="">Manuell (kein Auto-Scan)</option>
|
||
<option value="5" {{ old('scan_interval_minutes') == '5' ? 'selected' : '' }}>Alle 5 Minuten</option>
|
||
<option value="15" {{ old('scan_interval_minutes') == '15' ? 'selected' : '' }}>Alle 15 Minuten</option>
|
||
<option value="30" {{ old('scan_interval_minutes') == '30' ? 'selected' : '' }}>Alle 30 Minuten</option>
|
||
<option value="60" {{ old('scan_interval_minutes') == '60' ? 'selected' : '' }}>Stündlich</option>
|
||
<option value="360" {{ old('scan_interval_minutes') == '360' ? 'selected' : '' }}>Alle 6 Stunden</option>
|
||
<option value="720" {{ old('scan_interval_minutes') == '720' ? 'selected' : '' }}>Alle 12 Stunden</option>
|
||
<option value="1440" {{ old('scan_interval_minutes') == '1440' ? 'selected' : '' }}>Täglich</option>
|
||
</select>
|
||
<p class="mt-1 text-xs text-gray-500">Erfordert aktiven Laravel Scheduler (Cron).</p>
|
||
</div>
|
||
|
||
<div>
|
||
<x-input-label for="nmap_options" value="nmap-Parameter" />
|
||
<x-text-input id="nmap_options" name="nmap_options" type="text" class="mt-1 block w-full font-mono"
|
||
value="{{ old('nmap_options', '-sn') }}" placeholder="-sn" />
|
||
<p class="mt-1 text-xs text-gray-500">-sn = Ping-Scan (schnell) · -sn -p 22,80,443 = mit Ports</p>
|
||
</div>
|
||
|
||
<div class="flex items-center gap-2">
|
||
<input type="checkbox" id="active" name="active" value="1"
|
||
{{ old('active', '1') ? 'checked' : '' }}
|
||
class="rounded border-gray-300 text-indigo-600 focus:ring-indigo-500" />
|
||
<label for="active" class="text-sm text-gray-700 dark:text-gray-300">Aktiv (automatisch überwachen)</label>
|
||
</div>
|
||
|
||
<div class="flex justify-end gap-3">
|
||
<a href="{{ route('network.segments.index') }}"
|
||
class="px-4 py-2 text-sm font-medium rounded-md border border-gray-300 dark:border-gray-600 text-gray-700 dark:text-gray-300 hover:bg-gray-50 transition">
|
||
Abbrechen
|
||
</a>
|
||
<button type="submit" style="background-color: var(--color-primary)"
|
||
class="px-5 py-2 text-white text-sm font-medium rounded-md hover:opacity-90 transition">
|
||
Segment anlegen
|
||
</button>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<script>
|
||
document.getElementById('detect-subnet-btn').addEventListener('click', function() {
|
||
const btn = this;
|
||
const suggestions = document.getElementById('subnet-suggestions');
|
||
btn.textContent = '⏳ Suche...';
|
||
btn.disabled = true;
|
||
|
||
fetch('{{ route('network.detect-subnets') }}', {
|
||
headers: { 'Accept': 'application/json', 'X-Requested-With': 'XMLHttpRequest' }
|
||
})
|
||
.then(r => r.json())
|
||
.then(function(subnets) {
|
||
btn.textContent = '🔍 Erkennen';
|
||
btn.disabled = false;
|
||
if (!subnets.length) {
|
||
suggestions.innerHTML = '<p class="text-xs text-gray-400">Keine Daten in der Datenbank gefunden.</p>';
|
||
suggestions.classList.remove('hidden');
|
||
return;
|
||
}
|
||
suggestions.innerHTML = '<p class="text-xs text-gray-500 mb-1">Erkannte Subnetze – klicken zum Übernehmen:</p>' +
|
||
subnets.map(function(s) {
|
||
return '<button type="button" onclick="document.getElementById(\'subnet\').value=\'' + s + '\'" ' +
|
||
'class="mr-1 mb-1 px-2 py-1 text-xs font-mono rounded border border-indigo-300 text-indigo-700 hover:bg-indigo-50 transition">' + s + '</button>';
|
||
}).join('');
|
||
suggestions.classList.remove('hidden');
|
||
})
|
||
.catch(function() {
|
||
btn.textContent = '🔍 Erkennen';
|
||
btn.disabled = false;
|
||
suggestions.innerHTML = '<p class="text-xs text-red-500">Fehler bei der Erkennung.</p>';
|
||
suggestions.classList.remove('hidden');
|
||
});
|
||
});
|
||
</script>
|
||
</x-app-layout>
|