Add debug Remove entry, Show more auto-picker, and update docs.

DELETE /api/paintings/:id removes works and image files with gallery refresh and catalog navigation; Show more opens the search modal on load; documentation updated for migrate schema and debug workflow.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Danila Khodjaef
2026-06-22 22:32:23 +03:00
co-authored by Cursor
parent b2cae284ac
commit f542c689c9
31 changed files with 396 additions and 30 deletions
+25
View File
@@ -189,6 +189,30 @@ function unlinkPortraitFiles(row, safeBase) {
}
}
async function deletePainting(paintingId) {
const result = await pool.query(
`SELECT p.id, p.title, p.image_path, p.thumbnail_path, p.artist_id, a.name AS artist_name
FROM paintings p
JOIN artists a ON a.id = p.artist_id
WHERE p.id = $1`,
[paintingId]
);
if (result.rows.length === 0) {
throw new Error('Painting not found');
}
const row = result.rows[0];
const safeBase = safePaintingBase(row.artist_name, row.title);
unlinkPaintingFiles(row, safeBase);
inflight.delete(`${paintingId}:thumb`);
inflight.delete(`${paintingId}:full`);
await pool.query(`DELETE FROM paintings WHERE id = $1`, [paintingId]);
return { id: row.id, artistId: row.artist_id, title: row.title };
}
async function clearPaintingImage(paintingId) {
const result = await pool.query(
`SELECT p.id, p.title, p.image_path, p.thumbnail_path, a.name AS artist_name
@@ -436,6 +460,7 @@ module.exports = {
replacePaintingImageFromUrl,
replaceArtistPortraitFromUrl,
clearPaintingImage,
deletePainting,
clearArtistPortrait,
replacePaintingImageFromBuffer,
replaceArtistPortraitFromBuffer,
+16 -1
View File
@@ -5,7 +5,7 @@ const fs = require('fs');
require('dotenv').config();
const pool = require('./db');
const { ensurePaintingImages, preloadArtistImagesLocal, replacePaintingImageFromUrl, replaceArtistPortraitFromUrl, clearPaintingImage, clearArtistPortrait, replacePaintingImageFromBuffer, replaceArtistPortraitFromBuffer, IMAGE_DIR } = require('./image-service');
const { ensurePaintingImages, preloadArtistImagesLocal, replacePaintingImageFromUrl, replaceArtistPortraitFromUrl, clearPaintingImage, deletePainting, clearArtistPortrait, replacePaintingImageFromBuffer, replaceArtistPortraitFromBuffer, IMAGE_DIR } = require('./image-service');
const { searchGoogleImagesFirst, searchArtistPortraitFirst, searchPaintingImagesMany, searchArtistPortraitMany, fetchImageBuffer, friendlyImageFetchError, pickExt } = require('../scripts/image-fetcher');
const app = express();
@@ -733,6 +733,21 @@ app.post('/api/paintings/:id/fix-image', async (req, res) => {
}
});
app.delete('/api/paintings/:id', async (req, res) => {
try {
const paintingId = parseInt(req.params.id, 10);
if (!Number.isFinite(paintingId)) {
return res.status(400).json({ error: 'Invalid painting id' });
}
const removed = await deletePainting(paintingId);
res.json(removed);
} catch (err) {
console.error('Delete painting error:', err.message);
const status = err.message === 'Painting not found' ? 404 : 500;
res.status(status).json({ error: err.message || 'Could not remove painting' });
}
});
app.post('/api/paintings/:id/clear-image', async (req, res) => {
try {
const paintingId = parseInt(req.params.id, 10);