Revert "sad"

This reverts commit 550a8f26a2.
This commit is contained in:
alorig
2025-11-30 06:14:54 +05:00
parent 550a8f26a2
commit 8d47d6a555
5 changed files with 31 additions and 142 deletions

View File

@@ -342,7 +342,7 @@ export default function Keywords() {
}; };
// Import/Export handlers // Import/Export handlers
const { handleExport, handleImportClick: baseHandleImportClick, ImportModal } = useKeywordsImportExport( const { handleExport, handleImportClick, ImportModal } = useKeywordsImportExport(
() => { () => {
toast.success('Import successful', 'Keywords imported successfully.'); toast.success('Import successful', 'Keywords imported successfully.');
loadKeywords(); loadKeywords();
@@ -350,34 +350,12 @@ export default function Keywords() {
(error) => { (error) => {
toast.error('Import failed', error.message); toast.error('Import failed', error.message);
}, },
// Pass active site_id and active sector_id for import, but validate sector belongs to site // Pass active site_id and active sector_id for import
activeSite && activeSector && activeSector.site_id === activeSite.id activeSite && activeSector
? { site_id: activeSite.id, sector_id: activeSector.id } ? { site_id: activeSite.id, sector_id: activeSector.id }
: activeSite // Only pass site_id if sector doesn't belong to site
? { site_id: activeSite.id }
: undefined : undefined
); );
// Custom import click handler with validation
const handleImportClick = () => {
// Validate that sector belongs to the selected site
if (activeSite && activeSector && activeSector.site_id !== activeSite.id) {
toast.error('Import failed', `Selected sector "${activeSector.name}" does not belong to site "${activeSite.name}". Please select a sector from the current site.`);
return;
}
// Debug logging
console.log('Import attempt:', {
site_id: activeSite?.id,
site_name: activeSite?.name,
sector_id: activeSector?.id,
sector_name: activeSector?.name,
sector_site_id: activeSector?.site_id
});
baseHandleImportClick();
};
// Handle bulk actions (delete, export, update_status are now handled by TablePageTemplate) // Handle bulk actions (delete, export, update_status are now handled by TablePageTemplate)
// This is only for actions that don't have modals (like auto_cluster) // This is only for actions that don't have modals (like auto_cluster)
const handleBulkAction = useCallback(async (action: string, ids: string[]) => { const handleBulkAction = useCallback(async (action: string, ids: string[]) => {

View File

@@ -404,84 +404,29 @@ export default function IndustriesSectorsKeywords() {
const formData = new FormData(); const formData = new FormData();
formData.append('file', importFile); formData.append('file', importFile);
// Get token from auth store (consistent with other API calls)
const getAuthToken = () => {
try {
const authStorage = localStorage.getItem('auth-storage');
if (authStorage) {
const parsed = JSON.parse(authStorage);
return parsed?.state?.token || null;
}
} catch (e) {
// Ignore parsing errors
}
return null;
};
const token = getAuthToken();
const headers: HeadersInit = {};
if (token) {
headers['Authorization'] = `Bearer ${token}`;
}
const response = await fetch('/api/v1/auth/seed-keywords/import_seed_keywords/', { const response = await fetch('/api/v1/auth/seed-keywords/import_seed_keywords/', {
method: 'POST', method: 'POST',
headers, headers: {
'Authorization': `Token ${localStorage.getItem('authToken')}`,
},
body: formData, body: formData,
credentials: 'include', // Add credentials for consistency
}); });
let errorMessage = 'Import failed'; if (!response.ok) {
const errorData = await response.json();
// Handle common HTTP status codes throw new Error(errorData.error || 'Import failed');
if (response.status === 404) {
errorMessage = 'Import endpoint not found. Please check if the backend service is running.';
} else if (response.status === 429) {
errorMessage = 'Too many requests. Please wait a moment before trying again.';
} else if (response.status === 403) {
errorMessage = 'Access denied. Admin privileges required for seed keyword import.';
} }
try { const result = await response.json();
const result = await response.json(); toast.success(`Successfully imported ${result.created || 0} keywords`);
if (!response.ok) { // Reset and close modal
// Try to get error message from response (override status-based message if available) setImportFile(null);
if (result.error) { setIsImportModalOpen(false);
errorMessage = result.error;
} else if (result.message) {
errorMessage = result.message;
}
throw new Error(errorMessage);
}
// Success case // Reload keywords
const importedCount = result.data?.imported || result.imported || 0; if (activeSite) {
const skippedCount = result.data?.skipped || result.skipped || 0; loadSeedKeywords();
const errors = result.data?.errors || result.errors || [];
toast.success(
`Successfully imported ${importedCount} keyword(s)${skippedCount > 0 ? `, ${skippedCount} skipped` : ''}`
);
if (errors.length > 0) {
toast.info(`Errors: ${errors.slice(0, 3).join(', ')}`);
}
// Reset and close modal
setImportFile(null);
setIsImportModalOpen(false);
// Reload keywords
if (activeSite) {
loadSeedKeywords();
}
} catch (jsonError: any) {
// If JSON parsing fails, handle it gracefully
if (!response.ok) {
throw new Error(errorMessage || `Server error: ${response.status}`);
}
throw jsonError;
} }
} catch (error: any) { } catch (error: any) {
console.error('Import error:', error); console.error('Import error:', error);
@@ -686,21 +631,6 @@ export default function IndustriesSectorsKeywords() {
title="Add Keywords" title="Add Keywords"
badge={{ icon: <BoltIcon />, color: 'blue' }} badge={{ icon: <BoltIcon />, color: 'blue' }}
/> />
{/* Action Buttons */}
{isAdmin && (
<div className="px-6 pt-4 pb-2 flex justify-end gap-2">
<Button
variant="secondary"
size="md"
startIcon={<PlusIcon className="w-4 h-4" />}
onClick={handleImportClick}
>
Import Keywords
</Button>
</div>
)}
<TablePageTemplate <TablePageTemplate
columns={pageConfig.columns} columns={pageConfig.columns}
data={seedKeywords} data={seedKeywords}
@@ -731,7 +661,18 @@ export default function IndustriesSectorsKeywords() {
} }
}} }}
bulkActions={pageConfig.bulkActions} bulkActions={pageConfig.bulkActions}
customActions={undefined} customActions={
isAdmin ? (
<Button
variant="secondary"
size="sm"
onClick={handleImportClick}
>
<PlusIcon className="w-4 h-4 mr-2" />
Import Keywords
</Button>
) : undefined
}
pagination={{ pagination={{
currentPage, currentPage,
totalPages, totalPages,
@@ -761,7 +702,6 @@ export default function IndustriesSectorsKeywords() {
setImportFile(null); setImportFile(null);
} }
}} }}
className="max-w-md"
> >
<div className="p-6 space-y-4"> <div className="p-6 space-y-4">
<h2 className="text-xl font-semibold text-gray-900 dark:text-white mb-4"> <h2 className="text-xl font-semibold text-gray-900 dark:text-white mb-4">

View File

@@ -155,29 +155,8 @@ export const importTableData = async (
const queryString = params.toString(); const queryString = params.toString();
const url = `${API_BASE_URL}${endpoint}${queryString ? `?${queryString}` : ''}`; const url = `${API_BASE_URL}${endpoint}${queryString ? `?${queryString}` : ''}`;
// Get authentication token (consistent with other API calls)
const getAuthToken = () => {
try {
const authStorage = localStorage.getItem('auth-storage');
if (authStorage) {
const parsed = JSON.parse(authStorage);
return parsed?.state?.token || null;
}
} catch (e) {
// Ignore parsing errors
}
return null;
};
const token = getAuthToken();
const headers: HeadersInit = {};
if (token) {
headers['Authorization'] = `Bearer ${token}`;
}
const response = await fetch(url, { const response = await fetch(url, {
method: 'POST', method: 'POST',
headers,
body: formData, body: formData,
credentials: 'include', credentials: 'include',
}); });

View File

@@ -1,4 +0,0 @@
keyword,volume,difficulty,intent,status
keyword 1,700,52,informational,pending
keyword 2,950,92,commercial,pending
keyword 3,850,76,commercial,pending
1 keyword volume difficulty intent status
2 keyword 1 700 52 informational pending
3 keyword 2 950 92 commercial pending
4 keyword 3 850 76 commercial pending

View File

@@ -1,4 +0,0 @@
keyword,volume,difficulty,intent,industry_name,sector_name
keyword 1,550,28,commercial,Home & Garden,Home Decor
keyword 2,700,52,informational,Home & Garden,Home Decor
keyword 3,950,92,commercial,Home & Garden,Home Decor
1 keyword volume difficulty intent industry_name sector_name
2 keyword 1 550 28 commercial Home & Garden Home Decor
3 keyword 2 700 52 informational Home & Garden Home Decor
4 keyword 3 950 92 commercial Home & Garden Home Decor