Refactor web server and release workflow
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
const { renderView } = require('../../view');
|
||||
|
||||
module.exports = function renderAccountPage(currentUser, message) {
|
||||
return renderView('account/password', {
|
||||
title: 'My account',
|
||||
active: 'account',
|
||||
currentUser: currentUser || null,
|
||||
message: message || '',
|
||||
username: currentUser ? currentUser.username : '',
|
||||
name: currentUser ? String(currentUser.name || '') : ''
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
const { renderView } = require('../../view');
|
||||
|
||||
module.exports = function renderLoginPage(message) {
|
||||
return renderView('login', {
|
||||
title: 'Sign in',
|
||||
authShell: true,
|
||||
bodyClass: 'login-page-body',
|
||||
message: message || ''
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
const { renderView } = require('../../view');
|
||||
|
||||
function buildDefaultCanvasSize() {
|
||||
return {
|
||||
id: null,
|
||||
name: '',
|
||||
width: 1920,
|
||||
height: 1080
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = function renderCanvasSizeFormPage(canvasSize, mode, message, currentUser) {
|
||||
const isEdit = mode === 'edit';
|
||||
return renderView(isEdit ? 'canvas-sizes/edit' : 'canvas-sizes/add', {
|
||||
title: isEdit ? 'Edit canvas size' : 'Add canvas size',
|
||||
active: 'canvas-sizes',
|
||||
message: message,
|
||||
currentUser: currentUser || null,
|
||||
canvasSize: canvasSize || buildDefaultCanvasSize()
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
const renderCanvasSizeFormPage = require('./add');
|
||||
|
||||
module.exports = function renderCanvasSizeEditPage(canvasSize, _data, message, currentUser) {
|
||||
return renderCanvasSizeFormPage(canvasSize, 'edit', message, currentUser);
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
const { renderView } = require('../../view');
|
||||
|
||||
module.exports = function renderCanvasSizesPage(data, message, currentUser) {
|
||||
const canvasSizes = (data.canvasSizes || []).map((size) => ({
|
||||
id: size.id,
|
||||
name: size.name,
|
||||
width: size.width,
|
||||
height: size.height,
|
||||
templateCount: (data.templates || []).filter((template) => Number(template.canvas_size_id) === Number(size.id)).length
|
||||
}));
|
||||
|
||||
return renderView('canvas-sizes/list', {
|
||||
title: 'Canvas sizes',
|
||||
active: 'canvas-sizes',
|
||||
message: message,
|
||||
currentUser: currentUser || null,
|
||||
canvasSizes: canvasSizes
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
const { renderView } = require('../../view');
|
||||
|
||||
module.exports = function renderConnectedClientsPage(data, message, currentUser) {
|
||||
return renderView('clients/list', {
|
||||
title: 'Connected clients',
|
||||
active: 'clients',
|
||||
message: message,
|
||||
currentUser: currentUser || null,
|
||||
clients: data.clients || []
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,56 @@
|
||||
const PLAYER_PUBLIC_BASE_URL = (process.env.PLAYER_PUBLIC_BASE_URL || process.env.PLAYER_BASE_URL || 'http://localhost:3001').replace(/\/$/, '');
|
||||
|
||||
function escapeHtml(value) {
|
||||
return String(value ?? '')
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''');
|
||||
}
|
||||
|
||||
function screenPlayerUrl(slug) {
|
||||
return `${PLAYER_PUBLIC_BASE_URL}/screen/${encodeURIComponent(slug)}`;
|
||||
}
|
||||
|
||||
function renderAdminShell(active, title, body, message) {
|
||||
const navItems = [
|
||||
{ key: 'dashboard', label: 'Dashboard', href: '/admin' },
|
||||
{ key: 'playlists', label: 'Playlists', href: '/admin/playlists' },
|
||||
{ key: 'screens', label: 'Screens', href: '/admin/screens' },
|
||||
{ key: 'slides', label: 'Slides', href: '/admin/slides' },
|
||||
{ key: 'templates', label: 'Slide templates', href: '/admin/templates' }
|
||||
].map((item) => `
|
||||
<a class="nav-item ${active === item.key ? 'active' : ''}" href="${item.href}">${escapeHtml(item.label)}</a>
|
||||
`).join('');
|
||||
|
||||
return `<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>${escapeHtml(title)} - Pulse Signage</title>
|
||||
<link rel="stylesheet" href="/assets/css/admin.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="app">
|
||||
<aside class="sidebar">
|
||||
<h1>Pulse Signage</h1>
|
||||
<nav class="nav">${navItems}</nav>
|
||||
</aside>
|
||||
<main class="content">
|
||||
<div class="page-header">
|
||||
<h2>${escapeHtml(title)}</h2>
|
||||
</div>
|
||||
${body}
|
||||
</main>
|
||||
</div>
|
||||
</body>
|
||||
</html>`;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
escapeHtml,
|
||||
screenPlayerUrl,
|
||||
renderAdminShell
|
||||
};
|
||||
@@ -0,0 +1,15 @@
|
||||
const { renderView } = require('../../view');
|
||||
|
||||
module.exports = function renderDashboardPage(data, message, currentUser) {
|
||||
return renderView('dashboard/index', {
|
||||
title: 'Dashboard',
|
||||
active: 'dashboard',
|
||||
message: message,
|
||||
currentUser: currentUser || null,
|
||||
playlists: data.playlists || [],
|
||||
screens: data.screens || [],
|
||||
clients: data.clients || [],
|
||||
slides: data.slides || [],
|
||||
connectedClientsCount: Number(data.connectedClientsCount || 0)
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
module.exports = {
|
||||
renderLoginPage: require('./auth/login'),
|
||||
renderAccountPage: require('./account/password'),
|
||||
renderUsersPage: require('./users/list'),
|
||||
renderUsersAddPage: require('./users/add'),
|
||||
renderUsersEditPage: require('./users/edit'),
|
||||
renderDashboardPage: require('./dashboard/index'),
|
||||
renderConnectedClientsPage: require('./clients/list'),
|
||||
renderPlaylistsPage: require('./playlists/list'),
|
||||
renderPlaylistFormPage: require('./playlists/add'),
|
||||
renderPlaylistEditPage: require('./playlists/edit'),
|
||||
renderPlaylistSlideConfigPage: require('./playlists/slide-config'),
|
||||
renderScreensPage: require('./screens/list'),
|
||||
renderScreenFormPage: require('./screens/add'),
|
||||
renderScreenEditPage: require('./screens/edit'),
|
||||
renderSlidesPage: require('./slides/list'),
|
||||
renderSlideFormPage: require('./slides/form'),
|
||||
renderTemplatesPage: require('./templates/list'),
|
||||
renderTemplateFormPage: require('./templates/add'),
|
||||
renderTemplateEditPage: require('./templates/edit'),
|
||||
renderCanvasSizesPage: require('./canvas-sizes/list'),
|
||||
renderCanvasSizeFormPage: require('./canvas-sizes/add'),
|
||||
renderCanvasSizeEditPage: require('./canvas-sizes/edit')
|
||||
};
|
||||
@@ -0,0 +1,14 @@
|
||||
const { renderView } = require('../../view');
|
||||
|
||||
module.exports = function renderPlaylistFormPage(message, currentUser) {
|
||||
return renderView('playlists/add', {
|
||||
title: 'Create playlist',
|
||||
active: 'playlists',
|
||||
playlist: {
|
||||
fade_between_slides: false
|
||||
},
|
||||
message: message,
|
||||
currentUser: currentUser || null
|
||||
});
|
||||
};
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
const { renderView } = require('../../view');
|
||||
|
||||
function formatDateTime(value) {
|
||||
if (!value) {
|
||||
return '';
|
||||
}
|
||||
const date = new Date(value);
|
||||
if (Number.isNaN(date.getTime())) {
|
||||
return '';
|
||||
}
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
const hours = String(date.getHours()).padStart(2, '0');
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}`;
|
||||
}
|
||||
|
||||
function formatTime(value) {
|
||||
return value ? String(value).slice(0, 5) : '';
|
||||
}
|
||||
|
||||
function formatDays(daysJson) {
|
||||
const dayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
||||
let days = [];
|
||||
if (Array.isArray(daysJson)) {
|
||||
days = daysJson;
|
||||
} else if (daysJson) {
|
||||
try {
|
||||
const parsed = JSON.parse(daysJson);
|
||||
days = Array.isArray(parsed) ? parsed : [];
|
||||
} catch (_error) {
|
||||
days = [];
|
||||
}
|
||||
}
|
||||
return days.map((day) => dayNames[Number(day)] || '').filter(Boolean).join(', ');
|
||||
}
|
||||
|
||||
function scheduleSummary(item) {
|
||||
const mode = String(item.schedule_mode || 'always');
|
||||
if (mode === 'dates') {
|
||||
const start = formatDateTime(item.schedule_start_datetime);
|
||||
const end = formatDateTime(item.schedule_end_datetime);
|
||||
return start && end ? `Dates: ${start} to ${end}` : 'Dates: not set';
|
||||
}
|
||||
if (mode === 'times') {
|
||||
const days = formatDays(item.schedule_days_json);
|
||||
const start = formatTime(item.schedule_start_time);
|
||||
const end = formatTime(item.schedule_end_time);
|
||||
return days && start && end ? `Times: ${days} ${start}-${end}` : 'Times: not set';
|
||||
}
|
||||
return 'Always visible';
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
module.exports = function renderPlaylistEditPage(playlist, data, message, currentUser) {
|
||||
const playlistSlides = (data.playlistSlides || [])
|
||||
.filter((item) => item.playlist_id === playlist.id)
|
||||
.sort((a, b) => {
|
||||
if (a.position !== b.position) {
|
||||
return a.position - b.position;
|
||||
}
|
||||
return a.id - b.id;
|
||||
})
|
||||
.map((item, index, items) => Object.assign({}, item, {
|
||||
displayOrder: index + 1,
|
||||
isFirst: index === 0,
|
||||
isLast: index === items.length - 1,
|
||||
canvasSignature: getCanvasSignature(item.canvas_width, item.canvas_height) || '',
|
||||
scheduleSummary: scheduleSummary(item)
|
||||
}));
|
||||
const assignedSlideIds = new Set(playlistSlides.map((item) => item.slide_id));
|
||||
const playlistCanvasSignatures = Array.from(new Set(playlistSlides.map((item) => getCanvasSignature(item.canvas_width, item.canvas_height)).filter(Boolean)));
|
||||
const playlistCanvasSignature = playlistCanvasSignatures.length === 1 ? playlistCanvasSignatures[0] : null;
|
||||
const playlistCanvasMismatch = playlistCanvasSignatures.length > 1;
|
||||
const selectableSlides = (data.slides || []).filter((slide) => {
|
||||
if (playlistCanvasMismatch) {
|
||||
return false;
|
||||
}
|
||||
if (!playlistCanvasSignature) {
|
||||
return true;
|
||||
}
|
||||
return getCanvasSignature(slide.canvas_width, slide.canvas_height) === playlistCanvasSignature;
|
||||
}).map((slide) => Object.assign({}, slide, {
|
||||
canvasSignature: getCanvasSignature(slide.canvas_width, slide.canvas_height) || '',
|
||||
isAssigned: assignedSlideIds.has(slide.id)
|
||||
}));
|
||||
const hasAddableSlides = selectableSlides.some((slide) => !slide.isAssigned);
|
||||
|
||||
return renderView('playlists/edit', {
|
||||
title: 'Edit playlist',
|
||||
active: 'playlists',
|
||||
message: message,
|
||||
currentUser: currentUser || null,
|
||||
playlist: playlist,
|
||||
playlistFadeBetweenSlides: Boolean(playlist.fade_between_slides),
|
||||
playlistSlides: playlistSlides,
|
||||
slides: data.slides || [],
|
||||
hasSlides: (data.slides || []).length > 0,
|
||||
hasSelectableSlides: selectableSlides.length > 0,
|
||||
hasAddableSlides: hasAddableSlides,
|
||||
selectableSlides: selectableSlides,
|
||||
playlistCanvasSignature: playlistCanvasSignature,
|
||||
playlistCanvasMismatch: playlistCanvasMismatch,
|
||||
scripts: ['js/playlist-schedule.js']
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
const { renderView } = require('../../view');
|
||||
|
||||
module.exports = function renderPlaylistsPage(data, message, currentUser) {
|
||||
const playlistSlides = data.playlistSlides || [];
|
||||
const playlists = (data.playlists || []).map((playlist) => {
|
||||
const slideCount = playlistSlides.filter((item) => item.playlist_id === playlist.id).length;
|
||||
return Object.assign({}, playlist, {
|
||||
slideCount: slideCount,
|
||||
slideCountIsOne: slideCount === 1
|
||||
});
|
||||
});
|
||||
|
||||
return renderView('playlists/list', {
|
||||
title: 'Playlists',
|
||||
active: 'playlists',
|
||||
message: message,
|
||||
currentUser: currentUser || null,
|
||||
playlists: playlists
|
||||
});
|
||||
};
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
const { renderFragment } = require('../../view');
|
||||
|
||||
const DAY_OPTIONS = [
|
||||
{ value: 0, label: 'Sun' },
|
||||
{ value: 1, label: 'Mon' },
|
||||
{ value: 2, label: 'Tue' },
|
||||
{ value: 3, label: 'Wed' },
|
||||
{ value: 4, label: 'Thu' },
|
||||
{ value: 5, label: 'Fri' },
|
||||
{ value: 6, label: 'Sat' }
|
||||
];
|
||||
|
||||
function formatDateTimeInput(value) {
|
||||
if (!value) {
|
||||
return '';
|
||||
}
|
||||
const date = new Date(value);
|
||||
if (Number.isNaN(date.getTime())) {
|
||||
return '';
|
||||
}
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
const hours = String(date.getHours()).padStart(2, '0');
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||||
return `${year}-${month}-${day}T${hours}:${minutes}`;
|
||||
}
|
||||
|
||||
function formatTimeInput(value) {
|
||||
if (!value) {
|
||||
return '';
|
||||
}
|
||||
return String(value).slice(0, 5);
|
||||
}
|
||||
|
||||
module.exports = function renderPlaylistSlideConfigPage(playlist, playlistSlide, message, rowKey, currentUser) {
|
||||
const scheduleMode = String(playlistSlide.schedule_mode || 'always');
|
||||
const selectedDays = new Set(Array.isArray(playlistSlide.schedule_days) ? playlistSlide.schedule_days.map(Number) : []);
|
||||
|
||||
return renderFragment('playlists/slide-config', {
|
||||
title: 'Slide schedule',
|
||||
hideFrameHeader: true,
|
||||
hideThemeToggle: true,
|
||||
frameBodyClass: 'admin-shell-body--frame-plain',
|
||||
message: message,
|
||||
currentUser: currentUser || null,
|
||||
playlist: playlist,
|
||||
playlistSlide: playlistSlide,
|
||||
scheduleMode: scheduleMode,
|
||||
isAlwaysMode: scheduleMode === 'always',
|
||||
isDatesMode: scheduleMode === 'dates',
|
||||
isTimesMode: scheduleMode === 'times',
|
||||
rowKey: String(rowKey || ''),
|
||||
startDateTimeValue: formatDateTimeInput(playlistSlide.schedule_start_datetime),
|
||||
endDateTimeValue: formatDateTimeInput(playlistSlide.schedule_end_datetime),
|
||||
startTimeValue: formatTimeInput(playlistSlide.schedule_start_time),
|
||||
endTimeValue: formatTimeInput(playlistSlide.schedule_end_time),
|
||||
dayOptions: DAY_OPTIONS.map((day) => ({
|
||||
...day,
|
||||
checked: selectedDays.has(day.value)
|
||||
})),
|
||||
scripts: ['js/playlist-schedule.js']
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
const { renderView } = require('../../view');
|
||||
|
||||
module.exports = function renderScreenFormPage(data, message, currentUser) {
|
||||
return renderView('screens/add', {
|
||||
title: 'Add screen',
|
||||
active: 'screens',
|
||||
message: message,
|
||||
currentUser: currentUser || null,
|
||||
playlists: data.playlists || []
|
||||
});
|
||||
};
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
const { renderView } = require('../../view');
|
||||
|
||||
module.exports = function renderScreenEditPage(screen, data, message, currentUser) {
|
||||
return renderView('screens/edit', {
|
||||
title: 'Edit screen',
|
||||
active: 'screens',
|
||||
message: message,
|
||||
currentUser: currentUser || null,
|
||||
screen: screen,
|
||||
playlists: data.playlists || []
|
||||
});
|
||||
};
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
const { renderView } = require('../../view');
|
||||
|
||||
module.exports = function renderScreensPage(data, message, currentUser) {
|
||||
return renderView('screens/list', {
|
||||
title: 'Screens',
|
||||
active: 'screens',
|
||||
message: message,
|
||||
currentUser: currentUser || null,
|
||||
screens: data.screens || []
|
||||
});
|
||||
};
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
const { renderView } = require('../../view');
|
||||
|
||||
module.exports = function renderSlideFormPage(data, mode, slide, message, currentUser) {
|
||||
const templateRegions = data.templateRegions || [];
|
||||
const templates = (data.templates || []).map((template) => ({
|
||||
...template,
|
||||
canvas_size_width: template.canvas_size_width,
|
||||
canvas_size_height: template.canvas_size_height,
|
||||
regions: templateRegions.filter((region) => Number(region.template_id) === Number(template.id))
|
||||
}));
|
||||
return renderView('slides/form', {
|
||||
title: mode === 'edit' ? 'Edit slide' : 'Create slide',
|
||||
active: 'slides',
|
||||
message: message,
|
||||
isEdit: mode === 'edit',
|
||||
action: mode === 'edit' ? `/admin/slides/${slide.id}` : '/admin/slides',
|
||||
slide: slide || { title: '', template_id: null, content: {} },
|
||||
templates: templates,
|
||||
slideEditorData: {
|
||||
templates: templates,
|
||||
existingTemplateId: slide && slide.template_id ? slide.template_id : null,
|
||||
existingContent: slide && slide.content ? slide.content : {}
|
||||
},
|
||||
currentUser: currentUser || null
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
const { renderView } = require('../../view');
|
||||
|
||||
module.exports = function renderSlidesPage(data, message, currentUser) {
|
||||
return renderView('slides/list', {
|
||||
title: 'Slides',
|
||||
active: 'slides',
|
||||
message: message,
|
||||
currentUser: currentUser || null,
|
||||
slides: data.slides || []
|
||||
});
|
||||
};
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
const { renderView } = require('../../view');
|
||||
|
||||
function buildDefaultTemplate() {
|
||||
return {
|
||||
id: null,
|
||||
name: '',
|
||||
canvas_size_id: null,
|
||||
canvas_size_width: 1920,
|
||||
canvas_size_height: 1080,
|
||||
background_image_path: '',
|
||||
regions: [{
|
||||
region_key: 'region_1',
|
||||
label: 'Region 1',
|
||||
region_type: 'text',
|
||||
x: 120,
|
||||
y: 120,
|
||||
width: 420,
|
||||
height: 160,
|
||||
z_index: 1
|
||||
}]
|
||||
};
|
||||
}
|
||||
|
||||
function resolveTemplateCanvasSize(template, canvasSizes) {
|
||||
const currentWidth = Math.max(1, Number(template.canvas_size_width || 1920));
|
||||
const currentHeight = Math.max(1, Number(template.canvas_size_height || 1080));
|
||||
const sizeId = template.canvas_size_id ? Number(template.canvas_size_id) : null;
|
||||
const matched = (canvasSizes || []).find((size) => Number(size.id) === sizeId)
|
||||
|| (canvasSizes || []).find((size) => Number(size.width) === currentWidth && Number(size.height) === currentHeight);
|
||||
|
||||
if (matched) {
|
||||
return Object.assign({}, template, {
|
||||
canvas_size_id: matched.id,
|
||||
canvas_size_label: matched.name,
|
||||
canvas_size_width: matched.width,
|
||||
canvas_size_height: matched.height
|
||||
});
|
||||
}
|
||||
|
||||
return Object.assign({}, template, {
|
||||
canvas_size_id: '',
|
||||
canvas_size_label: 'Current size (' + currentWidth + 'x' + currentHeight + ')',
|
||||
canvas_size_width: currentWidth,
|
||||
canvas_size_height: currentHeight
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = function renderTemplateFormPage(template, mode, message, canvasSizes, currentUser) {
|
||||
const isEdit = mode === 'edit';
|
||||
const current = resolveTemplateCanvasSize(template || buildDefaultTemplate(), canvasSizes || []);
|
||||
if (!current.regions || !current.regions.length) {
|
||||
current.regions = buildDefaultTemplate().regions;
|
||||
}
|
||||
|
||||
return renderView(isEdit ? 'templates/edit' : 'templates/add', {
|
||||
title: isEdit ? 'Edit template' : 'Create Template',
|
||||
active: 'templates',
|
||||
message: message,
|
||||
currentUser: currentUser || null,
|
||||
template: current,
|
||||
canvasSizes: canvasSizes || [],
|
||||
scripts: ['js/template-designer.js']
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
const renderTemplateFormPage = require('./add');
|
||||
|
||||
module.exports = function renderTemplateEditPage(template, data, message, currentUser) {
|
||||
return renderTemplateFormPage(template, 'edit', message, data && data.canvasSizes ? data.canvasSizes : [], currentUser);
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
const { renderView } = require('../../view');
|
||||
|
||||
module.exports = function renderTemplatesPage(data, message, currentUser) {
|
||||
const templates = (data.templates || []).map((template) => ({
|
||||
id: template.id,
|
||||
name: template.name,
|
||||
canvas_size_width: template.canvas_size_width,
|
||||
canvas_size_height: template.canvas_size_height,
|
||||
regionCount: (data.templateRegions || []).filter((region) => region.template_id === template.id).length
|
||||
}));
|
||||
|
||||
return renderView('templates/list', {
|
||||
title: 'Slide templates',
|
||||
active: 'templates',
|
||||
message: message,
|
||||
currentUser: currentUser || null,
|
||||
templates: templates
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
const { renderView } = require('../../view');
|
||||
|
||||
module.exports = function renderUsersAddPage(message, currentUser) {
|
||||
return renderView('users/add', {
|
||||
title: 'Add user',
|
||||
active: 'users',
|
||||
message: message,
|
||||
currentUser: currentUser || null
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
const { renderView } = require('../../view');
|
||||
|
||||
module.exports = function renderUsersEditPage(user, message, currentUser) {
|
||||
return renderView('users/edit', {
|
||||
title: 'Edit user',
|
||||
active: 'users',
|
||||
message: message,
|
||||
currentUser: currentUser || null,
|
||||
user: user
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
const { renderView } = require('../../view');
|
||||
|
||||
module.exports = function renderUsersPage(data, message, currentUser) {
|
||||
return renderView('users/list', {
|
||||
title: 'Users',
|
||||
active: 'users',
|
||||
message: message,
|
||||
currentUser: currentUser || null,
|
||||
users: data.users || []
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user