Release v1.5.12

This commit is contained in:
2026-07-26 16:22:28 +01:00
parent ef9cdd2986
commit 4afaeaafb1
20 changed files with 563 additions and 1602 deletions
+55
View File
@@ -104,6 +104,55 @@ module.exports = function registerAdminContentRoutes(app, deps) {
}
}
async function fetchTemplateSlideCount(templateId) {
const [rows] = await pool.query('SELECT COUNT(*) AS slide_count FROM slides WHERE template_id = ?', [templateId]);
return Number(rows[0] && rows[0].slide_count) || 0;
}
async function fetchTemplateRegionUsage(template) {
const [slides] = await pool.query('SELECT content_json FROM slides WHERE template_id = ?', [template.id]);
const usage = new Set();
const regionKeys = new Set((Array.isArray(template && template.regions) ? template.regions : [])
.map((region) => String(region && region.region_key || '').trim())
.filter(Boolean));
if (!regionKeys.size || !slides.length) {
return [];
}
slides.forEach((slide) => {
const content = typeof common.parseJsonSafe === 'function' ? common.parseJsonSafe(slide.content_json) : null;
if (!content || typeof content !== 'object') {
return;
}
regionKeys.forEach((regionKey) => {
if (Object.prototype.hasOwnProperty.call(content, regionKey)) {
usage.add(regionKey);
}
});
});
return Array.from(usage);
}
function getRemovedTemplateRegionKeys(existingRegions, nextRegions) {
const nextKeys = new Set((Array.isArray(nextRegions) ? nextRegions : []).map((region) => String(region && region.region_key || '').trim()).filter(Boolean));
return (Array.isArray(existingRegions) ? existingRegions : [])
.map((region) => String(region && region.region_key || '').trim())
.filter((regionKey) => regionKey && !nextKeys.has(regionKey));
}
async function getTemplateRegionDeleteBlockMessage(template, nextRegions) {
const removedRegionKeys = getRemovedTemplateRegionKeys(template && template.regions ? template.regions : [], nextRegions);
if (!removedRegionKeys.length) {
return '';
}
const usedRegionKeys = Array.isArray(template && template.region_usage) ? template.region_usage : [];
const blockedKeys = removedRegionKeys.filter((regionKey) => usedRegionKeys.includes(regionKey));
return blockedKeys.length > 0 ? 'This region is still used by one or more slides.' : '';
}
function queueSlideThumbnailRefresh(slideId, previousThumbnailPath) {
if (!backgroundTaskQueue || typeof backgroundTaskQueue.enqueueTask !== 'function') {
return Promise.resolve(null);
@@ -423,6 +472,7 @@ module.exports = function registerAdminContentRoutes(app, deps) {
if (!template) {
return res.status(404).send('Template not found');
}
template.region_usage = await fetchTemplateRegionUsage(template);
const sizeData = await common.fetchCanvasSizesData(pool);
res.send(pages.renderTemplateFormPage(template, 'edit', req.query.message ? String(req.query.message) : '', sizeData.canvasSizes, req.currentUser));
} catch (error) {
@@ -436,11 +486,16 @@ module.exports = function registerAdminContentRoutes(app, deps) {
if (!template) {
return res.status(404).send('Template not found');
}
template.region_usage = await fetchTemplateRegionUsage(template);
const existingUploadRefs = collectUploadReferencesFromTemplate(template);
const payload = await common.buildTemplatePayload(pool, req, template);
if (await common.fetchDuplicateName(pool, 'slide_templates', payload.name, template.id)) {
return res.redirect('/templates/' + template.id + '/edit?message=' + encodeURIComponent('A template with that name already exists.'));
}
const regionDeleteBlockMessage = await getTemplateRegionDeleteBlockMessage(template, payload.regions);
if (regionDeleteBlockMessage) {
return res.redirect('/templates/' + template.id + '/edit?message=' + encodeURIComponent(regionDeleteBlockMessage));
}
const nextUploadRefs = collectUploadReferencesFromPayload(payload);
const affectedScreens = await fetchScreensByTemplateId(pool, template.id);
const actorId = getAuditUserId(req);