// Admin data aggregation helpers for dashboards, playlists, slides, templates, and screens. const { fetchPagedRows } = require('./utils'); async function fetchAdminData(pool) { const [playlists] = await pool.query('SELECT id, name, fade_between_slides, skip_unavailable_rtmp, created_at, modified_at, created_by, modified_by FROM c_playlists ORDER BY id DESC'); const [canvasSizes] = await pool.query('SELECT id, name, width, height, created_at, modified_at, created_by, modified_by FROM c_canvas_sizes ORDER BY width ASC, height ASC, name ASC'); const [templates] = await pool.query(` SELECT st.id, st.name, st.canvas_size_id, st.background_image_path, st.background_color, st.created_at, st.modified_at, cs.name AS canvas_size_name, cs.width AS canvas_size_width, cs.height AS canvas_size_height FROM c_templates st LEFT JOIN c_canvas_sizes cs ON cs.id = st.canvas_size_id ORDER BY st.id DESC `); const [templateRegions] = await pool.query('SELECT id, template_id, region_key, region_type, label, lock_ratio, x, y, width, height, z_index, created_at, modified_at, created_by, modified_by FROM c_template_regions ORDER BY template_id ASC, z_index ASC, id ASC'); const [slides] = await pool.query(` SELECT s.id, s.title, s.template_id, s.content_json, s.thumbnail_path, s.created_at, s.modified_at, s.created_by, s.modified_by, st.name AS template_name, st.canvas_size_id, cs.width AS canvas_width, cs.height AS canvas_height, (SELECT COUNT(DISTINCT ps.playlist_id) FROM c_playlist_slides ps WHERE ps.slide_id = s.id) AS playlist_count FROM c_slides s LEFT JOIN c_templates st ON st.id = s.template_id LEFT JOIN c_canvas_sizes cs ON cs.id = st.canvas_size_id ORDER BY s.id DESC `); const [screens] = await pool.query(` SELECT s.id, s.name, s.slug, s.playlist_id, s.created_at, s.modified_at, s.created_by, s.modified_by, p.name AS playlist_name, pl.public_base_url FROM d_screens s LEFT JOIN c_playlists p ON p.id = s.playlist_id LEFT JOIN d_players pl ON pl.device_id = s.player_id ORDER BY s.id DESC `); const [playlistSlides] = await pool.query(` SELECT ps.id, ps.playlist_id, ps.position, ps.duration_seconds, ps.use_video_duration, ps.disable_audio, sl.id AS slide_id, sl.title, sl.content_json, sl.thumbnail_path, st.canvas_size_id, cs.width AS canvas_width, cs.height AS canvas_height FROM c_playlist_slides ps JOIN c_slides sl ON sl.id = ps.slide_id LEFT JOIN c_templates st ON st.id = sl.template_id LEFT JOIN c_canvas_sizes cs ON cs.id = st.canvas_size_id ORDER BY ps.playlist_id ASC, ps.position ASC, ps.id ASC `); const [playlistScheduleRules] = await pool.query(` SELECT id, playlist_slide_id, position, start_datetime, end_datetime, start_time, end_time, schedule_days_json, created_at, modified_at, created_by, modified_by FROM c_playlist_slide_schedule_rules ORDER BY playlist_slide_id ASC, position ASC, id ASC `); const rulesBySlideId = new Map(); playlistScheduleRules.forEach(function (rule) { const slideId = Number(rule.playlist_slide_id); if (!rulesBySlideId.has(slideId)) { rulesBySlideId.set(slideId, []); } rulesBySlideId.get(slideId).push(rule); }); const playlistSlidesWithRules = playlistSlides.map(function (slide) { return Object.assign({}, slide, { scheduleRules: rulesBySlideId.get(Number(slide.id)) || [] }); }); return { playlists, canvasSizes, templates, templateRegions, slides, screens, playlistSlides: playlistSlidesWithRules }; } async function fetchPlaylistsPage(pool, page, pageSize, searchTerm, sortKey, sortDirection) { const paged = await fetchPagedRows(pool, { selectSql: `SELECT p.id, p.name, p.fade_between_slides, p.skip_unavailable_rtmp, p.created_at, p.modified_at, p.created_by, p.modified_by, (SELECT COUNT(*) FROM c_playlist_slides ps WHERE ps.playlist_id = p.id) AS slide_count, (SELECT COUNT(*) FROM d_screens s WHERE s.playlist_id = p.id) AS screen_count FROM c_playlists p ORDER BY p.id DESC`, countSql: 'SELECT COUNT(*) AS count FROM c_playlists', searchColumns: ['p.name'], searchTerm: searchTerm, sortColumns: { name: 'p.name', slides: 'slide_count', created: 'p.created_at', modified: 'p.modified_at' }, sortKey: sortKey, sortDirection: sortDirection, page: page, pageSize: pageSize }); return Object.assign({ playlists: paged.rows }, paged); } async function fetchSlidesPage(pool, page, pageSize, searchTerm, sortKey, sortDirection) { const paged = await fetchPagedRows(pool, { selectSql: `SELECT s.id, s.title, s.template_id, s.content_json, s.thumbnail_path, s.created_at, s.modified_at, s.created_by, s.modified_by, st.name AS template_name, cs.width AS canvas_width, cs.height AS canvas_height, (SELECT COUNT(DISTINCT ps.playlist_id) FROM c_playlist_slides ps WHERE ps.slide_id = s.id) AS playlist_count FROM c_slides s LEFT JOIN c_templates st ON st.id = s.template_id LEFT JOIN c_canvas_sizes cs ON cs.id = st.canvas_size_id ORDER BY s.id DESC`, countSql: 'SELECT COUNT(*) AS count FROM c_slides', searchColumns: ['s.title', 'st.name'], searchTerm: searchTerm, sortColumns: { title: 's.title', template: 'st.name', created: 's.created_at', modified: 's.modified_at' }, sortKey: sortKey, sortDirection: sortDirection, page: page, pageSize: pageSize }); return Object.assign({ slides: paged.rows }, paged); } async function fetchTemplatesPage(pool, page, pageSize, searchTerm, sortKey, sortDirection) { const paged = await fetchPagedRows(pool, { selectSql: `SELECT st.id, st.name, st.canvas_size_id, st.background_image_path, st.background_color, st.created_at, st.modified_at, cs.name AS canvas_size_name, cs.width AS canvas_size_width, cs.height AS canvas_size_height, (SELECT COUNT(*) FROM c_template_regions str WHERE str.template_id = st.id) AS region_count, (SELECT COUNT(*) FROM c_slides s WHERE s.template_id = st.id) AS slide_count FROM c_templates st LEFT JOIN c_canvas_sizes cs ON cs.id = st.canvas_size_id ORDER BY st.id DESC`, countSql: 'SELECT COUNT(*) AS count FROM c_templates', searchColumns: ['st.name', 'st.background_image_path', 'st.background_color', 'cs.name'], searchTerm: searchTerm, sortColumns: { name: 'st.name', canvas: ['cs.width', 'cs.height', 'cs.name'], regions: 'region_count', slides: 'slide_count', created: 'st.created_at', modified: 'st.modified_at' }, sortKey: sortKey, sortDirection: sortDirection, page: page, pageSize: pageSize }); return Object.assign({ templates: paged.rows }, paged); } async function fetchCanvasSizesPage(pool, page, pageSize, searchTerm, sortKey, sortDirection) { const paged = await fetchPagedRows(pool, { selectSql: `SELECT id, name, width, height, created_at, modified_at, created_by, modified_by, (SELECT COUNT(*) FROM c_templates st WHERE st.canvas_size_id = c_canvas_sizes.id) AS template_count FROM c_canvas_sizes ORDER BY width ASC, height ASC, name ASC`, countSql: 'SELECT COUNT(*) AS count FROM c_canvas_sizes', searchColumns: ['name', 'width', 'height'], searchTerm: searchTerm, sortColumns: { name: 'name', dimensions: ['width', 'height', 'name'], templates: 'template_count', created: 'created_at', modified: 'modified_at' }, sortKey: sortKey, sortDirection: sortDirection, page: page, pageSize: pageSize }); return Object.assign({ canvasSizes: paged.rows }, paged); } async function fetchScreensPage(pool, page, pageSize, searchTerm, sortKey, sortDirection) { const paged = await fetchPagedRows(pool, { selectSql: `SELECT s.id, s.name, s.slug, s.playlist_id, s.created_at, s.modified_at, s.created_by, s.modified_by, p.name AS playlist_name FROM d_screens s LEFT JOIN c_playlists p ON p.id = s.playlist_id ORDER BY s.id DESC`, countSql: 'SELECT COUNT(*) AS count FROM d_screens', searchColumns: ['s.name', 's.slug', 'p.name'], searchTerm: searchTerm, sortColumns: { name: 's.name', url: 's.slug', playlist: 'p.name', created: 's.created_at', modified: 's.modified_at' }, sortKey: sortKey, sortDirection: sortDirection, page: page, pageSize: pageSize }); return Object.assign({ screens: paged.rows }, paged); } module.exports = { fetchAdminData, fetchPlaylistsPage, fetchSlidesPage, fetchTemplatesPage, fetchCanvasSizesPage, fetchScreensPage };