Private
Public Access
1
0

Refactor modal close behavior and improve styling

- Changed modal close event from `@click.away` to `@click.self` for better control over closing modals.
- Updated various modal button styles for consistency and improved accessibility.
- Adjusted transition durations for modal animations to enhance user experience.
- Added aria-labels to close buttons for better screen reader support.
This commit is contained in:
2026-02-23 20:02:41 -05:00
parent f394483daa
commit af62a16354
45 changed files with 393 additions and 4700 deletions

View File

@@ -50,7 +50,7 @@
x-transition:leave="transition ease-in duration-200"
x-transition:leave-start="opacity-100 scale-100"
x-transition:leave-end="opacity-0 scale-95"
@click.away="open = false"
@click.self="open = false"
@keydown.escape.window="open = false"
class="fixed inset-0 z-50 flex items-center justify-center p-4"
style="display: none;">
@@ -162,7 +162,7 @@
x-transition:leave="transition ease-in duration-200"
x-transition:leave-start="opacity-100 scale-100"
x-transition:leave-end="opacity-0 scale-95"
@click.away="open = false"
@click.self="open = false"
@keydown.escape.window="open = false"
class="fixed inset-0 z-50 flex items-center justify-center p-4"
style="display: none;">
@@ -251,7 +251,7 @@
x-transition:leave="transition ease-in duration-200"
x-transition:leave-start="opacity-100 scale-100"
x-transition:leave-end="opacity-0 scale-95"
@click.away="open = false"
@click.self="open = false"
@keydown.escape.window="open = false"
class="fixed inset-0 z-50 flex items-center justify-center p-4"
style="display: none;">
@@ -345,7 +345,7 @@
x-transition:leave="transition ease-in duration-200"
x-transition:leave-start="opacity-100 scale-100"
x-transition:leave-end="opacity-0 scale-95"
@click.away="open = false"
@click.self="open = false"
@keydown.escape.window="open = false"
class="fixed inset-0 z-50 flex items-center justify-center p-4"
style="display: none;">
@@ -442,7 +442,7 @@
x-transition:leave="transition ease-in duration-200"
x-transition:leave-start="opacity-100 scale-100"
x-transition:leave-end="opacity-0 scale-95"
@click.away="open = false"
@click.self="open = false"
@keydown.escape.window="open = false"
class="fixed inset-0 z-50 flex items-center justify-center p-4"
style="display: none;">
@@ -536,7 +536,7 @@
x-transition:leave="transition ease-in duration-200"
x-transition:leave-start="opacity-100 scale-100"
x-transition:leave-end="opacity-0 scale-95"
@click.away="open = false"
@click.self="open = false"
@keydown.escape.window="open = false"
class="fixed inset-0 z-50 flex items-center justify-center p-4"
style="display: none;">
@@ -632,7 +632,7 @@
x-transition:leave="transition ease-in duration-200"
x-transition:leave-start="opacity-100 scale-100"
x-transition:leave-end="opacity-0 scale-95"
@click.away="open = false"
@click.self="open = false"
@keydown.escape.window="open = false"
class="fixed inset-0 z-50 flex items-center justify-center p-4"
style="display: none;">
@@ -1054,7 +1054,7 @@
x-transition:leave="transition ease-in duration-200"
x-transition:leave-start="opacity-100 scale-100"
x-transition:leave-end="opacity-0 scale-95"
@click.away="open = false"
@click.self="open = false"
@keydown.escape.window="open = false"
class="fixed inset-0 z-50 flex items-center justify-center p-4"
style="display: none;">
@@ -1549,7 +1549,7 @@
x-transition:leave="transition ease-in duration-200"
x-transition:leave-start="opacity-100 scale-100"
x-transition:leave-end="opacity-0 scale-95"
@click.away="open = false"
@click.self="open = false"
@keydown.escape.window="open = false"
class="fixed inset-0 z-50 flex items-center justify-center p-4"
style="display: none;">
@@ -1968,7 +1968,7 @@
x-transition:leave="transition ease-in duration-200"
x-transition:leave-start="opacity-100 scale-100"
x-transition:leave-end="opacity-0 scale-95"
@click.away="open = false"
@click.self="open = false"
@keydown.escape.window="open = false"
class="fixed inset-0 z-50 flex items-center justify-center p-4"
style="display: none;">
@@ -2129,15 +2129,15 @@
<tr class="hover:bg-background-secondary/50 transition-colors">
<td class="py-3 px-4 text-sm whitespace-nowrap">
<div class="flex items-center gap-2">
<x-ri-hard-drive-line class="size-4" style="color: #9256b5" />
<x-ri-hard-drive-line class="size-4 text-purple-500 dark:text-purple-400" />
<span class="font-medium">Disk Read Rate</span>
</div>
</td>
<td class="py-3 px-4 text-sm whitespace-nowrap">
<span class="font-medium" style="color: #9256b5">{{ $this->formatBytes($diff['disk_read']['historical_rate']) }}/s</span>
<span class="font-medium text-purple-500 dark:text-purple-400">{{ $this->formatBytes($diff['disk_read']['historical_rate']) }}/s</span>
</td>
<td class="py-3 px-4 text-sm whitespace-nowrap">
<span class="font-medium" style="color: #9256b5">{{ $this->formatBytes($diff['disk_read']['current_rate']) }}/s</span>
<span class="font-medium text-purple-500 dark:text-purple-400">{{ $this->formatBytes($diff['disk_read']['current_rate']) }}/s</span>
</td>
<td class="py-3 px-4 text-sm whitespace-nowrap">
<span class="inline-flex items-center px-2 py-1 rounded-md text-xs font-semibold {{ $diff['disk_read']['percent_change'] > 0 ? 'bg-warning/20 text-warning' : ($diff['disk_read']['percent_change'] < 0 ? 'bg-success/20 text-success' : 'bg-base/20 text-base/70') }}">
@@ -2150,15 +2150,15 @@
<tr class="hover:bg-background-secondary/50 transition-colors">
<td class="py-3 px-4 text-sm whitespace-nowrap">
<div class="flex items-center gap-2">
<x-ri-hard-drive-line class="size-4" style="color: #60496f" />
<x-ri-hard-drive-line class="size-4 text-purple-700 dark:text-purple-300" />
<span class="font-medium">Disk Write Rate</span>
</div>
</td>
<td class="py-3 px-4 text-sm whitespace-nowrap">
<span class="font-medium" style="color: #60496f">{{ $this->formatBytes($diff['disk_write']['historical_rate']) }}/s</span>
<span class="font-medium text-purple-700 dark:text-purple-300">{{ $this->formatBytes($diff['disk_write']['historical_rate']) }}/s</span>
</td>
<td class="py-3 px-4 text-sm whitespace-nowrap">
<span class="font-medium" style="color: #60496f">{{ $this->formatBytes($diff['disk_write']['current_rate']) }}/s</span>
<span class="font-medium text-purple-700 dark:text-purple-300">{{ $this->formatBytes($diff['disk_write']['current_rate']) }}/s</span>
</td>
<td class="py-3 px-4 text-sm whitespace-nowrap">
<span class="inline-flex items-center px-2 py-1 rounded-md text-xs font-semibold {{ $diff['disk_write']['percent_change'] > 0 ? 'bg-warning/20 text-warning' : ($diff['disk_write']['percent_change'] < 0 ? 'bg-success/20 text-success' : 'bg-base/20 text-base/70') }}">
@@ -2289,7 +2289,7 @@
x-transition:leave="transition ease-in duration-200"
x-transition:leave-start="opacity-100 scale-100"
x-transition:leave-end="opacity-0 scale-95"
@click.away="open = false"
@click.self="open = false"
@keydown.escape.window="open = false"
class="fixed inset-0 z-50 flex items-center justify-center p-4"
style="display: none;">
@@ -3159,7 +3159,7 @@
x-transition:leave="transition ease-in duration-150"
x-transition:leave-start="opacity-100 scale-100"
x-transition:leave-end="opacity-0 scale-95"
@click.away="open = false"
@click.self="open = false"
@keydown.escape.window="open = false"
class="fixed inset-0 z-50 flex items-center justify-center p-4"
style="display: none;">
@@ -3375,7 +3375,7 @@
x-transition:leave="transition ease-in duration-150"
x-transition:leave-start="opacity-100 scale-100"
x-transition:leave-end="opacity-0 scale-95"
@click.away="open = false"
@click.self="open = false"
@keydown.escape.window="open = false"
class="fixed inset-0 z-50 flex items-center justify-center p-4"
style="display: none;">
@@ -3778,7 +3778,7 @@
x-transition:leave="transition ease-in duration-200"
x-transition:leave-start="opacity-100 scale-100"
x-transition:leave-end="opacity-0 scale-95"
@click.away="open = false"
@click.self="open = false"
@keydown.escape.window="open = false"
class="fixed inset-0 z-50 flex items-center justify-center p-4"
style="display: none;">
@@ -3868,7 +3868,7 @@
x-transition:leave="transition ease-in duration-200"
x-transition:leave-start="opacity-100 scale-100"
x-transition:leave-end="opacity-0 scale-95"
@click.away="$wire.closeClearStatisticsModal()"
@click.self="$wire.closeClearStatisticsModal()"
@keydown.escape.window="$wire.closeClearStatisticsModal()"
class="fixed inset-0 z-50 flex items-center justify-center p-4"
style="display: none;">
@@ -3928,7 +3928,7 @@
x-transition:leave="transition ease-in duration-200"
x-transition:leave-start="opacity-100 scale-100"
x-transition:leave-end="opacity-0 scale-95"
@click.away="$wire.closeExportInfoModal()"
@click.self="$wire.closeExportInfoModal()"
@keydown.escape.window="$wire.closeExportInfoModal()"
class="fixed inset-0 z-50 flex items-center justify-center p-4"
style="display: none;">
@@ -5088,7 +5088,6 @@
(!diskChartExpected || diskChartHasData);
if (allExpectedChartsHaveData) {
console.log('All expected charts have received data.');
try {
window.dispatchEvent(new CustomEvent('proxmox-all-stats-loaded'));
} catch (e) {}
@@ -5103,8 +5102,6 @@
}
chartRetryAttempts[chartType]++;
console.log('Requesting ' + chartType + ' chart data (attempt ' + chartRetryAttempts[chartType] + ')');
try {
// Dispatch individual chart event for more reliable loading
Livewire.dispatch('proxmox:stats:' + chartType);
@@ -5145,8 +5142,6 @@
// Request all chart data in parallel using individual events
// This ensures each chart loads independently - if one fails, others still work
console.log('Requesting all Proxmox stats (parallel individual requests)');
if (cpuChartExpected) {
requestChartData('cpu');
checkAndRetryChart('cpu', false, true);
@@ -5274,9 +5269,6 @@
// Get the current server ID from the DOM (dynamically)
var serverIdElement = document.querySelector('[data-server-id]');
var currentServerId = serverIdElement ? serverIdElement.getAttribute('data-server-id') : '{{ $server->id }}';
console.log('Setting up event listeners for server:', currentServerId);
var cpuCleanup = Livewire.on('proxmox:stats:' + currentServerId + ':cpu', function(eventData) {
if (!cpuChart) {
console.warn('CPU chart not initialized');
@@ -5453,7 +5445,6 @@
// Load Network Analysis after charts are initialized (non-blocking)
function loadNetworkAnalysisData() {
// Start the timeout FIRST before loading, so it's guaranteed to start
console.log('Starting Network Analysis load process - timeout will begin');
startNetworkAnalysisTimeout();
setTimeout(function() {
@@ -5461,7 +5452,6 @@
// Use a Livewire event instead of @this directly so that
// the initial load is reliable even on first-ever visits.
Livewire.dispatch('proxmox:network-analysis-load');
console.log('Network Analysis load event dispatched');
} catch (e) {
console.warn('Failed to dispatch Network Analysis load event:', e);
// Even if dispatch fails, timeout is already started
@@ -5478,7 +5468,6 @@
// Check if we've already refreshed once in this session for this server
var hasAlreadyRefreshed = sessionStorage.getItem(refreshKey);
if (hasAlreadyRefreshed === 'true') {
console.log('Network Analysis timeout skipped - page has already been refreshed once in this session for server ' + serverId);
return;
}
@@ -5486,10 +5475,6 @@
if (window.networkAnalysisTimeoutId) {
clearTimeout(window.networkAnalysisTimeoutId);
}
console.log('Network Analysis timeout started - page will refresh in 30 seconds if data does not load (one-time refresh only)');
console.log('Timeout ID will be stored at: window.networkAnalysisTimeoutId');
// Simple timeout: refresh after 30 seconds unless we can confirm it loaded
window.networkAnalysisTimeoutId = setTimeout(function() {
console.warn('=== Network Analysis timeout callback FIRED (30 seconds elapsed) ===');
@@ -5501,7 +5486,6 @@
// Double-check we haven't already refreshed (in case of race conditions)
var hasAlreadyRefreshedCheck = sessionStorage.getItem(refreshKey);
if (hasAlreadyRefreshedCheck === 'true') {
console.log('Network Analysis timeout - page was already refreshed for server ' + serverId + ', skipping');
return;
}
@@ -5522,9 +5506,6 @@
var hasLoadingText = loadingTextElements.some(function(p) {
return p && p.textContent && p.textContent.includes('Fetching data from Core Router');
});
console.log('Loading check:', { isLoadingVisible: isLoadingVisible, hasLoadingText: hasLoadingText });
// If loading indicator is visible, definitely refresh (but only once)
if (isLoadingVisible || hasLoadingText) {
console.warn('Network Analysis timeout - loading indicator still visible, refreshing page NOW (one-time refresh) for server ' + serverId);
@@ -5538,12 +5519,8 @@
var hasError = networkAnalysisCard.querySelector('[class*="border-warning"]');
var hasEmptyState = networkAnalysisCard.querySelector('.text-center.py-6');
var hasTabs = networkAnalysisCard.querySelector('[x-data*="tab"]');
console.log('Content check:', { hasTable: !!hasTable, hasError: !!hasError, hasEmptyState: !!hasEmptyState, hasTabs: !!hasTabs });
// Only skip refresh if we have clear evidence it loaded (tabs + content)
if ((hasTabs && (hasTable || hasError || hasEmptyState)) || hasError) {
console.log('Network Analysis loaded successfully (found tabs and content), NOT refreshing');
cancelNetworkAnalysisTimeout();
// Clear the refresh flag since we loaded successfully
sessionStorage.removeItem(refreshKey);
@@ -5555,8 +5532,6 @@
sessionStorage.setItem(refreshKey, 'true');
window.location.reload();
}, 30000); // 30 seconds
console.log('Timeout set with ID:', window.networkAnalysisTimeoutId);
}
// Function to cancel the Network Analysis timeout
@@ -5564,7 +5539,6 @@
if (window.networkAnalysisTimeoutId) {
clearTimeout(window.networkAnalysisTimeoutId);
window.networkAnalysisTimeoutId = null;
console.log('Network Analysis timeout cancelled - data has loaded');
}
// Clear the refresh flag since data loaded successfully (server-specific)
var serverId = {{ $server->id ?? 0 }};
@@ -5621,7 +5595,6 @@
var serverId = {{ $server->id ?? 0 }};
var refreshKey = 'networkAnalysisRefreshed_' + serverId;
sessionStorage.removeItem(refreshKey);
console.log('Network Analysis loaded successfully on page load, refresh flag cleared for server ' + serverId);
}
}, 2000);
@@ -5652,15 +5625,11 @@
document.addEventListener('network-analysis-502-retry', function(event) {
var retryCount = (event.detail && event.detail.retryCount) ? event.detail.retryCount : 1;
var delay = Math.min(2000 * retryCount, 5000); // Exponential backoff, max 5 seconds
console.log('Core Router API 502 error detected, retrying in ' + delay + 'ms (Attempt ' + retryCount + ')');
setTimeout(function() {
try {
// Dispatch the same event used for initial load so that
// retries are decoupled from any specific @this instance.
Livewire.dispatch('proxmox:network-analysis-load');
console.log('Network Analysis retry event dispatched after 502 (delay ' + delay + 'ms)');
} catch (e) {
console.error('Failed to retry Network Analysis after 502 error:', e);
}