Implement video region support

This commit is contained in:
2026-07-26 14:54:50 +01:00
parent 07ec17ad91
commit eb1f33d82f
30 changed files with 1243 additions and 134 deletions
+14 -5
View File
@@ -116,6 +116,7 @@ module.exports = function registerAdminManageRoutes(app, deps) {
const slideIds = readArrayField(req.body, ['slide_id[]', 'slide_id']);
const durations = readArrayField(req.body, ['duration_seconds[]', 'duration_seconds']);
const useVideoDurations = readArrayField(req.body, ['use_video_duration[]', 'use_video_duration']);
const scheduleModes = readArrayField(req.body, ['schedule_mode[]', 'schedule_mode']);
const scheduleStartDateTimes = readArrayField(req.body, ['schedule_start_datetime[]', 'schedule_start_datetime']);
const scheduleEndDateTimes = readArrayField(req.body, ['schedule_end_datetime[]', 'schedule_end_datetime']);
@@ -126,6 +127,9 @@ module.exports = function registerAdminManageRoutes(app, deps) {
if (durations.length && durations.length !== slideIds.length) {
return res.status(400).send('Playlist slide data is invalid.');
}
if (useVideoDurations.length && useVideoDurations.length !== slideIds.length) {
return res.status(400).send('Playlist slide data is invalid.');
}
if (scheduleModes.length && scheduleModes.length !== slideIds.length) {
return res.status(400).send('Playlist schedule data is invalid.');
}
@@ -143,7 +147,8 @@ module.exports = function registerAdminManageRoutes(app, deps) {
seenSlideIds.add(slideId);
const durationRaw = Number(durations[i]);
const durationSeconds = Number.isFinite(durationRaw) ? Math.max(1, Math.trunc(durationRaw)) : 10;
const durationSeconds = Number.isFinite(durationRaw) ? Math.max(0.001, Math.round(durationRaw * 1000) / 1000) : 10;
const useVideoDuration = String(useVideoDurations[i] || '') === '1' ? 1 : 0;
const scheduleMode = normalizeScheduleMode(scheduleModes[i]);
let scheduleStartDatetime = null;
@@ -188,6 +193,7 @@ module.exports = function registerAdminManageRoutes(app, deps) {
slideId,
position: i,
durationSeconds,
useVideoDuration,
scheduleMode,
scheduleStartDatetime,
scheduleEndDatetime,
@@ -227,12 +233,13 @@ module.exports = function registerAdminManageRoutes(app, deps) {
for (let i = 0; i < normalizedSlides.length; i += 1) {
const item = normalizedSlides[i];
await connection.query(
'INSERT INTO playlist_slides (playlist_id, slide_id, position, duration_seconds, schedule_mode, schedule_start_datetime, schedule_end_datetime, schedule_start_time, schedule_end_time, schedule_days_json, created_by, modified_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
'INSERT INTO playlist_slides (playlist_id, slide_id, position, duration_seconds, use_video_duration, schedule_mode, schedule_start_datetime, schedule_end_datetime, schedule_start_time, schedule_end_time, schedule_days_json, created_by, modified_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
[
playlist.id,
item.slideId,
item.position,
item.durationSeconds,
item.useVideoDuration,
item.scheduleMode,
item.scheduleStartDatetime,
item.scheduleEndDatetime,
@@ -303,11 +310,12 @@ module.exports = function registerAdminManageRoutes(app, deps) {
if (playlistCanvasSignature && slideCanvasSignature !== playlistCanvasSignature) {
return res.status(400).send('The slide canvas size must match the existing playlist items.');
}
const durationSeconds = Math.max(1, Number(req.body.duration_seconds || 10));
const durationValue = Number(req.body.duration_seconds || 10);
const durationSeconds = Number.isFinite(durationValue) ? Math.max(0.001, Math.round(durationValue * 1000) / 1000) : 10;
const [positionRows] = await pool.query('SELECT COALESCE(MAX(position), -1) AS max_position FROM playlist_slides WHERE playlist_id = ?', [playlist.id]);
const nextPosition = Number(positionRows[0].max_position) + 1;
const actorId = getAuditUserId(req);
await pool.query('INSERT INTO playlist_slides (playlist_id, slide_id, position, duration_seconds, created_by, modified_by) VALUES (?, ?, ?, ?, ?, ?)', [playlist.id, slideId, nextPosition, durationSeconds, actorId, actorId]);
await pool.query('INSERT INTO playlist_slides (playlist_id, slide_id, position, duration_seconds, use_video_duration, created_by, modified_by) VALUES (?, ?, ?, ?, ?, ?, ?)', [playlist.id, slideId, nextPosition, durationSeconds, 0, actorId, actorId]);
await notifyPlayerScreens(await fetchScreensByPlaylistId(pool, playlist.id), 'refresh');
await broadcastDashboardState();
res.redirect('/playlists?edit=' + playlist.id + '&message=' + encodeURIComponent('Slide added to playlist.'));
@@ -323,7 +331,8 @@ module.exports = function registerAdminManageRoutes(app, deps) {
return res.status(404).send('Playlist not found');
}
const playlistSlideId = Number(req.params.playlistSlideId);
const durationSeconds = Math.max(1, Number(req.body.duration_seconds || 10));
const durationValue = Number(req.body.duration_seconds || 10);
const durationSeconds = Number.isFinite(durationValue) ? Math.max(0.001, Math.round(durationValue * 1000) / 1000) : 10;
const actorId = getAuditUserId(req);
const [result] = await pool.query(
'UPDATE playlist_slides SET duration_seconds = ?, modified_by = ? WHERE id = ? AND playlist_id = ?',