Files
thetool/Layout/default/Device/Detail.php
2026-01-29 21:15:46 +01:00

1503 lines
80 KiB
PHP

<?php include(realpath(dirname(__FILE__) . "/../../$mfLayoutPackage") . "/header.php"); ?>
<link href="<?= self::getResourcePath() ?>assets/css/datatables-std.css" rel="stylesheet"
type="text/css"/>
<style>
.card-border {
border-left: 1px solid #428bca;
border-left-width: 5px;
border-radius: 3px;
}
.sp-table-border {
border: 1px solid #bfbfbf;
border-radius: 10px;
display: inline-block;
}
.sp-table-border > tbody {
padding: 10px;
display: table-cell;
}
.sp-table-border > thead td {
padding: 10px 0px 0px 0px;
font-weight: bold;
text-align: center;
font-size: 20px;
}
.sp-port-lines {
width: 50px;
border-bottom: 1px solid #bfbfbf;
padding-top: 22px;
}
#olt-splitter td {
height: 30px;
width: 150px;
border: 1px solid #bfbfbf;
margin-top: 15px;
display: block;
border-radius: 5px;
}
#olt-splitter-table thead {
padding: 10px 0px 0px 0px;
font-weight: bold;
font-size: 20px;
}
#olt-splitter-table thead td {
padding-top: 12px;
text-align: center;
}
.sp-splitter-count {
padding: 3px 10px 3px 10px;
width: 50px;
}
.sp-splitter-count-left {
padding: 3px 0px 3px 10px;
width: 50px;
}
.sp-splitter-count-right {
padding: 3px 10px 3px 0px;
width: 50px;
text-align: right;
}
.sp-splitter-count-edit {
-ms-user-select: None;
-moz-user-select: None;
-webkit-user-select: None;
user-select: None;
cursor: pointer;
}
.sp-splitter-count-show {
width: 46px;
display: inline-block;
text-align: center;
cursor: pointer;
text-decoration: underline;
padding-top: 2px;
-ms-user-select: None;
-moz-user-select: None;
-webkit-user-select: None;
user-select: None;
}
.sp-white-border {
border-color: #fff !important;
}
.sp-ont-text {
padding: 0px 5px 0px 5px;
}
.fa-circle-check {
color: #07ad2b;
}
.fa-circle-xmark {
color: #ff0000;
}
.fa-rotate-right {
color: #0d6efd;
cursor: pointer;
}
.ont-refresh-span, .ontdetail-refresh-span {
display: inline-block;
width: 20px;
margin-right: 50px;
min-height: 1px;
color: #0d6efd;
}
.text-decoration-underline {
text-decoration: underline;
cursor: pointer;
}
.condensed-ont th {
padding: 6px 0.85rem 6px 0.85rem !important;
}
.condensed-ont td {
padding: 6px 0.85rem 6px 0.85rem !important;
}
.fa-fileupload {
font-size: 28px;
color: #c76417;
margin-top: 4px;
cursor: pointer;
}
.form-label-upload {
margin-top: 10px;
}
.fa-backup-check {
font-size: 25px;
color: #25b343;
margin-left: 5px;
margin-top: 7px;
}
.fa-backup-check-uncheck {
color: #ff0000;
}
</style>
<!-- start page title -->
<div class="row">
<div class="col-12">
<div class="page-title-box">
<div class="page-title-right">
<ol class="breadcrumb m-0">
<li class="breadcrumb-item"><a href="<?= self::getUrl("Dashboard") ?>"><?= MFAPPNAME_SLUG ?></a>
</li>
<li class="breadcrumb-item"><a href="<?= self::getUrl("Device") ?>">Devices</a>
</li>
<li class="breadcrumb-item active">Device Detail</li>
</ol>
</div>
<h4 class="page-title">Device: <span class="font-weight-normal ml-1"><?= $devices->data->name ?></span>
<?php if ($me->is('Admin')) : ?>
<span class="ml-2">
<a href="<?= self::getUrl("Device", "edit", ["id" => $devices->id, 'returnto' => "device-detail"]) ?>">
<button class="btn btn-primary">Bearbeiten</button>
</a>
</span>
<?php endif; ?>
</h4>
</div>
</div>
</div>
<!-- end page title -->
<?php
if ($devices->price != "0.00") {
$price = $devices->price;
} else {
$price = $devices->devicetype->price;
}
if ($devices->power != "0.0") {
$power = $devices->power;
} else {
$power = $devices->devicetype->power;
}
foreach ($devicesall as $deviceall) {
$DevicesAll[$deviceall->id] = $deviceall->name;
}
?>
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-12 col-lg-5 card-border">
<div>
<h4>Allgemeine Informationen </h4>
</div>
<div>
<table class="table table-sm">
<tbody>
<tr>
<th class="w-30">Device Name</th>
<td><?= $devices->name ?> </td>
</tr>
<tr>
<th>IP-Adresse</th>
<td><?= $devices->ip ?> </td>
</tr>
<tr>
<th>Geräte Typ</th>
<td><?= $devices->devicetype->name ?> </td>
</tr>
<tr>
<th>Geräte Hersteller</th>
<td><?= $devices->devicetype->devicemanufactor->name ?> </td>
</tr>
<?php if ($devices->parent_id) : ?>
<tr>
<th>Parent Device</th>
<td>
<a href="<?= self::getUrl("Device", "Detail", ["id" => $devices->parent_id]) ?>"><?= $DevicesAll[$devices->parent_id] ?></a>
</td>
</tr>
<?php endif; ?>
<tr>
<th>Mac Adresse</th>
<td><?= $devices->mac ?> </td>
</tr>
<tr>
<th>Seriennummer</th>
<td><?= $devices->serial ?> </td>
</tr>
<tr>
<th>Preis</th>
<td><?= $price ?> €</td>
</tr>
<tr>
<th>Leistung</th>
<td><?= $power ?> Watt</td>
</tr>
<tr>
<th>Bemerkung</th>
<td><?= nl2br($devices->comment) ?> </td>
</tr>
</tbody>
</table>
</div>
</div>
<?php
if ((trim($devices->pop->name))) {
$StdHeader = "Pop Informationen";
$vlans = "";
if (!empty(trim($devices->pop->vlan_public)))
$vlans .= '<span class="order-date-pill active mb-0">Public: <span class="font-weight-500">' . $devices->pop->vlan_public . '</span class="font-weight-500"></span>';
if (!empty(trim($devices->pop->vlan_nat)))
$vlans .= '<span class="order-date-pill active mb-0">Nat: <span class="font-weight-500">' . $devices->pop->vlan_nat . '</span></span>';
if (!empty(trim($devices->pop->vlan_ipv6)))
$vlans .= '<span class="order-date-pill active mb-0">IPv6: <span class="font-weight-500">' . $devices->pop->vlan_ipv6 . '</span></span>';
} else if (trim($devices->addr_street)) {
if (trim($devices->addr_extended)) {
$addrExtended = ' / ' . $devices->addr_extended;
} else {
$addrExtended = "";
}
$StdHeader = "Standort Informationen";
$mapsHeader = "Adresse";
$mapsLink = '<a class="mapsLink"
href="http://maps.google.com/?q=' . $devices->addr_street . ' ' . $devices->addr_number . ' ' . $devices->addr_zip . ' ' . $devices->addr_city . '"
target="_blank"><div>' . $devices->addr_street . ' ' . $devices->addr_number . $addrExtended . '</div>
<div>' . $devices->addr_zip . ' ' . $devices->addr_city . '</div></a>';
} else if (trim($devices->gps_lat)) {
$StdHeader = "Standort Informationen";
$mapsHeader = "Koordinaten";
$mapsLink = '<a class="mapsLink"
href="http://maps.google.com/?q=' . $devices->gps_lat . ',' . $devices->gps_long . '"
target="_blank"><div>' . $devices->gps_lat . ' , ' . $devices->gps_long . '</div></a>';
}
?>
<div class="col-12 <?= ($me->is('Admin')) ? 'col-lg-4' : 'col-lg-7' ?> card-border">
<div>
<h4><?= $StdHeader ?></h4>
</div>
<?php
if ((trim($devices->pop->name))) {
?>
<div>
<table class="table table-sm">
<tbody>
<tr>
<th class="w-30">Pop Name</th>
<td>
<?= ($me->is('Admin')) ? '<a href="' . self::getUrl("Pop", "Detail", ["id" => $devices->pop->id]) . '">' . $devices->pop->name . '</a>' : $devices->pop->name ?>
</td>
</tr>
<tr>
<th>Adresse</th>
<td>
<a title="Google-Maps: <?= rtrim($devices->pop->gps_lat, '0') ?> , <?= $devices->pop->gps_long ?>"
class="mapsLink"
href="http://maps.google.com/?q=<?= $devices->pop->gps_lat ?> , <?= $devices->pop->gps_long ?>"
target="_blank"><?= rtrim($devices->pop->gps_lat, '0') ?>
, <?= rtrim($devices->pop->gps_long, 0) ?></a></td>
</tr>
<tr>
<th>Standort Info</th>
<td><?= nl2br($devices->pop->location) ?> </td>
</tr>
<tr>
<th>Access VLANs</th>
<td><?= $vlans ?> </td>
</tr>
</tbody>
</table>
</div>
<?php
} elseif (trim($devices->addr_street) || trim($devices->gps_lat)) {
?>
<div>
<table class="table table-sm">
<tbody>
<tr>
<th class="align-middle w-30"> <?= $mapsHeader ?></th>
<td>
<?= $mapsLink ?>
</td>
</tr>
<tr>
<td colspan="2"></td>
</tr>
</tbody>
</table>
</div>
<?php
} else {
?>
<h5 class="text-center">Keine Standort Informationen vorhanden</h5>
<?php
}
?>
</div>
<?php if ($me->is('Admin')) : ?>
<div class="col-12 col-lg-3 card-border">
<div class="overflow-auto">
<h4 class="float-left">Config Backups</h4>
<span><i class="fa-sharp fa-solid fa-arrows-spin fa-backup-check <?= ($devices->backup_check) ? '' : 'fa-backup-check-uncheck' ?>"
title=" <?= ($devices->backup_check) ? 'Backup Check aktiv' : 'Backup Check inaktiv' ?>"></i></span>
<?php if ($devices->devicetype->devicemanufactor->config_backup > 0): ?>
<span><i title="Switch config" class="fa-light fa-rectangle-code code-ico"
data-toggle="modal" data-target="#configCode"></i></span>
<?php endif;
?>
<?php
if ($me->is('Admin')):
?>
<div class="float-right">
<a id="create-backup-href"
href="<?= self::getUrl("Device", "api", ['do' => 'createconfig', 'ip' => $devices->ip, 'id' => $devices->id]) ?>"
<button class="btn btn-primary "><span id="create-backup-button-text">Backup erstellen</span>
<span id="create-backup-load"></i></span></button>
</a></div>
<span class="float-right mr-2"><i
class="fa-solid fa-cloud-arrow-up fa-fileupload"></i></span>
<?php endif; ?>
</div>
<div id="documents-upload" class="row mt-2 mb-2 justify-content-start"
style="display: none">
<div class="col-5 col-lg-4 text-center"><label
class="form-label form-label-upload">Backup Upload</label></div>
<div class="col-19 col-lg-8" id="attachments" data-newkey="">
<div class="input-group mb-2">
<div class="custom-file">
<input type="file" class="custom-file-input" id="files-input"
name="files[]"
multiple>
<label class="custom-file-label" for="files-input"
aria-describedby="">Datei(en)</label>
</div>
</div>
<div class="attachment-div mb-2"></div>
<div id="uploadsts"></div>
</div>
</div>
<?php
if ($devicesconfig->success == "true" && $devicesconfig->data) {
?>
<div>
<table class="table table-sm">
<thead>
<tr>
<th>Datum/Uhrzeit</th>
<th></th>
</tr>
</thead>
<tbody>
<?php foreach ($devicesconfig->data as $config) :
$configfileCleartext = trim($config->config_cleartext);
$configfileCleartextExtension = pathinfo($configfileCleartext, PATHINFO_EXTENSION);
if (empty($configfileCleartextExtension))
$configfileCleartextExtension = "txt";
$configfileCompressed = trim($config->config_compressed);
$configfileCompressedExtension = pathinfo($configfileCompressed, PATHINFO_EXTENSION);
$configid = $config->id;
if ($configfileCleartext && $configfileCompressed) :
$configLinks = '<a href="' . self::getUrl("Device", "api", ['do' => 'getconfig', 'id' => $configid, 'format' => 'txt', 'filename' => $configfileCleartext]) . '">
' . strtoupper($configfileCleartextExtension) . '</a> / <a href="' . self::getUrl("Device", "api", ['do' => 'getconfig', 'id' => $configid, 'format' => 'xml', 'filename' => $configfileCompressed]) . '">
' . strtoupper($configfileCompressedExtension) . '</a>';
elseif ($configfileCleartext || $configfileCompressed) :
$configLinks = '<a href="' . self::getUrl("Device", "api", ['do' => 'getconfig', 'id' => $configid, 'format' => 'txt', 'filename' => $configfileCleartext . $configfileCompressed]) . '">
' . strtoupper($configfileCleartextExtension) . '</a>';
endif;
?>
<tr>
<td><?= date("d.m.Y/H:i", $config->config_timestamp); ?></td>
<td><?= $configLinks; ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php
} else {
?>
<div class="mt-1">
<h5 class="text-center">Keine Configs vorhanden</h5>
</div>
<?php
}
?>
</div>
<?php
endif
?>
</div>
<?php
if ($devices->devicetype->olt && TT_MBI_API_ENABLE) :
?>
<button id="olt-info-button" class="btn btn-success d-none d-lg-block">OLT/ONT Infos</button>
<div class="spinner-big text-info" style="display:none">
<i class="fas fa-spinner fa-spin spinner-ico font-24 "></i>
</div>
<div id="olt-info" class="row pt-1 mt-1" style="border-top:1px dotted #428bca7d;display: none">
<div class="col-7 card-border">
<div class="row">
<div class="col-lg-4">
<h4>OLT/ONT Informationen </h4>
<h5><span id="olt-uptime"></span></h5>
</div>
<div id="service-ports-h4" class="col-lg-6" style="display:none">
<h4>Serviceports von <span style="width: 20px"
class="mr-4 ont-serviceport-refresh-span "><i
title="Refresh"
class="fa-solid fa-rotate-right ont-serviceport-refresh"></i></span>
</h4>
<h5><span id="olt-serviceports"></span></h5>
</div>
</div>
<div id="olt-body"></div>
</div>
<div id="olt-datatables" class="col-5 card-border" style="display: none">
<div>
<h4></h4>
</div>
<div>
<table style="font-size:12px;" id="datatable"
class="table table-striped table-hover table-sm">
<thead>
<tr>
<th>Port-ID</th>
<th>Kdnr.</th>
<th>Kunde</th>
<th class="text-center">Stat.</th>
<th class="text-center">Serial</th>
</tr>
<tr id="filterrow">
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
</div>
<div class="modal fade" id="ontDetailInfo" tabindex="-1" role="dialog"
aria-labelledby="ontDetailInfoLabel"
aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-xl" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="ontDetailInfoLabel">ONT Detail Information</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-6">
<h4>Allgemein<span class="ml-2"><i id="ont-detail-spinner"
class="fas fa-spinner fa-spin spinner-ico font-19 text-info"
style="display: none;"></i></span>
<span id="ont-detail-refresh" style="width: 20px;"
class="ontdetail-refresh-span"><i style="display: unset"
title="Refresh"
class="fa-solid fa-rotate-right "></i></span>
</h4>
<table class="table condensed-ont ">
<tr>
<th>Status</th>
<td class="text-right pr-3 ont-line-stat"
id="ont-detail-status">N/A
</td>
</tr>
<tr>
<th>Kdnr./Kunde</th>
<td class="text-right pr-3 ont-line-stat"
id="ont-detail-kd">N/A
</td>
</tr>
<tr>
<th>ONT Typ</th>
<td class="text-right pr-3 ont-line-stat"
id="ont-detail-ontequip">N/A
</td>
</tr>
<tr>
<th>Seriennummer</th>
<td class="text-right pr-3 ont-line-stat"
id="ont-detail-serial">N/A
</td>
</tr>
<tr>
<th>Lineprofile / Srvprofile</th>
<td class="text-right pr-3"><span class="ont-line-stat"
id="ont-detail-lineprofile">N/A</span>
/ <span class="ont-line-stat"
id="ont-detail-serviceeprofile">N/A</span></td>
</tr>
<tr>
<th>Version/Software Version</th>
<td class="text-right pr-3"><span class="ont-line-stat"
id="ont-detail-ontversion">N/A</span>
/ <span class="ont-line-stat"
id="ont-detail-ontsoftwarever">N/A</span></td>
</tr>
<tr>
<th>RX-Pegel OLT</th>
<td class="text-right pr-3"><span class="ont-line-stat"
id="ont-detail-rxolt">N/A</span>
dBm
</td>
</tr>
<tr>
<th>RX/TX ONT</th>
<td class="text-right pr-3"><span id="ont-detail-rx"
class="ont-line-stat">N/A</span>
dBm / <span class="ont-line-stat"
id="ont-detail-tx">N/A</span> dBm
</td>
</tr>
<tr>
<th>Leitungslänge</th>
<td class="text-right pr-3"><span id="ont-detail-len"
class="ont-line-stat">N/A</span>
Meter
</td>
</tr>
<tr>
<th>Uptime</th>
<td class="text-right pr-3 ont-line-stat"
id="ont-detail-uptime">N/A
</td>
</tr>
<tr>
<th>Zuletzt Up</th>
<td class="text-right pr-3 ont-line-stat"
id="ont-detail-lastonline">N/A
</td>
</tr>
<tr>
<th>Zuletzt Down</th>
<td class="text-right pr-3 ">
<span id="ont-detail-lastofflinecause" class="ont-line-stat"
data-toggle="tooltip"
data-placement="top"
title=""></span>
<span class="ml-3 ont-line-stat"
id="ont-detail-lastoffline">N/A</span>
</td>
</tr>
<tr>
<th>Letzter Dying Gasp</th>
<td class="text-right pr-3 ont-line-stat"
id="ont-detail-lastdying">N/A
</td>
</tr>
</table>
</div>
<div class="col-6">
<h4>CPE Port</h4>
<table class="table table-condensed">
<thead>
<tr>
<th class="text-center">Port ID</th>
<th class="text-center">Port Status</th>
<th class="text-center">Port Typ</th>
<th class="text-center">Speed</th>
<th class="text-center">Duplex</th>
</tr>
</thead>
<tbody>
<tr>
<td class="ont-line-stat text-center"
id="ont-detail-ethid"></td>
<td class="ont-line-stat text-center" id="ont-detail-eth"></td>
<td class="ont-line-stat text-center"
id="ont-detail-ethporttype"></td>
<td class="ont-line-stat text-center"
id="ont-detail-ethspeed"></td>
<td class="ont-line-stat text-center"
id="ont-detail-ethdpx"></td>
</tr>
</tbody>
</table>
<h4>MAC-Adressen<span class="ml-2"><i id="ont-detail-mac-spinner"
class="fas fa-spinner fa-spin spinner-ico font-19 text-info"
style="display: none;"></i></span>
<span id="ont-detail-mac-refresh" style="width: 20px;"
class="ontdetail-refresh-span"><i style="display: unset"
title="Refresh"
class="fa-solid fa-rotate-right "></i></span>
</h4>
<table class="table condensed-ont">
<thead id="ont-macadresses-head">
</thead>
<tbody id="ont-macadresses">
</tbody>
</table>
<h4>Service Ports</h4>
<table class="table condensed-ont">
<thead>
<tr>
<th>Vlan CPE</th>
<th>Vlan NNI</th>
<th>Status</th>
<th>Downstream</th>
<th>Upstream</th>
</tr>
</thead>
<tbody id="ont-serviceports">
</tbody>
</table>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Schließen
</button>
</div>
</div>
</div>
</div>
<?php
endif;
?>
</div>
</div>
</div>
</div>
<?php if ($devices->devicetype->devicemanufactor->config_backup):
$year = date("Y", time());
$month = date("n", time());
$day = date("d", time());
$config = $devices->devicetype->devicemanufactor->config_backup;
$config = str_replace("&&YEAR&&", $year, $config);
$config = str_replace("&&MONTH&&", $month, $config);
$config = str_replace("&&DAY&&", $day, $config);
$config = str_replace("&&IP&&", $devices->ip, $config);
?>
<div class="modal fade" id="configCode" tabindex="-1" role="dialog" aria-labelledby="configCodeLabel"
aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="configCodeLabel">SwitchConfig Autobackup</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<?= nl2br($config) ?>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Schließen</button>
</div>
</div>
</div>
</div>
<?php endif; ?>
<script type="text/javascript">
const customers =<?php echo json_encode($customer); ?>;
function uploadajax(totalFiles, currentIndex) {
let fileList = $('#files-input').prop("files");
let form_data = new FormData();
form_data.append("files[]", fileList[currentIndex]);
if ($('.fa-folder-open').data('id')) {
form_data.append("folder_id", $('.fa-folder-open').data('id'));
}
$.ajax({
url: '<?= self::getUrl("Device", "api", ['do' => 'uploadFile', 'id' => $devices->id]) ?>',
cache: false,
contentType: false,
processData: false,
async: true,
data: form_data,
type: 'POST',
xhr: function () {
let xhr = $.ajaxSettings.xhr();
if (xhr.upload) {
xhr.upload.addEventListener('progress', function (event) {
let percent = 0;
if (event.lengthComputable) {
percent = Math.ceil(event.loaded / event.total * 100);
}
$('.pb-' + currentIndex).css('width', percent + '%')
.attr('aria-valuenow', percent);
}, false);
}
return xhr;
},
success: function (res, status) {
$('.pb-' + currentIndex).closest('.progress').remove();
if (currentIndex < totalFiles - 1) {
uploadajax(totalFiles, currentIndex + 1);
} else {
window.location.reload();
}
},
error: function (res) {
alert('Upload fehlgeschlagen.');
}
});
}
function formatFileSize(bytes) {
if (bytes >= 1024 * 1024) {
const megabytes = bytes / (1024 * 1024);
return megabytes.toFixed(2) + ' MB';
} else if (bytes >= 1024) {
const kilobytes = bytes / 1024;
return kilobytes.toFixed(2) + ' KB';
} else {
return Math.round(bytes) + ' Bytes'; // Keine Nachkommastellen
}
}
$(document).ready(function () {
$('#create-backup-href').click(function () {
$('#create-backup-load').html('<i class="fas fa-spinner fa-spin spinner-ico text-info"></i>');
$('#create-backup-button-text').text('Backup wird erstellt.')
});
$("body").on("click", "#olt-info-button", function () {
$('.spinner-big').show();
$('#olt-info-button').remove();
$.getJSON("<?= self::getUrl("Device", "api", ['do' => 'getoltinfo', 'ip' => $devices->ip]) ?>", {})
.done(function (data) {
if (data.success == false) {
$('#olt-body').text('Keine OLT/ONT Daten verfügbar');
} else {
$('#service-ports-h4').show();
$('#olt-body').append(`<div >
<table class="sp-table-border float-left" >
<thead><tr><td>OLT</td></tr></thead>
<tbody id="olt-table"></tbody></table>
<table id="olt-port-table" class="float-left" >
<thead><tr><td style="height: 30px;"></td></tr></thead>
<tbody id="olt-ports"></tbody></table>
<table id="olt-splitter-table" class=" float-left" >
<thead><tr><td>Splitter</td></tr></thead>
<tbody id="olt-splitter"></tbody></table>
</div>`);
var datacounter = 1;
let customername;
let customerid;
$('#olt-uptime').html("(<b>Uptime:</b> " + data.data.olt.uptime + ")")
$.each(data.data.ports, function (i, item) {
$('#olt-table').append('<tr><td class="p-2">' + item['port'] + '</td></tr>');
$('#olt-ports').append('<tr><td data-oltport=' + i + ' class="sp-port-lines" ">&nbsp;</td></tr>');
if (typeof (item['ont']) === "object") {
var online = 0;
var offline = 0;
var allonts = 0;
$.each(item['ont'], function (o, ont) {
var status;
if (ont.status == "1") {
online++;
status = '<i class="fa-regular fa-circle-check"></i>';
} else if (ont.status == "2") {
offline++;
status = '<i class="fa-regular fa-circle-xmark"></i></i>'
}
allonts++;
if (typeof customers[ont['serial']] !== "undefined") {
customerid = customers[ont['serial']]['customer_number'];
if (customerid == "" || customerid == null) {
customerid = "N/A";
}
if (customers[ont['serial']]['company'] != "" && customers[ont['serial']]['company'] != null) {
customername = "" + customers[ont['serial']]['company'] + " (C)";
} else if (customers[ont['serial']]['lastname'] != "" && customers[ont['serial']]['lastname'] != null) {
customername = customers[ont['serial']]['lastname'] + " " + customers[ont['serial']]['firstname'];
} else if (customers[ont['serial']]['TerminationContact'] != "" && customers[ont['serial']]['TerminationContact'] != null) {
customername = customers[ont['serial']]['TerminationContact'];
} else if (customers[ont['serial']]['BuildingContact'] != "" && customers[ont['serial']]['BuildingContact'] != null) {
customername = customers[ont['serial']]['BuildingContact'];
} else if (customers[ont['serial']]['lastname'] == null) {
}
customername += '&nbsp;<br>' + customers[ont['serial']]['street'] + ", " + customers[ont['serial']]['zip'] + " " + customers[ont['serial']]['city']
} else {
customername = "N/A";
customerid = "N/A";
}
let orderPort = item['portshort'] + `/` + ont.id;
let parts = orderPort.split('/');
let formattedParts = parts.map(num => {
let number = parseInt(num, 10);
return number.toString().padStart(2, '0');
});
orderPort = formattedParts.join('');
$('#datatable tbody').append(`
<tr>
<td class="sp-ont-text" data-order="` + orderPort + `">` + item['portshort'] + `/` + ont.id + `</td>
<td class="sp-ont-text">` + customerid + `</td>
<td class="sp-ont-text">` + customername + `</td>
<td class="sp-ont-text text-center">` + status + `</td>
<td class="sp-ont-text"><div class="text-decoration-underline" data-port="` + item['portsimple'] + `" data-ontid="` + ont.id + `" data-portid="` + item['portindex'] + `" data-snr="` + ont['serial'] + `" data-toggle="modal" data-target="#ontDetailInfo">` + ont['serial'] + `</div></td>
</tr>
`);
}
)
;
$('#olt-splitter').append('<tr><td class=""><span title="Doppelklick zum editieren" data-portid="' + item['portindex'] + '" class="float-left sp-splitter-count-left ">' + allonts + '</span><span data-shown="0" data-port="' + item['portsimple'] + '" data-portid="' + item['portindex'] + '" data-splitcounter="' + datacounter + '" data-oltport=' + i + ' class="sp-splitter-count-show">show</span><span class="float-right sp-splitter-count-right"><span style="color: green">' + online + '</span>/<span style="color: red">' + offline + '</span></span></td></tr>');
} else {
$('#olt-splitter').append('<tr><td class=""><span title="Doppelklick zum editieren" data-portid="' + item['portindex'] + '" class="float-left sp-splitter-count-left ">N/A</span><span class="float-right sp-splitter-count-right">N/A</span></td></tr>');
}
datacounter++;
}
)
;
$('#olt-datatables').show();
}
$('.spinner-big').hide();
$('#olt-info').show();
}
).done(function (data) {
var hidesearch = [3];
let table;
if (typeof hidesearch === "undefined") {
var hidesearch;
hidesearch = [100];
}
if (typeof cstmdom === "undefined") {
var cstmdom;
cstmdom = "flBrtip";
}
if (typeof columndefs === "undefined") {
var columndefs;
columndefs = "";
}
$('#filterrow th').each(function (i) {
let title = $('#datatable thead th').eq($(this).index()).text();
if (hidesearch.includes($(this).index())) {
} else {
$(this).html('<input type="text" placeholder="' + title + '" class="form-control" data-index="' + i + '" value="" />');
}
});
table = $('#datatable').DataTable({
buttons: [
{
extend: 'excelHtml5',
text: 'XLSX Export',
className: 'btn-success margina'
}
], columnDefs: [
columndefs
],
"language": {
"url": "/datatables/json/german.json"
},
orderCellsTop: true,
stateSave: true,
"initComplete": function () {
$('#datatable_filter').append('<i id="clear_cookie" class="fas fa-times clear-fa" title="Filter löschen" aria-hidden="true" ></i>');
$('#clear_cookie').click(function () {
$('input').val('');
table.search('').columns().search('').draw();
});
},
"dom": cstmdom
});
$('#filterrow').on('keyup', 'input', function () {
table
.column($(this).data('index'))
.search(this.value)
.draw();
});
let state = table.state.loaded();
if (state) {
table.columns().eq(0).each(function (colIdx) {
var colSearch = state.columns[colIdx].search;
if (colSearch.search) {
$('#filterrow').find("[data-index='" + colIdx + "']").val(colSearch.search);
}
});
table.draw();
}
const apiUrl = "<?= self::getUrl('Device', 'api', ['do' => 'deviceoltserviceporttimestamp', 'ip' => $devices->ip]) ?>";
// Funktion, die die Daten holt und ins DOM schreibt
function updateTimestamp(firstCall = 0) {
$.getJSON(apiUrl)
.done(function(data) {
$('#olt-serviceports').text('(' + data.data.timestamp + ')');
})
.fail(function(jqxhr, textStatus, error) {
console.error('Error fetching timestamp:', textStatus, error);
});
}
// Erstaufruf direkt beim Laden der Seite
updateTimestamp(1);
// Dann alle 30 000 ms (30 Sekunden) wiederholen
setInterval(updateTimestamp, 5000);
}).fail(function (jqxhr, textStatus, error) {
window.location.href = "Dashboard";
console.log("Request Failed: " + err);
});
});
$("body").on("dblclick", ".sp-splitter-count-edit", function () {
var oldval = $(this).text();
var select8;
var select16;
var select32;
if (oldval == "8") {
select8 = 'selected="selected"';
} else if (oldval == "16") {
select16 = 'selected="selected"';
} else if (oldval == "32") {
select32 = 'selected="selected"';
}
$(this).html(`<SELECT id="change-splitter-ports" class="">
<option value="0">N/A</option>
<option ` + select8 + ` value="8">8</option>
<option ` + select16 + ` value="16">16</option>
<option ` + select32 + ` value="32">32</option>
`);
$("#change-splitter-ports").trigger("focus");
});
$("body").on("blur", "#change-splitter-ports", function () {
var portid = $(this).closest('span').data('portid');
$.getJSON("<?= self::getUrl("Device", "api", ['do' => 'changeoltsplitter', 'id' => $devices->id]) ?>&portid=" + portid + "&ports=" + $(this).val(), {})
.done(function (data) {
});
$(this).closest('span').text($('option:selected', this).text());
});
$("body").on("click", ".ont-serviceport-refresh", function () {
if ($(this).hasClass('noclick')) {
return;
}
$('.ont-serviceport-refresh').addClass('noclick');
$('.ont-serviceport-refresh-span').html('<i class="fas fa-spinner fa-spin spinner-ico text-info"></i>');
$.getJSON("<?= self::getUrl("Device", "api", ['do' => 'deviceoltserviceportrefresh', 'ip' => $devices->ip]) ?>", {})
.done(function (data) {
setTimeout(function () {
$('.spinner-border').remove();
$('.ont-serviceport-refresh').removeClass('noclick');
$('.ont-serviceport-refresh-span').html(
'<i title="Refresh" class="fa-solid fa-rotate-right ont-serviceport-refresh"></i>'
);
}, 5000);
});
});
$("body").on("click", ".sp-splitter-count-show", function () {
if ($(this).hasClass('noclick')) {
return;
}
var thisspan = $(this);
$('#ont-line-table').remove();
$('#ont-table').remove();
$('.sp-splitter-count-show').text('show');
if ($(this).data('shown') == "1") {
$('.sp-splitter-count-show').each(function (index) {
$(this).data('shown', '0');
});
} else if ($(this).data('shown') == "0") {
$('.sp-splitter-count-show').addClass('noclick');
$(this).html('<i class="fas fa-spinner fa-spin spinner-ico text-info"></i>');
$(this).data('shown', '1');
var oltport = $(this).data('oltport');
$('#olt-body').append(`<table style="display:none;" id="ont-line-table" data-oltport="` + $(this).data('oltport') + `" class="float-left">` + $('#olt-port-table').html() + `</table>`);
$("#ont-line-table .sp-port-lines").each(function (index) {
if (oltport != $(this).data('oltport')) {
$(this).addClass('sp-white-border');
}
});
$('#olt-body').append(` <table id="ont-table" data-portid="` + thisspan.data('portid') + `" style="text-align: center; display:none ; min-height: 500px;" class="sp-table-border float-left" >
<thead>
<tr><td><span class="ml-5">ONT's </span><span style="width: 20px;" class="float-right mr-4 ont-refresh-span "><i title="Refresh" class="fa-solid fa-rotate-right ont-refresh" ></i></span></td></tr>
</thead>
<tbody style="font-size:13px;" id="ont-table-body">
<tr>
<th class="sp-ont-text">ONT ID</th>
<th class="sp-ont-text" title="Online Status">Stat.</th>
<th class="sp-ont-text">Type</th>
<th class="sp-ont-text">Serial</th>
<th class="sp-ont-text">Distance</th>
<th class="sp-ont-text">Eth</th>
<th class="sp-ont-text">Eth Spd/Dpx</th>
</tr>
</tbody></table>`);
$.getJSON("<?= self::getUrl("Device", "api", ['do' => 'getoltinfo', 'ip' => $devices->ip]) ?>&portid=" + thisspan.data('portid'), {})
.done(function (data) {
if (typeof data.success === 'undefined') {
console.log('logged out');
// window.location.href = "/";
}
$.each(data.data[0]['ont'], function (o, ont) {
var status;
if (ont.status == "1") {
status = '<i class="fa-regular fa-circle-check"></i>';
} else {
status = '<i class="fa-regular fa-circle-xmark"></i></i>'
}
$('#ont-table-body').append(`<tr>
<td class="sp-ont-text">` + ont.id + `</td>
<td class="sp-ont-text">` + status + `</td>
<td class="sp-ont-text text-center ont-equip"><i class="fas fa-spinner fa-spin spinner-ico text-info"></i></td>
<td class="sp-ont-text"><div class="text-decoration-underline" data-port="` + thisspan.data('port') + `" data-ontid="` + ont.id + `" data-portid="` + thisspan.data('portid') + `" data-snr=` + ont['serial'] + ` data-toggle="modal" data-target="#ontDetailInfo">` + ont['serial'] + `</div></td>
<td class="sp-ont-text text-right">` + ont['len'] + ` (m)</td>
<!-- <td class="sp-ont-text text-center ont-rxtx"><i class="fas fa-spinner fa-spin spinner-ico text-info"></i></td>-->
<td class="sp-ont-text text-center ont-eth"><i class="fas fa-spinner fa-spin spinner-ico text-info"></i></td>
<td class="sp-ont-text text-center"><span class="ont-ethspeed"><i class="fas fa-spinner fa-spin spinner-ico text-info"></i></span>&nbsp;<span class="ont-ethdpx"></span></td>
</tr>`);
});
var onttablecount = Math.round($('#ont-table').height());
var heightcount = thisspan.data('splitcounter') * 45 - onttablecount / 2;
var maxheighcount = $('#ont-line-table').height();
if (heightcount < 0) {
heightcount = 0;
} else if (heightcount > maxheighcount - onttablecount) {
heightcount = maxheighcount - onttablecount + 30;
}
$('#ont-table').css('margin-top', heightcount + "px");
$('#ont-table').show();
$('#ont-line-table').show();
$('.spinner-border').remove();
thisspan.text('hide');
$('.sp-splitter-count-show').removeClass('noclick');
}).done(function (data) {
$.getJSON("<?= self::getUrl("Device", "api", ['do' => 'getoltinfo', 'ip' => $devices->ip]) ?>&portid=" + thisspan.data('portid') + "&adv=ext", {}).done(function (data) {
if (typeof data.success === 'undefined') {
console.log('logged out');
// window.location.href = "/";
}
if (thisspan.data('portid') == $('#ont-table').data('portid')) {
var countont=0;
$.each(data.data, function (o, ont) {
var eth = ont['eth'];
var rx = (ont['rx'] - 10000) / 100;
var rxdez = rx.toFixed(2);
if (rxdez > 10000) {
rxdez = "N/A";
}
var tx = ont['tx'] / 100;
var txdez = tx.toFixed(2);
if (txdez > 10000) {
txdez = "N/A";
}
if (ont['eth'] == "1") {
eth = '<i class="fa-regular fa-circle-check"></i>';
} else {
eth = '<i class="fa-regular fa-circle-xmark"></i></i>'
}
console.log(countont);
$('#ont-table .ont-eth').eq(countont).html(eth);
$('#ont-table .ont-ethspeed').eq(countont).html(ont['ethspeed']);
$('#ont-table .ont-ethdpx').eq(countont).html(ont['ethdpx']);
$('#ont-table .ont-rxtx').eq(countont).text(rxdez + "/" + txdez);
$('#ont-table .ont-equip').eq(countont).text(ont['equip']);
countont++;
});
}
$('.ont-refresh').show();
});
}).fail(function (jqxhr, textStatus, error) {
window.location.href = "Dashboard";
console.log("Request Failed: " + err);
});
}
});
$("body").on("click", ".ont-refresh", function () {
var thisspan = $(this).closest('table');
$('.ont-refresh-span').html('<i class="fas fa-spinner fa-spin spinner-ico text-info"></i>');
$('.sp-splitter-count-show').addClass('noclick');
$.getJSON("<?= self::getUrl("Device", "api", ['do' => 'getoltinfo', 'ip' => $devices->ip]) ?>&ip=<?= $devices->ip; ?>&portid=" + thisspan.data('portid') + "&adv=ext", {}).done(function (data) {
if (thisspan.data('portid') == $('#ont-table').data('portid')) {
$.each(data.data, function (o, ont) {
var eth = ont['eth'];
var rx = (ont['rx'] - 10000) / 100;
var rxdez = rx.toFixed(2);
if (rxdez > 10000) {
rxdez = "N/A";
}
var tx = ont['tx'] / 100;
var txdez = tx.toFixed(2);
if (txdez > 10000) {
txdez = "N/A";
}
if (ont['eth'] == "1") {
eth = '<i class="fa-regular fa-circle-check"></i>';
} else {
eth = '<i class="fa-regular fa-circle-xmark"></i></i>'
}
$('#ont-table .ont-eth').eq(o).html(eth);
$('#ont-table .ont-ethspeed').eq(o).html(ont['ethspeed']);
$('#ont-table .ont-ethdpx').eq(o).html(ont['ethdpx']);
$('#ont-table .ont-rxtx').eq(o).text(rxdez + "/" + txdez);
$('#ont-table .ont-equip').eq(o).text(ont['equip']);
});
}
$('.ont-refresh-span').html('<i title="Refresh" class="fa-solid fa-rotate-right ont-refresh"></i>');
$('.ont-refresh').show();
$('.sp-splitter-count-show').removeClass('noclick');
}).fail(function (jqxhr, textStatus, error) {
window.location.href = "Dashboard";
console.log("Request Failed: " + err);
});
;
});
$('#ontDetailInfo').on('show.bs.modal', function (event) {
let customername;
let customerid;
var button = $(event.relatedTarget) // Button that triggered the modal
var portid = button.closest('table').data('portid');
if (typeof customers[button.data('snr')] !== "undefined") {
customerid = customers[button.data('snr')]['customer_number'];
if (customers[button.data('snr')]['company'] != "" && customers[button.data('snr')]['company'] != null) {
customername = "" + customers[button.data('snr')]['company'] + " (C)";
} else if (customers[button.data('snr')]['lastname'] != "" && customers[button.data('snr')]['lastname'] != null) {
customername = customers[button.data('snr')]['lastname'] + " " + customers[button.data('snr')]['firstname'];
} else if (customers[button.data('snr')]['TerminationContact'] != "" && customers[button.data('snr')]['TerminationContact'] != null) {
customername = customers[button.data('snr')]['TerminationContact'];
} else if (customers[button.data('snr')]['BuildingContact'] != "" && customers[button.data('snr')]['BuildingContact'] != null) {
customername = customers[button.data('snr')]['BuildingContact'];
} else if (customers[button.data('snr')]['lastname'] == null) {
}
customername += '<br>' + customers[button.data('snr')]['street'] + ", " + customers[button.data('snr')]['zip'] + " " + customers[button.data('snr')]['city']
if (customerid != "" && customerid != null) {
customername = customerid + " / " + customername;
} else {
}
} else {
customername = "N/A";
customerid = "N/A";
}
$('#ont-macadresses').empty();
$('.ont-line-stat').text('N/A');
$('#ont-detail-kd').html(customername);
$('#ont-detail-lastofflinecause').attr('data-original-title', '');
$('#ont-detail-spinner').show();
$('#ont-detail-refresh').hide();
$('#ont-serviceports').empty();
$('#ont-detail-refresh').data('portid', button.data('portid'));
$('#ont-detail-refresh').data('port', button.data('port'));
$('#ont-detail-refresh').data('ontid', button.data('ontid'));
$('#ont-detail-refresh').data('snr', button.data('snr'));
$('#ont-detail-mac-refresh').data('snr', button.data('snr'));
$('#ont-detail-mac-refresh').data('portid', button.data('portid'));
$('#ont-detail-mac-refresh').data('port', button.data('port'));
$('#ont-detail-mac-refresh').data('ontid', button.data('ontid'));
$('#ont-detail-mac-refresh').data('snr', button.data('snr'));
$.getJSON("<?= self::getUrl("Device", "api", ['do' => 'getontinfo', 'ip' => $devices->ip]) ?>&portid=" + button.data('portid') + "&ont=" + button.data('port') + '-' + button.data('ontid'), {}).done(function (data) {
$.each(data.data.linestat, function (o, ont) {
if (o == "lastofflinecausetitle") {
$('#ont-detail-lastofflinecause').attr('data-original-title', ont);
} else {
$('#ont-detail-' + o).text(ont);
}
});
if (typeof data.data.serviceports === 'undefined') {
$('#ont-serviceports').append(`
<tr>
<td class="text-center" colspan="5">Keine Serviceports definiert.</td>
</tr>
`)
} else {
$.each(data.data.serviceports, function (o, ont) {
var operstatus;
if (ont.operstatus == "1") {
operstatus = "<span style='color:green'>UP</span>";
} else {
operstatus = "<span style='color:red'>Down</span>";
}
$('#ont-serviceports').append(`
<tr>
<td class="text-center">` + ont.vlanmap + `</td>
<td class="text-center">` + ont.vlan + `</td>
<td class="text-center">` + operstatus + `</td>
<td class="text-center">` + ont.traficdescrx + `</td>
<td class="text-center">` + ont.traficdesctx + `</td>
</tr>
`)
});
}
$('#ont-detail-spinner').hide();
$('#ont-detail-refresh').show();
}).fail(function (jqxhr, textStatus, error) {
window.location.href = "Dashboard";
console.log("Request Failed: " + err);
});
;
});
$("body").on("click", "#ont-detail-mac-refresh", function () {
$('#ont-detail-mac-spinner').show();
$('#ont-detail-mac-refresh').hide();
var button = $('#ont-detail-mac-refresh');
$('#ont-macadresses').empty();
$('#ont-macadresses-nomac').remove();
$.getJSON("<?= self::getUrl("Device", "api", ['do' => 'getontinfomac', 'ip' => $devices->ip]) ?>&portid=" + button.data('portid') + "&ont=" + button.data('port') + '-' + button.data('ontid'), {}).done(function (data) {
if (typeof data.data !== 'undefined' && data.data.length > 0) {
$('#ont-macadresses').html(`
<tr>
<th>Mac</th>
<th>Vlan</th>
</tr>
`);
$.each(data.data, function (o, mac) {
$('#ont-macadresses').append(`<tr>
<td>` + mac.mac + `</td>
<td>` + mac.vlan + `</td>
</tr>`);
});
} else {
$('#ont-macadresses').append(`<tr>
<td id="ont-macadresses-nomac" class="text-center" colspan="2">Keine Mac-Adressen verfügbar</td>
</tr>`);
}
$('#ont-detail-mac-spinner').hide();
$('#ont-detail-mac-refresh').show();
}).fail(function (jqxhr, textStatus, error) {
window.location.href = "Dashboard";
});
;
});
$("body").on("click", "#ont-detail-refresh", function () {
let customername;
let customerid;
var button = $(this);
var portid = button.closest('table').data('portid');
if (typeof customers[button.data('snr')] !== "undefined") {
customerid = customers[button.data('snr')]['customer_number'];
if (customers[button.data('snr')]['lastname'] != "" && customers[button.data('snr')]['lastname'] != null) {
customername = customerid + " / " + customers[button.data('snr')]['lastname'] + " " + customers[button.data('snr')]['firstname'];
} else if (customers[button.data('snr')]['lastname'] == null) {
customername = customers[button.data('snr')]['street'] + ", " + customers[button.data('snr')]['zip'] + " " + customers[button.data('snr')]['city'];
} else {
customername = customerid + " / " + customers[button.data('snr')]['company'] + " (C)";
}
} else {
customername = "N/A";
customerid = "N/A";
}
$('.ont-line-stat').text('N/A');
$('#ont-detail-kd').text(customername);
$('#ont-detail-lastofflinecause').attr('data-original-title', '');
$('#ont-macadresses').empty();
$('#ont-detail-spinner').show();
$('#ont-detail-refresh').hide();
$('#ont-serviceports').empty();
$('#ont-detail-refresh').data('portid', button.data('portid'));
$('#ont-detail-refresh').data('port', button.data('port'));
$('#ont-detail-refresh').data('ontid', button.data('ontid'));
$.getJSON("<?= self::getUrl("Device", "api", ['do' => 'getontinfo', 'ip' => $devices->ip]) ?>&portid=" + button.data('portid') + "&ont=" + button.data('port') + '-' + button.data('ontid'), {}).done(function (data) {
$.each(data.data.linestat, function (o, ont) {
if (o == "lastofflinecausetitle") {
$('#ont-detail-lastofflinecause').attr('data-original-title', ont);
} else {
$('#ont-detail-' + o).text(ont);
}
});
if (typeof data.data.serviceports === 'undefined') {
$('#ont-serviceports').append(`
<tr>
<td class="text-center" colspan="5">Keine Serviceports definiert.</td>
</tr>
`)
} else {
$.each(data.data.serviceports, function (o, ont) {
var operstatus;
if (ont.operstatus == "1") {
operstatus = "<span style='color:green'>UP</span>";
} else {
operstatus = "<span style='color:red'>Down</span>";
}
$('#ont-serviceports').append(`
<tr>
<td class="text-center">` + ont.vlanmap + `</td>
<td class="text-center">` + ont.vlan + `</td>
<td class="text-center">` + operstatus + `</td>
<td class="text-center">` + ont.traficdescrx + `</td>
<td class="text-center">` + ont.traficdesctx + `</td>
</tr>
`)
});
}
$('#ont-detail-spinner').hide();
$('#ont-detail-refresh').show();
}).fail(function (jqxhr, textStatus, error) {
window.location.href = "Dashboard";
});
;
});
$('[data-toggle="tooltip"]').tooltip()
$(document).on('change', '#files-input', function () {
let fileList = $('#files-input').prop("files");
// Leeren des Upload-Status-Containers
$('#uploadsts').html('');
$('.attachment-div').html('');
// Erzeuge für jede Datei einen eigenen Fortschrittsbalken (eindeutig per Index)
for (let i = 0; i < fileList.length; i++) {
$('.attachment-div').append(`
<div class="progress" style="margin-bottom: 10px;">
<div class="progress-bar progress-bar-striped progress-bar-animated pb-${i}"
role="progressbar"
style="width: 0%;"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100"></div>
</div>
`);
}
if (fileList.length > 0) {
uploadajax(fileList.length, 0);
}
});
$(document).on('click', '.fa-fileupload', function () {
$('#documents-upload').toggle();
});
});
</script>
<?php include(realpath(dirname(__FILE__) . "/../../$mfLayoutPackage") . "/footer.php"); ?>