Files
pulse-signage/src/web/lib/playlist-schedule.js
T
2026-08-03 12:45:27 +01:00

215 lines
5.3 KiB
JavaScript

// Shared schedule rule helpers for playlist playback and editor rendering.
const DAY_NAMES = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
function normalizeDateTimeValue(value) {
const raw = String(value || '').trim();
return raw ? raw : null;
}
function normalizeTimeValue(value) {
const raw = String(value || '').trim();
if (!raw) {
return null;
}
const match = raw.match(/^(\d{2}):(\d{2})(?::\d{2})?$/);
if (!match) {
return null;
}
return match[1] + ':' + match[2];
}
function normalizeDayValues(value) {
let days = [];
if (Array.isArray(value)) {
days = value;
} else if (value !== undefined && value !== null && String(value).trim()) {
try {
const parsed = typeof value === 'string' ? JSON.parse(value) : value;
if (Array.isArray(parsed)) {
days = parsed;
}
} catch (_error) {
days = String(value)
.split(',')
.map(function (item) {
return item.trim();
})
.filter(Boolean);
}
}
return Array.from(new Set(days.map(function (day) {
return Number(day);
}).filter(function (day) {
return Number.isInteger(day) && day >= 0 && day <= 6;
}))).sort(function (left, right) {
return left - right;
});
}
function normalizeScheduleRule(rule) {
const input = rule && typeof rule === 'object' ? rule : {};
const startDatetime = normalizeDateTimeValue(
input.start_datetime || input.startDateTime || input.schedule_start_datetime || input.scheduleStartDatetime
);
const endDatetime = normalizeDateTimeValue(
input.end_datetime || input.endDateTime || input.schedule_end_datetime || input.scheduleEndDatetime
);
const startTime = normalizeTimeValue(
input.start_time || input.startTime || input.schedule_start_time || input.scheduleStartTime
);
const endTime = normalizeTimeValue(
input.end_time || input.endTime || input.schedule_end_time || input.scheduleEndTime
);
const days = normalizeDayValues(
input.days || input.day_list || input.schedule_days || input.schedule_days_json || input.scheduleDays
);
if (startDatetime || endDatetime) {
if (!startDatetime || !endDatetime) {
return null;
}
}
if (startTime || endTime) {
if (!startTime || !endTime) {
return null;
}
}
if (!startDatetime && !endDatetime && !startTime && !endTime && !days.length) {
return null;
}
const normalized = {};
if (startDatetime) {
normalized.start_datetime = startDatetime;
}
if (endDatetime) {
normalized.end_datetime = endDatetime;
}
if (startTime) {
normalized.start_time = startTime;
}
if (endTime) {
normalized.end_time = endTime;
}
if (days.length) {
normalized.days = days;
}
return normalized;
}
function parseScheduleRules(value) {
let rawRules = [];
if (Array.isArray(value)) {
rawRules = value;
} else if (value && typeof value === 'object' && Array.isArray(value.rules)) {
rawRules = value.rules;
} else {
const rawValue = String(value || '').trim();
if (!rawValue) {
return [];
}
try {
const parsed = JSON.parse(rawValue);
rawRules = Array.isArray(parsed) ? parsed : [];
} catch (_error) {
return null;
}
}
return rawRules
.map(function (rule) {
return normalizeScheduleRule(rule);
})
.filter(Boolean);
}
function serializeScheduleRules(value) {
const normalized = parseScheduleRules(value);
if (normalized === null) {
return null;
}
return JSON.stringify(normalized);
}
function formatDateTime(value) {
const raw = String(value || '').trim();
if (!raw) {
return '';
}
return raw.replace('T', ' ').slice(0, 16);
}
function formatTime(value) {
const raw = String(value || '').trim();
if (!raw) {
return '';
}
return raw.slice(0, 5);
}
function formatDays(value) {
const days = normalizeDayValues(value);
return days
.map(function (day) {
return DAY_NAMES[day] || '';
})
.filter(Boolean)
.join(', ');
}
function formatScheduleRuleSummary(rule) {
const normalized = normalizeScheduleRule(rule);
if (!normalized) {
return 'Always visible';
}
const leftParts = [];
if (normalized.start_datetime && normalized.end_datetime) {
leftParts.push('Dates ' + formatDateTime(normalized.start_datetime) + ' to ' + formatDateTime(normalized.end_datetime));
} else {
leftParts.push('Any date');
}
const rightParts = [];
const days = formatDays(normalized.days || []);
if (days) {
rightParts.push(days);
}
if (normalized.start_time && normalized.end_time) {
rightParts.push(formatTime(normalized.start_time) + '-' + formatTime(normalized.end_time));
}
if (rightParts.length) {
return leftParts[0] + ': ' + rightParts.join(' ');
}
return leftParts[0];
}
function formatScheduleRulesSummary(value) {
const rules = parseScheduleRules(value) || [];
if (!rules.length) {
return 'Always visible';
}
return rules.length === 1 ? '1 rule' : String(rules.length) + ' rules';
}
module.exports = {
normalizeDateTimeValue: normalizeDateTimeValue,
normalizeTimeValue: normalizeTimeValue,
normalizeDayValues: normalizeDayValues,
normalizeScheduleRule: normalizeScheduleRule,
parseScheduleRules: parseScheduleRules,
serializeScheduleRules: serializeScheduleRules,
formatScheduleRuleSummary: formatScheduleRuleSummary,
formatScheduleRulesSummary: formatScheduleRulesSummary
};