courrier multi account
This commit is contained in:
parent
c787d6a1a5
commit
6516a726e9
@ -208,17 +208,42 @@ export default function CourrierPage() {
|
|||||||
const response = await fetch('/api/courrier/session');
|
const response = await fetch('/api/courrier/session');
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
||||||
console.log('[DEBUG] Session API response:', {
|
// Log the raw API response to inspect structure
|
||||||
authenticated: data.authenticated,
|
console.log('[DEBUG] Raw session API response:', JSON.stringify(data, null, 2));
|
||||||
hasEmailCredentials: data.hasEmailCredentials,
|
|
||||||
email: data.email,
|
// Add detailed logging to inspect the accounts and folders structure
|
||||||
allAccountsExists: !!data.allAccounts,
|
console.log('=== SESSION API RESPONSE DETAILED INSPECTION ===');
|
||||||
allAccountsIsArray: Array.isArray(data.allAccounts),
|
console.log('Session authenticated:', data.authenticated);
|
||||||
allAccountsLength: data.allAccounts?.length || 0,
|
console.log('Has email credentials:', data.hasEmailCredentials);
|
||||||
mailboxesExists: !!data.mailboxes,
|
console.log('Primary email:', data.email);
|
||||||
mailboxesIsArray: Array.isArray(data.mailboxes),
|
console.log('Redis status:', data.redisStatus);
|
||||||
mailboxesLength: data.mailboxes?.length || 0
|
|
||||||
});
|
// Log mailboxes structure - what the frontend used previously
|
||||||
|
console.log('=== MAILBOXES STRUCTURE (OLD API FORMAT) ===');
|
||||||
|
console.log('Global mailboxes exists:', !!data.mailboxes);
|
||||||
|
console.log('Global mailboxes is array:', Array.isArray(data.mailboxes));
|
||||||
|
console.log('Global mailboxes:', data.mailboxes);
|
||||||
|
|
||||||
|
// Log allAccounts structure - the new per-account folders approach
|
||||||
|
console.log('=== ALL ACCOUNTS STRUCTURE (NEW API FORMAT) ===');
|
||||||
|
console.log('allAccounts exists:', !!data.allAccounts);
|
||||||
|
console.log('allAccounts is array:', Array.isArray(data.allAccounts));
|
||||||
|
console.log('allAccounts length:', data.allAccounts?.length || 0);
|
||||||
|
|
||||||
|
// Inspect each account's structure
|
||||||
|
if (data.allAccounts && Array.isArray(data.allAccounts)) {
|
||||||
|
data.allAccounts.forEach((account: any, idx: number) => {
|
||||||
|
console.log(`Account ${idx + 1}:`, {
|
||||||
|
id: account.id,
|
||||||
|
email: account.email,
|
||||||
|
display_name: account.display_name,
|
||||||
|
foldersExist: !!account.folders,
|
||||||
|
foldersIsArray: Array.isArray(account.folders),
|
||||||
|
foldersLength: account.folders?.length || 0,
|
||||||
|
folders: account.folders
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (!isMounted) return;
|
if (!isMounted) return;
|
||||||
|
|
||||||
@ -234,33 +259,39 @@ export default function CourrierPage() {
|
|||||||
|
|
||||||
// Check if we have multiple accounts returned
|
// Check if we have multiple accounts returned
|
||||||
if (data.allAccounts && Array.isArray(data.allAccounts) && data.allAccounts.length > 0) {
|
if (data.allAccounts && Array.isArray(data.allAccounts) && data.allAccounts.length > 0) {
|
||||||
console.log('Multiple accounts found:', data.allAccounts.length);
|
console.log('[DEBUG] Multiple accounts found:', data.allAccounts.length);
|
||||||
|
|
||||||
|
// First, validate the structure of each account
|
||||||
|
data.allAccounts.forEach((account: any, index: number) => {
|
||||||
|
console.log(`[DEBUG] Account ${index+1} structure check:`, {
|
||||||
|
id: account.id,
|
||||||
|
email: account.email,
|
||||||
|
display_name: account.display_name,
|
||||||
|
hasFolders: !!account.folders,
|
||||||
|
foldersIsArray: Array.isArray(account.folders),
|
||||||
|
foldersCount: Array.isArray(account.folders) ? account.folders.length : 0,
|
||||||
|
folders: account.folders || []
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// Add each account from the server
|
// Add each account from the server
|
||||||
data.allAccounts.forEach((account: any, index: number) => {
|
data.allAccounts.forEach((account: any, index: number) => {
|
||||||
console.log(`[DEBUG] Processing account: ${account.email}, id: ${account.id}, display_name: ${account.display_name}, has folders: ${account.folders ? account.folders.length : 0}`);
|
// Check if the account has a valid folders array
|
||||||
|
if (!account.folders || !Array.isArray(account.folders)) {
|
||||||
|
console.warn(`[WARN] Account ${account.email} has invalid folders structure:`, account.folders);
|
||||||
|
// Use the global mailboxes as a fallback if available
|
||||||
|
account.folders = data.mailboxes && Array.isArray(data.mailboxes) ?
|
||||||
|
data.mailboxes : ['INBOX', 'Sent', 'Drafts', 'Trash', 'Junk'];
|
||||||
|
console.log(`[DEBUG] Using fallback folders for ${account.email}:`, account.folders);
|
||||||
|
}
|
||||||
|
|
||||||
// Force include some hardcoded folders if none are present
|
updatedAccounts.push({
|
||||||
const fallbackFolders = ['INBOX', 'Sent', 'Drafts', 'Trash', 'Junk'];
|
id: account.id || `account-${index}`,
|
||||||
|
|
||||||
// Prioritize account-specific folders over global mailboxes
|
|
||||||
const folderList = (account.folders && account.folders.length > 0) ?
|
|
||||||
account.folders :
|
|
||||||
(data.mailboxes && data.mailboxes.length > 0) ?
|
|
||||||
data.mailboxes :
|
|
||||||
fallbackFolders;
|
|
||||||
|
|
||||||
console.log(`[DEBUG] Using folders for ${account.email}:`, folderList);
|
|
||||||
|
|
||||||
const accountWithFolders = {
|
|
||||||
id: account.id || `account-${index + 1}`, // Use the database ID or generate a stable ID
|
|
||||||
name: account.display_name || account.email,
|
name: account.display_name || account.email,
|
||||||
email: account.email,
|
email: account.email,
|
||||||
color: account.color || 'bg-blue-500',
|
color: account.color || 'bg-blue-500',
|
||||||
folders: folderList
|
folders: account.folders
|
||||||
};
|
});
|
||||||
console.log(`[DEBUG] Adding account with id ${accountWithFolders.id} and ${accountWithFolders.folders.length} folders:`, accountWithFolders.folders);
|
|
||||||
updatedAccounts.push(accountWithFolders);
|
|
||||||
});
|
});
|
||||||
} else if (data.email) {
|
} else if (data.email) {
|
||||||
// Check if we have a single account from the API
|
// Check if we have a single account from the API
|
||||||
@ -312,6 +343,12 @@ export default function CourrierPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
console.log('Setting accounts:', updatedAccounts);
|
console.log('Setting accounts:', updatedAccounts);
|
||||||
|
// Debug each account's folders
|
||||||
|
updatedAccounts.forEach((acc: Account, idx: number) => {
|
||||||
|
console.log(`Account ${idx + 1}: ${acc.name} (${acc.email}) - Folders:`,
|
||||||
|
acc.folders ? acc.folders.length : 0,
|
||||||
|
acc.folders || []);
|
||||||
|
});
|
||||||
setAccounts(updatedAccounts);
|
setAccounts(updatedAccounts);
|
||||||
|
|
||||||
// Auto-select the first non-All account if available
|
// Auto-select the first non-All account if available
|
||||||
@ -522,8 +559,38 @@ export default function CourrierPage() {
|
|||||||
router.push('/courrier/login');
|
router.push('/courrier/login');
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
// Add this log right before the return statement in the CourrierPage component
|
||||||
<>
|
// Debug accounts and selectedAccount before rendering
|
||||||
|
useEffect(() => {
|
||||||
|
console.log('=== RENDER STATE INSPECTION ===');
|
||||||
|
console.log('Current accounts state:', accounts);
|
||||||
|
console.log('Selected account:', selectedAccount);
|
||||||
|
console.log('Current folder:', currentFolder);
|
||||||
|
console.log('Show folders:', showFolders);
|
||||||
|
}, [accounts, selectedAccount, currentFolder, showFolders]);
|
||||||
|
|
||||||
|
// Extra debugging for folder rendering
|
||||||
|
useEffect(() => {
|
||||||
|
if (selectedAccount && showFolders) {
|
||||||
|
console.log('Folder rendering debug:',
|
||||||
|
'account:', selectedAccount.id,
|
||||||
|
'folders:', selectedAccount.folders?.length || 0,
|
||||||
|
'showFolders:', showFolders
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [selectedAccount, showFolders]);
|
||||||
|
|
||||||
|
// Add useEffect for debugging near the other useEffect hooks
|
||||||
|
useEffect(() => {
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
console.log('[DEBUG] Rendering UI with:', {
|
||||||
|
accountsCount: accounts.length,
|
||||||
|
selectedAccountId: selectedAccount?.id,
|
||||||
|
showFolders,
|
||||||
|
currentFolder
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})}
|
||||||
<SimplifiedLoadingFix />
|
<SimplifiedLoadingFix />
|
||||||
<RedisCacheStatus />
|
<RedisCacheStatus />
|
||||||
|
|
||||||
@ -797,115 +864,136 @@ export default function CourrierPage() {
|
|||||||
|
|
||||||
{accountsDropdownOpen && (
|
{accountsDropdownOpen && (
|
||||||
<div className="space-y-1 pl-2 accounts-dropdown">
|
<div className="space-y-1 pl-2 accounts-dropdown">
|
||||||
{accounts.map(account => (
|
{accounts.map(account => {
|
||||||
<div key={account.id} className="relative group account-item">
|
// Log outside of the JSX to avoid linter issues
|
||||||
<Button
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
variant="ghost"
|
console.log('Rendering account:', account.id, account.name, 'has folders:', account.folders?.length || 0);
|
||||||
className="w-full justify-between px-2 py-1.5 text-sm group"
|
}
|
||||||
onClick={() => {
|
return (
|
||||||
// Toggle folders for this specific account
|
<div key={account.id} className="relative group account-item">
|
||||||
if (selectedAccount?.id === account.id) {
|
<Button
|
||||||
setShowFolders(!showFolders);
|
variant="ghost"
|
||||||
} else {
|
className="w-full justify-between px-2 py-1.5 text-sm group"
|
||||||
// When selecting a new account, make sure we show its folders
|
onClick={() => {
|
||||||
setShowFolders(true);
|
// Toggle folders for this specific account
|
||||||
|
if (selectedAccount?.id === account.id) {
|
||||||
|
console.log('[DEBUG] Toggling folders visibility for existing selection:', account.id, showFolders ? 'hiding' : 'showing');
|
||||||
|
setShowFolders(!showFolders);
|
||||||
|
} else {
|
||||||
|
// When selecting a new account, make sure we show its folders
|
||||||
|
console.log('[DEBUG] Selecting different account', {
|
||||||
|
oldAccount: selectedAccount ? selectedAccount.id : 'none',
|
||||||
|
newAccount: account.id,
|
||||||
|
folders: account.folders?.length || 0
|
||||||
|
});
|
||||||
|
setShowFolders(true);
|
||||||
|
|
||||||
// Reset to the inbox folder of the new account by default
|
// Reset to the inbox folder of the new account by default
|
||||||
if (account.folders && account.folders.length > 0) {
|
if (account.folders && account.folders.length > 0) {
|
||||||
// Find INBOX or default to first folder
|
// Find INBOX or default to first folder
|
||||||
const inboxFolder = account.folders.find(f =>
|
const inboxFolder = account.folders.find(f =>
|
||||||
f.toLowerCase() === 'inbox') || account.folders[0];
|
f.toLowerCase() === 'inbox') || account.folders[0];
|
||||||
|
|
||||||
// Change to this account's inbox folder
|
console.log('[DEBUG] Switching to folder:', inboxFolder, 'for account', account.id);
|
||||||
handleMailboxChange(inboxFolder, account.id);
|
|
||||||
|
// Change to this account's inbox folder
|
||||||
|
handleMailboxChange(inboxFolder, account.id);
|
||||||
|
} else {
|
||||||
|
console.log('[DEBUG] No folders found for account', account.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
setSelectedAccount(account);
|
console.log('[DEBUG] Setting selected account to:', account.id, account.email);
|
||||||
|
setSelectedAccount(account);
|
||||||
|
|
||||||
// Force the account to have folders if it doesn't already
|
// Force the account to have folders if it doesn't already
|
||||||
if (account.id !== 'all-accounts' && (!account.folders || account.folders.length === 0)) {
|
if (account.id !== 'all-accounts' && (!account.folders || account.folders.length === 0)) {
|
||||||
// Fetch folders for this account if not already available
|
console.log('[DEBUG] Account has no folders, fetching folders for account:', account.id);
|
||||||
fetch(`/api/courrier/account-folders?accountId=${account.id}`)
|
// Fetch folders for this account if not already available
|
||||||
.then(res => res.json())
|
fetch(`/api/courrier/account-folders?accountId=${account.id}`)
|
||||||
.then(data => {
|
.then(res => res.json())
|
||||||
if (data.folders && Array.isArray(data.folders)) {
|
.then(data => {
|
||||||
|
console.log('[DEBUG] Received folders from API:', data);
|
||||||
|
if (data.folders && Array.isArray(data.folders)) {
|
||||||
|
console.log('[DEBUG] Updating account with fetched folders:', data.folders.length);
|
||||||
|
const accountWithFolders = {
|
||||||
|
...account,
|
||||||
|
folders: data.folders
|
||||||
|
};
|
||||||
|
setSelectedAccount(accountWithFolders);
|
||||||
|
|
||||||
|
// Also update the account in the accounts array
|
||||||
|
const newAccounts = accounts.map(a =>
|
||||||
|
a.id === account.id ? accountWithFolders : a
|
||||||
|
);
|
||||||
|
setAccounts(newAccounts);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error(`[ERROR] Error fetching folders for account ${account.id}:`, err);
|
||||||
|
// Use default folders if API fails
|
||||||
const accountWithFolders = {
|
const accountWithFolders = {
|
||||||
...account,
|
...account,
|
||||||
folders: data.folders
|
folders: ['INBOX', 'Sent', 'Drafts', 'Trash', 'Junk']
|
||||||
};
|
};
|
||||||
setSelectedAccount(accountWithFolders);
|
setSelectedAccount(accountWithFolders);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<div className={`w-2.5 h-2.5 rounded-full ${account.color}`}></div>
|
||||||
|
<span className="font-medium text-gray-700 truncate">{account.name}</span>
|
||||||
|
</div>
|
||||||
|
{/* Show arrow for all accounts */}
|
||||||
|
<div className="flex items-center">
|
||||||
|
{selectedAccount?.id === account.id && showFolders ?
|
||||||
|
<ChevronDown className="h-3.5 w-3.5 text-gray-500" /> :
|
||||||
|
<ChevronRight className="h-3.5 w-3.5 text-gray-500" />
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</Button>
|
||||||
|
|
||||||
// Also update the account in the accounts array
|
{/* Show folders for this account if it's selected and folders are shown */}
|
||||||
const newAccounts = accounts.map(a =>
|
{((selectedAccount?.id === account.id && showFolders) ||
|
||||||
a.id === account.id ? accountWithFolders : a
|
(!selectedAccount && account.id !== 'all-accounts' && account.folders)) && (
|
||||||
);
|
<div className="pl-4 mt-1 mb-2 space-y-0.5 border-l border-gray-200 folder-container">
|
||||||
setAccounts(newAccounts);
|
{/* No console.log here - moved to useEffect */}
|
||||||
}
|
{account.folders && account.folders.length > 0 ? (
|
||||||
})
|
account.folders.map((folder, folderIndex) => (
|
||||||
.catch(err => {
|
<Button
|
||||||
console.error(`Error fetching folders for account ${account.id}:`, err);
|
key={folder}
|
||||||
// Use default folders if API fails
|
variant="ghost"
|
||||||
const accountWithFolders = {
|
className={`w-full justify-start py-1 px-2 text-xs folder-item ${
|
||||||
...account,
|
currentView === folder ? 'bg-gray-100 text-gray-900' : 'text-gray-600 hover:text-gray-900'
|
||||||
folders: ['INBOX', 'Sent', 'Drafts', 'Trash', 'Junk']
|
}`}
|
||||||
};
|
onClick={(e) => {
|
||||||
setSelectedAccount(accountWithFolders);
|
e.stopPropagation();
|
||||||
});
|
// Pass the account ID along with the folder name
|
||||||
}
|
handleMailboxChange(folder, selectedAccount?.id);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center justify-between w-full gap-1.5">
|
||||||
<div className={`w-2.5 h-2.5 rounded-full ${account.color}`}></div>
|
<div className="flex items-center gap-1.5">
|
||||||
<span className="font-medium text-gray-700 truncate">{account.name}</span>
|
{React.createElement(getFolderIcon(folder), { className: "h-3.5 w-3.5" })}
|
||||||
</div>
|
<span className="truncate">{formatFolderName(folder)}</span>
|
||||||
{/* Show arrow for all accounts */}
|
</div>
|
||||||
<div className="flex items-center">
|
{folder === 'INBOX' && unreadCount > 0 && (
|
||||||
{selectedAccount?.id === account.id && showFolders ?
|
<span className="inline-flex items-center justify-center px-1.5 py-0.5 text-xs font-medium bg-blue-100 text-blue-800 rounded">
|
||||||
<ChevronDown className="h-3.5 w-3.5 text-gray-500" /> :
|
{unreadCount}
|
||||||
<ChevronRight className="h-3.5 w-3.5 text-gray-500" />
|
</span>
|
||||||
}
|
)}
|
||||||
</div>
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
{/* Show folders for this account if it's selected and folders are shown */}
|
|
||||||
{((selectedAccount?.id === account.id && showFolders) ||
|
|
||||||
(!selectedAccount && account.id !== 'all-accounts' && account.folders)) && (
|
|
||||||
<div className="pl-4 mt-1 mb-2 space-y-0.5 border-l border-gray-200 folder-container">
|
|
||||||
{account.folders && account.folders.length > 0 ? (
|
|
||||||
account.folders.map((folder, folderIndex) => (
|
|
||||||
<Button
|
|
||||||
key={folder}
|
|
||||||
variant="ghost"
|
|
||||||
className={`w-full justify-start py-1 px-2 text-xs folder-item ${
|
|
||||||
currentView === folder ? 'bg-gray-100 text-gray-900' : 'text-gray-600 hover:text-gray-900'
|
|
||||||
}`}
|
|
||||||
onClick={(e) => {
|
|
||||||
e.stopPropagation();
|
|
||||||
// Pass the account ID along with the folder name
|
|
||||||
handleMailboxChange(folder, selectedAccount?.id);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className="flex items-center justify-between w-full gap-1.5">
|
|
||||||
<div className="flex items-center gap-1.5">
|
|
||||||
{React.createElement(getFolderIcon(folder), { className: "h-3.5 w-3.5" })}
|
|
||||||
<span className="truncate">{formatFolderName(folder)}</span>
|
|
||||||
</div>
|
</div>
|
||||||
{folder === 'INBOX' && unreadCount > 0 && (
|
</Button>
|
||||||
<span className="inline-flex items-center justify-center px-1.5 py-0.5 text-xs font-medium bg-blue-100 text-blue-800 rounded">
|
))
|
||||||
{unreadCount}
|
) : (
|
||||||
</span>
|
<div className="text-xs text-gray-500 px-2 py-1">No folders found</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</Button>
|
)}
|
||||||
))
|
</div>
|
||||||
) : (
|
);
|
||||||
<div className="text-xs text-gray-500 px-2 py-1">No folders found</div>
|
})}
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user