ports beim erstellen des types erstellen
This commit is contained in:
@@ -44,10 +44,11 @@ if (!in_array($action, $validActions)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* =========================
|
/* =========================
|
||||||
* Template-Header laden
|
* Template-Header laden (nur für non-save Aktionen)
|
||||||
* ========================= */
|
* ========================= */
|
||||||
require_once __DIR__ . '/templates/header.php';
|
if ($action !== 'save') {
|
||||||
// TODO: ggf. Navigation einbinden
|
require_once __DIR__ . '/templates/header.php';
|
||||||
|
}
|
||||||
|
|
||||||
/* =========================
|
/* =========================
|
||||||
* Modul laden
|
* Modul laden
|
||||||
@@ -58,10 +59,14 @@ if (file_exists($modulePath)) {
|
|||||||
require_once $modulePath;
|
require_once $modulePath;
|
||||||
} else {
|
} else {
|
||||||
// TODO: Fehlerseite oder 404
|
// TODO: Fehlerseite oder 404
|
||||||
|
if ($action !== 'save') {
|
||||||
echo "<p>Die Seite existiert noch nicht.</p>".$modulePath;
|
echo "<p>Die Seite existiert noch nicht.</p>".$modulePath;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* =========================
|
/* =========================
|
||||||
* Template-Footer laden
|
* Template-Footer laden (nur für non-save Aktionen)
|
||||||
* ========================= */
|
* ========================= */
|
||||||
require_once __DIR__ . '/templates/footer.php';
|
if ($action !== 'save') {
|
||||||
|
require_once __DIR__ . '/templates/footer.php';
|
||||||
|
}
|
||||||
|
|||||||
@@ -74,6 +74,13 @@ $pageTitle = $isEdit ? "Gerätetyp bearbeiten: " . htmlspecialchars($deviceType[
|
|||||||
<textarea id="comment" name="comment" rows="3"
|
<textarea id="comment" name="comment" rows="3"
|
||||||
placeholder="z.B. Rack-Mount, 48 RJ45 + 4 SFP"><?php echo htmlspecialchars($deviceType['comment'] ?? ''); ?></textarea>
|
placeholder="z.B. Rack-Mount, 48 RJ45 + 4 SFP"><?php echo htmlspecialchars($deviceType['comment'] ?? ''); ?></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="seed_ports">Ports automatisch anlegen</label>
|
||||||
|
<input type="number" id="seed_ports" name="seed_ports" min="0" step="1"
|
||||||
|
value="<?php echo htmlspecialchars((int)($_POST['seed_ports'] ?? 0)); ?>"
|
||||||
|
placeholder="z.B. 48">
|
||||||
|
<small>Beim Speichern werden bis zu dieser Zahl Platzhalter-Ports erstellt, bestehende Einträge bleiben erhalten.</small>
|
||||||
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<!-- =========================
|
<!-- =========================
|
||||||
|
|||||||
@@ -60,6 +60,31 @@
|
|||||||
<!-- TODO: Import / Export -->
|
<!-- TODO: Import / Export -->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<form id="port-form" class="port-form" aria-hidden="true">
|
||||||
|
<div>
|
||||||
|
<label for="port-name">Portname</label>
|
||||||
|
<input id="port-name" name="name" required placeholder="z. B. Gi1/0/1">
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="port-type">Port-Typ</label>
|
||||||
|
<input id="port-type" name="type" required placeholder="RJ45, SFP …">
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="port-medium">Medium</label>
|
||||||
|
<input id="port-medium" name="medium" placeholder="Kupfer, LWL …">
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="port-mode">Modus</label>
|
||||||
|
<input id="port-mode" name="mode" placeholder="Access, Trunk …">
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="port-vlan">VLAN</label>
|
||||||
|
<input id="port-vlan" name="vlan" placeholder="10, 20-30 …">
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="button button-primary">Port hinzufügen</button>
|
||||||
|
<button type="button" class="button" id="cancel-port">Abbrechen</button>
|
||||||
|
</form>
|
||||||
|
|
||||||
<!-- =========================
|
<!-- =========================
|
||||||
Port-Liste
|
Port-Liste
|
||||||
========================= -->
|
========================= -->
|
||||||
@@ -76,7 +101,7 @@
|
|||||||
<th>Aktionen</th>
|
<th>Aktionen</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody id="port-list-body">
|
||||||
|
|
||||||
<?php /* foreach ($ports as $port): */ ?>
|
<?php /* foreach ($ports as $port): */ ?>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -142,14 +167,99 @@
|
|||||||
JS-Konfiguration
|
JS-Konfiguration
|
||||||
========================= -->
|
========================= -->
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.port-form {
|
||||||
|
display: none;
|
||||||
|
margin: 20px 0;
|
||||||
|
gap: 10px;
|
||||||
|
padding: 15px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 6px;
|
||||||
|
background: #f9f9f9;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||||||
|
grid-auto-rows: minmax(50px, auto);
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.port-form.visible {
|
||||||
|
display: grid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.port-form div {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.port-form label {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.port-form input {
|
||||||
|
padding: 6px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #bbb;
|
||||||
|
font-family: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.port-form button {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.port-form .button-primary {
|
||||||
|
justify-self: flex-start;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
const addPortButton = document.getElementById('add-port');
|
||||||
|
const portForm = document.getElementById('port-form');
|
||||||
|
const portListBody = document.getElementById('port-list-body');
|
||||||
|
const cancelPortButton = document.getElementById('cancel-port');
|
||||||
|
let portCounter = portListBody.querySelectorAll('tr').length + 1;
|
||||||
|
|
||||||
|
function showPortForm(show = true) {
|
||||||
|
portForm.classList.toggle('visible', show);
|
||||||
|
portForm.setAttribute('aria-hidden', show ? 'false' : 'true');
|
||||||
|
if (show) {
|
||||||
|
portForm.querySelector('input').focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addPortButton.addEventListener('click', (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
showPortForm(portForm.getAttribute('aria-hidden') === 'true');
|
||||||
|
});
|
||||||
|
|
||||||
|
cancelPortButton.addEventListener('click', () => {
|
||||||
|
showPortForm(false);
|
||||||
|
portForm.reset();
|
||||||
|
});
|
||||||
|
|
||||||
|
portForm.addEventListener('submit', (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
const data = new FormData(portForm);
|
||||||
|
const row = document.createElement('tr');
|
||||||
|
row.innerHTML = `
|
||||||
|
<td>${portCounter++}</td>
|
||||||
|
<td>${data.get('name') || '-'}</td>
|
||||||
|
<td>${data.get('type') || '-'}</td>
|
||||||
|
<td>${data.get('medium') || '-'}</td>
|
||||||
|
<td>${data.get('mode') || '-'}</td>
|
||||||
|
<td>${data.get('vlan') || '-'}</td>
|
||||||
|
<td>
|
||||||
|
<button type="button">Bearbeiten</button>
|
||||||
|
<button type="button">Löschen</button>
|
||||||
|
</td>
|
||||||
|
`;
|
||||||
|
portListBody.appendChild(row);
|
||||||
|
showPortForm(false);
|
||||||
|
portForm.reset();
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Konfiguration für svg-editor.js
|
* TODO: Replace this mock logic with real AJAX once ports are
|
||||||
|
* persisted on the backend.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// TODO: Gerätetyp-ID setzen
|
|
||||||
// window.DEVICE_TYPE_ID = <?= (int)$deviceTypeId ?>;
|
|
||||||
|
|
||||||
// TODO: Ports an JS übergeben
|
|
||||||
// window.DEVICE_TYPE_PORTS = <?= json_encode($ports) ?>;
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ $deviceTypeId = (int)($_POST['id'] ?? 0);
|
|||||||
$name = trim($_POST['name'] ?? '');
|
$name = trim($_POST['name'] ?? '');
|
||||||
$category = $_POST['category'] ?? 'other';
|
$category = $_POST['category'] ?? 'other';
|
||||||
$comment = trim($_POST['comment'] ?? '');
|
$comment = trim($_POST['comment'] ?? '');
|
||||||
|
$seedPortCount = max(0, (int)($_POST['seed_ports'] ?? 0));
|
||||||
|
|
||||||
// =========================
|
// =========================
|
||||||
// Validierung
|
// Validierung
|
||||||
@@ -46,6 +47,7 @@ if (!empty($errors)) {
|
|||||||
// Bild-Upload verarbeiten
|
// Bild-Upload verarbeiten
|
||||||
// =========================
|
// =========================
|
||||||
$imagePath = null;
|
$imagePath = null;
|
||||||
|
$imageType = null;
|
||||||
if (!empty($_FILES['image']['name'])) {
|
if (!empty($_FILES['image']['name'])) {
|
||||||
$file = $_FILES['image'];
|
$file = $_FILES['image'];
|
||||||
$tmpName = $file['tmp_name'];
|
$tmpName = $file['tmp_name'];
|
||||||
@@ -71,6 +73,7 @@ if (!empty($_FILES['image']['name'])) {
|
|||||||
|
|
||||||
if (move_uploaded_file($tmpName, $destPath)) {
|
if (move_uploaded_file($tmpName, $destPath)) {
|
||||||
$imagePath = 'uploads/device_types/' . $newFileName;
|
$imagePath = 'uploads/device_types/' . $newFileName;
|
||||||
|
$imageType = $fileExt === 'svg' ? 'svg' : 'bitmap';
|
||||||
} else {
|
} else {
|
||||||
$_SESSION['error'] = "Datei-Upload fehlgeschlagen";
|
$_SESSION['error'] = "Datei-Upload fehlgeschlagen";
|
||||||
header('Location: ?module=device_types&action=edit' . ($deviceTypeId ? "&id=$deviceTypeId" : ""));
|
header('Location: ?module=device_types&action=edit' . ($deviceTypeId ? "&id=$deviceTypeId" : ""));
|
||||||
@@ -83,22 +86,40 @@ if (!empty($_FILES['image']['name'])) {
|
|||||||
// =========================
|
// =========================
|
||||||
if ($deviceTypeId > 0) {
|
if ($deviceTypeId > 0) {
|
||||||
// UPDATE
|
// UPDATE
|
||||||
|
if ($imagePath) {
|
||||||
$sql->set(
|
$sql->set(
|
||||||
"UPDATE device_types SET name = ?, category = ?, comment = ?" . ($imagePath ? ", image_path = ?, image_type = ?" : "") . " WHERE id = ?",
|
"UPDATE device_types SET name = ?, category = ?, comment = ?, image_path = ?, image_type = ? WHERE id = ?",
|
||||||
$imagePath ? "sssss" : "sssi",
|
"sssisi",
|
||||||
$imagePath ? [$name, $category, $comment, $imagePath, $fileExt, $deviceTypeId] : [$name, $category, $comment, $deviceTypeId]
|
[$name, $category, $comment, $imagePath, $imageType, $deviceTypeId]
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
$sql->set(
|
||||||
|
"UPDATE device_types SET name = ?, category = ?, comment = ? WHERE id = ?",
|
||||||
|
"sssi",
|
||||||
|
[$name, $category, $comment, $deviceTypeId]
|
||||||
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// INSERT
|
// INSERT
|
||||||
$imageType = $imagePath ? $fileExt : null;
|
if ($imagePath) {
|
||||||
$sql->set(
|
$deviceTypeId = $sql->set(
|
||||||
"INSERT INTO device_types (name, category, comment, image_path, image_type) VALUES (?, ?, ?, ?, ?)",
|
"INSERT INTO device_types (name, category, comment, image_path, image_type) VALUES (?, ?, ?, ?, ?)",
|
||||||
"sssss",
|
"sssss",
|
||||||
[$name, $category, $comment, $imagePath, $imageType]
|
[$name, $category, $comment, $imagePath, $imageType],
|
||||||
|
true
|
||||||
);
|
);
|
||||||
$deviceTypeId = $sql->h->insert_id;
|
} else {
|
||||||
|
$deviceTypeId = $sql->set(
|
||||||
|
"INSERT INTO device_types (name, category, comment, image_path, image_type) VALUES (?, ?, ?, NULL, ?)",
|
||||||
|
"ssss",
|
||||||
|
[$name, $category, $comment, 'bitmap'],
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
seedDeviceTypePorts($sql, $deviceTypeId, $seedPortCount);
|
||||||
|
|
||||||
$_SESSION['success'] = $deviceTypeId ? "Gerätetyp gespeichert" : "Fehler beim Speichern";
|
$_SESSION['success'] = $deviceTypeId ? "Gerätetyp gespeichert" : "Fehler beim Speichern";
|
||||||
|
|
||||||
// =========================
|
// =========================
|
||||||
@@ -107,3 +128,28 @@ $_SESSION['success'] = $deviceTypeId ? "Gerätetyp gespeichert" : "Fehler beim S
|
|||||||
header('Location: ?module=device_types&action=list');
|
header('Location: ?module=device_types&action=list');
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
|
function seedDeviceTypePorts($sql, $deviceTypeId, $targetCount)
|
||||||
|
{
|
||||||
|
if ($deviceTypeId <= 0 || $targetCount <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = $sql->single(
|
||||||
|
"SELECT COUNT(*) AS count FROM device_type_ports WHERE device_type_id = ?",
|
||||||
|
"i",
|
||||||
|
[$deviceTypeId]
|
||||||
|
);
|
||||||
|
|
||||||
|
$existing = (int)($result['count'] ?? 0);
|
||||||
|
$toCreate = max(0, $targetCount - $existing);
|
||||||
|
|
||||||
|
for ($i = 1; $i <= $toCreate; $i++) {
|
||||||
|
$index = $existing + $i;
|
||||||
|
$sql->set(
|
||||||
|
"INSERT INTO device_type_ports (device_type_id, name, port_type_id, x, y) VALUES (?, ?, NULL, 0, 0)",
|
||||||
|
"is",
|
||||||
|
[$deviceTypeId, "Port $index"]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ if ($rackId > 0) {
|
|||||||
// INSERT
|
// INSERT
|
||||||
$sql->set(
|
$sql->set(
|
||||||
"INSERT INTO racks (name, floor_id, height_he, comment) VALUES (?, ?, ?, ?)",
|
"INSERT INTO racks (name, floor_id, height_he, comment) VALUES (?, ?, ?, ?)",
|
||||||
"sii s",
|
"siis",
|
||||||
[$name, $floorId, $heightHe, $comment]
|
[$name, $floorId, $heightHe, $comment]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,12 +43,12 @@
|
|||||||
|
|
||||||
<nav class="main-nav">
|
<nav class="main-nav">
|
||||||
<ul>
|
<ul>
|
||||||
<?php foreach ($navItems as $module => $label): ?>
|
<?php foreach ($navItems as $navModule => $label): ?>
|
||||||
<?php
|
<?php
|
||||||
$active = ($currentModule === $module) ? 'active' : '';
|
$active = ($currentModule === $navModule) ? 'active' : '';
|
||||||
?>
|
?>
|
||||||
<li class="<?= $active ?>">
|
<li class="<?= $active ?>">
|
||||||
<a href="?module=<?= $module ?>&action=list">
|
<a href="?module=<?= $navModule ?>&action=list">
|
||||||
<?= $label ?>
|
<?= $label ?>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -104,9 +104,6 @@ Ein Serverschrank oder Netzwerkschrank.
|
|||||||
- Befindet sich auf einem Stockwerk
|
- Befindet sich auf einem Stockwerk
|
||||||
- Enthält Geräte
|
- Enthält Geräte
|
||||||
|
|
||||||
**Wichtige Attribute**
|
|
||||||
- `height_he`: Gesamthöhe des Racks in Höheneinheiten (HE)
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 4. Gerätetypen & Geräte
|
## 4. Gerätetypen & Geräte
|
||||||
@@ -280,3 +277,4 @@ Das Schema ist vorbereitet für:
|
|||||||
- Design-Themes
|
- Design-Themes
|
||||||
|
|
||||||
Diese Funktionen sind bewusst **nicht Bestandteil der ersten Version**.
|
Diese Funktionen sind bewusst **nicht Bestandteil der ersten Version**.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user