Release 2.8.0
This commit is contained in:
@@ -23,6 +23,7 @@ function buildAnnouncementFormViewModel(announcement, message, currentUser, opti
|
||||
const announcementTypes = Array.isArray(options && options.announcementTypes) ? options.announcementTypes : [];
|
||||
const announcementColors = Array.isArray(options && options.announcementColors) ? options.announcementColors : [];
|
||||
const announcementIcons = Array.isArray(options && options.announcementIcons) ? options.announcementIcons : [];
|
||||
const announcementIconCatalog = Array.isArray(options && options.announcementIconCatalog) ? options.announcementIconCatalog : announcementIcons;
|
||||
const announcementScreens = Array.isArray(options && options.announcementScreens) ? options.announcementScreens : [];
|
||||
const viewOptions = options || {};
|
||||
const viewAnnouncement = Object.assign({}, buildDefaultAnnouncement(), announcement || {});
|
||||
@@ -68,6 +69,7 @@ function buildAnnouncementFormViewModel(announcement, message, currentUser, opti
|
||||
announcementTypes: announcementTypes,
|
||||
announcementColors: announcementColors,
|
||||
announcementIcons: announcementIcons,
|
||||
announcementIconCatalog: announcementIconCatalog,
|
||||
announcementScreens: announcementScreens
|
||||
};
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ module.exports = function registerAnnouncementRoutes(app, deps) {
|
||||
const { buildPagination } = require('../../../lib/pagination');
|
||||
const announcementData = require('#src/data/announcements');
|
||||
const announcementIcons = require('#src/data/announcement-icons');
|
||||
const { fetchAppSettings } = require('#src/data/app-settings');
|
||||
const { buildDuplicateAnnouncementName, buildDuplicateAnnouncement } = require('./duplicate');
|
||||
|
||||
const LIST_PAGE_SIZE = 25;
|
||||
@@ -30,6 +31,21 @@ module.exports = function registerAnnouncementRoutes(app, deps) {
|
||||
{ value: 'light', label: 'Light' }
|
||||
];
|
||||
const ANNOUNCEMENT_ICONS = announcementIcons.ANNOUNCEMENT_ICON_OPTIONS || [];
|
||||
const ANNOUNCEMENT_ICON_CATALOG = announcementIcons.ANNOUNCEMENT_ICON_CATALOG || ANNOUNCEMENT_ICONS;
|
||||
|
||||
async function fetchSuggestedAnnouncementIcons() {
|
||||
const settings = await fetchAppSettings(pool);
|
||||
const catalogByKey = new Map(ANNOUNCEMENT_ICON_CATALOG.map(function (option) {
|
||||
return [option.value, option];
|
||||
}));
|
||||
const configuredKeys = Array.isArray(settings['announcements.suggested_icons'])
|
||||
? settings['announcements.suggested_icons']
|
||||
: [];
|
||||
const configuredOptions = configuredKeys.map(function (key) {
|
||||
return catalogByKey.get(String(key || '').trim().toLowerCase()) || null;
|
||||
}).filter(Boolean);
|
||||
return configuredOptions.length ? configuredOptions : ANNOUNCEMENT_ICONS;
|
||||
}
|
||||
|
||||
function normalizeDurationUnit(value) {
|
||||
return String(value || 'minutes').trim().toLowerCase() === 'seconds' ? 'seconds' : 'minutes';
|
||||
@@ -269,21 +285,28 @@ module.exports = function registerAnnouncementRoutes(app, deps) {
|
||||
app.get('/announcements/new', requirePermission('announcements.create'), async function (req, res, next) {
|
||||
try {
|
||||
const screens = await fetchAnnouncementScreens();
|
||||
const suggestedAnnouncementIcons = await fetchSuggestedAnnouncementIcons();
|
||||
const settings = await fetchAppSettings(pool);
|
||||
const configuredIcon = String(settings['announcements.default_icon'] || '').trim().toLowerCase();
|
||||
const defaultIcon = ANNOUNCEMENT_ICON_CATALOG.some(function (option) { return option.value === configuredIcon; })
|
||||
? configuredIcon
|
||||
: (suggestedAnnouncementIcons[0] && suggestedAnnouncementIcons[0].value ? suggestedAnnouncementIcons[0].value : announcementIcons.DEFAULT_ANNOUNCEMENT_ICON);
|
||||
res.send(pages.renderAnnouncementAddPage(buildAnnouncementFormData({
|
||||
message: '',
|
||||
short_label: '',
|
||||
announcement_type: 'lower-third',
|
||||
color_key: 'primary',
|
||||
icon_key: announcementIcons.DEFAULT_ANNOUNCEMENT_ICON,
|
||||
icon_key: defaultIcon,
|
||||
durationMode: 'duration',
|
||||
duration_seconds: null,
|
||||
durationValue: 5,
|
||||
durationUnit: 'minutes',
|
||||
durationValue: Number(settings['announcements.default_duration_value']) || 10,
|
||||
durationUnit: String(settings['announcements.default_duration_unit'] || 'seconds'),
|
||||
screen_ids: []
|
||||
}), req.query.message ? String(req.query.message) : '', req.currentUser, {
|
||||
announcementTypes: ANNOUNCEMENT_TYPES,
|
||||
announcementColors: ANNOUNCEMENT_COLORS,
|
||||
announcementIcons: ANNOUNCEMENT_ICONS,
|
||||
announcementIcons: suggestedAnnouncementIcons,
|
||||
announcementIconCatalog: ANNOUNCEMENT_ICON_CATALOG,
|
||||
announcementScreens: buildAnnouncementScreenOptions(screens, [])
|
||||
}));
|
||||
} catch (error) {
|
||||
@@ -301,7 +324,8 @@ module.exports = function registerAnnouncementRoutes(app, deps) {
|
||||
res.send(pages.renderAnnouncementEditPage(buildAnnouncementFormData(announcement), null, req.query.message ? String(req.query.message) : '', req.currentUser, {
|
||||
announcementTypes: ANNOUNCEMENT_TYPES,
|
||||
announcementColors: ANNOUNCEMENT_COLORS,
|
||||
announcementIcons: ANNOUNCEMENT_ICONS,
|
||||
announcementIcons: await fetchSuggestedAnnouncementIcons(),
|
||||
announcementIconCatalog: ANNOUNCEMENT_ICON_CATALOG,
|
||||
announcementScreens: buildAnnouncementScreenOptions(screens, announcement.screen_ids || [])
|
||||
}));
|
||||
} catch (error) {
|
||||
@@ -327,7 +351,8 @@ module.exports = function registerAnnouncementRoutes(app, deps) {
|
||||
res.send(pages.renderAnnouncementAddPage(buildAnnouncementFormData(buildDuplicateAnnouncement(announcement, duplicateName)), req.query.message ? String(req.query.message) : 'Review the copied values and save when ready.', req.currentUser, {
|
||||
announcementTypes: ANNOUNCEMENT_TYPES,
|
||||
announcementColors: ANNOUNCEMENT_COLORS,
|
||||
announcementIcons: ANNOUNCEMENT_ICONS,
|
||||
announcementIcons: await fetchSuggestedAnnouncementIcons(),
|
||||
announcementIconCatalog: ANNOUNCEMENT_ICON_CATALOG,
|
||||
announcementScreens: buildAnnouncementScreenOptions(screens, announcement.screen_ids || []),
|
||||
messageVariant: 'info'
|
||||
}));
|
||||
|
||||
@@ -175,6 +175,7 @@ function formatCanvasSizeLabel(size) {
|
||||
|
||||
function buildPlaylistFormViewModel(playlist, data, message, currentUser, options) {
|
||||
const isEdit = Boolean(options && options.isEdit);
|
||||
const defaultSlideDurationSeconds = Number(data && data.defaultSlideDurationSeconds) || 10;
|
||||
const viewPlaylist = Object.assign({
|
||||
id: null,
|
||||
name: '',
|
||||
@@ -245,7 +246,7 @@ function buildPlaylistFormViewModel(playlist, data, message, currentUser, option
|
||||
videoDurationSeconds: '',
|
||||
useVideoDuration: false,
|
||||
disableAudio: true,
|
||||
durationSeconds: 10,
|
||||
durationSeconds: defaultSlideDurationSeconds,
|
||||
scheduleRules: [],
|
||||
scheduleSummary: 'Always visible',
|
||||
displayOrder: ''
|
||||
@@ -280,7 +281,8 @@ function buildPlaylistFormViewModel(playlist, data, message, currentUser, option
|
||||
selectableSlides: selectableSlides,
|
||||
playlistCanvasId: playlistCanvasId,
|
||||
playlistCanvasMismatch: playlistCanvasMismatch,
|
||||
scripts: ['js/lib/modal.js?v=20260726.7', 'js/playlists/playlist-table-drag.js?v=20260802.5', 'js/playlists/playlist-schedule.js?v=20260803.1'],
|
||||
defaultSlideDurationSeconds: defaultSlideDurationSeconds,
|
||||
scripts: ['js/lib/modal.js?v=20260726.7', 'js/playlists/playlist-table-drag.js?v=20260802.5', 'js/playlists/playlist-schedule.js?v=20260816.1'],
|
||||
message: message,
|
||||
currentUser: currentUser || null,
|
||||
inUse: Boolean(viewPlaylist.inUse)
|
||||
|
||||
@@ -8,6 +8,7 @@ module.exports = function registerPlaylistsRoutes(app, deps) {
|
||||
const { buildPagination } = require('../../../lib/pagination');
|
||||
const requirePermission = deps.requirePermission;
|
||||
const { buildDuplicatePlaylistName, buildDuplicatePlaylist } = require('./duplicate');
|
||||
const { fetchAppSettings } = require('../../../../data/app-settings');
|
||||
|
||||
const LIST_PAGE_SIZE = 25;
|
||||
|
||||
@@ -31,6 +32,8 @@ module.exports = function registerPlaylistsRoutes(app, deps) {
|
||||
return res.status(404).send('Playlist not found');
|
||||
}
|
||||
playlist.inUse = (await fetchScreensByPlaylistId(pool, playlist.id)).length > 0;
|
||||
const settings = await fetchAppSettings(pool);
|
||||
data.defaultSlideDurationSeconds = Number(settings['player.default_slide_duration_seconds']) || 10;
|
||||
return res.send(pages.renderPlaylistEditPage(playlist, data, req.query.message ? String(req.query.message) : '', req.currentUser));
|
||||
}
|
||||
const data = await common.fetchPlaylistsPage(pool, page, LIST_PAGE_SIZE, search, sort, direction);
|
||||
@@ -46,7 +49,12 @@ module.exports = function registerPlaylistsRoutes(app, deps) {
|
||||
app.get('/playlists/new', requirePermission('playlists.create'), function (req, res) {
|
||||
(async function () {
|
||||
const data = await common.fetchAdminData(pool);
|
||||
res.send(await pages.renderPlaylistFormPage(req.query.message ? String(req.query.message) : '', req.currentUser, data, pool));
|
||||
const settings = await fetchAppSettings(pool);
|
||||
data.defaultSlideDurationSeconds = Number(settings['player.default_slide_duration_seconds']) || 10;
|
||||
res.send(await pages.renderPlaylistFormPage({
|
||||
fade_between_slides: Boolean(settings['player.default_fade_between_slides']),
|
||||
skip_unavailable_rtmp: Boolean(settings['player.skip_unavailable_rtmp'])
|
||||
}, req.query.message ? String(req.query.message) : '', req.currentUser, data, pool));
|
||||
})().catch(function (error) {
|
||||
res.status(500).send(error.message || 'Unable to load page.');
|
||||
});
|
||||
@@ -81,6 +89,8 @@ module.exports = function registerPlaylistsRoutes(app, deps) {
|
||||
return res.status(404).send('Playlist not found');
|
||||
}
|
||||
const data = await common.fetchAdminData(pool);
|
||||
const settings = await fetchAppSettings(pool);
|
||||
data.defaultSlideDurationSeconds = Number(settings['player.default_slide_duration_seconds']) || 10;
|
||||
playlist.inUse = (await fetchScreensByPlaylistId(pool, playlist.id)).length > 0;
|
||||
res.send(pages.renderPlaylistEditPage(playlist, data, req.query.message ? String(req.query.message) : '', req.currentUser));
|
||||
} catch (error) {
|
||||
|
||||
@@ -26,6 +26,7 @@ function buildSlideFormViewModel(data, slide, message, currentUser, isEdit) {
|
||||
const apiSources = data && data.apiSources ? data.apiSources : [];
|
||||
const timetableGroups = data && data.timetableGroups ? data.timetableGroups : [];
|
||||
const fontLibrary = data && data.fontLibrary ? data.fontLibrary : null;
|
||||
const uploadLimits = data && data.uploadLimits ? data.uploadLimits : {};
|
||||
const templates = buildTemplates(data && data.templates ? data.templates : [], templateRegions);
|
||||
const viewSlide = slide || buildDefaultSlide();
|
||||
|
||||
@@ -50,7 +51,8 @@ function buildSlideFormViewModel(data, slide, message, currentUser, isEdit) {
|
||||
fontStylesheetHref: fontLibrary && fontLibrary.stylesheetHref ? fontLibrary.stylesheetHref : '',
|
||||
fontFamilyFormats: fontLibrary && fontLibrary.fontFamilyFormats ? fontLibrary.fontFamilyFormats : '',
|
||||
existingTemplateId: viewSlide && viewSlide.template_id ? viewSlide.template_id : null,
|
||||
existingContent: viewSlide && viewSlide.content ? viewSlide.content : {}
|
||||
existingContent: viewSlide && viewSlide.content ? viewSlide.content : {},
|
||||
uploadLimits: uploadLimits
|
||||
},
|
||||
assetVersion: assetVersion,
|
||||
slideEditorScripts: ['vendor/qr-code-styling/qr-code-styling-loader.js?v=' + assetVersion].concat(getRegionEditorScripts(assetVersion)),
|
||||
|
||||
Reference in New Issue
Block a user