Dateien
Hetzner-Backup/v2_adminpanel/templates/batch_form.html
2025-06-07 23:46:27 +02:00

227 Zeilen
9.3 KiB
HTML
Originalformat Blame Verlauf

Diese Datei enthält unsichtbare Unicode-Zeichen
Diese Datei enthält unsichtbare Unicode-Zeichen, die für Menschen nicht unterscheidbar sind, aber von einem Computer unterschiedlich verarbeitet werden können. Wenn du glaubst, dass das absichtlich so ist, kannst du diese Warnung ignorieren. Benutze den „Escape“-Button, um versteckte Zeichen anzuzeigen.
Diese Datei enthält Unicode-Zeichen, die mit anderen Zeichen verwechselt werden können. Wenn du glaubst, dass das absichtlich so ist, kannst du diese Warnung ignorieren. Benutze den „Escape“-Button, um versteckte Zeichen anzuzeigen.
{% extends "base.html" %}
{% block title %}Batch-Lizenzen erstellen{% endblock %}
{% block content %}
<div class="container py-5">
<div class="d-flex justify-content-between align-items-center mb-4">
<h2>🔑 Batch-Lizenzen erstellen</h2>
<div>
<a href="/" class="btn btn-secondary">📊 Dashboard</a>
<a href="/create" class="btn btn-secondary"> Einzellizenz</a>
<a href="/licenses" class="btn btn-secondary">📋 Lizenzen</a>
<a href="/customers" class="btn btn-secondary">👥 Kunden</a>
</div>
</div>
<div class="alert alert-info">
<strong> Batch-Generierung:</strong> Erstellen Sie mehrere Lizenzen auf einmal für einen Kunden.
Die Lizenzen werden automatisch generiert und können anschließend als CSV exportiert werden.
</div>
<!-- Flash Messages -->
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ 'danger' if category == 'error' else 'success' }} alert-dismissible fade show" role="alert">
{{ message }}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
{% endfor %}
{% endif %}
{% endwith %}
<form method="post" action="/batch" accept-charset="UTF-8">
<div class="row g-3">
<div class="col-md-12">
<label for="customerSelect" class="form-label">Kunde auswählen</label>
<select class="form-select" id="customerSelect" name="customer_id" required>
<option value="">🔍 Kunde suchen oder neuen Kunden anlegen...</option>
<option value="new"> Neuer Kunde</option>
</select>
</div>
<div class="col-md-6" id="customerNameDiv" style="display: none;">
<label for="customerName" class="form-label">Kundenname</label>
<input type="text" class="form-control" id="customerName" name="customer_name"
placeholder="Firma GmbH" accept-charset="UTF-8">
</div>
<div class="col-md-6" id="emailDiv" style="display: none;">
<label for="email" class="form-label">E-Mail</label>
<input type="email" class="form-control" id="email" name="email"
placeholder="kontakt@firma.de" accept-charset="UTF-8">
</div>
<div class="col-md-3">
<label for="quantity" class="form-label">Anzahl Lizenzen</label>
<input type="number" class="form-control" id="quantity" name="quantity"
min="1" max="100" value="10" required>
<div class="form-text">Max. 100 Lizenzen pro Batch</div>
</div>
<div class="col-md-3">
<label for="licenseType" class="form-label">Lizenztyp</label>
<select class="form-select" id="licenseType" name="license_type" required>
<option value="full">Vollversion</option>
<option value="test">Testversion</option>
</select>
</div>
<div class="col-md-3">
<label for="validFrom" class="form-label">Gültig ab</label>
<input type="date" class="form-control" id="validFrom" name="valid_from" required>
</div>
<div class="col-md-3">
<label for="validUntil" class="form-label">Gültig bis</label>
<input type="date" class="form-control" id="validUntil" name="valid_until" required>
</div>
</div>
<div class="mt-4 d-flex gap-2">
<button type="submit" class="btn btn-primary btn-lg">
🔑 Batch generieren
</button>
<button type="button" class="btn btn-outline-secondary" onclick="previewKeys()">
👁️ Vorschau
</button>
</div>
</form>
<!-- Vorschau Modal -->
<div class="modal fade" id="previewModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Vorschau der generierten Keys</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<p>Es werden <strong id="previewQuantity">10</strong> Lizenzen im folgenden Format generiert:</p>
<div class="bg-light p-3 rounded font-monospace" id="previewFormat">
AF-YYYYMMFT-XXXX-YYYY-ZZZZ
</div>
<p class="mt-3 mb-0">Die Keys werden automatisch eindeutig generiert und in der Datenbank gespeichert.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Schließen</button>
</div>
</div>
</div>
</div>
</div>
<script>
// Setze heutiges Datum als Standard
document.addEventListener('DOMContentLoaded', function() {
const today = new Date().toISOString().split('T')[0];
document.getElementById('validFrom').value = today;
// Setze valid_until auf 1 Jahr später
const oneYearLater = new Date();
oneYearLater.setFullYear(oneYearLater.getFullYear() + 1);
document.getElementById('validUntil').value = oneYearLater.toISOString().split('T')[0];
// Initialisiere Select2 für Kundenauswahl
$('#customerSelect').select2({
theme: 'bootstrap-5',
placeholder: '🔍 Kunde suchen oder neuen Kunden anlegen...',
allowClear: true,
ajax: {
url: '/api/customers',
dataType: 'json',
delay: 250,
data: function (params) {
return {
q: params.term,
page: params.page || 1
};
},
processResults: function (data, params) {
params.page = params.page || 1;
// "Neuer Kunde" Option immer oben anzeigen
const results = data.results || [];
if (params.page === 1) {
results.unshift({
id: 'new',
text: ' Neuer Kunde',
isNew: true
});
}
return {
results: results,
pagination: data.pagination
};
},
cache: true
},
minimumInputLength: 0,
language: {
inputTooShort: function() { return ''; },
noResults: function() { return 'Keine Kunden gefunden'; },
searching: function() { return 'Suche...'; },
loadingMore: function() { return 'Lade weitere Ergebnisse...'; }
}
});
// Event Handler für Kundenauswahl
$('#customerSelect').on('select2:select', function (e) {
const selectedValue = e.params.data.id;
const nameDiv = document.getElementById('customerNameDiv');
const emailDiv = document.getElementById('emailDiv');
const nameInput = document.getElementById('customerName');
const emailInput = document.getElementById('email');
if (selectedValue === 'new') {
// Zeige Eingabefelder für neuen Kunden
nameDiv.style.display = 'block';
emailDiv.style.display = 'block';
nameInput.required = true;
emailInput.required = true;
} else {
// Verstecke Eingabefelder bei bestehendem Kunden
nameDiv.style.display = 'none';
emailDiv.style.display = 'none';
nameInput.required = false;
emailInput.required = false;
nameInput.value = '';
emailInput.value = '';
}
});
// Clear handler
$('#customerSelect').on('select2:clear', function (e) {
document.getElementById('customerNameDiv').style.display = 'none';
document.getElementById('emailDiv').style.display = 'none';
document.getElementById('customerName').required = false;
document.getElementById('email').required = false;
});
});
// Vorschau-Funktion
function previewKeys() {
const quantity = document.getElementById('quantity').value;
const type = document.getElementById('licenseType').value;
const typeChar = type === 'full' ? 'F' : 'T';
const date = new Date();
const dateStr = date.getFullYear() + ('0' + (date.getMonth() + 1)).slice(-2);
document.getElementById('previewQuantity').textContent = quantity;
document.getElementById('previewFormat').textContent = `AF-${dateStr}${typeChar}-XXXX-YYYY-ZZZZ`;
const modal = new bootstrap.Modal(document.getElementById('previewModal'));
modal.show();
}
// Validierung
document.getElementById('quantity').addEventListener('input', function(e) {
if (e.target.value > 100) {
e.target.value = 100;
}
if (e.target.value < 1) {
e.target.value = 1;
}
});
</script>
{% endblock %}