QR-Generator, Ordner-Sharing, Baustellenschild weg, Button-Fix

This commit is contained in:
2026-06-05 00:28:53 +02:00
parent 8ef217c49b
commit fa1eca6867
8 changed files with 624 additions and 16 deletions

View File

@@ -86,7 +86,32 @@ router.get('/', authenticate, (req, res) => {
ORDER BY l.title ASC
`).all(uid);
res.json({ own, folders, shared, sharedByMe });
// Ordner die mit mir geteilt wurden (inkl. deren Links)
const sharedFolders = db.prepare(`
SELECT f.*, u.username as owner_name
FROM link_list_folders f
JOIN link_folder_shares s ON s.folder_id=f.id
JOIN users u ON u.id=f.user_id
WHERE s.shared_with=?
ORDER BY f.name ASC
`).all(uid);
const sharedFolderLinks = sharedFolders.map(folder => ({
...folder,
links: db.prepare('SELECT * FROM link_list WHERE folder_id=? ORDER BY sort_order,id').all(folder.id)
}));
// Ordner die ich geteilt habe
const sharedFoldersByMe = db.prepare(`
SELECT f.*, u.username as shared_with_name
FROM link_list_folders f
JOIN link_folder_shares s ON s.folder_id=f.id
JOIN users u ON u.id=s.shared_with
WHERE f.user_id=?
ORDER BY f.name ASC
`).all(uid);
res.json({ own, folders, shared, sharedByMe, sharedFolders: sharedFolderLinks, sharedFoldersByMe });
});
router.post('/', authenticate, (req, res) => {
@@ -153,4 +178,35 @@ router.delete('/:id/share/:userId', authenticate, (req, res) => {
res.json({ ok: true });
});
// ── Ordner-Shares ─────────────────────────────────────────────────────────────
router.get('/folders/:id/shares', authenticate, (req, res) => {
const f = db.prepare('SELECT * FROM link_list_folders WHERE id=? AND user_id=?').get(req.params.id, req.user.id);
if (!f) return res.status(404).json({ error: 'Nicht gefunden' });
const shares = db.prepare(`
SELECT u.id, u.username, s.created_at as shared_at
FROM link_folder_shares s JOIN users u ON u.id=s.shared_with
WHERE s.folder_id=?
`).all(f.id);
res.json(shares);
});
router.post('/folders/:id/share', authenticate, (req, res) => {
const f = db.prepare('SELECT * FROM link_list_folders WHERE id=? AND user_id=?').get(req.params.id, req.user.id);
if (!f) return res.status(404).json({ error: 'Nicht gefunden' });
const target = db.prepare('SELECT * FROM users WHERE username=?').get(req.body.username);
if (!target) return res.status(404).json({ error: 'Benutzer nicht gefunden' });
if (target.id === req.user.id) return res.status(400).json({ error: 'Kann nicht mit dir selbst teilen' });
db.prepare(`INSERT OR IGNORE INTO link_folder_shares (folder_id, shared_by, shared_with, created_at) VALUES (?,?,?,datetime('now','localtime'))`)
.run(f.id, req.user.id, target.id);
res.json({ ok: true });
});
router.delete('/folders/:id/share/:userId', authenticate, (req, res) => {
const f = db.prepare('SELECT * FROM link_list_folders WHERE id=? AND user_id=?').get(req.params.id, req.user.id);
if (!f) return res.status(404).json({ error: 'Nicht gefunden' });
db.prepare('DELETE FROM link_folder_shares WHERE folder_id=? AND shared_with=?').run(f.id, req.params.userId);
res.json({ ok: true });
});
module.exports = router;

View File

@@ -0,0 +1,41 @@
const express = require('express');
const db = require('../../db');
const { authenticate } = require('../../middleware/auth');
const router = express.Router();
router.get('/', authenticate, (req, res) => {
res.json(db.prepare('SELECT * FROM qr_codes WHERE user_id=? ORDER BY created_at DESC').all(req.user.id));
});
router.post('/', authenticate, (req, res) => {
const uid = req.user.id;
const { label='', url, size=256, fg_color='#000000', bg_color='#ffffff', margin=4,
dot_style='square', corner_style='square', caption='', caption_pos='bottom',
caption_color='#000000', caption_size=14 } = req.body;
if (!url?.trim()) return res.status(400).json({ error: 'URL erforderlich' });
const r = db.prepare(`
INSERT INTO qr_codes (user_id,label,url,size,fg_color,bg_color,margin,dot_style,corner_style,caption,caption_pos,caption_color,caption_size,created_at)
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,datetime('now','localtime'))
`).run(uid, label.trim(), url.trim(), size, fg_color, bg_color, margin, dot_style, corner_style, caption.trim(), caption_pos, caption_color, caption_size);
res.json(db.prepare('SELECT * FROM qr_codes WHERE id=?').get(r.lastInsertRowid));
});
router.put('/:id', authenticate, (req, res) => {
const qr = db.prepare('SELECT * FROM qr_codes WHERE id=? AND user_id=?').get(req.params.id, req.user.id);
if (!qr) return res.status(404).json({ error: 'Nicht gefunden' });
const fields = ['label','url','size','fg_color','bg_color','margin','dot_style','corner_style','caption','caption_pos','caption_color','caption_size'];
const updates = {};
fields.forEach(f => { if (req.body[f] !== undefined) updates[f] = req.body[f]; });
if (!Object.keys(updates).length) return res.json(qr);
const sets = Object.keys(updates).map(f=>`${f}=?`).join(',');
db.prepare(`UPDATE qr_codes SET ${sets} WHERE id=?`).run(...Object.values(updates), qr.id);
res.json(db.prepare('SELECT * FROM qr_codes WHERE id=?').get(qr.id));
});
router.delete('/:id', authenticate, (req, res) => {
const r = db.prepare('DELETE FROM qr_codes WHERE id=? AND user_id=?').run(req.params.id, req.user.id);
if (!r.changes) return res.status(404).json({ error: 'Nicht gefunden' });
res.json({ ok: true });
});
module.exports = router;