(function (root) { var pendingToastStorageKey = 'pulse:pending-toast'; function readPendingToast() { try { if (!root.sessionStorage) { return null; } var rawValue = root.sessionStorage.getItem(pendingToastStorageKey); if (!rawValue) { return null; } root.sessionStorage.removeItem(pendingToastStorageKey); var payload = JSON.parse(rawValue); if (!payload || !payload.message) { return null; } return { message: String(payload.message || '').trim(), variant: String(payload.variant || 'info').trim().toLowerCase() || 'info' }; } catch (_error) { return null; } } function writePendingToast(message, variant) { try { if (!root.sessionStorage) { return false; } var text = String(message || '').trim(); if (!text) { return false; } root.sessionStorage.setItem(pendingToastStorageKey, JSON.stringify({ message: text, variant: String(variant || 'info').trim().toLowerCase() || 'info' })); return true; } catch (_error) { return false; } } function clearPendingToast() { try { if (root.sessionStorage) { root.sessionStorage.removeItem(pendingToastStorageKey); } } catch (_error) { // ignore storage cleanup failures } } function getToastTitle(variant, message) { var text = String(message || '').trim(); if (/\b(?:deleted|removed)\.?$/i.test(text)) { return 'Deleted'; } 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 '
' + '' + '' + title + '' + '' + timeLabel + '' + '' + '
' + '
'; } 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; } return window.bootstrap.Toast.getOrCreateInstance(toast, { autohide: true, delay: 4000 }); } function removeToast(toast) { if (toast && toast.parentNode) { toast.parentNode.removeChild(toast); } } function dismissToast(toast) { var instance = getBootstrapToast(toast); if (instance) { instance.hide(); return; } removeToast(toast); } function setToastVariant(toast, variant) { if (!toast || !toast.classList) { return; } setToastHeader(toast, variant, toast.getAttribute('data-toast-created-at') || Date.now()); } function getMessageVariant(message, fallbackVariant) { var text = String(message || '').trim(); var rules = [ { variant: 'danger', patterns: [/\b(?:deleted|removed)\.?\s*$/i, /\b(?:deleted|removed)\b/i] }, { variant: 'danger', patterns: [/\b(?:unable to|cannot|can't|could not|failed to)\s+delete\b/i, /\bdelete\b.*\b(?:before|first)\b/i, /\bstill (?:in use|linked|assigned|used)\b/i] }, { variant: 'warning', patterns: [/\b(?:already exists|already exist|already taken|duplicate|must be unique|name already exists)\b/i] } ]; for (var i = 0; i < rules.length; i += 1) { if (rules[i].patterns.some(function (pattern) { return pattern.test(text); })) { return rules[i].variant; } } return String(fallbackVariant || 'info').trim().toLowerCase() || 'info'; } function showToast(message, variant) { var text = String(message || '').trim(); if (!text) { return; } var container = document.getElementById('app-toast-container'); if (!container) { return; } var existingToast = document.getElementById('app-toast'); if (existingToast) { var existingBody = existingToast.querySelector('.toast-body'); if (existingBody) { existingBody.textContent = text; } 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(); } return; } var toast = document.createElement('div'); 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.setAttribute('data-toast-created-at', String(Date.now())); var toastVariant = getMessageVariant(text, variant); toast.setAttribute('data-toast-variant', toastVariant); toast.innerHTML = buildToastMarkup(getToastTitle(toastVariant, text), getToastTimeLabel(Date.now()), getToastButtonClass(toastVariant), getToastIconClass(toastVariant)); toast.querySelector('.toast-body').textContent = text; setToastVariant(toast, toastVariant); toast.addEventListener('hidden.bs.toast', function () { removeToast(toast); }); container.appendChild(toast); var instance = getBootstrapToast(toast); if (instance) { instance.show(); } } function initToast() { var toast = document.getElementById('app-toast'); if (!toast) { var pendingToast = readPendingToast(); if (pendingToast) { showToast(pendingToast.message, pendingToast.variant); } return; } clearPendingToast(); try { var url = new URL(window.location.href); if (url.searchParams.has('message')) { url.searchParams.delete('message'); window.history.replaceState({}, document.title, url.pathname + url.search + url.hash); } } catch (_error) { // ignore URL cleanup failures } var bodyText = (toast.querySelector('.toast-body') && toast.querySelector('.toast-body').textContent) || ''; var existingVariant = String(toast.getAttribute('data-toast-variant') || '').trim().toLowerCase() || getMessageVariant(bodyText, 'info'); setToastVariant(toast, existingVariant); var title = toast.querySelector('.toast-header .me-auto'); if (title) { title.textContent = getToastTitle(existingVariant, bodyText); } var instance = getBootstrapToast(toast); if (instance) { instance.show(); } } root.dismissToast = dismissToast; root.showToast = showToast; root.initToast = initToast; root.getMessageVariant = getMessageVariant; root.queueToastAfterRefresh = writePendingToast; if (typeof module !== 'undefined' && module.exports) { module.exports = { getMessageVariant: getMessageVariant }; } if (root.document) { initToast(); } }(typeof window !== 'undefined' ? window : globalThis));