fixed SPA

This commit is contained in:
2025-12-16 15:23:40 +01:00
parent 1555dc02e9
commit 2809d18c12
13 changed files with 3096 additions and 1026 deletions

View File

@@ -1,7 +1,9 @@
FROM node:22-alpine
FROM node:24-alpine
WORKDIR /app
ENV CXXFLAGS="-std=c++20"
COPY package*.json ./
RUN apk add --no-cache python3 make g++ \

1752
backend/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -10,9 +10,9 @@
"dependencies": {
"express": "^4.18.2",
"cors": "^2.8.5",
"better-sqlite3": "^9.2.2",
"better-sqlite3": "^12.5.0",
"uuid": "^9.0.1",
"nodemailer": "^6.9.14"
"nodemailer": "^7.0.11"
},
"devDependencies": {
"nodemon": "^3.0.2"

View File

@@ -747,6 +747,24 @@ function normalizeDailyBookmarkMarker(value) {
return marker;
}
function normalizeDailyBookmarkActive(value) {
if (value === undefined || value === null) {
return 1;
}
if (typeof value === 'string') {
const trimmed = value.trim().toLowerCase();
if (trimmed === 'false' || trimmed === '0' || trimmed === 'off') {
return 0;
}
if (trimmed === 'true' || trimmed === '1' || trimmed === 'on') {
return 1;
}
}
return value ? 1 : 0;
}
function serializeDailyBookmark(row, dayKey) {
if (!row) {
return null;
@@ -760,6 +778,7 @@ function serializeDailyBookmark(row, dayKey) {
title: row.title,
url_template: row.url_template,
marker: row.marker || '',
is_active: Number(row.is_active ?? 1) !== 0,
resolved_url: resolvedUrl,
notes: row.notes || '',
created_at: sqliteTimestampToUTC(row.created_at),
@@ -1218,6 +1237,7 @@ db.exec(`
title TEXT NOT NULL,
url_template TEXT NOT NULL,
notes TEXT,
is_active INTEGER NOT NULL DEFAULT 1,
marker TEXT DEFAULT '',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
@@ -1246,6 +1266,7 @@ db.exec(`
`);
ensureColumn('daily_bookmarks', 'marker', 'marker TEXT DEFAULT \'\'');
ensureColumn('daily_bookmarks', 'is_active', 'is_active INTEGER NOT NULL DEFAULT 1');
const listDailyBookmarksStmt = db.prepare(`
SELECT
@@ -1253,6 +1274,7 @@ const listDailyBookmarksStmt = db.prepare(`
b.title,
b.url_template,
b.notes,
b.is_active,
b.marker,
b.created_at,
b.updated_at,
@@ -1277,6 +1299,7 @@ const getDailyBookmarkStmt = db.prepare(`
b.title,
b.url_template,
b.notes,
b.is_active,
b.marker,
b.created_at,
b.updated_at,
@@ -1296,8 +1319,8 @@ const getDailyBookmarkStmt = db.prepare(`
`);
const insertDailyBookmarkStmt = db.prepare(`
INSERT INTO daily_bookmarks (id, title, url_template, notes, marker)
VALUES (@id, @title, @url_template, @notes, @marker)
INSERT INTO daily_bookmarks (id, title, url_template, notes, marker, is_active)
VALUES (@id, @title, @url_template, @notes, @marker, @is_active)
`);
const findDailyBookmarkByUrlStmt = db.prepare(`
@@ -1321,6 +1344,7 @@ const updateDailyBookmarkStmt = db.prepare(`
url_template = @url_template,
notes = @notes,
marker = @marker,
is_active = @is_active,
updated_at = CURRENT_TIMESTAMP
WHERE id = @id
`);
@@ -3942,6 +3966,9 @@ app.post('/api/daily-bookmarks', (req, res) => {
const normalizedTitle = normalizeDailyBookmarkTitle(payload.title || payload.label, normalizedUrl);
const normalizedNotes = normalizeDailyBookmarkNotes(payload.notes);
const normalizedMarker = normalizeDailyBookmarkMarker(payload.marker || payload.tag);
const normalizedActive = normalizeDailyBookmarkActive(
payload.is_active ?? payload.active ?? true
);
if (!normalizedUrl) {
return res.status(400).json({ error: 'URL-Template ist erforderlich' });
@@ -3958,7 +3985,8 @@ app.post('/api/daily-bookmarks', (req, res) => {
title: normalizedTitle,
url_template: normalizedUrl,
notes: normalizedNotes,
marker: normalizedMarker
marker: normalizedMarker,
is_active: normalizedActive
});
upsertDailyBookmarkCheckStmt.run({ bookmarkId: id, dayKey });
const saved = getDailyBookmarkStmt.get({ bookmarkId: id, dayKey });
@@ -3978,6 +4006,9 @@ app.post('/api/daily-bookmarks/import', (req, res) => {
}
const normalizedMarker = normalizeDailyBookmarkMarker(payload.marker || payload.tag);
const normalizedActive = normalizeDailyBookmarkActive(
payload.is_active ?? payload.active ?? true
);
const collected = [];
const addValue = (value) => {
if (typeof value !== 'string') {
@@ -4030,7 +4061,8 @@ app.post('/api/daily-bookmarks/import', (req, res) => {
title,
url_template: template,
notes: '',
marker: normalizedMarker
marker: normalizedMarker,
is_active: normalizedActive
});
const saved = getDailyBookmarkStmt.get({ bookmarkId: id, dayKey });
if (saved) {
@@ -4087,6 +4119,9 @@ app.put('/api/daily-bookmarks/:bookmarkId', (req, res) => {
const normalizedMarker = normalizeDailyBookmarkMarker(
payload.marker ?? existing.marker ?? ''
);
const normalizedActive = normalizeDailyBookmarkActive(
payload.is_active ?? payload.active ?? Number(existing.is_active ?? 1)
);
if (!normalizedUrl) {
return res.status(400).json({ error: 'URL-Template ist erforderlich' });
@@ -4106,7 +4141,8 @@ app.put('/api/daily-bookmarks/:bookmarkId', (req, res) => {
title: normalizedTitle,
url_template: normalizedUrl,
notes: normalizedNotes,
marker: normalizedMarker
marker: normalizedMarker,
is_active: normalizedActive
});
const updated = getDailyBookmarkStmt.get({ bookmarkId, dayKey });
res.json(serializeDailyBookmark(updated, dayKey));
@@ -4151,6 +4187,9 @@ app.post('/api/daily-bookmarks/:bookmarkId/check', (req, res) => {
if (!existing) {
return res.status(404).json({ error: 'Bookmark nicht gefunden' });
}
if (Number(existing.is_active ?? 1) === 0) {
return res.status(400).json({ error: 'Bookmark ist deaktiviert' });
}
upsertDailyBookmarkCheckStmt.run({ bookmarkId, dayKey });
const updated = getDailyBookmarkStmt.get({ bookmarkId, dayKey });
@@ -4178,6 +4217,9 @@ app.delete('/api/daily-bookmarks/:bookmarkId/check', (req, res) => {
if (!existing) {
return res.status(404).json({ error: 'Bookmark nicht gefunden' });
}
if (Number(existing.is_active ?? 1) === 0) {
return res.status(400).json({ error: 'Bookmark ist deaktiviert' });
}
deleteDailyBookmarkCheckStmt.run({ bookmarkId, dayKey });
const updated = getDailyBookmarkStmt.get({ bookmarkId, dayKey });