*** WOP ***
Liste bearbeiten geht noch nicht
This commit is contained in:
205
public/global.js
205
public/global.js
@@ -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';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
@@ -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' });
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
Reference in New Issue
Block a user