fixed SPA
This commit is contained in:
@@ -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
1752
backend/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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"
|
||||
|
||||
@@ -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 });
|
||||
|
||||
Reference in New Issue
Block a user