Release v2.5.6

This commit is contained in:
2026-08-05 19:38:16 +01:00
parent a8ef35b287
commit 9f831f04bc
161 changed files with 8487 additions and 1295 deletions
+96 -19
View File
@@ -114,7 +114,7 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
requestPreviewRender: requestPreviewRender
});
var regionUtils = window.pulseRegionUtils || {};
var slideRegionHelpers = createSlideFormRegionHelpers({
var slideRegionHelperOptions = {
templateFields: templateFields,
existingContent: existingContent,
rssFeeds: rssFeeds,
@@ -124,8 +124,10 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
uploadMaxLabel: uploadMaxLabel,
uploadVideoMaxLabel: uploadVideoMaxLabel,
escapeHtml: escapeHtml,
getRegionTypeModule: getRegionTypeModule
});
getRegionTypeModule: getRegionTypeModule,
requestPreviewRender: requestPreviewRender
};
var slideRegionHelpers = createSlideFormRegionHelpers(slideRegionHelperOptions);
var slidePreviewHelpers = createSlideFormPreviewHelpers({
getRegionTypeModule: getRegionTypeModule,
escapeHtml: escapeHtml
@@ -139,6 +141,8 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
var renderPreviewTextRegion = slidePreviewHelpers.renderPreviewTextRegion;
var buildRegionEditorCardContext = slideRegionHelpers.buildRegionEditorCardContext;
var getRegionEditorCardHtml = slideRegionHelpers.getRegionEditorCardHtml;
var bindRegionCards = slideRegionHelpers.bindRegionCards;
var syncRegionCards = slideRegionHelpers.syncRegionCards;
var getPreviewRegionContent = slideRegionHelpers.getPreviewRegionContent;
var buildPreviewRenderContext = slideRegionHelpers.buildPreviewRenderContext;
var startPreviewVideoPlayback = slidePreviewHelpers.startPreviewVideoPlayback;
@@ -147,6 +151,28 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
return templates.find(function (item) { return Number(item.id) === Number(templateSelect.value); }) || null;
}
function hasMeaningfulValue(value) {
if (value === null || value === undefined) {
return false;
}
if (Array.isArray(value)) {
return value.some(hasMeaningfulValue);
}
if (typeof value === 'object') {
return Object.keys(value).some(function (key) {
return hasMeaningfulValue(value[key]);
});
}
return String(value).trim() !== '';
}
function hasExistingSlideContent() {
return hasMeaningfulValue(existingContent);
}
function clearImagePreviewUrls() {
templateFields.querySelectorAll('input[type="file"][name^="region_image_"], input[type="file"][name^="region_video_"]').forEach(function (input) {
if (input.dataset.previewUrl) {
@@ -170,6 +196,10 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
return String(card.dataset.regionMediaType || '').trim();
}
if (card.querySelector && card.querySelector('input[type="file"][name^="region_qr_image_"], input[type="url"][name^="region_qr_code_"]')) {
return 'qr-code';
}
var regionTypeInput = card.querySelector ? card.querySelector('input[type="hidden"][name="region_type[]"]') : null;
return String(regionTypeInput && regionTypeInput.value || '').trim();
}
@@ -192,6 +222,7 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
return syncVideoRegionDuration(card, source);
},
markEdited: function () {
templateSelectorLock.arm();
templateSelectorLock.markEdited();
requestPreviewRender();
},
@@ -201,7 +232,7 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
}) : null;
function buildRegionMediaHookContext(input, file) {
var regionId = input && input.name ? input.name.replace(/^region_(?:image|video)_/, '') : '';
var regionId = input && input.name ? input.name.replace(/^region_(?:image|video|qr_image)_/, '') : '';
var card = regionId ? templateFields.querySelector('[data-region-id="' + regionId + '"]') : null;
return {
@@ -220,7 +251,7 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
}
function handleRegionMediaFileSelection(input, file) {
var card = input && input.name ? templateFields.querySelector('[data-region-id="' + input.name.replace(/^region_(?:image|video)_/, '') + '"]') : null;
var card = input && input.name ? templateFields.querySelector('[data-region-id="' + input.name.replace(/^region_(?:image|video|qr_image)_/, '') + '"]') : null;
var module = getRegionEditorModule(card);
var hookContext = buildRegionMediaHookContext(input, file);
@@ -241,14 +272,19 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
return;
}
var mediaType = card && card.dataset && String(card.dataset.regionMediaType || '').trim() === 'video' ? 'video' : 'image';
var mediaType = card && card.dataset && String(card.dataset.regionMediaType || '').trim() === 'video'
? 'video'
: card && card.querySelector && card.querySelector('input[type="file"][name^="region_qr_image_"]')
? 'qr-image'
: 'image';
var isVideo = mediaType === 'video';
var isQrImage = mediaType === 'qr-image';
previewBox.innerHTML = value
? '<div class="slide-image-region-preview-shell" data-remove-' + (isVideo ? 'region-video' : 'region-image') + '="' + escapeHtml(card.getAttribute('data-region-id') || '') + '" role="button" tabindex="0" aria-label="Remove ' + (isVideo ? 'video' : 'image') + '">' +
? '<div class="slide-image-region-preview-shell" data-remove-' + (isVideo ? 'region-video' : isQrImage ? 'region-qr-image' : 'region-image') + '="' + escapeHtml(card.getAttribute('data-region-id') || '') + '" role="button" tabindex="0" aria-label="Remove ' + (isVideo ? 'video' : isQrImage ? 'QR image' : 'image') + '">' +
(isVideo
? '<video class="slide-image-region-preview" src="' + escapeHtml(value) + '" autoplay loop muted playsinline preload="metadata"></video>'
: '<img class="slide-image-region-preview" src="' + escapeHtml(value) + '" alt="Current image preview" />') +
: '<img class="slide-image-region-preview" src="' + escapeHtml(value) + '" alt="' + (isQrImage ? 'Current QR image preview' : 'Current image preview') + '" />') +
'<span class="slide-image-region-preview-remove" aria-hidden="true"><i class="bi bi-trash3" aria-hidden="true"></i></span>' +
'</div>'
: '<div class="slide-image-region-preview slide-image-region-preview-empty">No ' + (isVideo ? 'video' : 'image') + '</div>';
@@ -389,15 +425,15 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
}
function getRegionImageInputs() {
return Array.prototype.slice.call(templateFields.querySelectorAll('input[type="file"][name^="region_image_"], input[type="file"][name^="region_video_"]'));
return Array.prototype.slice.call(templateFields.querySelectorAll('input[type="file"][name^="region_image_"], input[type="file"][name^="region_video_"], input[type="file"][name^="region_qr_image_"]'));
}
function getRegionMediaInputs() {
return getRegionImageInputs();
return Array.prototype.slice.call(templateFields.querySelectorAll('input[type="file"][name^="region_image_"], input[type="file"][name^="region_video_"], input[type="file"][name^="region_qr_image_"]'));
}
function hasPendingRegionImageUpload() {
return getRegionImageInputs().some(function (input) {
return getRegionMediaInputs().some(function (input) {
return Boolean(input && input.files && input.files.length);
});
}
@@ -448,6 +484,14 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
return;
}
try {
if (previewPopupWindow.location && previewPopupWindow.location.pathname !== '/slides/popup-preview') {
return;
}
} catch (_error) {
return;
}
previewPopupWindow.location.hash = buildPreviewPopupHash();
}
@@ -471,13 +515,18 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
'top=' + top
].join(',');
previewPopupWindow = window.open(buildPreviewPopupUrl(), 'slide-preview-popup', previewPopupFeatures);
previewPopupWindow = window.open('about:blank', 'slide-preview-popup', previewPopupFeatures);
if (!previewPopupWindow) {
return;
}
try {
previewPopupWindow.location.replace(buildPreviewPopupUrl());
} catch (_error) {
previewPopupWindow.location.href = buildPreviewPopupUrl();
}
previewPopupWindow.focus();
syncPopupPreview();
}
function syncSlideEditorSidebar() {
@@ -632,6 +681,7 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
var updateApiSampleDataPanel = slideRegionHelpers.updateApiSampleDataPanel;
var updateApiItemNumberLimit = slideRegionHelpers.updateApiItemNumberLimit;
var getCurrentApiConfig = slideRegionHelpers.getCurrentApiConfig;
var updateRssItemNumberLimit = slideRegionHelpers.updateRssItemNumberLimit;
function renderTemplate() {
templateSelectorLock.reset();
@@ -663,6 +713,9 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
});
slideFormEditorController.renderEditors();
window.requestAnimationFrame(function () {
bindRegionCards();
});
templateFields.querySelectorAll('input[name^="region_api_item_number_"]').forEach(function (input) {
var regionId = input.name.replace(/^region_api_item_number_/, '');
var sourceInput = templateFields.querySelector('select[name="region_api_source_id_' + regionId + '"]');
@@ -671,19 +724,42 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
updateApiItemNumberLimit(regionId, sourceInput.value, pathInput ? pathInput.value : '');
}
});
templateFields.querySelectorAll('input[name^="region_rss_item_number_"]').forEach(function (input) {
var regionId = input.name.replace(/^region_rss_item_number_/, '');
var feedInput = templateFields.querySelector('select[name="region_rss_feed_id_' + regionId + '"]');
if (feedInput) {
updateRssItemNumberLimit(regionId, feedInput.value);
}
});
if (typeof regionUtils.bindRegionMediaRemoveControls === 'function') {
regionUtils.bindRegionMediaRemoveControls(templateFields, {
getCardByRegionId: function (regionId) {
return templateFields.querySelector('[data-region-id="' + regionId + '"]');
},
getMediaType: function (card) {
getMediaType: function (card, button) {
if (button && button.hasAttribute && button.hasAttribute('data-remove-region-qr-image')) {
return 'qr-image';
}
if (button && button.hasAttribute && button.hasAttribute('data-remove-region-video')) {
return 'video';
}
return card && card.dataset && String(card.dataset.regionMediaType || '').trim() === 'video' ? 'video' : 'image';
},
getExistingMediaPrefix: function (mediaType) {
if (String(mediaType || '').trim() === 'qr-image') {
return 'existing_region_qr_image_';
}
return String(mediaType || '').trim() === 'video' ? 'existing_region_video_' : 'existing_region_image_';
},
getMediaPrefix: function (mediaType) {
if (String(mediaType || '').trim() === 'qr-image') {
return 'region_qr_image_';
}
return String(mediaType || '').trim() === 'video' ? 'region_video_' : 'region_image_';
},
getVideoDurationHiddenInput: function (regionId) {
@@ -711,6 +787,7 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
if (input.name.indexOf('region_rss_') === 0) {
var rssFeed = input.name.indexOf('region_rss_feed_id_') === 0 ? input.value : (templateFields.querySelector('select[name="region_rss_feed_id_' + regionId + '"]') || {}).value;
updateRssPlaceholderChips(regionId, rssFeed);
updateRssItemNumberLimit(regionId, rssFeed);
}
if (input.name.indexOf('region_api_') === 0) {
var apiSource = input.name.indexOf('region_api_source_id_') === 0 ? input.value : (templateFields.querySelector('select[name="region_api_source_id_' + regionId + '"]') || {}).value;
@@ -728,6 +805,7 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
if (input.name.indexOf('region_rss_') === 0) {
var rssFeed = input.name.indexOf('region_rss_feed_id_') === 0 ? input.value : (templateFields.querySelector('select[name="region_rss_feed_id_' + regionId + '"]') || {}).value;
updateRssPlaceholderChips(regionId, rssFeed);
updateRssItemNumberLimit(regionId, rssFeed);
}
if (input.name.indexOf('region_api_') === 0) {
var apiSource = input.name.indexOf('region_api_source_id_') === 0 ? input.value : (templateFields.querySelector('select[name="region_api_source_id_' + regionId + '"]') || {}).value;
@@ -742,16 +820,12 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
});
});
if (existingTemplateId) {
if (existingTemplateId && hasExistingSlideContent()) {
templateSelectorLock.arm();
templateSelectorLock.markEdited();
requestPreviewRender();
return;
}
window.requestAnimationFrame(function () {
templateSelectorLock.arm();
});
requestPreviewRender();
}
@@ -766,6 +840,7 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
throw new Error('Wait for the image upload to finish before saving.');
}
await slideFormEditorController.syncEditors();
await syncRegionCards();
},
fallbackSuccessMessage: 'Saved slide.',
afterSuccess: function () {
@@ -792,10 +867,12 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
templateSelect.addEventListener('change', renderTemplate);
templateFields.addEventListener('change', function () {
templateSelectorLock.arm();
templateSelectorLock.markEdited();
requestPreviewRender();
});
templateFields.addEventListener('input', function () {
templateSelectorLock.arm();
templateSelectorLock.markEdited();
requestPreviewRender();
});