Release 2.8.0
This commit is contained in:
@@ -441,6 +441,21 @@
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
form.dispatchEvent(new CustomEvent('web-async-save:success', {
|
||||
bubbles: true,
|
||||
detail: {
|
||||
form: form,
|
||||
response: response,
|
||||
responseText: responseText,
|
||||
responseDocument: responseDocument,
|
||||
submitterValue: submitterValue
|
||||
}
|
||||
}));
|
||||
} catch (_error) {
|
||||
// Ignore event dispatch failures and continue the save flow.
|
||||
}
|
||||
|
||||
clearFormDirty(form);
|
||||
|
||||
if (submitterValue === 'close' || submitterValue === 'new') {
|
||||
|
||||
@@ -39,6 +39,63 @@ function setAnnouncementScreenSelection(isSelected) {
|
||||
});
|
||||
}
|
||||
|
||||
function getAnnouncementActionButtonState() {
|
||||
var actionForm = document.getElementById('announcement-action-form');
|
||||
var visibleButton = document.querySelector('button[form="announcement-action-form"]');
|
||||
var actionPath = actionForm ? String(actionForm.getAttribute('action') || '').trim() : '';
|
||||
var isPlay = /\/play$/.test(actionPath);
|
||||
var isActive = !isPlay;
|
||||
var selectedScreenCount = document.querySelectorAll('input[name="screen_ids[]"]:checked').length;
|
||||
|
||||
return {
|
||||
visibleButton: visibleButton,
|
||||
actionForm: actionForm,
|
||||
isActive: isActive,
|
||||
hasTargets: selectedScreenCount > 0,
|
||||
actionDisabled: !isActive && selectedScreenCount === 0,
|
||||
actionLabel: isActive ? 'Stop' : 'Play',
|
||||
actionIcon: isActive ? 'bi-stop-fill' : 'bi-play-fill',
|
||||
actionClassName: !isActive && selectedScreenCount === 0
|
||||
? 'btn-outline-info'
|
||||
: (isActive ? 'btn-outline-warning' : 'btn-info'),
|
||||
actionDisabledTitle: !isActive && selectedScreenCount === 0
|
||||
? 'Select at least one screen group to play this announcement.'
|
||||
: '',
|
||||
actionConfirmMessage: isActive
|
||||
? 'Stop this announcement on the selected screens now?'
|
||||
: 'Send this announcement to the selected screens now?'
|
||||
};
|
||||
}
|
||||
|
||||
function updateAnnouncementActionButtonState() {
|
||||
var state = getAnnouncementActionButtonState();
|
||||
if (!state.visibleButton) {
|
||||
return;
|
||||
}
|
||||
|
||||
state.visibleButton.className = state.visibleButton.className.replace(/btn-outline-(info|warning|success)|btn-info/g, state.actionClassName);
|
||||
state.visibleButton.disabled = state.actionDisabled;
|
||||
state.visibleButton.setAttribute('aria-disabled', state.actionDisabled ? 'true' : 'false');
|
||||
state.visibleButton.setAttribute('title', state.actionDisabled ? state.actionDisabledTitle : state.actionConfirmMessage);
|
||||
state.visibleButton.setAttribute('aria-label', state.actionLabel);
|
||||
|
||||
var icon = state.visibleButton.querySelector('i.bi');
|
||||
if (icon) {
|
||||
icon.className = 'bi ' + state.actionIcon + ' me-1';
|
||||
}
|
||||
|
||||
var label = state.visibleButton.childNodes.length > 1 ? state.visibleButton.childNodes[state.visibleButton.childNodes.length - 1] : null;
|
||||
if (label && label.nodeType === Node.TEXT_NODE) {
|
||||
label.textContent = state.actionLabel;
|
||||
} else {
|
||||
state.visibleButton.textContent = state.actionLabel;
|
||||
}
|
||||
|
||||
if (state.actionForm) {
|
||||
state.actionForm.setAttribute('data-confirm-message', state.actionConfirmMessage);
|
||||
}
|
||||
}
|
||||
|
||||
function positionAnnouncementTypePicker() {
|
||||
var picker = document.querySelector('[data-announcement-type-picker]');
|
||||
var toggle = document.querySelector('[data-announcement-type-picker-toggle]');
|
||||
@@ -141,125 +198,6 @@ function setAnnouncementTypeValue(typeKey) {
|
||||
updateAnnouncementTypePickerSelection();
|
||||
}
|
||||
|
||||
function updateAnnouncementIconPreview() {
|
||||
var iconSelect = document.getElementById('announcement-icon');
|
||||
var preview = document.querySelector('[data-announcement-icon-preview]');
|
||||
if (!iconSelect || !preview) {
|
||||
return;
|
||||
}
|
||||
|
||||
var selectedOption = iconSelect.options[iconSelect.selectedIndex] || null;
|
||||
var iconKey = selectedOption ? String(selectedOption.value || '').trim().toLowerCase() : '';
|
||||
var label = selectedOption ? String(selectedOption.textContent || selectedOption.label || iconKey).trim() : iconKey;
|
||||
|
||||
preview.className = 'announcement-icon-preview';
|
||||
preview.innerHTML = '<i class="bi bi-' + iconKey + '" aria-hidden="true"></i>';
|
||||
preview.setAttribute('aria-label', label);
|
||||
preview.setAttribute('title', label);
|
||||
}
|
||||
|
||||
function positionAnnouncementIconPicker() {
|
||||
var picker = document.querySelector('[data-announcement-icon-picker]');
|
||||
var toggle = document.querySelector('[data-announcement-icon-picker-toggle]');
|
||||
var shell = document.querySelector('[data-announcement-icon-picker-shell]');
|
||||
if (!picker || picker.hidden || !toggle || !shell) {
|
||||
return;
|
||||
}
|
||||
|
||||
var padding = 8;
|
||||
var toggleRect = toggle.getBoundingClientRect();
|
||||
var menuRect = picker.getBoundingClientRect();
|
||||
var viewportHeight = window.innerHeight || document.documentElement.clientHeight || toggleRect.bottom;
|
||||
var placementAbove = false;
|
||||
var spaceBelow = viewportHeight - toggleRect.bottom - padding;
|
||||
var spaceAbove = toggleRect.top - padding;
|
||||
|
||||
if (menuRect.height > spaceBelow && spaceAbove > spaceBelow) {
|
||||
placementAbove = true;
|
||||
}
|
||||
|
||||
picker.classList.toggle('is-open-above', placementAbove);
|
||||
}
|
||||
|
||||
function closeAnnouncementIconPicker() {
|
||||
var picker = document.querySelector('[data-announcement-icon-picker]');
|
||||
var toggle = document.querySelector('[data-announcement-icon-picker-toggle]');
|
||||
if (!picker) {
|
||||
return;
|
||||
}
|
||||
|
||||
picker.hidden = true;
|
||||
picker.classList.remove('is-open-above');
|
||||
if (toggle) {
|
||||
toggle.setAttribute('aria-expanded', 'false');
|
||||
}
|
||||
}
|
||||
|
||||
function openAnnouncementIconPicker() {
|
||||
var picker = document.querySelector('[data-announcement-icon-picker]');
|
||||
var toggle = document.querySelector('[data-announcement-icon-picker-toggle]');
|
||||
if (!picker) {
|
||||
return;
|
||||
}
|
||||
|
||||
picker.hidden = false;
|
||||
if (toggle) {
|
||||
toggle.setAttribute('aria-expanded', 'true');
|
||||
}
|
||||
|
||||
if (typeof window !== 'undefined' && window.requestAnimationFrame) {
|
||||
window.requestAnimationFrame(positionAnnouncementIconPicker);
|
||||
} else {
|
||||
positionAnnouncementIconPicker();
|
||||
}
|
||||
}
|
||||
|
||||
function updateAnnouncementIconPickerSelection() {
|
||||
var iconSelect = document.getElementById('announcement-icon');
|
||||
var previewButton = document.querySelector('[data-announcement-icon-picker-toggle]');
|
||||
var picker = document.querySelector('[data-announcement-icon-picker]');
|
||||
if (!iconSelect || !previewButton || !picker) {
|
||||
return;
|
||||
}
|
||||
|
||||
var selectedOption = iconSelect.options[iconSelect.selectedIndex] || null;
|
||||
var selectedValue = selectedOption ? String(selectedOption.value || '').trim().toLowerCase() : '';
|
||||
var label = selectedOption ? String(selectedOption.textContent || selectedOption.label || selectedValue).trim() : selectedValue;
|
||||
var icon = previewButton.querySelector('[data-announcement-icon-picker-icon]');
|
||||
var text = previewButton.querySelector('[data-announcement-icon-picker-label]');
|
||||
|
||||
previewButton.setAttribute('aria-label', label);
|
||||
previewButton.setAttribute('title', label);
|
||||
if (icon) {
|
||||
icon.className = 'bi bi-' + selectedValue;
|
||||
}
|
||||
if (text) {
|
||||
text.textContent = label;
|
||||
}
|
||||
|
||||
picker.querySelectorAll('[data-announcement-icon-option]').forEach(function (button) {
|
||||
var isSelected = String(button.getAttribute('data-icon-key') || '').trim().toLowerCase() === selectedValue;
|
||||
button.classList.toggle('is-selected', isSelected);
|
||||
button.setAttribute('aria-pressed', isSelected ? 'true' : 'false');
|
||||
});
|
||||
}
|
||||
|
||||
function setAnnouncementIconValue(iconKey) {
|
||||
var iconSelect = document.getElementById('announcement-icon');
|
||||
if (!iconSelect) {
|
||||
return;
|
||||
}
|
||||
|
||||
var normalized = String(iconKey || '').trim().toLowerCase();
|
||||
if (!normalized) {
|
||||
return;
|
||||
}
|
||||
|
||||
iconSelect.value = normalized;
|
||||
updateAnnouncementIconPreview();
|
||||
updateAnnouncementIconPickerSelection();
|
||||
}
|
||||
|
||||
function initAnnouncementForm() {
|
||||
var typeInput = document.getElementById('announcement-type');
|
||||
var typePickerToggle = document.querySelector('[data-announcement-type-picker-toggle]');
|
||||
@@ -270,10 +208,6 @@ function initAnnouncementForm() {
|
||||
var colorPicker = document.querySelector('[data-announcement-color-picker-shell]');
|
||||
var screenSelectAll = document.querySelector('[data-announcement-screen-select-all]');
|
||||
var screenSelectNone = document.querySelector('[data-announcement-screen-select-none]');
|
||||
var iconSelect = document.getElementById('announcement-icon');
|
||||
var iconPickerToggle = document.querySelector('[data-announcement-icon-picker-toggle]');
|
||||
var iconPicker = document.querySelector('[data-announcement-icon-picker]');
|
||||
var iconPickerClose = document.querySelector('[data-announcement-icon-picker-close]');
|
||||
|
||||
if (typeInput) {
|
||||
updateAnnouncementTypePickerSelection();
|
||||
@@ -347,44 +281,16 @@ function initAnnouncementForm() {
|
||||
});
|
||||
}
|
||||
|
||||
if (iconSelect) {
|
||||
iconSelect.addEventListener('change', updateAnnouncementIconPreview);
|
||||
updateAnnouncementIconPreview();
|
||||
}
|
||||
document.addEventListener('web-async-save:success', function (event) {
|
||||
var detail = event && event.detail ? event.detail : null;
|
||||
var form = detail && detail.form ? detail.form : null;
|
||||
if (!form || form.id !== 'announcement-form') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (iconPickerToggle) {
|
||||
iconPickerToggle.addEventListener('click', function (event) {
|
||||
event.preventDefault();
|
||||
var isExpanded = iconPicker && !iconPicker.hidden;
|
||||
if (isExpanded) {
|
||||
closeAnnouncementIconPicker();
|
||||
} else {
|
||||
openAnnouncementIconPicker();
|
||||
}
|
||||
});
|
||||
}
|
||||
updateAnnouncementActionButtonState();
|
||||
});
|
||||
|
||||
if (iconPickerClose) {
|
||||
iconPickerClose.addEventListener('click', function (event) {
|
||||
event.preventDefault();
|
||||
closeAnnouncementIconPicker();
|
||||
});
|
||||
}
|
||||
|
||||
if (iconPicker) {
|
||||
iconPicker.addEventListener('click', function (event) {
|
||||
var button = event.target && event.target.closest ? event.target.closest('[data-announcement-icon-option]') : null;
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
setAnnouncementIconValue(button.getAttribute('data-icon-key'));
|
||||
closeAnnouncementIconPicker();
|
||||
});
|
||||
}
|
||||
|
||||
window.addEventListener('resize', positionAnnouncementIconPicker);
|
||||
window.addEventListener('resize', positionAnnouncementTypePicker);
|
||||
|
||||
document.addEventListener('click', function (event) {
|
||||
@@ -396,20 +302,9 @@ function initAnnouncementForm() {
|
||||
}
|
||||
}
|
||||
|
||||
var picker = document.querySelector('[data-announcement-icon-picker]');
|
||||
var toggle = document.querySelector('[data-announcement-icon-picker-toggle]');
|
||||
if (!picker || picker.hidden) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (picker.contains(event.target) || (toggle && toggle.contains(event.target))) {
|
||||
return;
|
||||
}
|
||||
|
||||
closeAnnouncementIconPicker();
|
||||
});
|
||||
|
||||
updateAnnouncementIconPickerSelection();
|
||||
updateAnnouncementActionButtonState();
|
||||
}
|
||||
|
||||
if (typeof document !== 'undefined') {
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function initIconPicker(root) {
|
||||
var select = root.querySelector('select');
|
||||
var toggle = root.querySelector('[data-icon-picker-toggle]');
|
||||
var menu = root.querySelector('[data-icon-picker-menu]');
|
||||
var preview = root.querySelector('[data-icon-picker-preview]');
|
||||
var label = root.querySelector('[data-icon-picker-label]');
|
||||
var search = root.querySelector('[data-icon-picker-search]');
|
||||
var close = root.querySelector('[data-icon-picker-close]');
|
||||
var grid = root.querySelector('[data-icon-picker-grid]');
|
||||
var empty = root.querySelector('[data-icon-picker-empty]');
|
||||
var initialOptions = Array.prototype.slice.call(root.querySelectorAll('[data-icon-picker-option]'));
|
||||
|
||||
if (!select || !toggle || !menu || !grid) {
|
||||
return;
|
||||
}
|
||||
|
||||
function catalogOptions() {
|
||||
return Array.prototype.slice.call(select.options).map(function (option) {
|
||||
return { value: option.value, label: option.textContent || option.label || option.value };
|
||||
});
|
||||
}
|
||||
|
||||
function createOption(option, selectedValue) {
|
||||
var button = document.createElement('button');
|
||||
button.type = 'button';
|
||||
button.className = 'announcement-icon-picker__option';
|
||||
button.setAttribute('data-icon-picker-option', '');
|
||||
button.setAttribute('data-icon-key', option.value);
|
||||
button.setAttribute('data-icon-label', option.label);
|
||||
button.setAttribute('aria-pressed', option.value === selectedValue ? 'true' : 'false');
|
||||
button.title = option.label;
|
||||
button.innerHTML = '<i class="bi bi-' + option.value + '" aria-hidden="true"></i><span class="visually-hidden">' + option.label + '</span>';
|
||||
return button;
|
||||
}
|
||||
|
||||
function getOptionLimit() {
|
||||
var firstOption = grid.querySelector('[data-icon-picker-option]');
|
||||
var gridStyle = window.getComputedStyle(grid);
|
||||
var gap = parseFloat(gridStyle.columnGap || gridStyle.gap || '0') || 0;
|
||||
var optionWidth = firstOption ? firstOption.getBoundingClientRect().width : 0;
|
||||
var columns = optionWidth && grid.clientWidth
|
||||
? Math.max(1, Math.floor((grid.clientWidth + gap) / (optionWidth + gap)))
|
||||
: 4;
|
||||
return columns * 6;
|
||||
}
|
||||
|
||||
function updatePreview() {
|
||||
var option = select.options[select.selectedIndex];
|
||||
var value = option ? option.value : '';
|
||||
if (preview) {
|
||||
preview.className = 'announcement-icon-picker__toggle-icon bi bi-' + value;
|
||||
}
|
||||
if (label) {
|
||||
label.textContent = option ? option.textContent : 'Select an icon';
|
||||
}
|
||||
root.querySelectorAll('[data-icon-picker-option]').forEach(function (optionButton) {
|
||||
var selected = optionButton.getAttribute('data-icon-key') === value;
|
||||
optionButton.classList.toggle('is-selected', selected);
|
||||
optionButton.setAttribute('aria-pressed', selected ? 'true' : 'false');
|
||||
});
|
||||
}
|
||||
|
||||
function render(query) {
|
||||
var normalizedQuery = String(query || '').trim().toLowerCase();
|
||||
var selectedValue = String(select.value || '').trim();
|
||||
var options = normalizedQuery
|
||||
? catalogOptions().filter(function (option) { return (option.value + ' ' + option.label).toLowerCase().indexOf(normalizedQuery) !== -1; })
|
||||
: initialOptions.map(function (option) { return { value: option.getAttribute('data-icon-key') || '', label: option.getAttribute('data-icon-label') || '' }; });
|
||||
var visibleOptions = options.slice(0, getOptionLimit());
|
||||
grid.innerHTML = '';
|
||||
visibleOptions.forEach(function (option) { grid.appendChild(createOption(option, selectedValue)); });
|
||||
if (empty) empty.hidden = options.length > 0;
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
function closeMenu() {
|
||||
menu.hidden = true;
|
||||
toggle.setAttribute('aria-expanded', 'false');
|
||||
}
|
||||
|
||||
toggle.addEventListener('click', function (event) {
|
||||
event.preventDefault();
|
||||
menu.hidden = !menu.hidden;
|
||||
toggle.setAttribute('aria-expanded', menu.hidden ? 'false' : 'true');
|
||||
if (!menu.hidden) {
|
||||
render(search ? search.value : '');
|
||||
if (search) search.focus();
|
||||
}
|
||||
});
|
||||
if (close) close.addEventListener('click', function (event) { event.preventDefault(); closeMenu(); });
|
||||
grid.addEventListener('click', function (event) {
|
||||
var option = event.target.closest ? event.target.closest('[data-icon-picker-option]') : null;
|
||||
if (!option) return;
|
||||
select.value = option.getAttribute('data-icon-key') || '';
|
||||
select.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
closeMenu();
|
||||
});
|
||||
if (search) search.addEventListener('input', function () { render(search.value); });
|
||||
select.addEventListener('change', updatePreview);
|
||||
document.addEventListener('click', function (event) {
|
||||
if (!menu.hidden && !root.contains(event.target)) closeMenu();
|
||||
});
|
||||
updatePreview();
|
||||
}
|
||||
|
||||
window.PulseIconPicker = { init: initIconPicker };
|
||||
document.querySelectorAll('[data-icon-picker]').forEach(initIconPicker);
|
||||
}());
|
||||
@@ -1665,6 +1665,7 @@
|
||||
var slidePickerSlides = [];
|
||||
var lastDurationPointerDown = null;
|
||||
var lastDurationPointerUp = null;
|
||||
var defaultSlideDuration = Number(tbody.getAttribute('data-default-slide-duration')) || 10;
|
||||
|
||||
if (!tbody || !form) {
|
||||
return;
|
||||
@@ -1961,8 +1962,8 @@
|
||||
videoDurationSeconds: slide.videoDurationSeconds,
|
||||
disableAudio: slide.disableAudio,
|
||||
title: slide.title || 'Slide',
|
||||
duration_seconds: 10,
|
||||
durationSeconds: 10,
|
||||
duration_seconds: defaultSlideDuration,
|
||||
durationSeconds: defaultSlideDuration,
|
||||
scheduleRules: [],
|
||||
summary: 'Always visible'
|
||||
});
|
||||
|
||||
@@ -105,6 +105,13 @@
|
||||
return document.querySelector('[data-permission-row-id="' + targetId + '"]');
|
||||
}
|
||||
|
||||
function markPermissionFormDirty(control) {
|
||||
var form = control && (control.form || (typeof control.closest === 'function' ? control.closest('form') : null));
|
||||
if (form && form.dataset) {
|
||||
form.dataset.dirty = 'true';
|
||||
}
|
||||
}
|
||||
|
||||
function handleRowChange(event) {
|
||||
var checkbox = event.target && event.target.matches ? event.target : null;
|
||||
if (!checkbox || checkbox.tagName !== 'INPUT' || checkbox.type !== 'checkbox') {
|
||||
@@ -162,6 +169,7 @@
|
||||
|
||||
if (control.hasAttribute('data-permission-row-toggle')) {
|
||||
toggleRowCheckboxes(findPermissionRow(targetId));
|
||||
markPermissionFormDirty(control);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -76,17 +76,31 @@
|
||||
|
||||
function buildEditorCardContext(context) {
|
||||
var defaultConfig = context && context.uploadConfig ? context.uploadConfig : {};
|
||||
var configuredTypes = Array.isArray(context && context.uploadMimeTypes)
|
||||
? context.uploadMimeTypes.filter(function (mimeType) { return String(mimeType || '').indexOf('image/') === 0; })
|
||||
: [];
|
||||
var accept = configuredTypes.length
|
||||
? configuredTypes
|
||||
: (Array.isArray(defaultConfig.accept) ? defaultConfig.accept : ['image/png', 'image/jpeg', 'image/gif', 'image/webp', 'image/svg+xml']);
|
||||
var acceptLabels = accept.map(function (mimeType) {
|
||||
var subtype = String(mimeType).split('/')[1] || '';
|
||||
return subtype === 'jpeg' ? 'JPG' : subtype === 'svg+xml' ? 'SVG' : subtype.toUpperCase();
|
||||
});
|
||||
var acceptLabel = acceptLabels.length > 1
|
||||
? acceptLabels.slice(0, -1).join(', ') + ' or ' + acceptLabels[acceptLabels.length - 1]
|
||||
: (acceptLabels[0] || 'supported image');
|
||||
return {
|
||||
region: context.region,
|
||||
current: String(context.current || ''),
|
||||
regionRatio: String(context.regionRatio || '1:1'),
|
||||
uploadConfig: {
|
||||
accept: Array.isArray(defaultConfig.accept) ? defaultConfig.accept : ['image/png', 'image/jpeg', 'image/gif', 'image/webp', 'image/svg+xml'],
|
||||
limitBytes: defaultConfig.limitBytes,
|
||||
accept: accept,
|
||||
limitBytes: defaultConfig.limitBytes || context.uploadMaxBytes,
|
||||
limitLabel: defaultConfig.limitLabel || context.uploadMaxLabel || '100 MB',
|
||||
helpText: defaultConfig.helpText || 'PNG, JPG, GIF, WebP, or SVG'
|
||||
helpText: defaultConfig.helpText || acceptLabel
|
||||
},
|
||||
uploadMaxLabel: context.uploadMaxLabel || '100 MB'
|
||||
uploadMaxLabel: context.uploadMaxLabel || '100 MB',
|
||||
uploadMimeTypes: context.uploadMimeTypes || []
|
||||
};
|
||||
}
|
||||
|
||||
@@ -108,10 +122,17 @@
|
||||
|
||||
var uploadConfig = context.uploadConfig || {};
|
||||
var accept = uploadConfig.accept || ['image/png', 'image/jpeg', 'image/gif', 'image/webp', 'image/svg+xml'];
|
||||
var acceptLabels = accept.map(function (mimeType) {
|
||||
var subtype = String(mimeType).split('/')[1] || '';
|
||||
return subtype === 'jpeg' ? 'JPG' : subtype === 'svg+xml' ? 'SVG' : subtype.toUpperCase();
|
||||
});
|
||||
var acceptLabel = acceptLabels.length > 1
|
||||
? acceptLabels.slice(0, -1).join(', ') + (acceptLabels.length > 2 ? ', or ' : ' or ') + acceptLabels[acceptLabels.length - 1]
|
||||
: (acceptLabels[0] || 'supported image');
|
||||
var limitBytes = Number(uploadConfig.limitBytes || 100 * 1024 * 1024);
|
||||
|
||||
if (!utils.fileMatchesAccept || !utils.fileMatchesAccept(context.file, accept)) {
|
||||
showUploadWarning('This image region accepts PNG, JPG, GIF, WebP, or SVG files.');
|
||||
showUploadWarning('This image region accepts ' + acceptLabel + ' files.');
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -133,7 +154,7 @@
|
||||
|
||||
return {
|
||||
accept: ['image/png', 'image/jpeg', 'image/gif', 'image/webp', 'image/svg+xml'],
|
||||
limitBytes: defaultConfig.limitBytes,
|
||||
limitBytes: defaultConfig.limitBytes || context.uploadMaxBytes,
|
||||
limitLabel: defaultConfig.limitLabel,
|
||||
helpText: 'PNG, JPG, GIF, WebP, or SVG'
|
||||
};
|
||||
|
||||
@@ -82,17 +82,30 @@
|
||||
|
||||
function buildEditorCardContext(context) {
|
||||
var defaultConfig = context && context.uploadConfig ? context.uploadConfig : {};
|
||||
var configuredTypes = Array.isArray(context && context.uploadMimeTypes)
|
||||
? context.uploadMimeTypes.filter(function (mimeType) { return String(mimeType || '').indexOf('video/') === 0; })
|
||||
: [];
|
||||
var accept = configuredTypes.length
|
||||
? configuredTypes
|
||||
: (Array.isArray(defaultConfig.accept) ? defaultConfig.accept : ['video/mp4', 'video/webm', 'video/ogg']);
|
||||
var acceptLabels = accept.map(function (mimeType) {
|
||||
return (String(mimeType).split('/')[1] || '').toUpperCase();
|
||||
});
|
||||
var acceptLabel = acceptLabels.length > 1
|
||||
? acceptLabels.slice(0, -1).join(', ') + ' or ' + acceptLabels[acceptLabels.length - 1]
|
||||
: (acceptLabels[0] || 'supported video');
|
||||
return {
|
||||
region: context.region,
|
||||
current: String(context.current || ''),
|
||||
currentDuration: String(context.currentDuration || ''),
|
||||
uploadConfig: {
|
||||
accept: Array.isArray(defaultConfig.accept) ? defaultConfig.accept : ['video/mp4', 'video/webm', 'video/ogg'],
|
||||
limitBytes: defaultConfig.limitBytes,
|
||||
accept: accept,
|
||||
limitBytes: defaultConfig.limitBytes || context.uploadVideoMaxBytes,
|
||||
limitLabel: defaultConfig.limitLabel || context.uploadVideoMaxLabel || '1 GB',
|
||||
helpText: defaultConfig.helpText || 'MP4, WebM, or Ogg'
|
||||
helpText: defaultConfig.helpText || acceptLabel
|
||||
},
|
||||
uploadVideoMaxLabel: context.uploadVideoMaxLabel || '1 GB'
|
||||
uploadVideoMaxLabel: context.uploadVideoMaxLabel || '1 GB',
|
||||
uploadMimeTypes: context.uploadMimeTypes || []
|
||||
};
|
||||
}
|
||||
|
||||
@@ -114,10 +127,16 @@
|
||||
|
||||
var uploadConfig = context.uploadConfig || {};
|
||||
var accept = uploadConfig.accept || ['video/mp4', 'video/webm', 'video/ogg'];
|
||||
var acceptLabels = accept.map(function (mimeType) {
|
||||
return (String(mimeType).split('/')[1] || '').toUpperCase();
|
||||
});
|
||||
var acceptLabel = acceptLabels.length > 1
|
||||
? acceptLabels.slice(0, -1).join(', ') + (acceptLabels.length > 2 ? ', or ' : ' or ') + acceptLabels[acceptLabels.length - 1]
|
||||
: (acceptLabels[0] || 'supported video');
|
||||
var limitBytes = Number(uploadConfig.limitBytes || 1024 * 1024 * 1024);
|
||||
|
||||
if (!utils.fileMatchesAccept || !utils.fileMatchesAccept(context.file, accept)) {
|
||||
showUploadWarning('This video region accepts MP4, WebM, or Ogg files.');
|
||||
showUploadWarning('This video region accepts ' + acceptLabel + ' files.');
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -163,7 +182,7 @@
|
||||
|
||||
return {
|
||||
accept: ['video/mp4', 'video/webm', 'video/ogg'],
|
||||
limitBytes: defaultConfig.limitBytes,
|
||||
limitBytes: defaultConfig.limitBytes || context.uploadVideoMaxBytes,
|
||||
limitLabel: defaultConfig.limitLabel,
|
||||
helpText: 'MP4, WebM, or Ogg'
|
||||
};
|
||||
|
||||
@@ -0,0 +1,392 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function initIconSuggestions() {
|
||||
var searchInput = document.querySelector('[data-icon-suggestions-search]');
|
||||
var countNode = document.querySelector('[data-icon-suggestions-count]');
|
||||
var selectedList = document.querySelector('[data-selected-icon-list]');
|
||||
var noSelectedNode = document.querySelector('[data-no-selected-icons]');
|
||||
var addButton = document.querySelector('[data-add-icon-button]');
|
||||
var iconForm = document.querySelector('[data-settings-form="icons"]');
|
||||
var options = Array.prototype.slice.call(document.querySelectorAll('[data-icon-suggestion-option]'));
|
||||
var maxSelected = 48;
|
||||
var draggedItem = null;
|
||||
var initialOrder = [];
|
||||
|
||||
if (!searchInput || !countNode || !selectedList || !options.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
function getOptionByKey(key) {
|
||||
return options.find(function (option) {
|
||||
var checkbox = option.querySelector('[data-icon-picker-checkbox]');
|
||||
return checkbox && checkbox.value === key;
|
||||
}) || null;
|
||||
}
|
||||
|
||||
function getCheckedKeys() {
|
||||
return options.filter(function (option) {
|
||||
var checkbox = option.querySelector('[data-icon-picker-checkbox]');
|
||||
return checkbox && checkbox.checked;
|
||||
}).map(function (option) {
|
||||
return option.querySelector('[data-icon-picker-checkbox]').value;
|
||||
});
|
||||
}
|
||||
|
||||
function getSelectedOrder() {
|
||||
return Array.prototype.slice.call(selectedList.querySelectorAll('[data-selected-icon-item]')).map(function (item) {
|
||||
return item.getAttribute('data-icon-key');
|
||||
});
|
||||
}
|
||||
|
||||
function createSelectedItem(key) {
|
||||
var option = getOptionByKey(key);
|
||||
var checkbox = option && option.querySelector('[data-icon-picker-checkbox]');
|
||||
if (!option || !checkbox) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var item = document.createElement('div');
|
||||
var content = document.createElement('div');
|
||||
var dragButton = document.createElement('button');
|
||||
var dragIcon = document.createElement('i');
|
||||
var icon = document.createElement('i');
|
||||
var label = document.createElement('span');
|
||||
var hiddenInput = document.createElement('input');
|
||||
var removeButton = document.createElement('button');
|
||||
var removeIcon = document.createElement('i');
|
||||
var iconLabel = String(option.getAttribute('data-icon-label') || key);
|
||||
|
||||
item.className = 'col-12 col-sm-6 col-xl-3';
|
||||
content.className = 'd-flex align-items-center gap-2 border rounded p-2 h-100';
|
||||
item.draggable = true;
|
||||
item.setAttribute('data-selected-icon-item', '');
|
||||
item.setAttribute('data-icon-key', key);
|
||||
|
||||
dragButton.type = 'button';
|
||||
dragButton.className = 'btn btn-link text-body-secondary p-1';
|
||||
dragButton.setAttribute('data-drag-icon', '');
|
||||
dragButton.title = 'Drag to reorder';
|
||||
dragButton.setAttribute('aria-label', 'Drag ' + iconLabel + ' to reorder');
|
||||
dragIcon.className = 'bi bi-grip-vertical';
|
||||
dragIcon.setAttribute('aria-hidden', 'true');
|
||||
dragButton.appendChild(dragIcon);
|
||||
|
||||
icon.className = 'bi bi-' + key + ' fs-5 text-primary';
|
||||
icon.setAttribute('aria-hidden', 'true');
|
||||
label.className = 'flex-grow-1';
|
||||
label.textContent = iconLabel;
|
||||
|
||||
hiddenInput.type = 'hidden';
|
||||
hiddenInput.name = 'suggested_icons[]';
|
||||
hiddenInput.value = key;
|
||||
hiddenInput.setAttribute('data-ordered-icon-input', '');
|
||||
|
||||
removeButton.type = 'button';
|
||||
removeButton.className = 'btn btn-link text-danger p-1';
|
||||
removeButton.setAttribute('data-remove-icon', '');
|
||||
removeButton.title = 'Remove ' + iconLabel;
|
||||
removeButton.setAttribute('aria-label', 'Remove ' + iconLabel);
|
||||
removeIcon.className = 'bi bi-x-lg';
|
||||
removeIcon.setAttribute('aria-hidden', 'true');
|
||||
removeButton.appendChild(removeIcon);
|
||||
|
||||
content.appendChild(dragButton);
|
||||
content.appendChild(icon);
|
||||
content.appendChild(label);
|
||||
content.appendChild(hiddenInput);
|
||||
content.appendChild(removeButton);
|
||||
item.appendChild(content);
|
||||
return item;
|
||||
}
|
||||
|
||||
function renderSelectedItems(order) {
|
||||
selectedList.querySelectorAll('[data-selected-icon-item]').forEach(function (item) {
|
||||
item.remove();
|
||||
});
|
||||
order.forEach(function (key) {
|
||||
var item = createSelectedItem(key);
|
||||
if (item) {
|
||||
selectedList.insertBefore(item, noSelectedNode);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function syncSelectionState() {
|
||||
var checkedKeys = getCheckedKeys();
|
||||
var checkedSet = new Set(checkedKeys);
|
||||
var currentOrder = getSelectedOrder().filter(function (key) {
|
||||
return checkedSet.has(key);
|
||||
});
|
||||
checkedKeys.forEach(function (key) {
|
||||
if (currentOrder.indexOf(key) === -1) {
|
||||
currentOrder.push(key);
|
||||
}
|
||||
});
|
||||
renderSelectedItems(currentOrder);
|
||||
countNode.textContent = String(currentOrder.length);
|
||||
if (noSelectedNode) {
|
||||
noSelectedNode.hidden = currentOrder.length > 0;
|
||||
}
|
||||
if (addButton) {
|
||||
addButton.disabled = currentOrder.length >= maxSelected;
|
||||
addButton.setAttribute('aria-disabled', addButton.disabled ? 'true' : 'false');
|
||||
}
|
||||
options.forEach(function (option) {
|
||||
var checkbox = option.querySelector('[data-icon-picker-checkbox]');
|
||||
if (checkbox) {
|
||||
checkbox.disabled = !checkbox.checked && currentOrder.length >= maxSelected;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function resetIconForm() {
|
||||
var initialSet = new Set(initialOrder);
|
||||
options.forEach(function (option) {
|
||||
var checkbox = option.querySelector('[data-icon-picker-checkbox]');
|
||||
if (checkbox) {
|
||||
checkbox.checked = initialSet.has(checkbox.value);
|
||||
}
|
||||
});
|
||||
renderSelectedItems(initialOrder.slice());
|
||||
syncSelectionState();
|
||||
if (iconForm) {
|
||||
iconForm.dataset.dirty = 'false';
|
||||
}
|
||||
}
|
||||
|
||||
function markIconFormDirty() {
|
||||
if (iconForm) {
|
||||
iconForm.dataset.dirty = 'true';
|
||||
}
|
||||
}
|
||||
|
||||
function filterOptions() {
|
||||
var query = String(searchInput.value || '').trim().toLowerCase();
|
||||
options.forEach(function (option) {
|
||||
var label = String(option.getAttribute('data-icon-label') || '').toLowerCase();
|
||||
option.hidden = Boolean(query && label.indexOf(query) === -1);
|
||||
});
|
||||
}
|
||||
|
||||
options.forEach(function (option) {
|
||||
var checkbox = option.querySelector('[data-icon-picker-checkbox]');
|
||||
if (checkbox) {
|
||||
checkbox.addEventListener('change', function () {
|
||||
markIconFormDirty();
|
||||
syncSelectionState();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
selectedList.addEventListener('click', function (event) {
|
||||
var removeButton = event.target.closest ? event.target.closest('[data-remove-icon]') : null;
|
||||
if (!removeButton) {
|
||||
return;
|
||||
}
|
||||
var item = removeButton.closest('[data-selected-icon-item]');
|
||||
var key = item && item.getAttribute('data-icon-key');
|
||||
var option = getOptionByKey(key);
|
||||
var checkbox = option && option.querySelector('[data-icon-picker-checkbox]');
|
||||
if (checkbox) {
|
||||
checkbox.checked = false;
|
||||
}
|
||||
markIconFormDirty();
|
||||
syncSelectionState();
|
||||
});
|
||||
|
||||
selectedList.addEventListener('dragstart', function (event) {
|
||||
var item = event.target.closest ? event.target.closest('[data-selected-icon-item]') : null;
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
draggedItem = item;
|
||||
item.classList.add('opacity-50');
|
||||
event.dataTransfer.effectAllowed = 'move';
|
||||
event.dataTransfer.setData('text/plain', item.getAttribute('data-icon-key') || '');
|
||||
});
|
||||
|
||||
selectedList.addEventListener('dragover', function (event) {
|
||||
if (!draggedItem) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
var target = event.target.closest ? event.target.closest('[data-selected-icon-item]') : null;
|
||||
if (!target || target === draggedItem) {
|
||||
return;
|
||||
}
|
||||
var bounds = target.getBoundingClientRect();
|
||||
var insertBefore = event.clientY < bounds.top + bounds.height / 2;
|
||||
selectedList.insertBefore(draggedItem, insertBefore ? target : target.nextSibling);
|
||||
});
|
||||
|
||||
selectedList.addEventListener('dragend', function () {
|
||||
if (!draggedItem) {
|
||||
return;
|
||||
}
|
||||
draggedItem.classList.remove('opacity-50');
|
||||
draggedItem = null;
|
||||
markIconFormDirty();
|
||||
syncSelectionState();
|
||||
});
|
||||
|
||||
searchInput.addEventListener('input', filterOptions);
|
||||
syncSelectionState();
|
||||
initialOrder = getSelectedOrder();
|
||||
document.addEventListener('settings:reset', resetIconForm);
|
||||
}
|
||||
|
||||
function initDefaultAnnouncementIconPicker() {
|
||||
return;
|
||||
var shell = document.querySelector('[data-settings-default-icon-picker]');
|
||||
if (!shell) return;
|
||||
var select = shell.querySelector('select');
|
||||
var toggle = shell.querySelector('[data-settings-default-icon-toggle]');
|
||||
var menu = shell.querySelector('[data-settings-default-icon-menu]');
|
||||
var preview = shell.querySelector('[data-settings-default-icon-preview]');
|
||||
var label = shell.querySelector('[data-settings-default-icon-label]');
|
||||
var search = shell.querySelector('[data-settings-default-icon-search]');
|
||||
var empty = shell.querySelector('[data-settings-default-icon-empty]');
|
||||
var options = Array.prototype.slice.call(shell.querySelectorAll('[data-settings-default-icon-option]'));
|
||||
|
||||
function getCatalogOptions() {
|
||||
return Array.prototype.slice.call(select.options).map(function (option) {
|
||||
return { value: option.value, label: option.textContent || option.label || option.value };
|
||||
});
|
||||
}
|
||||
|
||||
function createOption(option, selectedValue) {
|
||||
var item = document.createElement('button');
|
||||
item.type = 'button';
|
||||
item.className = 'announcement-icon-picker__option';
|
||||
item.setAttribute('data-settings-default-icon-option', '');
|
||||
item.setAttribute('data-icon-key', option.value);
|
||||
item.setAttribute('data-icon-label', option.label);
|
||||
item.setAttribute('data-icon-search-terms', option.value + ' ' + option.label);
|
||||
item.setAttribute('aria-pressed', option.value === selectedValue ? 'true' : 'false');
|
||||
item.title = option.label;
|
||||
item.innerHTML = '<i class="bi bi-' + option.value + '" aria-hidden="true"></i><span class="visually-hidden">' + option.label + '</span>';
|
||||
return item;
|
||||
}
|
||||
|
||||
function renderOptions(query) {
|
||||
var normalizedQuery = String(query || '').trim().toLowerCase();
|
||||
var selectedValue = String(select.value || '').trim();
|
||||
var sourceOptions = normalizedQuery ? getCatalogOptions().filter(function (option) {
|
||||
return (option.value + ' ' + option.label).toLowerCase().indexOf(normalizedQuery) !== -1;
|
||||
}) : options.map(function (option) {
|
||||
return { value: option.getAttribute('data-icon-key') || '', label: option.getAttribute('data-icon-label') || '' };
|
||||
});
|
||||
var grid = shell.querySelector('[data-settings-default-icon-grid]');
|
||||
grid.innerHTML = '';
|
||||
sourceOptions.forEach(function (option) {
|
||||
grid.appendChild(createOption(option, selectedValue));
|
||||
});
|
||||
options = Array.prototype.slice.call(grid.querySelectorAll('[data-settings-default-icon-option]'));
|
||||
options.forEach(bindOption);
|
||||
empty.hidden = Boolean(sourceOptions.length);
|
||||
}
|
||||
|
||||
function bindOption(item) {
|
||||
item.addEventListener('click', function () {
|
||||
select.value = item.getAttribute('data-icon-key') || '';
|
||||
select.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
menu.hidden = true;
|
||||
toggle.setAttribute('aria-expanded', 'false');
|
||||
});
|
||||
}
|
||||
|
||||
function render() {
|
||||
var option = select.options[select.selectedIndex];
|
||||
var key = option ? option.value : '';
|
||||
var text = option ? option.textContent : 'Select an icon';
|
||||
preview.className = 'announcement-icon-picker__toggle-icon bi bi-' + key;
|
||||
if (label) label.textContent = text;
|
||||
options.forEach(function (item) {
|
||||
item.classList.toggle('is-selected', item.getAttribute('data-icon-key') === key);
|
||||
});
|
||||
}
|
||||
toggle.addEventListener('click', function () {
|
||||
menu.hidden = !menu.hidden;
|
||||
toggle.setAttribute('aria-expanded', menu.hidden ? 'false' : 'true');
|
||||
if (!menu.hidden && search) search.focus();
|
||||
});
|
||||
shell.querySelector('[data-settings-default-icon-close]').addEventListener('click', function () {
|
||||
menu.hidden = true;
|
||||
toggle.setAttribute('aria-expanded', 'false');
|
||||
});
|
||||
options.forEach(bindOption);
|
||||
if (search) search.addEventListener('input', function () {
|
||||
renderOptions(search.value);
|
||||
});
|
||||
select.addEventListener('change', render);
|
||||
render();
|
||||
}
|
||||
|
||||
function initSettingsSectionNavigation() {
|
||||
var links = Array.prototype.slice.call(document.querySelectorAll('[data-settings-section-link]'));
|
||||
var sections = Array.prototype.slice.call(document.querySelectorAll('[data-settings-section]'));
|
||||
if (!links.length || !sections.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
function setActiveSection(sectionId) {
|
||||
links.forEach(function (link) {
|
||||
var isActive = link.getAttribute('href') === '#' + sectionId;
|
||||
link.classList.toggle('active', isActive);
|
||||
link.setAttribute('aria-current', isActive ? 'page' : 'false');
|
||||
});
|
||||
sections.forEach(function (section) {
|
||||
section.hidden = section.id !== sectionId;
|
||||
});
|
||||
}
|
||||
|
||||
function hasDirtySettingsForm() {
|
||||
return Array.prototype.some.call(document.querySelectorAll('[data-settings-form]'), function (form) {
|
||||
return form.dataset && form.dataset.dirty === 'true';
|
||||
});
|
||||
}
|
||||
|
||||
function resetSettingsForms() {
|
||||
document.querySelectorAll('[data-settings-form]').forEach(function (form) {
|
||||
if (typeof form.reset === 'function') {
|
||||
form.reset();
|
||||
}
|
||||
form.dataset.dirty = 'false';
|
||||
});
|
||||
document.dispatchEvent(new CustomEvent('settings:reset'));
|
||||
}
|
||||
|
||||
links.forEach(function (link) {
|
||||
link.addEventListener('click', function (event) {
|
||||
var target = document.getElementById(String(link.getAttribute('href') || '').replace(/^#/, ''));
|
||||
if (!target) {
|
||||
return;
|
||||
}
|
||||
var currentSection = sections.find(function (section) { return !section.hidden; });
|
||||
if (currentSection && target.id !== currentSection.id && hasDirtySettingsForm()) {
|
||||
if (!window.confirm('You have unsaved settings. Switch sections anyway?')) {
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
resetSettingsForms();
|
||||
}
|
||||
event.preventDefault();
|
||||
setActiveSection(target.id);
|
||||
window.history.replaceState(null, '', '#' + target.id);
|
||||
});
|
||||
});
|
||||
|
||||
var hashSectionId = String(window.location.hash || '').replace(/^#/, '');
|
||||
var initialSection = sections.some(function (section) {
|
||||
return section.id === hashSectionId;
|
||||
}) ? hashSectionId : sections[0].id;
|
||||
setActiveSection(initialSection);
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
initIconSuggestions();
|
||||
initDefaultAnnouncementIconPicker();
|
||||
initSettingsSectionNavigation();
|
||||
});
|
||||
}());
|
||||
@@ -3,6 +3,7 @@ export function createSlideFormEditorController(options) {
|
||||
var templateFields = settings.templateFields || null;
|
||||
var templateSelectorLock = settings.templateSelectorLock || null;
|
||||
var requestPreviewRender = typeof settings.requestPreviewRender === 'function' ? settings.requestPreviewRender : function () {};
|
||||
var markFormDirty = typeof settings.markFormDirty === 'function' ? settings.markFormDirty : function () {};
|
||||
var defaultFontSize = Math.max(1, Number(settings.defaultFontSize || 32));
|
||||
var fontFamilyFormats = String(settings.fontFamilyFormats || '').trim();
|
||||
var fontStylesheetHref = String(settings.fontStylesheetHref || '').trim();
|
||||
@@ -17,8 +18,16 @@ export function createSlideFormEditorController(options) {
|
||||
var imageUploadMaxBytes = Math.max(1, Number(settings.imageUploadMaxBytes || 2 * 1024 * 1024));
|
||||
var imageUploadLimitLabel = String(settings.imageUploadLimitLabel || '').trim() || Math.max(1, Math.round(imageUploadMaxBytes / (1024 * 1024))) + ' MB';
|
||||
var imageUploadContext = String(settings.imageUploadContext || 'wysiwyg').trim() || 'wysiwyg';
|
||||
var imageUploadAllowedExtensions = ['png', 'jpg', 'jpeg', 'gif', 'webp', 'svg'];
|
||||
var imageUploadAllowedMimeTypes = ['image/png', 'image/jpeg', 'image/gif', 'image/webp', 'image/svg+xml'];
|
||||
var configuredImageMimeTypes = Array.isArray(settings.uploadMimeTypes)
|
||||
? settings.uploadMimeTypes.filter(function (mimeType) { return String(mimeType || '').indexOf('image/') === 0; })
|
||||
: [];
|
||||
var imageUploadAllowedMimeTypes = configuredImageMimeTypes.length
|
||||
? configuredImageMimeTypes
|
||||
: ['image/png', 'image/jpeg', 'image/gif', 'image/webp', 'image/svg+xml'];
|
||||
var imageUploadAllowedExtensions = imageUploadAllowedMimeTypes.map(function (mimeType) {
|
||||
var subtype = String(mimeType).split('/')[1] || '';
|
||||
return subtype === 'jpeg' ? 'jpg' : subtype === 'svg+xml' ? 'svg' : subtype;
|
||||
});
|
||||
var imageUploadFileTypes = imageUploadAllowedExtensions.join(',');
|
||||
var wysiwygEditorHeightStep = Math.max(1, Number(settings.wysiwygEditorHeightStep || 80));
|
||||
var wysiwygEditorHeightMin = Math.max(1, Number(settings.wysiwygEditorHeightMin || 240));
|
||||
@@ -542,6 +551,9 @@ export function createSlideFormEditorController(options) {
|
||||
['change', 'keyup', 'undo', 'redo', 'Paste', 'input'].forEach(function (eventName) {
|
||||
editor.on(eventName, function () {
|
||||
syncState(true);
|
||||
if (hydrated) {
|
||||
markFormDirty();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -30,6 +30,9 @@ export function createSlideFormRegionHelpers(options) {
|
||||
var defaultFontSize = Math.max(1, Number(settings.defaultFontSize || 32));
|
||||
var uploadMaxLabel = String(settings.uploadMaxLabel || '100 MB');
|
||||
var uploadVideoMaxLabel = String(settings.uploadVideoMaxLabel || '1 GB');
|
||||
var uploadMaxBytes = Number(settings.uploadMaxBytes || 100 * 1024 * 1024);
|
||||
var uploadVideoMaxBytes = Number(settings.uploadVideoMaxBytes || 1024 * 1024 * 1024);
|
||||
var uploadMimeTypes = Array.isArray(settings.uploadMimeTypes) ? settings.uploadMimeTypes : [];
|
||||
|
||||
function sanitizeFontSize(value) {
|
||||
var raw = String(value || '').trim().toLowerCase();
|
||||
@@ -539,6 +542,9 @@ export function createSlideFormRegionHelpers(options) {
|
||||
regionRatio: reduceAspectRatio(region.width, region.height),
|
||||
uploadMaxLabel: uploadMaxLabel,
|
||||
uploadVideoMaxLabel: uploadVideoMaxLabel,
|
||||
uploadMaxBytes: uploadMaxBytes,
|
||||
uploadVideoMaxBytes: uploadVideoMaxBytes,
|
||||
uploadMimeTypes: uploadMimeTypes,
|
||||
disableAudio: (existingContent[region.region_key] || {}).disable_audio,
|
||||
config: region.region_type === 'api' ? getCurrentApiConfig(region) : region.region_type === 'timetable' ? getCurrentTimetableConfig(region) : getCurrentRssConfig(region),
|
||||
style: getCurrentTextStyle(region),
|
||||
@@ -579,6 +585,9 @@ export function createSlideFormRegionHelpers(options) {
|
||||
regionRatio: reduceAspectRatio(region.width, region.height),
|
||||
uploadMaxLabel: uploadMaxLabel,
|
||||
uploadVideoMaxLabel: uploadVideoMaxLabel,
|
||||
uploadMaxBytes: uploadMaxBytes,
|
||||
uploadVideoMaxBytes: uploadVideoMaxBytes,
|
||||
uploadMimeTypes: uploadMimeTypes,
|
||||
disableAudio: currentContent.disable_audio,
|
||||
config: region.region_type === 'api' ? apiConfig : region.region_type === 'timetable' ? getCurrentTimetableConfig(region) : rssConfig,
|
||||
style: textStyle,
|
||||
|
||||
@@ -6,6 +6,14 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
|
||||
(function () {
|
||||
var DEFAULT_FONT_SIZE = 32;
|
||||
|
||||
function formatUploadLimitLabel(bytes) {
|
||||
var megabytes = Number(bytes || 0) / 1024 / 1024;
|
||||
if (megabytes >= 1024 && megabytes % 1024 === 0) {
|
||||
return String(megabytes / 1024) + ' GB';
|
||||
}
|
||||
return (Number.isInteger(megabytes) ? String(megabytes) : megabytes.toFixed(2).replace(/0+$/, '').replace(/\.$/, '')) + ' MB';
|
||||
}
|
||||
|
||||
var dataElement = document.getElementById('slide-editor-data');
|
||||
if (!dataElement) {
|
||||
return;
|
||||
@@ -37,12 +45,14 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
|
||||
var slidePreviewEmpty = document.getElementById('slide-preview-empty');
|
||||
var slidePreviewOverlay = document.getElementById('slide-preview-overlay');
|
||||
var openPreviewPopupButton = document.getElementById('open-preview-popup');
|
||||
var uploadMaxBytes = 100 * 1024 * 1024;
|
||||
var uploadMaxLabel = '100 MB';
|
||||
var uploadVideoMaxBytes = 1024 * 1024 * 1024;
|
||||
var uploadVideoMaxLabel = '1 GB';
|
||||
var wysiwygImageUploadMaxBytes = 2 * 1024 * 1024;
|
||||
var wysiwygImageUploadLimitLabel = '2 MB';
|
||||
var uploadLimits = slideEditorData.uploadLimits || {};
|
||||
var uploadMaxBytes = Number(uploadLimits.imageMaxBytes || 100 * 1024 * 1024);
|
||||
var uploadMaxLabel = formatUploadLimitLabel(uploadMaxBytes);
|
||||
var uploadVideoMaxBytes = Number(uploadLimits.videoMaxBytes || 1024 * 1024 * 1024);
|
||||
var uploadVideoMaxLabel = formatUploadLimitLabel(uploadVideoMaxBytes);
|
||||
var wysiwygImageUploadMaxBytes = Number(uploadLimits.wysiwygImageMaxBytes || 2 * 1024 * 1024);
|
||||
var wysiwygImageUploadLimitLabel = formatUploadLimitLabel(wysiwygImageUploadMaxBytes);
|
||||
var uploadMimeTypes = Array.isArray(uploadLimits.allowedMimeTypes) ? uploadLimits.allowedMimeTypes : [];
|
||||
var videoDurationCache = Object.create(null);
|
||||
var previewRenderFrame = 0;
|
||||
var previewPopupWindow = null;
|
||||
@@ -111,7 +121,11 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
|
||||
imageUploadMaxBytes: wysiwygImageUploadMaxBytes,
|
||||
imageUploadLimitLabel: wysiwygImageUploadLimitLabel,
|
||||
imageUploadContext: 'wysiwyg',
|
||||
uploadMimeTypes: uploadMimeTypes,
|
||||
getRegionTypeModule: getRegionTypeModule,
|
||||
markFormDirty: function () {
|
||||
slideForm.dataset.dirty = 'true';
|
||||
},
|
||||
getEditorBackgroundColor: function () {
|
||||
var template = getTemplateById(templateSelect.value);
|
||||
return template && template.background_color ? String(template.background_color) : '#111111';
|
||||
@@ -128,6 +142,9 @@ import { createSlideFormPreviewHelpers } from '/assets/js/slides/slide-form-prev
|
||||
defaultFontSize: DEFAULT_FONT_SIZE,
|
||||
uploadMaxLabel: uploadMaxLabel,
|
||||
uploadVideoMaxLabel: uploadVideoMaxLabel,
|
||||
uploadMaxBytes: uploadMaxBytes,
|
||||
uploadVideoMaxBytes: uploadVideoMaxBytes,
|
||||
uploadMimeTypes: uploadMimeTypes,
|
||||
escapeHtml: escapeHtml,
|
||||
getRegionTypeModule: getRegionTypeModule,
|
||||
requestPreviewRender: requestPreviewRender
|
||||
|
||||
@@ -23,6 +23,14 @@
|
||||
var listenersAttached = false;
|
||||
var uploadMaxBytes = 100 * 1024 * 1024;
|
||||
var uploadMaxLabel = '100 MB';
|
||||
var editorDataElement = document.getElementById('slide-editor-data');
|
||||
try {
|
||||
var editorData = JSON.parse(editorDataElement && (editorDataElement.value || editorDataElement.textContent) || '{}') || {};
|
||||
uploadMaxBytes = Number(editorData.uploadLimits && editorData.uploadLimits.imageMaxBytes) || uploadMaxBytes;
|
||||
var megabytes = uploadMaxBytes / 1024 / 1024;
|
||||
uploadMaxLabel = Number.isInteger(megabytes) ? String(megabytes) + ' MB' : megabytes.toFixed(2).replace(/0+$/, '').replace(/\.$/, '') + ' MB';
|
||||
} catch (_error) {
|
||||
}
|
||||
|
||||
function getRegionId(input) {
|
||||
var match = String(input && input.name || '').match(/^region_image_(\d+)$/);
|
||||
|
||||
Reference in New Issue
Block a user