Save worktree changes
This commit is contained in:
@@ -0,0 +1,192 @@
|
||||
const dashboardDateFormatter = new Intl.DateTimeFormat('en-US', {
|
||||
month: 'short',
|
||||
day: '2-digit',
|
||||
year: 'numeric',
|
||||
hour: 'numeric',
|
||||
minute: '2-digit',
|
||||
second: '2-digit'
|
||||
});
|
||||
|
||||
function normalizeUploadRoot(uploadDir) {
|
||||
return require('path').resolve(String(uploadDir || '').trim());
|
||||
}
|
||||
|
||||
function formatDashboardDate(value) {
|
||||
if (!value) {
|
||||
return '';
|
||||
}
|
||||
const date = new Date(value);
|
||||
if (Number.isNaN(date.getTime())) {
|
||||
return '';
|
||||
}
|
||||
return dashboardDateFormatter.format(date);
|
||||
}
|
||||
|
||||
function buildDashboardPayload(state) {
|
||||
return JSON.stringify({
|
||||
type: 'dashboard-state',
|
||||
state: state
|
||||
});
|
||||
}
|
||||
|
||||
function readArrayField(body, keys) {
|
||||
const searchKeys = Array.isArray(keys) ? keys : [keys];
|
||||
for (let i = 0; i < searchKeys.length; i += 1) {
|
||||
const key = searchKeys[i];
|
||||
const value = body && Object.prototype.hasOwnProperty.call(body, key) ? body[key] : undefined;
|
||||
if (Array.isArray(value)) {
|
||||
return value.filter(function (item) {
|
||||
return item !== undefined && item !== null && String(item).trim() !== '';
|
||||
}).map(function (item) {
|
||||
return String(item);
|
||||
});
|
||||
}
|
||||
if (value !== undefined && value !== null && String(value).trim() !== '') {
|
||||
return [String(value)];
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
function parseDateTimeLocal(value) {
|
||||
if (!value) {
|
||||
return null;
|
||||
}
|
||||
const date = new Date(String(value));
|
||||
return Number.isNaN(date.getTime()) ? null : date;
|
||||
}
|
||||
|
||||
function parseTimeLocal(value) {
|
||||
const raw = String(value || '').trim();
|
||||
if (!raw) {
|
||||
return null;
|
||||
}
|
||||
if (!/^\d{2}:\d{2}(:\d{2})?$/.test(raw)) {
|
||||
return null;
|
||||
}
|
||||
return raw.length === 5 ? raw + ':00' : raw;
|
||||
}
|
||||
|
||||
function normalizeScheduleMode(value) {
|
||||
const mode = String(value || 'always');
|
||||
if (mode === 'dates' || mode === 'times') {
|
||||
return mode;
|
||||
}
|
||||
return 'always';
|
||||
}
|
||||
|
||||
function getAuditUserId(req) {
|
||||
return req && req.currentUser ? Number(req.currentUser.id) : null;
|
||||
}
|
||||
|
||||
function getCanvasSignature(width, height) {
|
||||
const normalizedWidth = Number(width);
|
||||
const normalizedHeight = Number(height);
|
||||
if (!Number.isFinite(normalizedWidth) || !Number.isFinite(normalizedHeight)) {
|
||||
return null;
|
||||
}
|
||||
return normalizedWidth + 'x' + normalizedHeight;
|
||||
}
|
||||
|
||||
async function fetchPlaylistCanvasSignature(pool, playlistId) {
|
||||
const [rows] = await pool.query(
|
||||
`SELECT DISTINCT cs.width AS canvas_width, cs.height AS canvas_height
|
||||
FROM playlist_slides ps
|
||||
JOIN slides sl ON sl.id = ps.slide_id
|
||||
LEFT JOIN slide_templates st ON st.id = sl.template_id
|
||||
LEFT JOIN canvas_sizes cs ON cs.id = st.canvas_size_id
|
||||
WHERE ps.playlist_id = ?
|
||||
AND cs.width IS NOT NULL
|
||||
AND cs.height IS NOT NULL`,
|
||||
[playlistId]
|
||||
);
|
||||
const signatures = Array.from(new Set(rows.map(function (row) {
|
||||
return getCanvasSignature(row.canvas_width, row.canvas_height);
|
||||
}).filter(Boolean)));
|
||||
if (!signatures.length) {
|
||||
return null;
|
||||
}
|
||||
return signatures.length === 1 ? signatures[0] : 'mismatch';
|
||||
}
|
||||
|
||||
async function fetchScreensByPlaylistId(connection, playlistId) {
|
||||
const [rows] = await connection.query(
|
||||
'SELECT slug FROM screens WHERE playlist_id = ? AND slug IS NOT NULL',
|
||||
[playlistId]
|
||||
);
|
||||
return rows.map(function (row) {
|
||||
return row.slug;
|
||||
});
|
||||
}
|
||||
|
||||
async function fetchScreensBySlideId(connection, slideId) {
|
||||
const [rows] = await connection.query(
|
||||
`SELECT DISTINCT s.slug
|
||||
FROM screens s
|
||||
JOIN playlist_slides ps ON ps.playlist_id = s.playlist_id
|
||||
WHERE ps.slide_id = ?
|
||||
AND s.slug IS NOT NULL`,
|
||||
[slideId]
|
||||
);
|
||||
return rows.map(function (row) {
|
||||
return row.slug;
|
||||
});
|
||||
}
|
||||
|
||||
async function fetchScreensByTemplateId(connection, templateId) {
|
||||
const [rows] = await connection.query(
|
||||
`SELECT DISTINCT s.slug
|
||||
FROM screens s
|
||||
JOIN playlist_slides ps ON ps.playlist_id = s.playlist_id
|
||||
JOIN slides sl ON sl.id = ps.slide_id
|
||||
WHERE sl.template_id = ?
|
||||
AND s.slug IS NOT NULL`,
|
||||
[templateId]
|
||||
);
|
||||
return rows.map(function (row) {
|
||||
return row.slug;
|
||||
});
|
||||
}
|
||||
|
||||
async function fetchOrderedPlaylistSlides(connection, playlistId) {
|
||||
const [rows] = await connection.query(
|
||||
'SELECT id, position FROM playlist_slides WHERE playlist_id = ? ORDER BY position ASC, id ASC',
|
||||
[playlistId]
|
||||
);
|
||||
return rows;
|
||||
}
|
||||
|
||||
function redirectAfterSave(req, res, defaultUrl, options) {
|
||||
const safeOptions = options || {};
|
||||
const action = String((req && req.body && req.body.action) || req.query.action || '').toLowerCase();
|
||||
if (action === 'close') {
|
||||
return res.redirect(safeOptions.closeUrl || defaultUrl);
|
||||
}
|
||||
if (action === 'new') {
|
||||
return res.redirect(safeOptions.newUrl || defaultUrl);
|
||||
}
|
||||
const message = safeOptions.message || '';
|
||||
if (message) {
|
||||
const joiner = defaultUrl.indexOf('?') === -1 ? '?' : '&';
|
||||
return res.redirect(defaultUrl + joiner + 'message=' + encodeURIComponent(message));
|
||||
}
|
||||
return res.redirect(defaultUrl);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
normalizeUploadRoot: normalizeUploadRoot,
|
||||
formatDashboardDate: formatDashboardDate,
|
||||
buildDashboardPayload: buildDashboardPayload,
|
||||
readArrayField: readArrayField,
|
||||
parseDateTimeLocal: parseDateTimeLocal,
|
||||
parseTimeLocal: parseTimeLocal,
|
||||
normalizeScheduleMode: normalizeScheduleMode,
|
||||
getAuditUserId: getAuditUserId,
|
||||
getCanvasSignature: getCanvasSignature,
|
||||
fetchPlaylistCanvasSignature: fetchPlaylistCanvasSignature,
|
||||
fetchScreensByPlaylistId: fetchScreensByPlaylistId,
|
||||
fetchScreensBySlideId: fetchScreensBySlideId,
|
||||
fetchScreensByTemplateId: fetchScreensByTemplateId,
|
||||
fetchOrderedPlaylistSlides: fetchOrderedPlaylistSlides,
|
||||
redirectAfterSave: redirectAfterSave
|
||||
};
|
||||
Reference in New Issue
Block a user