Prepare v2.0.0 release

This commit is contained in:
2026-07-28 22:20:40 +01:00
parent de1469c29d
commit c643d2fb07
64 changed files with 809 additions and 1391 deletions
+23 -23
View File
@@ -22,7 +22,7 @@ module.exports = function registerAdminManageRoutes(app, deps) {
const requirePermission = deps.requirePermission;
async function fetchAllScreenSlugs() {
const [rows] = await pool.query('SELECT slug FROM screens ORDER BY slug ASC');
const [rows] = await pool.query('SELECT slug FROM d_screens ORDER BY slug ASC');
return (rows || [])
.map(function (row) {
return String(row && row.slug ? row.slug : '').trim();
@@ -89,11 +89,11 @@ module.exports = function registerAdminManageRoutes(app, deps) {
if (!name) {
return res.status(400).send('Playlist name is required.');
}
if (await common.fetchDuplicateName(pool, 'playlists', name)) {
if (await common.fetchDuplicateName(pool, 'c_playlists', name)) {
return res.status(400).send('A playlist with that name already exists.');
}
const actorId = getAuditUserId(req);
const [result] = await pool.query('INSERT INTO playlists (name, fade_between_slides, skip_unavailable_rtmp, created_by, modified_by) VALUES (?, ?, ?, ?, ?)', [name, fadeBetweenSlides, skipUnavailableRtmp, actorId, actorId]);
const [result] = await pool.query('INSERT INTO c_playlists (name, fade_between_slides, skip_unavailable_rtmp, created_by, modified_by) VALUES (?, ?, ?, ?, ?)', [name, fadeBetweenSlides, skipUnavailableRtmp, actorId, actorId]);
redirectAfterSave(req, res, '/playlists?edit=' + result.insertId, {
closeUrl: '/playlists',
newUrl: '/playlists/new',
@@ -117,7 +117,7 @@ module.exports = function registerAdminManageRoutes(app, deps) {
if (!playlist) {
return res.status(404).send('Playlist not found');
}
if (await common.fetchDuplicateName(pool, 'playlists', name, playlist.id)) {
if (await common.fetchDuplicateName(pool, 'c_playlists', name, playlist.id)) {
return res.status(400).send('A playlist with that name already exists.');
}
@@ -215,9 +215,9 @@ module.exports = function registerAdminManageRoutes(app, deps) {
if (normalizedSlides.length) {
const [slides] = await connection.query(
`SELECT sl.id, cs.width AS canvas_width, cs.height AS canvas_height
FROM slides sl
LEFT JOIN slide_templates st ON st.id = sl.template_id
LEFT JOIN canvas_sizes cs ON cs.id = st.canvas_size_id
FROM c_slides sl
LEFT JOIN c_templates st ON st.id = sl.template_id
LEFT JOIN c_canvas_sizes cs ON cs.id = st.canvas_size_id
WHERE sl.id IN (?)`,
[normalizedSlides.map(function (item) { return item.slideId; })]
);
@@ -237,12 +237,12 @@ module.exports = function registerAdminManageRoutes(app, deps) {
const actorId = getAuditUserId(req);
await connection.beginTransaction();
await connection.query('UPDATE playlists SET name = ?, fade_between_slides = ?, skip_unavailable_rtmp = ?, modified_by = ? WHERE id = ?', [name, fadeBetweenSlides, skipUnavailableRtmp, actorId, playlist.id]);
await connection.query('DELETE FROM playlist_slides WHERE playlist_id = ?', [playlist.id]);
await connection.query('UPDATE c_playlists SET name = ?, fade_between_slides = ?, skip_unavailable_rtmp = ?, modified_by = ? WHERE id = ?', [name, fadeBetweenSlides, skipUnavailableRtmp, actorId, playlist.id]);
await connection.query('DELETE FROM c_playlist_slides WHERE playlist_id = ?', [playlist.id]);
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, 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 (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
'INSERT INTO c_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,
@@ -290,7 +290,7 @@ module.exports = function registerAdminManageRoutes(app, deps) {
if (blockMessage) {
return res.redirect('/playlists?message=' + encodeURIComponent(blockMessage));
}
await pool.query('DELETE FROM playlists WHERE id = ?', [playlist.id]);
await pool.query('DELETE FROM c_playlists WHERE id = ?', [playlist.id]);
res.redirect('/playlists?message=' + encodeURIComponent('Playlist deleted.'));
} catch (error) {
next(error);
@@ -321,10 +321,10 @@ module.exports = function registerAdminManageRoutes(app, deps) {
}
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 [positionRows] = await pool.query('SELECT COALESCE(MAX(position), -1) AS max_position FROM c_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, use_video_duration, created_by, modified_by) VALUES (?, ?, ?, ?, ?, ?, ?)', [playlist.id, slideId, nextPosition, durationSeconds, 0, actorId, actorId]);
await pool.query('INSERT INTO c_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.'));
@@ -344,7 +344,7 @@ module.exports = function registerAdminManageRoutes(app, deps) {
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 = ?',
'UPDATE c_playlist_slides SET duration_seconds = ?, modified_by = ? WHERE id = ? AND playlist_id = ?',
[durationSeconds, actorId, playlistSlideId, playlist.id]
);
if (!result.affectedRows) {
@@ -391,8 +391,8 @@ module.exports = function registerAdminManageRoutes(app, deps) {
const swapSlide = orderedSlides[swapIndex];
const actorId = getAuditUserId(req);
await connection.query('UPDATE playlist_slides SET position = ?, modified_by = ? WHERE id = ? AND playlist_id = ?', [swapSlide.position, actorId, currentSlide.id, playlist.id]);
await connection.query('UPDATE playlist_slides SET position = ?, modified_by = ? WHERE id = ? AND playlist_id = ?', [currentSlide.position, actorId, swapSlide.id, playlist.id]);
await connection.query('UPDATE c_playlist_slides SET position = ?, modified_by = ? WHERE id = ? AND playlist_id = ?', [swapSlide.position, actorId, currentSlide.id, playlist.id]);
await connection.query('UPDATE c_playlist_slides SET position = ?, modified_by = ? WHERE id = ? AND playlist_id = ?', [currentSlide.position, actorId, swapSlide.id, playlist.id]);
await connection.commit();
await notifyPlayerScreens(await fetchScreensByPlaylistId(connection, playlist.id), 'refresh');
await broadcastDashboardState();
@@ -508,7 +508,7 @@ module.exports = function registerAdminManageRoutes(app, deps) {
const actorId = getAuditUserId(req);
const [result] = await pool.query(
'UPDATE playlist_slides SET schedule_mode = ?, schedule_start_datetime = ?, schedule_end_datetime = ?, schedule_start_time = ?, schedule_end_time = ?, schedule_days_json = ?, modified_by = ? WHERE id = ? AND playlist_id = ?',
'UPDATE c_playlist_slides SET schedule_mode = ?, schedule_start_datetime = ?, schedule_end_datetime = ?, schedule_start_time = ?, schedule_end_time = ?, schedule_days_json = ?, modified_by = ? WHERE id = ? AND playlist_id = ?',
[scheduleMode, scheduleStartDatetime, scheduleEndDatetime, scheduleStartTime, scheduleEndTime, scheduleDaysJson, actorId, playlistSlideId, playlist.id]
);
if (!result.affectedRows) {
@@ -528,7 +528,7 @@ module.exports = function registerAdminManageRoutes(app, deps) {
if (!playlist) {
return res.status(404).send('Playlist not found');
}
await pool.query('DELETE FROM playlist_slides WHERE id = ? AND playlist_id = ?', [Number(req.params.playlistSlideId), playlist.id]);
await pool.query('DELETE FROM c_playlist_slides WHERE id = ? AND playlist_id = ?', [Number(req.params.playlistSlideId), playlist.id]);
await notifyPlayerScreens(await fetchScreensByPlaylistId(pool, playlist.id), 'refresh');
await broadcastDashboardState();
res.redirect('/playlists?edit=' + playlist.id + '&message=' + encodeURIComponent('Slide removed.'));
@@ -552,14 +552,14 @@ module.exports = function registerAdminManageRoutes(app, deps) {
if (!name) {
return res.status(400).send('Screen name is required.');
}
if (await common.fetchDuplicateName(pool, 'screens', name)) {
if (await common.fetchDuplicateName(pool, 'd_screens', name)) {
return res.status(400).send('A screen with that name already exists.');
}
const slugInput = String(req.body.slug || '').trim();
const playlistId = req.body.playlist_id ? Number(req.body.playlist_id) : null;
const slug = await common.uniqueScreenSlug(pool, common.slugify(slugInput || name));
const actorId = getAuditUserId(req);
const [result] = await pool.query('INSERT INTO screens (name, slug, playlist_id, created_by, modified_by) VALUES (?, ?, ?, ?, ?)', [name, slug, playlistId, actorId, actorId]);
const [result] = await pool.query('INSERT INTO d_screens (name, slug, playlist_id, created_by, modified_by) VALUES (?, ?, ?, ?, ?)', [name, slug, playlistId, actorId, actorId]);
redirectAfterSave(req, res, '/screens?edit=' + result.insertId, {
closeUrl: '/screens',
newUrl: '/screens/new',
@@ -580,7 +580,7 @@ module.exports = function registerAdminManageRoutes(app, deps) {
if (!screen) {
return res.status(404).send('Screen not found');
}
if (await common.fetchDuplicateName(pool, 'screens', name, screen.id)) {
if (await common.fetchDuplicateName(pool, 'd_screens', name, screen.id)) {
return res.status(400).send('A screen with that name already exists.');
}
const slugInput = String(req.body.slug || '').trim();
@@ -588,7 +588,7 @@ module.exports = function registerAdminManageRoutes(app, deps) {
const previousPlaylistId = screen.playlist_id;
const slug = await common.uniqueScreenSlug(pool, common.slugify(slugInput || name), screen.id);
const previousSlug = String(screen.slug || '').trim();
await pool.query('UPDATE screens SET name = ?, slug = ?, playlist_id = ?, modified_by = ? WHERE id = ?', [name, slug, playlistId, getAuditUserId(req), screen.id]);
await pool.query('UPDATE d_screens SET name = ?, slug = ?, playlist_id = ?, modified_by = ? WHERE id = ?', [name, slug, playlistId, getAuditUserId(req), screen.id]);
if (previousPlaylistId !== playlistId && previousSlug) {
await notifyPlayerScreens([previousSlug], 'refresh');
}
@@ -618,7 +618,7 @@ module.exports = function registerAdminManageRoutes(app, deps) {
if (blockMessage) {
return res.redirect('/screens?message=' + encodeURIComponent(blockMessage));
}
await pool.query('DELETE FROM screens WHERE id = ?', [screen.id]);
await pool.query('DELETE FROM d_screens WHERE id = ?', [screen.id]);
res.redirect('/screens?message=' + encodeURIComponent('Screen deleted.'));
} catch (error) {
next(error);