Add canvas size disable controls
This commit is contained in:
1 parent
68e1f80190
commit
f0601f823d
22 files changed
+205
-87
No files matched your search
@@ -36,7 +36,6 @@ module.exports = function registerContentRoutes(app, deps) {
|
||||
const hasAnyPermission = deps.hasAnyPermission;
|
||||
const { buildPagination } = require('#src/web/lib/pagination');
|
||||
const { buildDuplicateSlideName, buildDuplicateSlide } = require('#src/web/routes/signage/slides/duplicate');
|
||||
const { buildDuplicateCanvasSizeName, buildDuplicateCanvasSize } = require('#src/web/routes/signage/canvas-sizes/duplicate');
|
||||
|
||||
const LIST_PAGE_SIZE = 25;
|
||||
const WYSIWYG_IMAGE_UPLOAD_MAX_BYTES = 2 * 1024 * 1024;
|
||||
@@ -337,7 +336,11 @@ module.exports = function registerContentRoutes(app, deps) {
|
||||
duplicateIndex += 1;
|
||||
}
|
||||
|
||||
res.send(pages.renderTemplateAddPage(buildDuplicateTemplate(template, duplicateName), req.query.message ? String(req.query.message) : 'Review the copied values and save when ready.', canvasSizes.canvasSizes, req.currentUser, null, Number(settings['uploads.image_max_bytes']) || IMAGE_UPLOAD_MAX_BYTES));
|
||||
const duplicateTemplate = buildDuplicateTemplate(template, duplicateName);
|
||||
if (!canvasSizes.canvasSizes.some((size) => Number(size.id) === Number(duplicateTemplate.canvas_size_id))) {
|
||||
duplicateTemplate.canvas_size_id = null;
|
||||
}
|
||||
res.send(pages.renderTemplateAddPage(duplicateTemplate, req.query.message ? String(req.query.message) : 'Review the copied values and save when ready.', canvasSizes.canvasSizes, req.currentUser, null, Number(settings['uploads.image_max_bytes']) || IMAGE_UPLOAD_MAX_BYTES));
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
@@ -749,7 +752,7 @@ module.exports = function registerContentRoutes(app, deps) {
|
||||
}
|
||||
template.region_usage = await fetchTemplateRegionUsage(template);
|
||||
template.inUse = (await fetchSlidesByTemplateId(template.id)).length > 0;
|
||||
const sizeData = await common.fetchCanvasSizesData(pool);
|
||||
const sizeData = await common.fetchCanvasSizesData(pool, template.canvas_size_id);
|
||||
await syncMediaAssetsFromDirectory(pool, deps.uploadDir);
|
||||
const mediaAssets = await fetchMediaAssets(pool);
|
||||
const settings = await fetchAppSettings(pool);
|
||||
@@ -882,26 +885,6 @@ module.exports = function registerContentRoutes(app, deps) {
|
||||
res.send(pages.renderCanvasSizeAddPage(null, req.query.message ? String(req.query.message) : '', req.currentUser));
|
||||
});
|
||||
|
||||
app.get('/canvas-sizes/:id/duplicate', requirePermission('canvas-sizes.read'), requirePermission('canvas-sizes.create'), async function (req, res, next) {
|
||||
try {
|
||||
const canvasSize = await common.fetchCanvasSizeById(pool, Number(req.params.id));
|
||||
if (!canvasSize) {
|
||||
return res.status(404).send('Canvas size not found');
|
||||
}
|
||||
|
||||
let duplicateName = buildDuplicateCanvasSizeName(canvasSize.name);
|
||||
let duplicateIndex = 2;
|
||||
while (await common.fetchDuplicateName(pool, 'c_canvas_sizes', duplicateName)) {
|
||||
duplicateName = buildDuplicateCanvasSizeName(canvasSize.name) + ' (' + duplicateIndex + ')';
|
||||
duplicateIndex += 1;
|
||||
}
|
||||
|
||||
res.send(pages.renderCanvasSizeAddPage(buildDuplicateCanvasSize(canvasSize, duplicateName), req.query.message ? String(req.query.message) : 'Review the copied values and save when ready.', req.currentUser));
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/canvas-sizes', requirePermission('canvas-sizes.create'), async function (req, res, next) {
|
||||
try {
|
||||
const payload = common.buildCanvasSizePayload(req, null);
|
||||
@@ -975,6 +958,21 @@ module.exports = function registerContentRoutes(app, deps) {
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/canvas-sizes/:id/toggle', requirePermission('canvas-sizes.update'), async function (req, res, next) {
|
||||
try {
|
||||
const canvasSize = await common.fetchCanvasSizeById(pool, Number(req.params.id));
|
||||
if (!canvasSize) {
|
||||
return res.status(404).send('Canvas size not found');
|
||||
}
|
||||
const enabled = canvasSize.enabled === 0 || canvasSize.enabled === false ? 1 : 0;
|
||||
await pool.query('UPDATE c_canvas_sizes SET enabled = ?, modified_by = ? WHERE id = ?', [enabled, getAuditUserId(req), canvasSize.id]);
|
||||
if (typeof recordRequestAuditEvent === 'function') await recordRequestAuditEvent(pool, req, { category: 'canvas-sizes', eventType: enabled ? 'canvas-size.enabled' : 'canvas-size.disabled', actorUserId: getAuditUserId(req), targetType: 'canvas-size', targetId: canvasSize.id, targetLabel: canvasSize.name });
|
||||
res.redirect('/canvas-sizes?message=' + encodeURIComponent(enabled ? 'Canvas size enabled.' : 'Canvas size disabled.'));
|
||||
} catch (error) {
|
||||
next(error);
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/canvas-sizes/:id/delete', requirePermission('canvas-sizes.delete'), async function (req, res, next) {
|
||||
try {
|
||||
const canvasSize = await common.fetchCanvasSizeById(pool, Number(req.params.id));
|
||||
|
||||
@@ -134,6 +134,9 @@ module.exports = function registerPlaylistRoutes(app, deps) {
|
||||
throw createValidationError('Canvas size not found.');
|
||||
}
|
||||
requestedCanvasId = Number(canvasSize.id);
|
||||
if ((canvasSize.enabled === 0 || canvasSize.enabled === false) && (!shouldUpdatePlaylist || Number(playlist.canvas_id) !== requestedCanvasId)) {
|
||||
throw createValidationError('Canvas size is disabled.');
|
||||
}
|
||||
if (Number.isInteger(Number(playlist.canvas_id)) && Number(playlist.canvas_id) > 0 && Number(playlist.canvas_id) !== requestedCanvasId) {
|
||||
throw new Error('Canvas size cannot be changed after the playlist is created.');
|
||||
}
|
||||
@@ -387,6 +390,9 @@ module.exports = function registerPlaylistRoutes(app, deps) {
|
||||
if (!canvasSize) {
|
||||
return res.status(400).send('Canvas size not found.');
|
||||
}
|
||||
if (canvasSize.enabled === 0 || canvasSize.enabled === false) {
|
||||
return res.status(400).send('Canvas size is disabled.');
|
||||
}
|
||||
const actorId = getAuditUserId(req);
|
||||
await connection.beginTransaction();
|
||||
const [result] = await connection.query('INSERT INTO c_playlists (name, fade_between_slides, skip_unavailable_rtmp, canvas_id, created_by, modified_by) VALUES (?, ?, ?, ?, ?, ?)', [name, fadeBetweenSlides, skipUnavailableRtmp, canvasSize.id, actorId, actorId]);
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
// Canvas size duplicate helpers.
|
||||
|
||||
function buildDuplicateCanvasSizeName(name) {
|
||||
const source = String(name || 'Canvas size').trim() || 'Canvas size';
|
||||
return 'Copy of ' + source;
|
||||
}
|
||||
|
||||
function buildDuplicateCanvasSize(canvasSize, duplicateName) {
|
||||
const source = canvasSize || {};
|
||||
return {
|
||||
id: null,
|
||||
name: String(duplicateName || buildDuplicateCanvasSizeName(source.name)).trim(),
|
||||
width: Math.max(1, Number(source.width || 1920)),
|
||||
height: Math.max(1, Number(source.height || 1080))
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
buildDuplicateCanvasSizeName,
|
||||
buildDuplicateCanvasSize
|
||||
};
|
||||
@@ -8,6 +8,7 @@ module.exports = function renderCanvasSizesPage(data, message, currentUser) {
|
||||
name: size.name,
|
||||
width: size.width,
|
||||
height: size.height,
|
||||
enabled: size.enabled !== 0 && size.enabled !== false,
|
||||
templateCount: size.template_count !== undefined
|
||||
? Number(size.template_count) || 0
|
||||
: (data.templates || []).filter((template) => Number(template.canvas_size_id) === Number(size.id)).length
|
||||
|
||||
@@ -228,8 +228,11 @@ function buildPlaylistFormViewModel(playlist, data, message, currentUser, option
|
||||
const computedPlaylistCanvasId = playlistSlideCanvasIds.length === 1 ? playlistSlideCanvasIds[0] : null;
|
||||
const playlistCanvasId = storedCanvasId || computedPlaylistCanvasId;
|
||||
const selectedCanvasSize = (data.canvasSizes || []).find((size) => Number(size.id) === Number(playlistCanvasId)) || null;
|
||||
const canvasSizes = (data.canvasSizes || []).map((size) => Object.assign({}, size, {
|
||||
label: formatCanvasSizeLabel(size),
|
||||
const canvasSizes = (data.canvasSizes || []).filter((size) => {
|
||||
const enabled = size.enabled !== 0 && size.enabled !== false;
|
||||
return enabled || (playlistCanvasId && Number(size.id) === playlistCanvasId);
|
||||
}).map((size) => Object.assign({}, size, {
|
||||
label: formatCanvasSizeLabel(size) + (size.enabled === 0 || size.enabled === false ? ' (Disabled)' : ''),
|
||||
canvasId: Number(size.id) || null,
|
||||
selected: Boolean(selectedCanvasSize && Number(selectedCanvasSize.id) === Number(size.id))
|
||||
}));
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
<tr>
|
||||
<th data-table-sort-key="name">Name</th>
|
||||
<th data-table-sort-key="dimensions">Dimensions</th>
|
||||
<th>Status</th>
|
||||
<th data-table-sort-key="templates">Templates</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
@@ -34,15 +35,18 @@
|
||||
<tr data-table-search-row>
|
||||
<td data-label="Name">{{name}}</td>
|
||||
<td data-label="Dimensions">{{width}}x{{height}}</td>
|
||||
<td data-label="Status"><span class="badge text-bg-{{#if enabled}}success{{else}}secondary{{/if}}">{{#if enabled}}Enabled{{else}}Disabled{{/if}}</span></td>
|
||||
<td data-label="Templates"><span class="chip">{{templateCount}} template{{#if (gt templateCount 1)}}s{{else}}{{/if}}{{#if (lt templateCount 1)}}s{{/if}}</span></td>
|
||||
<td data-label="Actions">
|
||||
{{#if (anyPermission ../currentUser 'canvas-sizes.create' 'canvas-sizes.update' 'canvas-sizes.delete')}}
|
||||
{{#if (anyPermission ../currentUser 'canvas-sizes.update' 'canvas-sizes.delete')}}
|
||||
<div class="actions">
|
||||
{{#if (hasPermission ../currentUser 'canvas-sizes.update')}}
|
||||
<a class="btn btn-sm btn-primary" href="/canvas-sizes/{{id}}/edit">Edit</a>
|
||||
{{/if}}
|
||||
{{#if (hasPermission ../currentUser 'canvas-sizes.create')}}
|
||||
<a class="btn btn-sm btn-secondary" href="/canvas-sizes/{{id}}/duplicate">Dupe</a>
|
||||
{{#if (hasPermission ../currentUser 'canvas-sizes.update')}}
|
||||
<form class="inline-form" method="post" action="/canvas-sizes/{{id}}/toggle" data-confirm-message="{{#if enabled}}Disable{{else}}Enable{{/if}} this canvas size?">
|
||||
<button class="btn btn-sm btn-secondary" type="submit">{{#if enabled}}Disable{{else}}Enable{{/if}}</button>
|
||||
</form>
|
||||
{{/if}}
|
||||
{{#if (hasPermission ../currentUser 'canvas-sizes.delete')}}
|
||||
<form class="inline-form" method="post" action="/canvas-sizes/{{id}}/delete" data-confirm-message="Delete this canvas size?">
|
||||
@@ -61,7 +65,7 @@
|
||||
</tr>
|
||||
{{/each}}
|
||||
{{else}}
|
||||
<tr data-table-search-empty-default><td colspan="4" class="empty">No canvas sizes yet.</td></tr>
|
||||
<tr data-table-search-empty-default><td colspan="5" class="empty">No canvas sizes yet.</td></tr>
|
||||
{{/if}}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
{{/unless}}
|
||||
{{#if canvasSizes.length}}
|
||||
{{#each canvasSizes}}
|
||||
<option value="{{id}}" data-width="{{width}}" data-height="{{height}}" {{#if (eq ../template.canvas_size_id id)}}selected{{/if}}>{{name}} ({{width}}x{{height}})</option>
|
||||
<option value="{{id}}" data-width="{{width}}" data-height="{{height}}" {{#if (eq ../template.canvas_size_id id)}}selected{{/if}}>{{name}} ({{width}}x{{height}}){{#unless enabled}} (Disabled){{/unless}}</option>
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
</select>
|
||||
|
||||
Reference in new issue
Block a user