*** WOP ***

Liste bearbeiten geht noch nicht
This commit is contained in:
2025-08-21 15:11:14 +00:00
parent 326b30206d
commit 6c0aaf0123
4 changed files with 168 additions and 71 deletions

View File

@@ -1,3 +1,20 @@
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';
});
}
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
const saveBtn = document.getElementById('saveBtn'); const saveBtn = document.getElementById('saveBtn');
const refreshBtn = document.getElementById('refreshBtn'); const refreshBtn = document.getElementById('refreshBtn');
@@ -43,32 +60,41 @@ document.addEventListener('DOMContentLoaded', () => {
document.body.appendChild(modal); document.body.appendChild(modal);
} }
// Sensornummer nur Zahlen erlauben // Sensornummer nur Zahlen erlauben
sensorNumberInput.addEventListener('input', () => { sensorNumberInput.addEventListener('input', () => {
sensorNumberInput.value = sensorNumberInput.value.replace(/\D/g, ''); sensorNumberInput.value = sensorNumberInput.value.replace(/\D/g, '');
}); });
// Adresse vom Server holen, wenn Enter oder Feld verlassen // Adresse vom Server holen, wenn Enter oder Feld verlassen
async function fetchAddressIfValid() { async function fetchAddressIfValid() {
const value = sensorNumberInput.value.trim(); const value = sensorNumberInput.value.trim();
if (value.length > 0) { if (value.length > 0) {
try { try {
const res = await fetch(`/api/address/${value}`); const res = await fetch(`/api/address/${value}`);
const data = await res.json(); const data = await res.json();
console.dir(data) console.dir(data)
if (!data.error && data.address) { if (!data.error && data.address) {
addressInput.value = data.address; addressInput.value = data.address;
// Felder automatisch füllen, wenn props vorhanden // Felder automatisch füllen, wenn props vorhanden
if (!data.props.error) { if (!data.props.error) {
if(data.props.erg.chip !== undefined) { if (data.props.erg.chip !== undefined) {
let pp = data.props.erg.chip let pp = data.props.erg.chip
espIdInput.value = pp.id || '' espIdInput.value = pp.id || ''
nameInput.value = pp.name || '' nameInput.value = pp.name || ''
descriptionInput.value = pp.description || '' descriptionInput.value = pp.description || ''
// Weitere Felder nach Bedarf // Weitere Felder nach Bedarf
}
} }
} else {
addressInput.value = '';
sensorNumberInput.disabled = true;
showModal('Sensor unbekannt', () => {
sensorNumberInput.disabled = false;
sensorNumberInput.focus();
});
} }
} else { } catch (err) {
console.error('Fehler beim Abrufen der Adresse:', err);
addressInput.value = ''; addressInput.value = '';
sensorNumberInput.disabled = true; sensorNumberInput.disabled = true;
showModal('Sensor unbekannt', () => { showModal('Sensor unbekannt', () => {
@@ -76,28 +102,19 @@ async function fetchAddressIfValid() {
sensorNumberInput.focus(); 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 // Enter-Taste
sensorNumberInput.addEventListener('keydown', (e) => { sensorNumberInput.addEventListener('keydown', (e) => {
if (e.key === 'Enter') { if (e.key === 'Enter') {
e.preventDefault(); e.preventDefault();
fetchAddressIfValid(); fetchAddressIfValid();
} }
}); });
// Feld verlassen // Feld verlassen
sensorNumberInput.addEventListener('blur', fetchAddressIfValid); sensorNumberInput.addEventListener('blur', fetchAddressIfValid);
async function saveEntry() { async function saveEntry() {
@@ -146,27 +163,91 @@ sensorNumberInput.addEventListener('blur', fetchAddressIfValid);
saveBtn.textContent = 'Speichern'; saveBtn.textContent = 'Speichern';
} }
// Globale Sortier-Variable
window.currentSort = window.currentSort || { key: null, asc: true };
async function loadEntries() { async function loadEntries() {
const page = parseInt(pageInput.value) || 1; const page = parseInt(pageInput.value) || 1;
const limit = parseInt(limitInput.value) || 10; const limit = parseInt(limitInput.value) || 50;
try { try {
const res = await fetch(`/api/list?page=${page}&limit=${limit}`); const res = await fetch(`/api/list?page=${page}&limit=${limit}`);
const items = await res.json(); const erg = await res.json();
const items = erg.items
const gz = document.getElementById('gzahl');
gz.innerHTML = `Gesamtzahl: ${erg.anzahl}`
tableBody.innerHTML = ''; let currentSort = window.currentSort || { key: null, asc: true };
items.forEach(item => { function renderTable(sortedItems) {
const date = new Date(item.chip.createdAt).toISOString().split('T')[0]; tableBody.innerHTML = '';
const tr = document.createElement('tr'); sortedItems.forEach(item => {
tr.innerHTML = ` const date = new Date(item.chip.createdAt).toISOString().split('T')[0];
<td>${item._id}</td> const tr = document.createElement('tr');
<td>${item.chip.id}</td> tr.innerHTML = `
<td>${item.chip.name || ''}</td> <td>${item._id}</td>
<td id="tdBeschreibung">${item.chip.description || ''}</td> <td>${item.chip.id}</td>
<td id="tdDate">${date}</td> <td>${item.chip.name || ''}</td>
`; <td id="tdBeschreibung">${item.chip.description || ''}</td>
tableBody.appendChild(tr); <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 => { document.querySelectorAll('.deleteBtn').forEach(btn => {
btn.addEventListener('click', async () => { btn.addEventListener('click', async () => {
@@ -180,13 +261,13 @@ sensorNumberInput.addEventListener('blur', fetchAddressIfValid);
const id = btn.getAttribute('data-id'); const id = btn.getAttribute('data-id');
const res = await fetch(`/api/list?page=1&limit=1&id=${id}`); const res = await fetch(`/api/list?page=1&limit=1&id=${id}`);
const items = await res.json(); const items = await res.json();
const item = items.find(e => e._id === id); const item = items.find(e => e._id === parseInt(id));
if (item) { if (item) {
espIdInput.value = item.espId; espIdInput.value = item.chip.id;
sensorNumberInput.value = item.sensorNumber; sensorNumberInput.value = item._id;
nameInput.value = item.name || ''; nameInput.value = item.chip.name || '';
descriptionInput.value = item.description || ''; descriptionInput.value = item.chip.description || '';
addressInput.value = item.address || ''; // addressInput.value = item.address || '';
editId = id; editId = id;
saveBtn.textContent = 'Aktualisieren'; saveBtn.textContent = 'Aktualisieren';
} }

View File

@@ -196,4 +196,8 @@ p.error {
.card form textarea { .card form textarea {
min-height: 60px; min-height: 60px;
resize: vertical; resize: vertical;
}
#gzahl {
margin-left: 30px;
} }

View File

@@ -2,6 +2,8 @@ import { MongoAPIError, ObjectId } from 'mongodb';
import bcrypt from 'bcrypt'; import bcrypt from 'bcrypt';
import { getCollections, update_pflux } from '../db/mongo.js'; import { getCollections, update_pflux } from '../db/mongo.js';
export function registerApiRoutes(app, requireLogin) { export function registerApiRoutes(app, requireLogin) {
const { usersCollection, prop_fluxCollection } = getCollections(); const { usersCollection, prop_fluxCollection } = getCollections();
@@ -61,7 +63,7 @@ export function registerApiRoutes(app, requireLogin) {
const { id } = req.query; const { id } = req.query;
if (id) { if (id) {
try { try {
const item = await prop_fluxCollection.findOne({ _id: new ObjectId(id) }); const item = await prop_fluxCollection.findOne({ _id: parseInt(id) });
if (item) return res.json([item]); if (item) return res.json([item]);
return res.json([]); return res.json([]);
} catch (err) { } catch (err) {
@@ -69,8 +71,15 @@ export function registerApiRoutes(app, requireLogin) {
return res.status(500).json({ error: 'Fehler beim Laden' }); return res.status(500).json({ error: 'Fehler beim Laden' });
} }
} }
let gesamtZahl = 0
try {
gesamtZahl = await prop_fluxCollection.countDocuments({chip: {$exists: true}})
} catch (err) {
console.error(err);
}
const page = parseInt(req.query.page) || 1; const page = parseInt(req.query.page) || 1;
const limit = parseInt(req.query.limit) || 10; const limit = parseInt(req.query.limit) || 50;
const skip = (page - 1) * limit; const skip = (page - 1) * limit;
try { try {
const items = await prop_fluxCollection.find({chip: {$exists: true}}) const items = await prop_fluxCollection.find({chip: {$exists: true}})
@@ -78,7 +87,8 @@ export function registerApiRoutes(app, requireLogin) {
.skip(skip) .skip(skip)
.limit(limit) .limit(limit)
.toArray(); .toArray();
res.json(items); const data = {items: items, anzahl: gesamtZahl}
res.json(data);
} catch (err) { } catch (err) {
console.error(err); console.error(err);
res.status(500).json({ error: 'Fehler beim Laden' }); res.status(500).json({ error: 'Fehler beim Laden' });

View File

@@ -41,16 +41,18 @@ html(lang="de")
| Seite: | Seite:
input#page(value="1") input#page(value="1")
| Limit: | Limit:
input#limit(value="10") input#limit(value="50")
span#gzahl
table#entriesTable table#entriesTable
thead thead
tr tr
th SensorNr th(id="thSensorNr" data-sort="sensorNr" style="cursor:pointer") SensorNr <span id="sortArrowSensorNr">↑</span>
th ESP-ID th(id="thEspId" data-sort="espId" style="cursor:pointer") ESP-ID <span id="sortArrowEspId">↑</span>
th Bezeichnung th Bezeichnung
th Beschreibung th Beschreibung
th Datum th(id="thDate" data-sort="date" style="cursor:pointer") Datum <span id="sortArrowDate">↑</span>
th Aktionen
tbody tbody
script(type="module" src="/global.js") script(type="module" src="/global.js")
script. script.