Fix: Prevent console message loop on maintenance updates
The console was generating excessive messages after schedule maintenance updates.
This commit is contained in:
@@ -58,7 +58,6 @@ export const useMaintenanceData = ({ refreshTrigger = 0 }: UseMaintenanceDataPro
|
||||
|
||||
// Prevent duplicate requests
|
||||
if (currentRequestRef.current) {
|
||||
console.log("Request already in progress, waiting...");
|
||||
await currentRequestRef.current;
|
||||
return;
|
||||
}
|
||||
@@ -72,14 +71,11 @@ export const useMaintenanceData = ({ refreshTrigger = 0 }: UseMaintenanceDataPro
|
||||
|
||||
const requestPromise = (async () => {
|
||||
try {
|
||||
console.log("Fetching maintenance data...", force ? "(forced)" : "");
|
||||
const data = await maintenanceService.getMaintenanceRecords();
|
||||
|
||||
// Check if component is still mounted before updating state
|
||||
if (!mountedRef.current) return;
|
||||
|
||||
console.log(`Fetched ${data.length} maintenance records`);
|
||||
|
||||
// Update state with fetched data
|
||||
setAllMaintenanceData(data);
|
||||
setInitialized(true);
|
||||
@@ -119,7 +115,6 @@ export const useMaintenanceData = ({ refreshTrigger = 0 }: UseMaintenanceDataPro
|
||||
|
||||
// Initial fetch on mount - NO AUTOMATIC POLLING
|
||||
useEffect(() => {
|
||||
console.log("useMaintenanceData hook mounted, fetching initial data");
|
||||
mountedRef.current = true;
|
||||
|
||||
// Only fetch initial data, no polling
|
||||
@@ -134,7 +129,6 @@ export const useMaintenanceData = ({ refreshTrigger = 0 }: UseMaintenanceDataPro
|
||||
// Handle refresh trigger changes - ONLY when explicitly triggered
|
||||
useEffect(() => {
|
||||
if (refreshTrigger > 0) {
|
||||
console.log("Manual refresh triggered, forcing data fetch");
|
||||
fetchMaintenanceData(true); // Force refresh to bypass cache
|
||||
}
|
||||
}, [refreshTrigger, fetchMaintenanceData]);
|
||||
|
||||
+125
-42
@@ -19,74 +19,157 @@ export const MaintenanceStatusChecker = ({
|
||||
const { toast } = useToast();
|
||||
const checkedItemsRef = useRef<Set<string>>(new Set());
|
||||
const notificationSentRef = useRef<Set<string>>(new Set());
|
||||
const intervalRef = useRef<number | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!maintenanceData || maintenanceData.length === 0) return;
|
||||
|
||||
// Check for maintenance items that need status update
|
||||
const now = new Date();
|
||||
const checkAndUpdateStatus = async () => {
|
||||
const currentTime = new Date();
|
||||
let hasUpdates = false;
|
||||
|
||||
console.log('MaintenanceStatusChecker: Checking status updates at', currentTime.toISOString());
|
||||
console.log('MaintenanceStatusChecker: Checking', maintenanceData.length, 'maintenance items');
|
||||
|
||||
for (const item of maintenanceData) {
|
||||
if (item.status.toLowerCase() !== 'scheduled') continue;
|
||||
|
||||
// Skip if we've already checked this item in this session
|
||||
if (checkedItemsRef.current.has(item.id)) continue;
|
||||
|
||||
try {
|
||||
const startTime = new Date(item.start_time);
|
||||
const endTime = new Date(item.end_time);
|
||||
const status = item.status.toLowerCase();
|
||||
|
||||
// If current time is past start time but before end time, update to in_progress
|
||||
if (startTime <= now && now <= endTime) {
|
||||
console.log(`Auto-updating maintenance ${item.title} to in_progress status`);
|
||||
console.log(`MaintenanceStatusChecker: Item ${item.id} - Status: ${status}, Start: ${startTime.toISOString()}, End: ${endTime.toISOString()}, Current: ${currentTime.toISOString()}`);
|
||||
|
||||
// Check if scheduled maintenance should start (become in_progress)
|
||||
if (status === 'scheduled' && currentTime >= startTime && currentTime <= endTime) {
|
||||
const checkKey = `${item.id}-started`;
|
||||
const notificationKey = `${item.id}-start-notification`;
|
||||
|
||||
// Update status to in_progress
|
||||
await maintenanceService.updateMaintenanceStatus(item.id, 'in_progress');
|
||||
|
||||
// Only send notification if not sent before
|
||||
if (!notificationSentRef.current.has(item.id)) {
|
||||
console.log(`Sending start notification for maintenance ${item.title}`);
|
||||
if (!checkedItemsRef.current.has(checkKey)) {
|
||||
console.log(`MaintenanceStatusChecker: Starting maintenance ${item.id} at ${currentTime.toISOString()}`);
|
||||
|
||||
// Send notification for maintenance start
|
||||
await maintenanceNotificationService.sendMaintenanceNotification({
|
||||
maintenance: item,
|
||||
notificationType: 'start'
|
||||
// Update status to in_progress first
|
||||
await maintenanceService.updateMaintenanceStatus(item.id, 'in_progress');
|
||||
|
||||
// Send start notification only once
|
||||
if (!notificationSentRef.current.has(notificationKey)) {
|
||||
try {
|
||||
await maintenanceNotificationService.sendMaintenanceNotification({
|
||||
maintenance: item,
|
||||
notificationType: 'start'
|
||||
});
|
||||
notificationSentRef.current.add(notificationKey);
|
||||
console.log(`MaintenanceStatusChecker: Start notification sent for ${item.id}`);
|
||||
} catch (notificationError) {
|
||||
console.log('MaintenanceStatusChecker: Start notification failed', notificationError);
|
||||
}
|
||||
}
|
||||
|
||||
toast({
|
||||
title: t('maintenanceInProgress'),
|
||||
description: `${item.title} ${t('isNowInProgress')}`,
|
||||
});
|
||||
|
||||
// Mark as notified
|
||||
notificationSentRef.current.add(item.id);
|
||||
checkedItemsRef.current.add(checkKey);
|
||||
hasUpdates = true;
|
||||
}
|
||||
|
||||
toast({
|
||||
title: t('maintenanceInProgress'),
|
||||
description: `${item.title} ${t('isNowInProgress')}`,
|
||||
});
|
||||
|
||||
onStatusUpdated();
|
||||
}
|
||||
|
||||
// Mark as checked regardless of outcome
|
||||
checkedItemsRef.current.add(item.id);
|
||||
// Check if in_progress maintenance should be completed
|
||||
if (status === 'in_progress' && currentTime >= endTime) {
|
||||
const checkKey = `${item.id}-completed`;
|
||||
const notificationKey = `${item.id}-end-notification`;
|
||||
|
||||
if (!checkedItemsRef.current.has(checkKey)) {
|
||||
console.log(`MaintenanceStatusChecker: Completing maintenance ${item.id} at ${currentTime.toISOString()}`);
|
||||
|
||||
// Update status to completed first
|
||||
await maintenanceService.updateMaintenanceStatus(item.id, 'completed');
|
||||
|
||||
// Send completion notification only once
|
||||
if (!notificationSentRef.current.has(notificationKey)) {
|
||||
try {
|
||||
await maintenanceNotificationService.sendMaintenanceNotification({
|
||||
maintenance: item,
|
||||
notificationType: 'end'
|
||||
});
|
||||
notificationSentRef.current.add(notificationKey);
|
||||
console.log(`MaintenanceStatusChecker: Completion notification sent for ${item.id}`);
|
||||
} catch (notificationError) {
|
||||
console.log('MaintenanceStatusChecker: Completion notification failed', notificationError);
|
||||
}
|
||||
}
|
||||
|
||||
toast({
|
||||
title: t('maintenanceCompleted'),
|
||||
description: `${item.title} ${t('hasBeenCompleted')}`,
|
||||
});
|
||||
|
||||
checkedItemsRef.current.add(checkKey);
|
||||
hasUpdates = true;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error auto-updating maintenance status for ${item.id}:`, error);
|
||||
|
||||
// Add a small delay before trying again to prevent rapid retry cycles
|
||||
console.error('MaintenanceStatusChecker: Error updating status for item', item.id, error);
|
||||
// Clear the check flags after 2 minutes to allow retry
|
||||
setTimeout(() => {
|
||||
checkedItemsRef.current.delete(item.id); // Allow retry on next check
|
||||
}, 300000); // 5 minutes before retry
|
||||
checkedItemsRef.current.delete(`${item.id}-started`);
|
||||
checkedItemsRef.current.delete(`${item.id}-completed`);
|
||||
notificationSentRef.current.delete(`${item.id}-start-notification`);
|
||||
notificationSentRef.current.delete(`${item.id}-end-notification`);
|
||||
}, 120000);
|
||||
}
|
||||
}
|
||||
|
||||
if (hasUpdates) {
|
||||
console.log('MaintenanceStatusChecker: Status updates detected, triggering refresh');
|
||||
// Force immediate refresh to update the UI
|
||||
onStatusUpdated();
|
||||
}
|
||||
};
|
||||
|
||||
// Run the check immediately
|
||||
// Clear the interval if it exists
|
||||
if (intervalRef.current) {
|
||||
clearInterval(intervalRef.current);
|
||||
}
|
||||
|
||||
// Initial check immediately
|
||||
checkAndUpdateStatus();
|
||||
|
||||
// Set up interval to check every minute
|
||||
const intervalId = setInterval(checkAndUpdateStatus, 60000);
|
||||
// Check every 5 seconds for immediate status updates
|
||||
intervalRef.current = window.setInterval(checkAndUpdateStatus, 5000);
|
||||
|
||||
return () => clearInterval(intervalId);
|
||||
return () => {
|
||||
if (intervalRef.current) {
|
||||
clearInterval(intervalRef.current);
|
||||
intervalRef.current = null;
|
||||
}
|
||||
};
|
||||
}, [maintenanceData, onStatusUpdated, t, toast]);
|
||||
|
||||
// This is a utility component with no UI render
|
||||
// Clear check flags when maintenance data changes significantly
|
||||
useEffect(() => {
|
||||
const currentIds = new Set(maintenanceData.map(item => item.id));
|
||||
|
||||
// Clean up check flags for items that no longer exist
|
||||
const keysToDelete = Array.from(checkedItemsRef.current).filter(key => {
|
||||
const itemId = key.split('-')[0];
|
||||
return !currentIds.has(itemId);
|
||||
});
|
||||
|
||||
keysToDelete.forEach(key => {
|
||||
checkedItemsRef.current.delete(key);
|
||||
});
|
||||
|
||||
// Clean up notification flags for items that no longer exist
|
||||
const notificationKeysToDelete = Array.from(notificationSentRef.current).filter(key => {
|
||||
const itemId = key.split('-')[0];
|
||||
return !currentIds.has(itemId);
|
||||
});
|
||||
|
||||
notificationKeysToDelete.forEach(key => {
|
||||
notificationSentRef.current.delete(key);
|
||||
});
|
||||
}, [maintenanceData]);
|
||||
|
||||
return null;
|
||||
};
|
||||
};
|
||||
+1
-27
@@ -25,7 +25,6 @@ export const MaintenanceDetailContent = ({
|
||||
queryKey: ['users'],
|
||||
queryFn: async () => {
|
||||
const usersList = await userService.getUsers();
|
||||
console.log("Fetched users for maintenance detail:", usersList);
|
||||
return usersList || [];
|
||||
},
|
||||
enabled: true
|
||||
@@ -36,7 +35,6 @@ export const MaintenanceDetailContent = ({
|
||||
queryKey: ['notificationChannels'],
|
||||
queryFn: async () => {
|
||||
const channels = await alertConfigService.getAlertConfigurations();
|
||||
console.log("Fetched notification channels:", channels);
|
||||
return channels || [];
|
||||
},
|
||||
enabled: true
|
||||
@@ -45,9 +43,6 @@ export const MaintenanceDetailContent = ({
|
||||
// Process user information when users data is available
|
||||
useEffect(() => {
|
||||
if (users.length > 0 && maintenance) {
|
||||
console.log("Processing maintenance data with users:", maintenance);
|
||||
console.log("Maintenance assigned_users:", maintenance.assigned_users);
|
||||
|
||||
// Create a copy of the maintenance object for modifications
|
||||
const enhancedMaintenance = { ...maintenance };
|
||||
|
||||
@@ -58,7 +53,6 @@ export const MaintenanceDetailContent = ({
|
||||
// Step 1: Extract user IDs from various formats
|
||||
if (Array.isArray(maintenance.assigned_users)) {
|
||||
userIds = maintenance.assigned_users;
|
||||
console.log("Assigned users is an array:", userIds);
|
||||
} else if (typeof maintenance.assigned_users === 'string') {
|
||||
// Try parsing the string to extract user IDs
|
||||
try {
|
||||
@@ -67,34 +61,28 @@ export const MaintenanceDetailContent = ({
|
||||
if (Array.isArray(parsedData)) {
|
||||
// Direct array format
|
||||
userIds = parsedData;
|
||||
console.log("Parsed assigned_users from JSON array:", userIds);
|
||||
} else if (typeof parsedData === 'string') {
|
||||
// Nested JSON string
|
||||
try {
|
||||
const nestedData = JSON.parse(parsedData);
|
||||
if (Array.isArray(nestedData)) {
|
||||
userIds = nestedData;
|
||||
console.log("Parsed assigned_users from nested JSON:", userIds);
|
||||
}
|
||||
} catch (e) {
|
||||
// If nested parsing fails, treat as single ID
|
||||
userIds = [parsedData];
|
||||
console.log("Using parsed string as single ID:", userIds);
|
||||
}
|
||||
} else {
|
||||
// Unknown format, use as is
|
||||
userIds = [String(parsedData)];
|
||||
console.log("Using parsed data as single ID:", userIds);
|
||||
}
|
||||
} catch (e) {
|
||||
// If JSON parsing fails, try comma splitting
|
||||
if (maintenance.assigned_users.includes(',')) {
|
||||
userIds = maintenance.assigned_users.split(',').map(id => id.trim()).filter(Boolean);
|
||||
console.log("Split assigned_users by comma:", userIds);
|
||||
} else {
|
||||
// Single ID
|
||||
userIds = [maintenance.assigned_users];
|
||||
console.log("Using string as single ID:", userIds);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -107,20 +95,15 @@ export const MaintenanceDetailContent = ({
|
||||
cleanId = cleanId.replace(/[\[\]"'\\]/g, '');
|
||||
return cleanId;
|
||||
}).filter(Boolean);
|
||||
|
||||
console.log("Cleaned user IDs:", userIds);
|
||||
|
||||
// Step 3: Find matching users from the users array
|
||||
if (userIds.length > 0) {
|
||||
const matchedUsers = users.filter(user => userIds.includes(user.id));
|
||||
console.log("Matched assigned users:", matchedUsers);
|
||||
setAssignedUsers(matchedUsers);
|
||||
} else {
|
||||
console.log("No user IDs found in assigned_users");
|
||||
setAssignedUsers([]);
|
||||
}
|
||||
} else {
|
||||
console.log("No assigned users found in maintenance data");
|
||||
setAssignedUsers([]);
|
||||
}
|
||||
|
||||
@@ -138,24 +121,15 @@ export const MaintenanceDetailContent = ({
|
||||
const channelId = maintenance.notification_channel_id || maintenance.notification_id;
|
||||
|
||||
if (channelId && notificationChannels.length > 0) {
|
||||
console.log("Looking for notification channel with ID:", channelId);
|
||||
console.log("Available notification channels:", notificationChannels.map(c => ({ id: c.id, name: c.notify_name })));
|
||||
|
||||
const channel = notificationChannels.find(ch => ch.id === channelId);
|
||||
if (channel) {
|
||||
console.log("Found notification channel:", channel);
|
||||
enhancedMaintenance.notification_channel_name = `${channel.notify_name} (${channel.notification_type})`;
|
||||
} else {
|
||||
console.log("No matching notification channel found for ID:", channelId);
|
||||
enhancedMaintenance.notification_channel_name = `Channel ID: ${channelId}`;
|
||||
}
|
||||
} else {
|
||||
console.log("No channel ID available or no notification channels loaded");
|
||||
}
|
||||
}
|
||||
|
||||
console.log("Enhanced maintenance with details:", enhancedMaintenance);
|
||||
console.log("Assigned users for display:", assignedUsers);
|
||||
setMaintenanceWithDetails(enhancedMaintenance);
|
||||
}
|
||||
}, [maintenance, users, notificationChannels]);
|
||||
@@ -173,4 +147,4 @@ export const MaintenanceDetailContent = ({
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user