feat&fix: implement auto-refresh functionality and disable animation when refresh

This commit is contained in:
adlsdztony
2025-06-01 08:45:58 +00:00
parent 9c0cbebf9a
commit 37505f4c3b
2 changed files with 154 additions and 1 deletions

View File

@@ -10,8 +10,33 @@ document.addEventListener('DOMContentLoaded', () => {
let allTaskData = null;
let currentFilter = 'all';
let isRefreshing = false; // Flag to indicate page refresh state
let lastRefreshTime = 0; // Track last refresh time to prevent too frequent refreshes
const REFRESH_COOLDOWN = 3000; // 3 seconds cooldown between refreshes
function refreshPage() {
// Check if enough time has passed since last refresh
const now = Date.now();
if (isRefreshing || now - lastRefreshTime < REFRESH_COOLDOWN) {
console.log('Refresh cooldown in progress...');
return;
}
lastRefreshTime = now;
// Add refresh animation to button
const refreshBtn = document.querySelector('.fab-refresh i');
if (refreshBtn) {
refreshBtn.classList.add('fa-spin');
// Remove spin after 1 second
setTimeout(() => {
refreshBtn.classList.remove('fa-spin');
}, 1000);
}
// Add no-transition to body during refresh
document.body.classList.add('no-transition');
// Save expanded state before refresh
const expandedTaskTypes = [];
document.querySelectorAll('.task-type').forEach(section => {
@@ -24,18 +49,64 @@ function refreshPage() {
// Store in sessionStorage
sessionStorage.setItem('expandedTaskTypes', JSON.stringify(expandedTaskTypes));
// Set refreshing flag to true before fetching data
isRefreshing = true;
fetchTasks();
}
function fetchTasks() {
const currentTime = Date.now();
// Check if the last refresh was within the cooldown period
if (currentTime - lastRefreshTime < REFRESH_COOLDOWN) {
// If within cooldown, just reset the refreshing flag and return
isRefreshing = false;
return;
}
// Show loading spinner or add refreshing class
const container = document.getElementById('task-container');
if (isRefreshing) {
// Don't show loading spinner on refresh to avoid flickering
container.classList.add('refreshing');
} else {
container.innerHTML = `
<div class="loading-spinner">
<div class="spinner"></div>
<div>Loading task data...</div>
</div>
`;
}
fetch('/api/tasks')
.then(response => response.json())
.then(data => {
allTaskData = data;
renderTasks(data);
updateStatistics(data);
// Reset refreshing flag and classes after rendering
container.classList.remove('refreshing');
setTimeout(() => {
isRefreshing = false;
document.body.classList.remove('no-transition');
document.querySelectorAll('.no-transition').forEach(el => {
el.classList.remove('no-transition');
});
}, 50);
// Update the last refresh time
lastRefreshTime = currentTime;
})
.catch(error => console.error('Error fetching tasks:', error));
.catch(error => {
console.error('Error fetching tasks:', error);
container.innerHTML = `
<div class="error-message">
<i class="fas fa-exclamation-triangle"></i>
<div>Error loading task data. Please try again.</div>
</div>
`;
isRefreshing = false;
container.classList.remove('refreshing');
document.body.classList.remove('no-transition');
});
}
function setTaskFilter(filter) {
@@ -139,6 +210,11 @@ function renderTasks(data) {
const typeSection = document.createElement('div');
typeSection.className = 'task-type';
// Add no-transition class if page is refreshing
if (isRefreshing) {
typeSection.classList.add('no-transition');
}
// Create header with task type name and statistics
const typeHeader = document.createElement('div');
typeHeader.className = 'task-type-header';
@@ -284,6 +360,8 @@ function renderTasks(data) {
typeHeader.addEventListener('click', (event) => {
// Prevent toggling when clicking task cards
if (!event.target.closest('.task-card')) {
// Remove no-transition class if it exists before toggling
typeSection.classList.remove('no-transition');
typeSection.classList.toggle('collapsed');
// Set appropriate aria attributes for accessibility
@@ -311,4 +389,20 @@ function renderTasks(data) {
container.appendChild(typeSection);
});
// Remove no-transition class after rendering all elements
if (isRefreshing) {
setTimeout(() => {
document.querySelectorAll('.no-transition').forEach(el => {
el.classList.remove('no-transition');
});
}, 100);
}
}
// add auto-refresh with time interval 10 seconds
setInterval(() => {
if (!isRefreshing) {
refreshPage();
}
}, 10000); // 10 seconds interval

View File

@@ -0,0 +1,59 @@
/* No transition class to disable animations */
.no-transition,
.no-transition * {
-webkit-transition: none !important;
-moz-transition: none !important;
-ms-transition: none !important;
-o-transition: none !important;
transition: none !important;
animation: none !important;
}
/* Immediate display changes for elements with no-transition */
.task-type.no-transition.collapsed .tasks-container {
display: none;
max-height: 0 !important;
opacity: 0;
padding: 0;
margin: 0;
overflow: hidden;
}
.task-type.no-transition:not(.collapsed) .tasks-container {
display: block;
max-height: none !important;
opacity: 1;
overflow: visible;
}
/* Styles for refreshing state */
.refreshing .tasks-container {
pointer-events: none; /* Prevent interactions during refresh */
}
.refreshing .task-card {
opacity: 0.7; /* Dim the cards during refresh */
}
/* Override progress bar animation during page refresh */
.no-transition .progress-fill,
.refreshing .progress-fill {
transition: none !important;
}
/* Error message styling */
.error-message {
text-align: center;
padding: 30px;
color: #e74c3c;
font-size: 1.1em;
background: #fef2f2;
border-radius: 8px;
margin: 20px 0;
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
}
.error-message i {
font-size: 2em;
margin-bottom: 15px;
}