Release 1.5.16
This commit is contained in:
@@ -353,6 +353,25 @@
|
||||
var rowKeyInput = form.querySelector('[name="row_key"]');
|
||||
var dayCheckboxes = form.querySelectorAll('[name="schedule_days"]');
|
||||
|
||||
function getDayButton(checkbox) {
|
||||
return checkbox && checkbox.id ? form.querySelector('label[for="' + checkbox.id + '"]') : null;
|
||||
}
|
||||
|
||||
function syncDayButtonState(checkbox) {
|
||||
var button = getDayButton(checkbox);
|
||||
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
|
||||
button.classList.toggle('active', Boolean(checkbox.checked));
|
||||
button.setAttribute('aria-pressed', checkbox.checked ? 'true' : 'false');
|
||||
}
|
||||
|
||||
function syncAllDayButtonStates() {
|
||||
Array.prototype.forEach.call(dayCheckboxes, syncDayButtonState);
|
||||
}
|
||||
|
||||
function clearScheduleValidity() {
|
||||
[startDateInput, endDateInput, startTimeInput, endTimeInput].forEach(function (input) {
|
||||
if (input) {
|
||||
@@ -412,7 +431,20 @@
|
||||
}
|
||||
});
|
||||
Array.prototype.forEach.call(dayCheckboxes, function (checkbox) {
|
||||
checkbox.addEventListener('change', clearScheduleValidity);
|
||||
checkbox.addEventListener('change', function () {
|
||||
syncDayButtonState(checkbox);
|
||||
clearScheduleValidity();
|
||||
});
|
||||
|
||||
var button = getDayButton(checkbox);
|
||||
if (button) {
|
||||
button.addEventListener('click', function (event) {
|
||||
event.preventDefault();
|
||||
checkbox.checked = !checkbox.checked;
|
||||
checkbox.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
checkbox.focus();
|
||||
});
|
||||
}
|
||||
});
|
||||
select.addEventListener('change', clearScheduleValidity);
|
||||
|
||||
@@ -436,6 +468,7 @@
|
||||
|
||||
select.addEventListener('change', updateVisibility);
|
||||
updateVisibility();
|
||||
syncAllDayButtonStates();
|
||||
|
||||
form.addEventListener('submit', function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
+113
-9
@@ -1,4 +1,110 @@
|
||||
(function () {
|
||||
function getToastTitle(variant) {
|
||||
var textVariant = String(variant || '').trim().toLowerCase();
|
||||
if (textVariant === 'danger') {
|
||||
return 'Error';
|
||||
}
|
||||
if (textVariant === 'warning') {
|
||||
return 'Warning';
|
||||
}
|
||||
if (textVariant === 'success') {
|
||||
return 'Success';
|
||||
}
|
||||
return 'Pulse';
|
||||
}
|
||||
|
||||
function getToastTimeLabel(createdAt) {
|
||||
var timestamp = Number(createdAt);
|
||||
if (!timestamp || Number.isNaN(timestamp)) {
|
||||
return 'just now';
|
||||
}
|
||||
|
||||
var elapsed = Date.now() - timestamp;
|
||||
if (elapsed < 60 * 1000) {
|
||||
return 'just now';
|
||||
}
|
||||
|
||||
var minutes = Math.floor(elapsed / (60 * 1000));
|
||||
if (minutes < 60) {
|
||||
return minutes + ' min' + (minutes === 1 ? '' : 's') + ' ago';
|
||||
}
|
||||
|
||||
var hours = Math.floor(minutes / 60);
|
||||
if (hours < 24) {
|
||||
return hours + ' hour' + (hours === 1 ? '' : 's') + ' ago';
|
||||
}
|
||||
|
||||
var days = Math.floor(hours / 24);
|
||||
if (days < 7) {
|
||||
return days + ' day' + (days === 1 ? '' : 's') + ' ago';
|
||||
}
|
||||
|
||||
return new Date(timestamp).toLocaleString();
|
||||
}
|
||||
|
||||
function getToastButtonClass(variant) {
|
||||
var textVariant = String(variant || '').trim().toLowerCase();
|
||||
return textVariant === 'light' || textVariant === 'warning' ? 'btn-close' : 'btn-close-white';
|
||||
}
|
||||
|
||||
function getToastIconClass(variant) {
|
||||
var textVariant = String(variant || '').trim().toLowerCase();
|
||||
if (textVariant === 'success') {
|
||||
return 'bi-check-circle-fill';
|
||||
}
|
||||
if (textVariant === 'warning') {
|
||||
return 'bi-exclamation-triangle-fill';
|
||||
}
|
||||
if (textVariant === 'danger') {
|
||||
return 'bi-x-circle-fill';
|
||||
}
|
||||
if (textVariant === 'primary') {
|
||||
return 'bi-bell-fill';
|
||||
}
|
||||
return 'bi-info-circle-fill';
|
||||
}
|
||||
|
||||
function buildToastMarkup(title, timeLabel, buttonClass, iconClass) {
|
||||
return '<div class="toast-header border-0">' +
|
||||
'<i class="bi ' + iconClass + ' me-2"></i>' +
|
||||
'<strong class="me-auto">' + title + '</strong>' +
|
||||
'<small class="toast-time text-nowrap">' + timeLabel + '</small>' +
|
||||
'<button type="button" class="btn-close ' + buttonClass + ' ms-2" data-bs-dismiss="toast" aria-label="Dismiss notification"></button>' +
|
||||
'</div>' +
|
||||
'<div class="toast-body"></div>';
|
||||
}
|
||||
|
||||
function setToastHeader(toast, variant, createdAt) {
|
||||
if (!toast) {
|
||||
return;
|
||||
}
|
||||
|
||||
var header = toast.querySelector('.toast-header');
|
||||
var icon = toast.querySelector('.toast-header i');
|
||||
var title = toast.querySelector('.toast-header .me-auto');
|
||||
var time = toast.querySelector('.toast-time');
|
||||
var closeButton = toast.querySelector('.toast-header .btn-close');
|
||||
var nextVariant = getMessageVariant('', variant);
|
||||
|
||||
if (!header) {
|
||||
return;
|
||||
}
|
||||
|
||||
header.className = 'toast-header border-0 text-bg-' + nextVariant;
|
||||
if (icon) {
|
||||
icon.className = 'bi ' + getToastIconClass(nextVariant) + ' me-2';
|
||||
}
|
||||
if (title) {
|
||||
title.textContent = getToastTitle(nextVariant);
|
||||
}
|
||||
if (time) {
|
||||
time.textContent = getToastTimeLabel(createdAt);
|
||||
}
|
||||
if (closeButton) {
|
||||
closeButton.className = 'btn-close ' + getToastButtonClass(nextVariant) + ' ms-2';
|
||||
}
|
||||
}
|
||||
|
||||
function getBootstrapToast(toast) {
|
||||
if (!toast || !window.bootstrap || !window.bootstrap.Toast) {
|
||||
return null;
|
||||
@@ -30,12 +136,7 @@
|
||||
return;
|
||||
}
|
||||
|
||||
var nextVariant = String(variant || 'info').trim().toLowerCase();
|
||||
var variants = ['primary', 'secondary', 'success', 'danger', 'warning', 'info', 'light', 'dark'];
|
||||
variants.forEach(function (value) {
|
||||
toast.classList.remove('text-bg-' + value);
|
||||
});
|
||||
toast.classList.add('text-bg-' + (variants.indexOf(nextVariant) === -1 ? 'info' : nextVariant));
|
||||
setToastHeader(toast, variant, toast.getAttribute('data-toast-created-at') || Date.now());
|
||||
}
|
||||
|
||||
function getMessageVariant(message, fallbackVariant) {
|
||||
@@ -68,7 +169,9 @@
|
||||
}
|
||||
var nextVariant = getMessageVariant(text, variant);
|
||||
existingToast.setAttribute('data-toast-variant', nextVariant);
|
||||
existingToast.setAttribute('data-toast-created-at', String(Date.now()));
|
||||
setToastVariant(existingToast, nextVariant);
|
||||
setToastHeader(existingToast, nextVariant, Date.now());
|
||||
var existingInstance = getBootstrapToast(existingToast);
|
||||
if (existingInstance) {
|
||||
existingInstance.show();
|
||||
@@ -77,18 +180,19 @@
|
||||
}
|
||||
|
||||
var toast = document.createElement('div');
|
||||
toast.className = 'toast align-items-center border-0';
|
||||
toast.className = 'toast shadow-lg border-0';
|
||||
toast.id = 'app-toast';
|
||||
toast.setAttribute('role', 'status');
|
||||
toast.setAttribute('aria-live', 'polite');
|
||||
toast.setAttribute('aria-atomic', 'true');
|
||||
toast.setAttribute('data-bs-autohide', 'true');
|
||||
toast.setAttribute('data-bs-delay', '4000');
|
||||
toast.innerHTML = '<div class="d-flex"><div class="toast-body"></div><button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast" aria-label="Dismiss notification"></button></div>';
|
||||
toast.setAttribute('data-toast-created-at', String(Date.now()));
|
||||
var toastVariant = getMessageVariant(text, variant);
|
||||
toast.setAttribute('data-toast-variant', toastVariant);
|
||||
setToastVariant(toast, toastVariant);
|
||||
toast.innerHTML = buildToastMarkup(getToastTitle(toastVariant), getToastTimeLabel(Date.now()), getToastButtonClass(toastVariant), getToastIconClass(toastVariant));
|
||||
toast.querySelector('.toast-body').textContent = text;
|
||||
setToastVariant(toast, toastVariant);
|
||||
|
||||
toast.addEventListener('hidden.bs.toast', function () {
|
||||
removeToast(toast);
|
||||
|
||||
Reference in New Issue
Block a user