Release v2.19.0: indexed content references
Publish Docker Image / build-and-push-existing-registry (./build/Dockerfile, web, pulse-signage-web) (push) Successful in 1m11s
Publish Docker Image / build-and-push-existing-registry (./build/Dockerfile.player, player, pulse-signage-player) (push) Successful in 33s

This commit is contained in:
lzstealth committed 2026-10-24 19:50:12 +01:00
1 parent 24f1603b43
commit b59fe08298
31 files changed
+663 -237

No files matched your search

@@ -161,7 +161,7 @@ module.exports = function registerApiSourceRoutes(app, deps) {
const usage = await getApiRequestUsage(connection);
if (requests.some(function (request) { return usage.has(Number(request.id)); })) {
await connection.rollback();
return res.redirect(base + '?message=' + encodeURIComponent('This API source has requests used by slides.'));
return res.redirect(base + '?message=' + encodeURIComponent('This API source has requests used by slides or template defaults.'));
}
await connection.query('DELETE FROM i_api_sources WHERE auth_source_id = ?', [Number(req.params.id)]);
await connection.query('DELETE FROM i_api_source_groups WHERE id = ?', [Number(req.params.id)]);
@@ -6,45 +6,10 @@ const renderRssFeedAddPage = require('#src/web/routes/data-sources/rss-feeds/add
const renderRssFeedEditPage = require('#src/web/routes/data-sources/rss-feeds/edit');
const { buildDuplicateRssFeedName, buildDuplicateRssFeed } = require('#src/web/routes/data-sources/rss-feeds/duplicate');
const { fetchAppSettings } = require('#src/data/app-settings');
const { getContentReferenceValues } = require('#src/data/content-references');
async function getDataSourceUsageMaps(pool, common) {
const [slides] = await pool.query('SELECT content_json FROM c_slides WHERE content_json IS NOT NULL');
const [templateRegions] = await pool.query('SELECT default_content_json FROM c_template_regions WHERE default_content_json IS NOT NULL');
const rssFeedIds = new Set();
function collectUsage(json) {
const content = typeof common.parseJsonSafe === 'function' ? common.parseJsonSafe(json) : null;
if (!content || typeof content !== 'object') {
return;
}
(function walk(value) {
if (!value || typeof value !== 'object') {
return;
}
if (Array.isArray(value)) {
value.forEach(walk);
return;
}
if (Object.prototype.hasOwnProperty.call(value, 'feed_id')) {
const feedId = Number(value.feed_id);
if (Number.isFinite(feedId)) {
rssFeedIds.add(feedId);
}
}
Object.keys(value).forEach(function (key) {
walk(value[key]);
});
})(content);
}
slides.forEach(function (slide) { collectUsage(slide.content_json); });
templateRegions.forEach(function (region) { collectUsage(region.default_content_json); });
return rssFeedIds;
return new Set((await getContentReferenceValues(pool, 'rss-feed')).map(Number).filter(Number.isFinite));
}
async function isRssFeedInUse(pool, common, rssFeedId) {
@@ -5,45 +5,10 @@ const renderTimetableGroupsPage = require('#src/web/routes/data-sources/timetabl
const renderTimetableGroupAddPage = require('#src/web/routes/data-sources/timetables/add');
const renderTimetableGroupEditPage = require('#src/web/routes/data-sources/timetables/edit');
const { buildDuplicateTimetableGroupName, buildDuplicateTimetableGroup, buildDuplicateTimetableEntry } = require('#src/web/routes/data-sources/timetables/duplicate');
const { getContentReferenceValues } = require('#src/data/content-references');
async function getDataSourceUsageMaps(pool, common) {
const [slides] = await pool.query('SELECT content_json FROM c_slides WHERE content_json IS NOT NULL');
const [templateRegions] = await pool.query('SELECT default_content_json FROM c_template_regions WHERE default_content_json IS NOT NULL');
const timetableGroupIds = new Set();
function collectUsage(json) {
const content = typeof common.parseJsonSafe === 'function' ? common.parseJsonSafe(json) : null;
if (!content || typeof content !== 'object') {
return;
}
(function walk(value) {
if (!value || typeof value !== 'object') {
return;
}
if (Array.isArray(value)) {
value.forEach(walk);
return;
}
if (Object.prototype.hasOwnProperty.call(value, 'timetable_group_id')) {
const timetableGroupId = Number(value.timetable_group_id);
if (Number.isFinite(timetableGroupId)) {
timetableGroupIds.add(timetableGroupId);
}
}
Object.keys(value).forEach(function (key) {
walk(value[key]);
});
})(content);
}
slides.forEach(function (slide) { collectUsage(slide.content_json); });
templateRegions.forEach(function (region) { collectUsage(region.default_content_json); });
return timetableGroupIds;
return new Set((await getContentReferenceValues(pool, 'timetable-group')).map(Number).filter(Number.isFinite));
}
function readTimetableArrayFieldValue(body, keys) {
+2 -22
View File
@@ -7,30 +7,10 @@ const renderWeatherLocationEditPage = require('#src/web/routes/data-sources/weat
const { buildDuplicateWeatherLocationName, buildDuplicateWeatherLocation } = require('#src/web/routes/data-sources/weather/duplicate');
const { fetchAppSettings } = require('#src/data/app-settings');
const { buildAuditChanges } = require('#src/data/audit-log');
const { getContentReferenceValues } = require('#src/data/content-references');
async function getWeatherLocationUsageIds(pool, common) {
const [slides] = await pool.query('SELECT content_json FROM c_slides WHERE content_json IS NOT NULL');
const [templateRegions] = await pool.query('SELECT default_content_json FROM c_template_regions WHERE default_content_json IS NOT NULL');
const weatherLocationIds = new Set();
function collectUsage(json) {
const content = typeof common.parseJsonSafe === 'function' ? common.parseJsonSafe(json) : null;
if (!content || typeof content !== 'object') return;
(function walk(value) {
if (!value || typeof value !== 'object') return;
if (Array.isArray(value)) {
value.forEach(walk);
return;
}
if (Object.prototype.hasOwnProperty.call(value, 'weather_location_id')) {
const locationId = Number(value.weather_location_id);
if (Number.isFinite(locationId)) weatherLocationIds.add(locationId);
}
Object.keys(value).forEach(function (key) { walk(value[key]); });
}(content));
}
slides.forEach(function (slide) { collectUsage(slide.content_json); });
templateRegions.forEach(function (region) { collectUsage(region.default_content_json); });
return weatherLocationIds;
return new Set((await getContentReferenceValues(pool, 'weather-location')).map(Number).filter(Number.isFinite));
}
async function isWeatherLocationInUse(pool, common, locationId) {