326 lines
11 KiB
JavaScript
326 lines
11 KiB
JavaScript
|
|
function updateSortArrows() {
|
|
const arrows = {
|
|
sensorNr: document.getElementById('sortArrowSensorNr'),
|
|
espId: document.getElementById('sortArrowEspId'),
|
|
date: document.getElementById('sortArrowDate')
|
|
};
|
|
Object.entries(arrows).forEach(([key, el]) => {
|
|
if (!el) return;
|
|
// Aktiver Pfeil fett, andere ausgegraut
|
|
el.textContent = currentSort.key === key
|
|
? (currentSort.asc ? '↑' : '↓')
|
|
: '↑';
|
|
el.style.fontWeight = currentSort.key === key ? 'bold' : 'normal';
|
|
el.style.opacity = currentSort.key === key ? '1' : '0.3';
|
|
});
|
|
}
|
|
|
|
// Tab-Wechsel Funktion aus index.pug
|
|
function showTab(tab) {
|
|
document.getElementById('tabInputContent').style.display = tab === 'input' ? '' : 'none';
|
|
document.getElementById('tabListContent').style.display = tab === 'list' ? '' : 'none';
|
|
document.getElementById('tabInput').classList.toggle('active', tab === 'input');
|
|
document.getElementById('tabList').classList.toggle('active', tab === 'list');
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
const saveBtn = document.getElementById('saveBtn');
|
|
const refreshBtn = document.getElementById('refreshBtn');
|
|
const espIdInput = document.getElementById('espId');
|
|
const sensorNumberInput = document.getElementById('sensorNumber');
|
|
const nameInput = document.getElementById('name');
|
|
const descriptionInput = document.getElementById('description');
|
|
const addressInput = document.getElementById('address');
|
|
const pageInput = document.getElementById('page');
|
|
const limitInput = document.getElementById('limit');
|
|
const resultDiv = document.getElementById('result');
|
|
const tableBody = document.querySelector('#entriesTable tbody');
|
|
const tabInput = document.getElementById('tabInput');
|
|
const tabList = document.getElementById('tabList');
|
|
|
|
let editId = null;
|
|
|
|
// Modal für Fehleranzeige
|
|
function showModal(message, callback) {
|
|
// Vorherige Modals entfernen
|
|
document.querySelectorAll('.custom-modal-popup').forEach(m => m.remove());
|
|
|
|
let modal = document.createElement('div');
|
|
modal.className = 'custom-modal-popup';
|
|
|
|
let box = document.createElement('div');
|
|
box.className = 'custom-modal-box';
|
|
|
|
let msg = document.createElement('div');
|
|
msg.className = 'custom-modal-msg';
|
|
msg.textContent = message;
|
|
box.appendChild(msg);
|
|
|
|
let btn = document.createElement('button');
|
|
btn.className = 'custom-modal-btn';
|
|
btn.textContent = 'OK';
|
|
btn.onclick = () => {
|
|
if (modal.parentNode) {
|
|
modal.parentNode.removeChild(modal);
|
|
}
|
|
if (callback) callback();
|
|
};
|
|
box.appendChild(btn);
|
|
modal.appendChild(box);
|
|
document.body.appendChild(modal);
|
|
}
|
|
|
|
// Sensornummer nur Zahlen erlauben
|
|
sensorNumberInput.addEventListener('input', () => {
|
|
sensorNumberInput.value = sensorNumberInput.value.replace(/\D/g, '');
|
|
});
|
|
|
|
// Adresse vom Server holen, wenn Enter oder Feld verlassen
|
|
async function fetchAddressIfValid() {
|
|
const value = sensorNumberInput.value.trim();
|
|
if (value.length > 0) {
|
|
try {
|
|
const res = await fetch(`/api/address/${value}`);
|
|
const data = await res.json();
|
|
console.dir(data)
|
|
if (!data.error && data.address) {
|
|
addressInput.value = data.address;
|
|
// Felder automatisch füllen, wenn props vorhanden
|
|
if (!data.props.error) {
|
|
if (data.props.erg.chip !== undefined) {
|
|
let pp = data.props.erg.chip
|
|
espIdInput.value = pp.id || ''
|
|
nameInput.value = pp.name || ''
|
|
descriptionInput.value = pp.description || ''
|
|
// Weitere Felder nach Bedarf
|
|
}
|
|
}
|
|
} else {
|
|
addressInput.value = '';
|
|
sensorNumberInput.disabled = true;
|
|
showModal('Sensor unbekannt', () => {
|
|
sensorNumberInput.disabled = false;
|
|
sensorNumberInput.focus();
|
|
});
|
|
}
|
|
} catch (err) {
|
|
console.error('Fehler beim Abrufen der Adresse:', err);
|
|
addressInput.value = '';
|
|
sensorNumberInput.disabled = true;
|
|
showModal('Sensor unbekannt', () => {
|
|
sensorNumberInput.disabled = false;
|
|
sensorNumberInput.focus();
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
// Enter-Taste
|
|
sensorNumberInput.addEventListener('keydown', (e) => {
|
|
if (e.key === 'Enter') {
|
|
e.preventDefault();
|
|
fetchAddressIfValid();
|
|
}
|
|
});
|
|
|
|
// Feld verlassen
|
|
sensorNumberInput.addEventListener('blur', fetchAddressIfValid);
|
|
|
|
|
|
async function saveEntry() {
|
|
const espId = espIdInput.value.trim();
|
|
const sensorNumber = sensorNumberInput.value.trim();
|
|
const name = nameInput.value.trim();
|
|
const description = descriptionInput.value.trim();
|
|
const address = addressInput.value.trim();
|
|
|
|
if (!espId || !sensorNumber) {
|
|
resultDiv.textContent = 'ESP-ID und Sensornummer sind Pflichtfelder.';
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const url = editId ? `/api/update/${editId}` : '/api/save';
|
|
const method = editId ? 'PUT' : 'POST';
|
|
|
|
const res = await fetch(url, {
|
|
method,
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ espId, sensorNumber, name, description, address })
|
|
});
|
|
|
|
const data = await res.json();
|
|
if (data.error) {
|
|
resultDiv.textContent = data.error;
|
|
} else {
|
|
resultDiv.textContent = editId ? 'Aktualisiert!' : 'Gespeichert!';
|
|
clearForm();
|
|
await loadEntries();
|
|
}
|
|
} catch (err) {
|
|
console.error(err);
|
|
resultDiv.textContent = 'Fehler beim Speichern.';
|
|
}
|
|
}
|
|
|
|
|
|
function clearForm() {
|
|
espIdInput.value = '';
|
|
sensorNumberInput.value = '';
|
|
nameInput.value = '';
|
|
descriptionInput.value = '';
|
|
addressInput.value = '';
|
|
editId = null;
|
|
saveBtn.textContent = 'Speichern';
|
|
}
|
|
|
|
// Globale Sortier-Variable
|
|
window.currentSort = window.currentSort || { key: null, asc: true };
|
|
|
|
async function loadEntries() {
|
|
const page = parseInt(pageInput.value) || 1;
|
|
const limit = parseInt(limitInput.value) || 50;
|
|
|
|
try {
|
|
const res = await fetch(`/api/list?page=${page}&limit=${limit}`);
|
|
const erg = await res.json();
|
|
const items = erg.items
|
|
const gz = document.getElementById('gzahl');
|
|
gz.innerHTML = `Gesamtzahl: ${erg.anzahl}`
|
|
|
|
let currentSort = window.currentSort || { key: null, asc: true };
|
|
function renderTable(sortedItems) {
|
|
tableBody.innerHTML = '';
|
|
sortedItems.forEach(item => {
|
|
const date = new Date(item.chip.createdAt).toISOString().split('T')[0];
|
|
const tr = document.createElement('tr');
|
|
tr.innerHTML = `
|
|
<td>${item._id}</td>
|
|
<td>${item.chip.id}</td>
|
|
<td>${item.chip.name || ''}</td>
|
|
<td id="tdBeschreibung">${item.chip.description || ''}</td>
|
|
<td id="tdDate">${date}</td>
|
|
<td>
|
|
<button data-id="${item._id}" class="editBtn">Bearbeiten</button>
|
|
</td>
|
|
`;
|
|
tableBody.appendChild(tr);
|
|
});
|
|
}
|
|
|
|
function sortItems(items, key, asc) {
|
|
return items.slice().sort((a, b) => {
|
|
let valA, valB;
|
|
if (key === 'sensorNr') {
|
|
valA = a._id;
|
|
valB = b._id;
|
|
} else if (key === 'espId') {
|
|
valA = a.chip.id;
|
|
valB = b.chip.id;
|
|
} else if (key === 'date') {
|
|
valA = new Date(a.chip.createdAt);
|
|
valB = new Date(b.chip.createdAt);
|
|
}
|
|
if (valA < valB) return asc ? -1 : 1;
|
|
if (valA > valB) return asc ? 1 : -1;
|
|
return 0;
|
|
});
|
|
}
|
|
|
|
// Initial render: Standard nach SensorNr, ESP-ID oder Datum aufsteigend
|
|
// Ändere hier die Spalte für die Standardsortierung:
|
|
const defaultSortKey = window.currentSort && window.currentSort.key ? window.currentSort.key : 'sensorNr';
|
|
const defaultSortAsc = window.currentSort && typeof window.currentSort.asc === 'boolean' ? window.currentSort.asc : true;
|
|
currentSort.key = defaultSortKey;
|
|
currentSort.asc = defaultSortAsc;
|
|
window.currentSort = currentSort;
|
|
renderTable(sortItems(items, defaultSortKey, defaultSortAsc));
|
|
updateSortArrows();
|
|
|
|
// Add sort listeners
|
|
document.getElementById('thSensorNr').onclick = () => {
|
|
currentSort.asc = currentSort.key === 'sensorNr' ? !currentSort.asc : true;
|
|
currentSort.key = 'sensorNr';
|
|
window.currentSort = currentSort;
|
|
renderTable(sortItems(items, 'sensorNr', currentSort.asc));
|
|
updateSortArrows();
|
|
};
|
|
document.getElementById('thEspId').onclick = () => {
|
|
currentSort.asc = currentSort.key === 'espId' ? !currentSort.asc : true;
|
|
currentSort.key = 'espId';
|
|
window.currentSort = currentSort;
|
|
renderTable(sortItems(items, 'espId', currentSort.asc));
|
|
updateSortArrows();
|
|
};
|
|
document.getElementById('thDate').onclick = () => {
|
|
currentSort.asc = currentSort.key === 'date' ? !currentSort.asc : true;
|
|
currentSort.key = 'date';
|
|
window.currentSort = currentSort;
|
|
renderTable(sortItems(items, 'date', currentSort.asc));
|
|
updateSortArrows();
|
|
};
|
|
|
|
document.querySelectorAll('.deleteBtn').forEach(btn => {
|
|
btn.addEventListener('click', async () => {
|
|
const id = btn.getAttribute('data-id');
|
|
await deleteEntry(id);
|
|
});
|
|
});
|
|
|
|
document.querySelectorAll('.editBtn').forEach(btn => {
|
|
btn.addEventListener('click', async () => {
|
|
const id = btn.getAttribute('data-id');
|
|
const res = await fetch(`/api/list?page=1&limit=1&id=${id}`);
|
|
const items = await res.json();
|
|
const item = items.find(e => e._id === parseInt(id));
|
|
if (item) {
|
|
espIdInput.value = item.chip.id;
|
|
sensorNumberInput.value = item._id;
|
|
nameInput.value = item.chip.name || '';
|
|
descriptionInput.value = item.chip.description || '';
|
|
addressInput.value = '';
|
|
editId = id;
|
|
try {
|
|
const rt = await fetch(`api/holAdresse/${item._id}`)
|
|
const data = await rt.json();
|
|
console.dir(data)
|
|
if (!data.error && data.address) {
|
|
addressInput.value = data.address;
|
|
}
|
|
} catch (e) {
|
|
console.log("Fehler beim Adresse holen", e)
|
|
}
|
|
saveBtn.textContent = 'Aktualisieren';
|
|
showTab('input')
|
|
}
|
|
});
|
|
});
|
|
} catch (err) {
|
|
console.error(err);
|
|
resultDiv.textContent = 'Fehler beim Laden.';
|
|
}
|
|
}
|
|
|
|
async function deleteEntry(id) {
|
|
if (!confirm('Wirklich löschen?')) return;
|
|
try {
|
|
const res = await fetch(`/api/delete/${id}`, { method: 'DELETE' });
|
|
const data = await res.json();
|
|
if (data.success) {
|
|
await loadEntries();
|
|
}
|
|
} catch (err) {
|
|
console.error(err);
|
|
resultDiv.textContent = 'Fehler beim Löschen.';
|
|
}
|
|
}
|
|
|
|
|
|
saveBtn.addEventListener('click', saveEntry);
|
|
refreshBtn.addEventListener('click', loadEntries);
|
|
tabInput.addEventListener('click', () => showTab('input'))
|
|
tabList.addEventListener('click', () => showTab('list'))
|
|
|
|
loadEntries();
|
|
}); |