343 lines
12 KiB
HTML
343 lines
12 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="de">
|
|
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>Fertigungsbaum</title>
|
|
<script src="/backend/xlsx/xlsx.full.min.js"></script>
|
|
<script src="/backend/handsontable/handsontable/dist/handsontable.full.min.js"></script>
|
|
<link rel="stylesheet" href="/backend/handsontable/handsontable/dist/handsontable.full.min.css">
|
|
<link rel="stylesheet" href="/backend/jstree/dist/themes/default/style.min.css" />
|
|
<script src="/backend/jquery/jquery-3.7.1.min.js"></script>
|
|
<script src="/backend/jstree/dist/jstree.min.js"></script>
|
|
|
|
<style>
|
|
body {
|
|
font-family: Arial, sans-serif;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
height: 100vh;
|
|
margin: 0;
|
|
background-color: #f4f4f4;
|
|
}
|
|
|
|
#tree-container {
|
|
width: 60%;
|
|
max-width: 800px;
|
|
background: white;
|
|
padding: 20px;
|
|
border-radius: 10px;
|
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
|
}
|
|
|
|
#tree {
|
|
max-height: 600px;
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.button-container {
|
|
position: fixed;
|
|
bottom: 20px;
|
|
right: 20px;
|
|
display: flex;
|
|
gap: 10px;
|
|
}
|
|
|
|
.button-container button {
|
|
background-color: red;
|
|
color: white;
|
|
padding: 10px 20px;
|
|
border: none;
|
|
border-radius: 5px;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.modal {
|
|
display: none;
|
|
position: fixed;
|
|
left: 0;
|
|
top: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
background: rgba(0, 0, 0, 0.5);
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
|
|
.modal-content {
|
|
background: white;
|
|
padding: 20px;
|
|
border-radius: 5px;
|
|
width: 600px;
|
|
text-align: center;
|
|
position: relative;
|
|
}
|
|
|
|
.close {
|
|
cursor: pointer;
|
|
position: absolute;
|
|
right: 10px;
|
|
top: 10px;
|
|
font-size: 20px;
|
|
}
|
|
|
|
#import-table {
|
|
width: 100%;
|
|
margin-top: 10px;
|
|
}
|
|
|
|
/* Neues Modal für die Config.html */
|
|
#config-modal iframe {
|
|
width: 100%;
|
|
height: 100%;
|
|
border: none;
|
|
}
|
|
#config-modal {
|
|
position: fixed;
|
|
top: 0; left: 0; right: 0; bottom: 0;
|
|
background-color: rgba(0,0,0,0.6); /* halbtransparenter Hintergrund */
|
|
display: none; /* per default ausgeblendet */
|
|
justify-content: center;
|
|
align-items: center;
|
|
z-index: 9999; /* ganz oben anzeigen */
|
|
}
|
|
|
|
/* Der weiße Container im Overlay: hier auf 100% */
|
|
#config-modal-content {
|
|
width: 100%;
|
|
height: 100%;
|
|
background-color: #fff;
|
|
position: relative; /* für den Close-Button */
|
|
}
|
|
|
|
/* Kopfbereich mit Title + Close-Button (optional) */
|
|
#config-modal-header {
|
|
background: #f2f2f2;
|
|
padding: 10px;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
}
|
|
#config-modal-header h2 {
|
|
margin: 0;
|
|
}
|
|
#config-modal-close {
|
|
font-weight: bold;
|
|
cursor: pointer;
|
|
}
|
|
|
|
/* Körper: hier das iframe auf Vollbild */
|
|
#config-modal-body {
|
|
width: 100%;
|
|
height: calc(100% - 50px); /* 50px = ungefährer Header-Höhenwert */
|
|
overflow: hidden; /* Kein Scrollen auf dem Container selbst */
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="config-modal">
|
|
<div id="config-modal-content">
|
|
<div id="config-modal-header">
|
|
<h2>Konfiguration</h2>
|
|
<span id="config-modal-close" onclick="closeConfigModal()">[X]</span>
|
|
</div>
|
|
<div id="config-modal-body">
|
|
<iframe id="config-iframe"></iframe>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="tree-container">
|
|
<h2 style="text-align: center;">Fertigungsbaum</h2>
|
|
<div id="tree"></div>
|
|
</div>
|
|
|
|
<div class="button-container">
|
|
<button onclick="exportExcel()">Excel Export</button>
|
|
<button onclick="openImportModal()">Excel Import</button>
|
|
</div>
|
|
|
|
<!-- Import-Modal -->
|
|
<div id="import-modal" class="modal">
|
|
<div class="modal-content">
|
|
<span class="close" onclick="closeImportModal()">×</span>
|
|
<h3>Excel Datei hochladen</h3>
|
|
<input type="file" id="file-input" accept=".xlsx">
|
|
<div id="import-table"></div>
|
|
<button onclick="importExcelData()">Importieren</button>
|
|
<button onclick="sendExcelData()">Senden</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Neues Modal für die Config.html -->
|
|
<div id="config-modal" class="modal">
|
|
<div class="modal-content">
|
|
<span class="close" onclick="closeConfigModal()">×</span>
|
|
<!-- Hier das iframe, das Config.html lädt -->
|
|
<iframe id="config-iframe" src=""></iframe>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
let rawTable;
|
|
const url = sessionStorage.getItem("url");
|
|
|
|
function fetchTreeData() {
|
|
fetch(url + '/backend/api/getStations', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },
|
|
body: JSON.stringify({'station': sessionStorage.getItem("stationNumber")})
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
let treeData = buildJsTree(data);
|
|
$('#tree').jstree({ 'core': { 'data': treeData } });
|
|
})
|
|
.catch(error => console.error('Fehler beim Laden der Daten:', error));
|
|
}
|
|
|
|
function buildJsTree(data) {
|
|
return data.map(node => ({
|
|
id: node.id,
|
|
text: node.id + " | " + node.text,
|
|
children: node.children ? buildJsTree(node.children) : []
|
|
}));
|
|
}
|
|
|
|
function exportExcel() {
|
|
fetch(url + '/backend/api/getStationExport', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({'station': sessionStorage.getItem("stationNumber")})
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
data.sort((a, b) =>
|
|
a.line_nr.localeCompare(b.line_nr) ||
|
|
a.line_bez.localeCompare(b.line_bez) ||
|
|
a.ma_grp_nr.localeCompare(b.ma_grp_nr) ||
|
|
a.ma_grp_bez.localeCompare(b.ma_grp_bez) ||
|
|
a.kap_nr.localeCompare(b.kap_nr) ||
|
|
a.kap_bez.localeCompare(b.kap_bez)
|
|
);
|
|
|
|
const worksheet = XLSX.utils.json_to_sheet(data, {
|
|
header: ["line_nr", "line_bez", "ma_grp_nr", "ma_grp_bez", "kap_nr", "kap_bez"]
|
|
});
|
|
const workbook = XLSX.utils.book_new();
|
|
XLSX.utils.book_append_sheet(workbook, worksheet, "Export");
|
|
XLSX.writeFile(workbook, "StationsExport.xlsx");
|
|
})
|
|
.catch(error => {
|
|
console.error('Fehler beim Excel-Export:', error);
|
|
alert('Fehler beim Excel-Export: ' + error.message);
|
|
});
|
|
}
|
|
|
|
function importExcelData() {
|
|
const fileInput = document.getElementById("file-input");
|
|
if (!fileInput.files.length) return;
|
|
|
|
const reader = new FileReader();
|
|
reader.onload = function (event) {
|
|
const workbook = XLSX.read(event.target.result, { type: "binary" });
|
|
const sheet = workbook.Sheets[workbook.SheetNames[0]];
|
|
|
|
// Rohdaten als Objekte
|
|
const data = XLSX.utils.sheet_to_json(sheet, { defval: "" });
|
|
|
|
// ✅ Leere Zeilen ignorieren
|
|
rawTable = data.filter(row =>
|
|
Object.values(row).some(
|
|
val => val !== null && val !== undefined && String(val).trim() !== ""
|
|
)
|
|
);
|
|
|
|
if (rawTable.length === 0) {
|
|
alert("Keine gültigen Daten gefunden.");
|
|
return;
|
|
}
|
|
|
|
const container = document.getElementById("import-table");
|
|
container.innerHTML = ""; // wichtig bei erneutem Import
|
|
|
|
new Handsontable(container, {
|
|
data: rawTable,
|
|
colHeaders: Object.keys(rawTable[0]),
|
|
rowHeaders: true,
|
|
width: "100%",
|
|
height: 300,
|
|
licenseKey: "non-commercial-and-evaluation"
|
|
});
|
|
};
|
|
|
|
reader.readAsBinaryString(fileInput.files[0]);
|
|
}
|
|
|
|
function sendExcelData() {
|
|
const stationNumber = sessionStorage.getItem("stationNumber") || "TEST";
|
|
const filteredData = rawTable.map(item => ({
|
|
line_nr: item.line_nr,
|
|
line_bez: item.line_bez,
|
|
ma_grp_nr: item.ma_grp_nr,
|
|
ma_grp_bez: item.ma_grp_bez,
|
|
kap_nr: item.kap_nr,
|
|
kap_bez: item.kap_bez
|
|
}));
|
|
|
|
let sendata = JSON.stringify({
|
|
station: stationNumber,
|
|
data: filteredData
|
|
});
|
|
console.log(sendata);
|
|
|
|
fetch(url + '/backend/api/updateStations', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: sendata
|
|
})
|
|
//.then(response => response.json())
|
|
.then(result => alert("Daten erfolgreich gesendet!"))
|
|
.catch(error => alert("Fehler beim Senden der Daten: " + error.message));
|
|
}
|
|
|
|
// Modal-Steuerung für den Import-Dialog
|
|
function openImportModal() {
|
|
document.getElementById("import-modal").style.display = "flex";
|
|
}
|
|
function closeImportModal() {
|
|
document.getElementById("import-modal").style.display = "none";
|
|
}
|
|
|
|
// Modal-Steuerung für das Config-Dialog
|
|
function openConfigModal() {
|
|
document.getElementById("config-modal").style.display = "flex";
|
|
}
|
|
function closeConfigModal() {
|
|
document.getElementById("config-modal").style.display = "none";
|
|
}
|
|
|
|
$(document).ready(function() {
|
|
fetchTreeData();
|
|
|
|
$('#tree').on("dblclick.jstree", function (e) {
|
|
let node = $('#tree').jstree(true).get_node(e.target);
|
|
// Nur wenn kein weiterer Kindknoten vorhanden ist
|
|
if (node && node.children.length === 0) {
|
|
sessionStorage.setItem("selectedStation", node.id);
|
|
|
|
// Hier iframe-Source setzen, ggf. mit Parametern
|
|
let iframe = document.getElementById("config-iframe");
|
|
iframe.src = url + "/backend/Config.html?station=" + node.id;
|
|
|
|
// Modal öffnen
|
|
openConfigModal();
|
|
}
|
|
});
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|