316 lines
11 KiB
JavaScript
316 lines
11 KiB
JavaScript
function updateAnnouncementDurationFields() {
|
|
var modeSelect = document.getElementById('announcement-duration-mode');
|
|
var durationFields = document.querySelector('[data-announcement-duration-value-fields]');
|
|
if (!modeSelect || !durationFields) {
|
|
return;
|
|
}
|
|
|
|
var durationValueInput = document.getElementById('announcement-duration-value');
|
|
var durationUnitSelect = document.getElementById('announcement-duration-unit');
|
|
var isDurationMode = String(modeSelect.value || '').trim() === 'duration';
|
|
|
|
durationFields.hidden = !isDurationMode;
|
|
if (durationValueInput) {
|
|
durationValueInput.disabled = !isDurationMode;
|
|
}
|
|
if (durationUnitSelect) {
|
|
durationUnitSelect.disabled = !isDurationMode;
|
|
}
|
|
}
|
|
|
|
function updateAnnouncementColorPickerSelection() {
|
|
var colorInput = document.getElementById('announcement-color');
|
|
var picker = document.querySelector('[data-announcement-color-picker-shell]');
|
|
if (!colorInput || !picker) {
|
|
return;
|
|
}
|
|
|
|
var selectedValue = String(colorInput.value || '').trim().toLowerCase() || 'primary';
|
|
picker.querySelectorAll('[data-announcement-color-option]').forEach(function (button) {
|
|
var isSelected = String(button.getAttribute('data-color-key') || '').trim().toLowerCase() === selectedValue;
|
|
button.classList.toggle('is-selected', isSelected);
|
|
button.setAttribute('aria-pressed', isSelected ? 'true' : 'false');
|
|
});
|
|
}
|
|
|
|
function setAnnouncementScreenSelection(isSelected) {
|
|
document.querySelectorAll('input[name="screen_ids[]"]').forEach(function (input) {
|
|
input.checked = 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]');
|
|
var shell = document.querySelector('[data-announcement-type-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 closeAnnouncementTypePicker() {
|
|
var picker = document.querySelector('[data-announcement-type-picker]');
|
|
var toggle = document.querySelector('[data-announcement-type-picker-toggle]');
|
|
if (!picker) {
|
|
return;
|
|
}
|
|
|
|
picker.hidden = true;
|
|
picker.classList.remove('is-open-above');
|
|
if (toggle) {
|
|
toggle.setAttribute('aria-expanded', 'false');
|
|
}
|
|
}
|
|
|
|
function openAnnouncementTypePicker() {
|
|
var picker = document.querySelector('[data-announcement-type-picker]');
|
|
var toggle = document.querySelector('[data-announcement-type-picker-toggle]');
|
|
if (!picker) {
|
|
return;
|
|
}
|
|
|
|
picker.hidden = false;
|
|
if (toggle) {
|
|
toggle.setAttribute('aria-expanded', 'true');
|
|
}
|
|
|
|
if (typeof window !== 'undefined' && window.requestAnimationFrame) {
|
|
window.requestAnimationFrame(positionAnnouncementTypePicker);
|
|
} else {
|
|
positionAnnouncementTypePicker();
|
|
}
|
|
}
|
|
|
|
function updateAnnouncementTypePickerSelection() {
|
|
var typeInput = document.getElementById('announcement-type');
|
|
var previewButton = document.querySelector('[data-announcement-type-picker-toggle]');
|
|
var picker = document.querySelector('[data-announcement-type-picker]');
|
|
if (!typeInput || !previewButton || !picker) {
|
|
return;
|
|
}
|
|
|
|
var selectedValue = String(typeInput.value || '').trim().toLowerCase();
|
|
var selectedOption = picker.querySelector('[data-announcement-type-option][data-type-key="' + selectedValue + '"]');
|
|
var label = selectedOption ? String(selectedOption.getAttribute('data-type-label') || selectedOption.textContent || selectedValue).trim() : selectedValue;
|
|
var iconKey = selectedOption ? String(selectedOption.getAttribute('data-type-icon') || '').trim().toLowerCase() : '';
|
|
var icon = previewButton.querySelector('[data-announcement-type-picker-icon]');
|
|
var text = previewButton.querySelector('[data-announcement-type-picker-label]');
|
|
|
|
previewButton.setAttribute('aria-label', label);
|
|
previewButton.setAttribute('title', label);
|
|
if (icon) {
|
|
icon.className = 'bi bi-' + iconKey;
|
|
}
|
|
if (text) {
|
|
text.textContent = label;
|
|
}
|
|
|
|
picker.querySelectorAll('[data-announcement-type-option]').forEach(function (button) {
|
|
var isSelected = String(button.getAttribute('data-type-key') || '').trim().toLowerCase() === selectedValue;
|
|
button.classList.toggle('is-selected', isSelected);
|
|
button.setAttribute('aria-pressed', isSelected ? 'true' : 'false');
|
|
});
|
|
}
|
|
|
|
function setAnnouncementTypeValue(typeKey) {
|
|
var typeInput = document.getElementById('announcement-type');
|
|
if (!typeInput) {
|
|
return;
|
|
}
|
|
|
|
var normalized = String(typeKey || '').trim().toLowerCase();
|
|
if (!normalized) {
|
|
return;
|
|
}
|
|
|
|
typeInput.value = normalized;
|
|
updateAnnouncementTypePickerSelection();
|
|
}
|
|
|
|
function initAnnouncementForm() {
|
|
var typeInput = document.getElementById('announcement-type');
|
|
var typePickerToggle = document.querySelector('[data-announcement-type-picker-toggle]');
|
|
var typePicker = document.querySelector('[data-announcement-type-picker]');
|
|
var typePickerClose = document.querySelector('[data-announcement-type-picker-close]');
|
|
var modeSelect = document.getElementById('announcement-duration-mode');
|
|
var colorInput = document.getElementById('announcement-color');
|
|
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]');
|
|
|
|
if (typeInput) {
|
|
updateAnnouncementTypePickerSelection();
|
|
}
|
|
|
|
if (typePickerToggle) {
|
|
typePickerToggle.addEventListener('click', function (event) {
|
|
event.preventDefault();
|
|
var isExpanded = typePicker && !typePicker.hidden;
|
|
if (isExpanded) {
|
|
closeAnnouncementTypePicker();
|
|
} else {
|
|
openAnnouncementTypePicker();
|
|
}
|
|
});
|
|
}
|
|
|
|
if (typePickerClose) {
|
|
typePickerClose.addEventListener('click', function (event) {
|
|
event.preventDefault();
|
|
closeAnnouncementTypePicker();
|
|
});
|
|
}
|
|
|
|
if (typePicker) {
|
|
typePicker.addEventListener('click', function (event) {
|
|
var button = event.target && event.target.closest ? event.target.closest('[data-announcement-type-option]') : null;
|
|
if (!button) {
|
|
return;
|
|
}
|
|
|
|
event.preventDefault();
|
|
setAnnouncementTypeValue(button.getAttribute('data-type-key'));
|
|
closeAnnouncementTypePicker();
|
|
});
|
|
}
|
|
|
|
if (modeSelect) {
|
|
modeSelect.addEventListener('change', updateAnnouncementDurationFields);
|
|
updateAnnouncementDurationFields();
|
|
}
|
|
|
|
if (colorInput) {
|
|
updateAnnouncementColorPickerSelection();
|
|
}
|
|
|
|
if (colorPicker) {
|
|
colorPicker.addEventListener('click', function (event) {
|
|
var button = event.target && event.target.closest ? event.target.closest('[data-announcement-color-option]') : null;
|
|
if (!button) {
|
|
return;
|
|
}
|
|
|
|
event.preventDefault();
|
|
colorInput.value = String(button.getAttribute('data-color-key') || '').trim().toLowerCase();
|
|
updateAnnouncementColorPickerSelection();
|
|
});
|
|
}
|
|
|
|
if (screenSelectAll) {
|
|
screenSelectAll.addEventListener('click', function (event) {
|
|
event.preventDefault();
|
|
setAnnouncementScreenSelection(true);
|
|
});
|
|
}
|
|
|
|
if (screenSelectNone) {
|
|
screenSelectNone.addEventListener('click', function (event) {
|
|
event.preventDefault();
|
|
setAnnouncementScreenSelection(false);
|
|
});
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
updateAnnouncementActionButtonState();
|
|
});
|
|
|
|
window.addEventListener('resize', positionAnnouncementTypePicker);
|
|
|
|
document.addEventListener('click', function (event) {
|
|
var typePickerNode = document.querySelector('[data-announcement-type-picker]');
|
|
var typeToggleNode = document.querySelector('[data-announcement-type-picker-toggle]');
|
|
if (typePickerNode && !typePickerNode.hidden) {
|
|
if (!(typePickerNode.contains(event.target) || (typeToggleNode && typeToggleNode.contains(event.target)))) {
|
|
closeAnnouncementTypePicker();
|
|
}
|
|
}
|
|
|
|
});
|
|
|
|
updateAnnouncementActionButtonState();
|
|
}
|
|
|
|
if (typeof document !== 'undefined') {
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', initAnnouncementForm, { once: true });
|
|
} else {
|
|
initAnnouncementForm();
|
|
}
|
|
} |