Release v2.5.6
This commit is contained in:
@@ -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();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user