This commit is contained in:
sebseb7
2025-12-25 06:22:05 +01:00
parent dcdfb27684
commit 822045b06d
3 changed files with 82 additions and 3 deletions

View File

@@ -558,9 +558,7 @@ class ViewManager extends Component {
); );
})} })}
</Box> </Box>
<Typography variant="body2" color="text.secondary" sx={{ mt: 2, textAlign: 'center' }}>
📊 Current outputs: {Object.entries(this.state.outputValues).filter(([k, v]) => v > 0).map(([k, v]) => `${k}=${v}`).join(', ') || 'all off'}
</Typography>
</Paper> </Paper>
)} )}
</Box> </Box>

View File

@@ -18,6 +18,29 @@ let db;
try { try {
db = new Database(dbPath); db = new Database(dbPath);
console.log(`[UI Server] Connected to database at ${dbPath}`); console.log(`[UI Server] Connected to database at ${dbPath}`);
// Create changelog table
db.exec(`
CREATE TABLE IF NOT EXISTS changelog (
id INTEGER PRIMARY KEY AUTOINCREMENT,
date TEXT NOT NULL,
user TEXT,
text TEXT NOT NULL
)
`);
// Helper to insert changelog entry
global.insertChangelog = (user, text) => {
try {
if (!db) return;
const stmt = db.prepare('INSERT INTO changelog (date, user, text) VALUES (?, ?, ?)');
stmt.run(new Date().toISOString(), user || 'system', text);
console.log(`[Changelog] ${user || 'system'}: ${text}`);
} catch (err) {
console.error('[Changelog] Error inserting entry:', err.message);
}
};
} catch (err) { } catch (err) {
console.error(`[UI Server] Failed to connect to database at ${dbPath}:`, err.message); console.error(`[UI Server] Failed to connect to database at ${dbPath}:`, err.message);
} }
@@ -655,6 +678,7 @@ module.exports = {
try { try {
const stmt = db.prepare('INSERT INTO views (name, config, created_by) VALUES (?, ?, ?)'); const stmt = db.prepare('INSERT INTO views (name, config, created_by) VALUES (?, ?, ?)');
const info = stmt.run(name, JSON.stringify(config), req.user.id); const info = stmt.run(name, JSON.stringify(config), req.user.id);
global.insertChangelog(req.user.username, `Created view "${name}"`);
res.json({ id: info.lastInsertRowid, name, config }); res.json({ id: info.lastInsertRowid, name, config });
} catch (err) { } catch (err) {
res.status(500).json({ error: err.message }); res.status(500).json({ error: err.message });
@@ -698,8 +722,11 @@ module.exports = {
app.delete('/api/views/:id', requireAdmin, (req, res) => { app.delete('/api/views/:id', requireAdmin, (req, res) => {
try { try {
const stmt = db.prepare('DELETE FROM views WHERE id = ?'); const stmt = db.prepare('DELETE FROM views WHERE id = ?');
// Get name before delete for logging
const viewName = db.prepare('SELECT name FROM views WHERE id = ?').get(req.params.id)?.name || 'Unknown View';
const info = stmt.run(req.params.id); const info = stmt.run(req.params.id);
if (info.changes > 0) { if (info.changes > 0) {
global.insertChangelog(req.user.username, `Deleted view "${viewName}" (ID: ${req.params.id})`);
res.json({ success: true }); res.json({ success: true });
} else { } else {
res.status(404).json({ error: 'View not found' }); res.status(404).json({ error: 'View not found' });
@@ -716,6 +743,7 @@ module.exports = {
const stmt = db.prepare('UPDATE views SET name = ?, config = ? WHERE id = ?'); const stmt = db.prepare('UPDATE views SET name = ?, config = ? WHERE id = ?');
const info = stmt.run(name, JSON.stringify(config), req.params.id); const info = stmt.run(name, JSON.stringify(config), req.params.id);
if (info.changes > 0) { if (info.changes > 0) {
global.insertChangelog(req.user.username, `Updated view "${name}" (ID: ${req.params.id})`);
res.json({ id: req.params.id, name, config }); res.json({ id: req.params.id, name, config });
} else { } else {
res.status(404).json({ error: 'View not found' }); res.status(404).json({ error: 'View not found' });
@@ -871,6 +899,7 @@ module.exports = {
req.user?.id || null req.user?.id || null
); );
runRules(); // Trigger rules immediately runRules(); // Trigger rules immediately
global.insertChangelog(req.user?.username || 'admin', `Created rule "${name}"`);
res.json({ id: info.lastInsertRowid, name, type, enabled, conditions, action }); res.json({ id: info.lastInsertRowid, name, type, enabled, conditions, action });
} catch (err) { } catch (err) {
res.status(500).json({ error: err.message }); res.status(500).json({ error: err.message });
@@ -895,6 +924,7 @@ module.exports = {
); );
if (info.changes > 0) { if (info.changes > 0) {
runRules(); // Trigger rules immediately runRules(); // Trigger rules immediately
global.insertChangelog(req.user?.username || 'admin', `Updated rule "${name}" (ID: ${req.params.id})`);
res.json({ id: req.params.id, name, type, enabled, conditions, action }); res.json({ id: req.params.id, name, type, enabled, conditions, action });
} else { } else {
res.status(404).json({ error: 'Rule not found' }); res.status(404).json({ error: 'Rule not found' });
@@ -908,9 +938,12 @@ module.exports = {
app.delete('/api/rules/:id', requireAdmin, (req, res) => { app.delete('/api/rules/:id', requireAdmin, (req, res) => {
try { try {
const stmt = db.prepare('DELETE FROM rules WHERE id = ?'); const stmt = db.prepare('DELETE FROM rules WHERE id = ?');
// Get name before delete
const ruleName = db.prepare('SELECT name FROM rules WHERE id = ?').get(req.params.id)?.name || 'Unknown Rule';
const info = stmt.run(req.params.id); const info = stmt.run(req.params.id);
if (info.changes > 0) { if (info.changes > 0) {
runRules(); // Trigger rules immediately runRules(); // Trigger rules immediately
global.insertChangelog(req.user?.username || 'admin', `Deleted rule "${ruleName}" (ID: ${req.params.id})`);
res.json({ success: true }); res.json({ success: true });
} else { } else {
res.status(404).json({ error: 'Rule not found' }); res.status(404).json({ error: 'Rule not found' });

48
verify_changelog.js Normal file
View File

@@ -0,0 +1,48 @@
const Database = require('better-sqlite3');
const path = require('path');
const dbPath = path.resolve(__dirname, 'server/data/sensors.db');
console.log(`Connecting to database at ${dbPath}`);
const db = new Database(dbPath);
// 1. Verify Table Creation
console.log('Creating changelog table...');
try {
db.exec(`
CREATE TABLE IF NOT EXISTS changelog (
id INTEGER PRIMARY KEY AUTOINCREMENT,
date TEXT NOT NULL,
user TEXT,
text TEXT NOT NULL
)
`);
console.log('PASS: Table creation successful (or already exists)');
} catch (err) {
console.error('FAIL: Table creation failed:', err.message);
process.exit(1);
}
// 2. Verify Insert
console.log('Inserting test entry...');
try {
const stmt = db.prepare('INSERT INTO changelog (date, user, text) VALUES (?, ?, ?)');
const info = stmt.run(new Date().toISOString(), 'test_user', 'Test changelog entry');
console.log(`PASS: Insert successful, ID: ${info.lastInsertRowid}`);
} catch (err) {
console.error('FAIL: Insert failed:', err.message);
process.exit(1);
}
// 3. Verify Read
console.log('Reading entries...');
try {
const rows = db.prepare('SELECT * FROM changelog ORDER BY id DESC LIMIT 5').all();
console.table(rows);
if (rows.length > 0 && rows[0].user === 'test_user') {
console.log('PASS: Read verification successful');
} else {
console.error('FAIL: Read verification failed or data mismatch');
}
} catch (err) {
console.error('FAIL: Read failed:', err.message);
}