Add SEO fields to Tasks model, improve content generation response handling, and enhance progress bar animation
- Added primary_keyword, secondary_keywords, tags, and categories fields to Tasks model - Updated generate_content function to handle full JSON response with all SEO fields - Improved progress bar animation: smooth 1% increments every 300ms - Enhanced step detection for content generation vs clustering vs ideas - Fixed progress modal to show correct messages for each function type - Added comprehensive logging to Keywords and Tasks pages for AI functions - Fixed error handling to show meaningful error messages instead of generic failures
This commit is contained in:
@@ -32,14 +32,15 @@ const LayoutContent: React.FC = () => {
|
||||
trackLoading('site-loading', true);
|
||||
|
||||
// Add timeout to prevent infinite loading
|
||||
// Match API timeout (30s) + buffer for network delays
|
||||
const timeoutId = setTimeout(() => {
|
||||
if (isLoadingSite.current) {
|
||||
console.error('AppLayout: Site loading timeout after 10 seconds');
|
||||
console.error('AppLayout: Site loading timeout after 35 seconds');
|
||||
trackLoading('site-loading', false);
|
||||
isLoadingSite.current = false;
|
||||
addError(new Error('Site loading timeout - check network connection'), 'AppLayout.loadActiveSite');
|
||||
}
|
||||
}, 10000);
|
||||
}, 35000); // 35 seconds to match API timeout (30s) + buffer
|
||||
|
||||
loadActiveSite()
|
||||
.catch((error) => {
|
||||
@@ -69,14 +70,15 @@ const LayoutContent: React.FC = () => {
|
||||
trackLoading('sector-loading', true);
|
||||
|
||||
// Add timeout to prevent infinite loading
|
||||
// Match API timeout (30s) + buffer for network delays
|
||||
const timeoutId = setTimeout(() => {
|
||||
if (isLoadingSector.current) {
|
||||
console.error('AppLayout: Sector loading timeout after 10 seconds');
|
||||
console.error('AppLayout: Sector loading timeout after 35 seconds');
|
||||
trackLoading('sector-loading', false);
|
||||
isLoadingSector.current = false;
|
||||
addError(new Error('Sector loading timeout - check network connection'), 'AppLayout.loadSectorsForSite');
|
||||
}
|
||||
}, 10000);
|
||||
}, 35000); // 35 seconds to match API timeout (30s) + buffer
|
||||
|
||||
loadSectorsForSite(currentSiteId)
|
||||
.catch((error) => {
|
||||
@@ -99,27 +101,42 @@ const LayoutContent: React.FC = () => {
|
||||
}
|
||||
}, [activeSite?.id, activeSite?.is_active]); // Depend on both ID and is_active
|
||||
|
||||
// Refresh user data on mount and periodically to get latest account/plan changes
|
||||
// Refresh user data on mount and when app version changes (after code updates)
|
||||
// This ensures changes are reflected immediately without requiring re-login
|
||||
useEffect(() => {
|
||||
if (!isAuthenticated) return;
|
||||
|
||||
const refreshUserData = async () => {
|
||||
const APP_VERSION = import.meta.env.VITE_APP_VERSION || '2.0.2';
|
||||
const VERSION_STORAGE_KEY = 'igny8-app-version';
|
||||
|
||||
const refreshUserData = async (force = false) => {
|
||||
const now = Date.now();
|
||||
// Throttle: only refresh if last refresh was more than 30 seconds ago
|
||||
if (now - lastUserRefresh.current < 30000) return;
|
||||
// Throttle: only refresh if last refresh was more than 30 seconds ago (unless forced)
|
||||
if (!force && now - lastUserRefresh.current < 30000) return;
|
||||
|
||||
try {
|
||||
lastUserRefresh.current = now;
|
||||
await refreshUser();
|
||||
|
||||
// Store current version after successful refresh
|
||||
if (force) {
|
||||
localStorage.setItem(VERSION_STORAGE_KEY, APP_VERSION);
|
||||
}
|
||||
} catch (error) {
|
||||
// Silently fail - user might still be authenticated
|
||||
console.debug('User data refresh failed (non-critical):', error);
|
||||
}
|
||||
};
|
||||
|
||||
// Refresh on mount
|
||||
refreshUserData();
|
||||
// Check if app version changed (indicates code update)
|
||||
const storedVersion = localStorage.getItem(VERSION_STORAGE_KEY);
|
||||
if (storedVersion !== APP_VERSION) {
|
||||
// Force refresh on version change
|
||||
refreshUserData(true);
|
||||
} else {
|
||||
// Normal refresh on mount
|
||||
refreshUserData();
|
||||
}
|
||||
|
||||
// Refresh when window becomes visible (user switches back to tab)
|
||||
const handleVisibilityChange = () => {
|
||||
@@ -134,7 +151,7 @@ const LayoutContent: React.FC = () => {
|
||||
};
|
||||
|
||||
// Periodic refresh every 2 minutes
|
||||
const intervalId = setInterval(refreshUserData, 120000);
|
||||
const intervalId = setInterval(() => refreshUserData(), 120000);
|
||||
|
||||
document.addEventListener('visibilitychange', handleVisibilityChange);
|
||||
window.addEventListener('focus', handleFocus);
|
||||
|
||||
Reference in New Issue
Block a user