Release 2.8.2
Publish Docker Image / build-and-push-existing-registry (./build/Dockerfile, web, pulse-signage-web) (push) Successful in 1m12s
Publish Docker Image / build-and-push-existing-registry (./build/Dockerfile.player, player, pulse-signage-player) (push) Successful in 34s

This commit is contained in:
2026-08-16 22:41:39 +01:00
parent a5bf8e6f7f
commit ea72747822
31 changed files with 379 additions and 31 deletions
+55 -3
View File
@@ -4,6 +4,7 @@ const fs = require('fs');
const path = require('path');
const { loadFontLibrary } = require('#src/web/lib/media/font-library');
const { fetchAppSettings } = require('#src/data/app-settings');
const { buildAuditChanges } = require('#src/data/audit-log');
const { PERMISSION_DENIED_MESSAGE } = require('#src/rbac');
module.exports = function registerContentRoutes(app, deps) {
@@ -39,6 +40,26 @@ module.exports = function registerContentRoutes(app, deps) {
const IMAGE_UPLOAD_MAX_BYTES = 100 * 1024 * 1024;
const VIDEO_UPLOAD_MAX_BYTES = 1024 * 1024 * 1024;
function normalizeTemplateRegionsForAudit(regions) {
return (Array.isArray(regions) ? regions : []).map(function (region) {
const animation = typeof region.animation_json === 'string'
? common.parseJsonSafe(region.animation_json) || {}
: region.animation_json || {};
return {
region_key: region.region_key,
region_type: region.region_type,
label: region.label,
lock_ratio: region.lock_ratio,
animation_json: animation,
x: Number(region.x),
y: Number(region.y),
width: Number(region.width),
height: Number(region.height),
z_index: Number(region.z_index)
};
});
}
async function fetchSlideFormData() {
const data = await common.fetchTemplatesData(pool);
const rssData = await common.fetchRssFeedsData(pool);
@@ -497,6 +518,15 @@ module.exports = function registerContentRoutes(app, deps) {
}
const nextUploadRefs = collectUploadReferencesFromPayload(payload);
const actorId = getAuditUserId(req);
const changes = buildAuditChanges({
title: slide.title,
templateId: Number(slide.template_id),
content: slide.content
}, {
title: payload.title,
templateId: Number(payload.templateId),
content: common.parseJsonSafe(payload.contentJson) || {}
});
await pool.query(
'UPDATE c_slides SET title = ?, template_id = ?, content_json = ?, modified_by = ? WHERE id = ?',
[payload.title, payload.templateId, payload.contentJson, actorId, slide.id]
@@ -512,7 +542,7 @@ module.exports = function registerContentRoutes(app, deps) {
screenSlideCounts: screenSlideCounts
});
await broadcastDashboardState();
if (typeof recordRequestAuditEvent === 'function') await recordRequestAuditEvent(pool, req, { category: 'slides', eventType: 'slide.updated', actorUserId: actorId, targetType: 'slide', targetId: slide.id, targetLabel: payload.title });
if (typeof recordRequestAuditEvent === 'function') await recordRequestAuditEvent(pool, req, { category: 'slides', eventType: 'slide.updated', actorUserId: actorId, targetType: 'slide', targetId: slide.id, targetLabel: payload.title, details: { changes: changes } });
queueSlideThumbnailRefresh(slide.id, slide.thumbnail_path).catch(function (error) {
console.warn('Unable to queue slide thumbnail refresh:', error);
});
@@ -655,6 +685,19 @@ module.exports = function registerContentRoutes(app, deps) {
const nextUploadRefs = collectUploadReferencesFromPayload(payload);
const affectedScreens = await fetchScreensByTemplateId(pool, template.id);
const actorId = getAuditUserId(req);
const changes = buildAuditChanges({
name: template.name,
canvasSizeId: Number(template.canvas_size_id),
backgroundImagePath: template.background_image_path,
backgroundColor: template.background_color,
regions: normalizeTemplateRegionsForAudit(template.regions)
}, {
name: payload.name,
canvasSizeId: Number(payload.canvasSizeId),
backgroundImagePath: payload.backgroundImagePath,
backgroundColor: payload.backgroundColor,
regions: normalizeTemplateRegionsForAudit(payload.regions)
});
await pool.query(
'UPDATE c_templates SET name = ?, canvas_size_id = ?, background_image_path = ?, background_color = ?, modified_by = ? WHERE id = ?',
[payload.name, payload.canvasSizeId, payload.backgroundImagePath, payload.backgroundColor, actorId, template.id]
@@ -681,7 +724,7 @@ module.exports = function registerContentRoutes(app, deps) {
});
}
await notifyPlayerScreens(affectedScreens, 'refresh');
if (typeof recordRequestAuditEvent === 'function') await recordRequestAuditEvent(pool, req, { category: 'templates', eventType: 'template.updated', actorUserId: actorId, targetType: 'template', targetId: template.id, targetLabel: payload.name });
if (typeof recordRequestAuditEvent === 'function') await recordRequestAuditEvent(pool, req, { category: 'templates', eventType: 'template.updated', actorUserId: actorId, targetType: 'template', targetId: template.id, targetLabel: payload.name, details: { changes: changes } });
redirectAfterSave(req, res, '/templates/' + template.id + '/edit', {
closeUrl: '/templates',
newUrl: '/templates/new',
@@ -813,8 +856,17 @@ module.exports = function registerContentRoutes(app, deps) {
if (await canvasSizeExists(payload.width, payload.height, canvasSize.id)) {
return res.status(400).send('That canvas size already exists.');
}
const changes = buildAuditChanges({
name: canvasSize.name,
width: Number(canvasSize.width),
height: Number(canvasSize.height)
}, {
name: payload.name,
width: payload.width,
height: payload.height
});
await pool.query('UPDATE c_canvas_sizes SET name = ?, width = ?, height = ?, modified_by = ? WHERE id = ?', [payload.name, payload.width, payload.height, getAuditUserId(req), canvasSize.id]);
if (typeof recordRequestAuditEvent === 'function') await recordRequestAuditEvent(pool, req, { category: 'canvas-sizes', eventType: 'canvas-size.updated', actorUserId: getAuditUserId(req), targetType: 'canvas-size', targetId: canvasSize.id, targetLabel: payload.name, details: { width: payload.width, height: payload.height } });
if (typeof recordRequestAuditEvent === 'function') await recordRequestAuditEvent(pool, req, { category: 'canvas-sizes', eventType: 'canvas-size.updated', actorUserId: getAuditUserId(req), targetType: 'canvas-size', targetId: canvasSize.id, targetLabel: payload.name, details: { changes: changes } });
redirectAfterSave(req, res, '/canvas-sizes', {
closeUrl: '/canvas-sizes',
newUrl: '/canvas-sizes/new',