Refactor ProgressModal and API logging
- Removed AI request logging from `autoGenerateIdeas`, `generateSingleIdea`, `autoGenerateContent`, and `autoGenerateImages` functions to streamline API calls. - Updated `useProgressModal` to enhance step logging by directly processing request and response steps, improving clarity and performance. - Cleaned up deprecated logging imports in `TablePageTemplate` to reflect the removal of frontend debug logging.
This commit is contained in:
@@ -496,33 +496,6 @@ export function useProgressModal(): UseProgressModalReturn {
|
||||
// Sort by step number and update state
|
||||
allSteps.sort((a, b) => a.stepNumber - b.stepNumber);
|
||||
setStepLogs(allSteps);
|
||||
|
||||
// Also update AI request logs store
|
||||
const { useAIRequestLogsStore } = await import('../store/aiRequestLogsStore').catch(() => ({ useAIRequestLogsStore: null }));
|
||||
const logs = useAIRequestLogsStore?.getState().logs || [];
|
||||
const log = logs.find(l => l.response?.data?.task_id === taskId);
|
||||
if (log) {
|
||||
const addRequestStep = useAIRequestLogsStore?.getState().addRequestStep;
|
||||
const addResponseStep = useAIRequestLogsStore?.getState().addResponseStep;
|
||||
|
||||
if (meta.request_steps && Array.isArray(meta.request_steps)) {
|
||||
meta.request_steps.forEach((step: any) => {
|
||||
// Only add if not already present
|
||||
if (!log.requestSteps.find(s => s.stepNumber === step.stepNumber)) {
|
||||
addRequestStep?.(log.id, step);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (meta.response_steps && Array.isArray(meta.response_steps)) {
|
||||
meta.response_steps.forEach((step: any) => {
|
||||
// Only add if not already present
|
||||
if (!log.responseSteps.find(s => s.stepNumber === step.stepNumber)) {
|
||||
addResponseStep?.(log.id, step);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (response.state === 'SUCCESS') {
|
||||
const meta = response.meta || {};
|
||||
@@ -586,32 +559,6 @@ export function useProgressModal(): UseProgressModalReturn {
|
||||
// Sort by step number and update state
|
||||
allSteps.sort((a, b) => a.stepNumber - b.stepNumber);
|
||||
setStepLogs(allSteps);
|
||||
|
||||
// Also update AI request logs store
|
||||
const { useAIRequestLogsStore } = await import('../store/aiRequestLogsStore').catch(() => ({ useAIRequestLogsStore: null }));
|
||||
const logs = useAIRequestLogsStore?.getState().logs || [];
|
||||
// Find log by task_id in response data or by matching the most recent log
|
||||
const log = logs.find(l => l.response?.data?.task_id === taskId) || logs[0];
|
||||
if (log) {
|
||||
const addRequestStep = useAIRequestLogsStore?.getState().addRequestStep;
|
||||
const addResponseStep = useAIRequestLogsStore?.getState().addResponseStep;
|
||||
|
||||
if (meta.request_steps && Array.isArray(meta.request_steps)) {
|
||||
meta.request_steps.forEach((step: any) => {
|
||||
if (!log.requestSteps.find(s => s.stepNumber === step.stepNumber)) {
|
||||
addRequestStep?.(log.id, step);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (meta.response_steps && Array.isArray(meta.response_steps)) {
|
||||
meta.response_steps.forEach((step: any) => {
|
||||
if (!log.responseSteps.find(s => s.stepNumber === step.stepNumber)) {
|
||||
addResponseStep?.(log.id, step);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Stop polling on SUCCESS
|
||||
@@ -634,29 +581,40 @@ export function useProgressModal(): UseProgressModalReturn {
|
||||
|
||||
// Update step logs from failure response
|
||||
if (meta.request_steps || meta.response_steps) {
|
||||
const { useAIRequestLogsStore } = await import('../store/aiRequestLogsStore').catch(() => ({ useAIRequestLogsStore: null }));
|
||||
const logs = useAIRequestLogsStore?.getState().logs || [];
|
||||
const log = logs.find(l => l.response?.data?.task_id === taskId);
|
||||
if (log) {
|
||||
const addRequestStep = useAIRequestLogsStore?.getState().addRequestStep;
|
||||
const addResponseStep = useAIRequestLogsStore?.getState().addResponseStep;
|
||||
|
||||
if (meta.request_steps && Array.isArray(meta.request_steps)) {
|
||||
meta.request_steps.forEach((step: any) => {
|
||||
if (!log.requestSteps.find(s => s.stepNumber === step.stepNumber)) {
|
||||
addRequestStep?.(log.id, step);
|
||||
}
|
||||
const allSteps: Array<{
|
||||
stepNumber: number;
|
||||
stepName: string;
|
||||
status: string;
|
||||
message: string;
|
||||
timestamp?: number;
|
||||
}> = [];
|
||||
|
||||
if (meta.request_steps && Array.isArray(meta.request_steps)) {
|
||||
meta.request_steps.forEach((step: any) => {
|
||||
allSteps.push({
|
||||
stepNumber: step.stepNumber || 0,
|
||||
stepName: step.stepName || 'Unknown',
|
||||
status: step.status || 'error',
|
||||
message: step.message || '',
|
||||
timestamp: step.timestamp,
|
||||
});
|
||||
}
|
||||
|
||||
if (meta.response_steps && Array.isArray(meta.response_steps)) {
|
||||
meta.response_steps.forEach((step: any) => {
|
||||
if (!log.responseSteps.find(s => s.stepNumber === step.stepNumber)) {
|
||||
addResponseStep?.(log.id, step);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (meta.response_steps && Array.isArray(meta.response_steps)) {
|
||||
meta.response_steps.forEach((step: any) => {
|
||||
allSteps.push({
|
||||
stepNumber: step.stepNumber || 0,
|
||||
stepName: step.stepName || 'Unknown',
|
||||
status: step.status || 'error',
|
||||
message: step.message || '',
|
||||
timestamp: step.timestamp,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
allSteps.sort((a, b) => a.stepNumber - b.stepNumber);
|
||||
setStepLogs(allSteps);
|
||||
}
|
||||
|
||||
// Stop polling on FAILURE
|
||||
|
||||
@@ -596,165 +596,33 @@ export async function autoClusterKeywords(keywordIds: number[], sectorId?: numbe
|
||||
}
|
||||
|
||||
export async function autoGenerateIdeas(clusterIds: number[]): Promise<{ success: boolean; task_id?: string; ideas_created?: number; message?: string; error?: string }> {
|
||||
const startTime = Date.now();
|
||||
const { useAIRequestLogsStore } = await import('../store/aiRequestLogsStore').catch(() => ({ useAIRequestLogsStore: null }));
|
||||
const addLog = useAIRequestLogsStore?.getState().addLog;
|
||||
|
||||
const endpoint = `/v1/planner/clusters/auto_generate_ideas/`;
|
||||
const requestBody = { ids: clusterIds };
|
||||
|
||||
addLog?.({
|
||||
function: 'autoGenerateIdeas',
|
||||
endpoint,
|
||||
request: {
|
||||
method: 'POST',
|
||||
body: requestBody,
|
||||
},
|
||||
status: 'pending',
|
||||
});
|
||||
|
||||
try {
|
||||
const response = await fetchAPI(endpoint, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(requestBody),
|
||||
});
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
addLog({
|
||||
function: 'autoGenerateIdeas',
|
||||
endpoint,
|
||||
request: {
|
||||
method: 'POST',
|
||||
body: requestBody,
|
||||
},
|
||||
response: {
|
||||
status: 200,
|
||||
data: response,
|
||||
},
|
||||
status: 'success',
|
||||
duration,
|
||||
});
|
||||
|
||||
return response;
|
||||
} catch (error: any) {
|
||||
const duration = Date.now() - startTime;
|
||||
|
||||
// Parse error message to extract error type
|
||||
let errorType = 'UNKNOWN_ERROR';
|
||||
let errorMessage = error.message || 'Unknown error';
|
||||
|
||||
if (errorMessage.includes('OperationalError')) {
|
||||
errorType = 'DATABASE_ERROR';
|
||||
errorMessage = errorMessage.replace(/API Error \(\d+\): /, '').replace(/ - .*OperationalError.*/, ' - Database operation failed');
|
||||
} else if (errorMessage.includes('ValidationError')) {
|
||||
errorType = 'VALIDATION_ERROR';
|
||||
} else if (errorMessage.includes('PermissionDenied')) {
|
||||
errorType = 'PERMISSION_ERROR';
|
||||
} else if (errorMessage.match(/API Error \(\d+\): ([^-]+)/)) {
|
||||
const match = errorMessage.match(/API Error \(\d+\): ([^-]+)/);
|
||||
if (match) {
|
||||
errorType = match[1].trim();
|
||||
errorMessage = errorMessage.replace(/API Error \(\d+\): [^-]+ - /, '');
|
||||
}
|
||||
}
|
||||
|
||||
addLog?.({
|
||||
function: 'autoGenerateIdeas',
|
||||
endpoint,
|
||||
request: {
|
||||
method: 'POST',
|
||||
body: requestBody,
|
||||
},
|
||||
response: {
|
||||
status: 500,
|
||||
error: errorMessage,
|
||||
errorType,
|
||||
},
|
||||
status: 'error',
|
||||
duration,
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export async function generateSingleIdea(ideaId: string | number, clusterId: number): Promise<{ success: boolean; task_id?: string; idea_created?: number; message?: string; error?: string }> {
|
||||
const startTime = Date.now();
|
||||
const { useAIRequestLogsStore } = await import('../store/aiRequestLogsStore').catch(() => ({ useAIRequestLogsStore: null }));
|
||||
const addLog = useAIRequestLogsStore?.getState().addLog;
|
||||
|
||||
const endpoint = `/v1/planner/ideas/${ideaId}/generate_idea/`;
|
||||
const requestBody = { cluster_id: clusterId };
|
||||
|
||||
addLog?.({
|
||||
function: 'generateSingleIdea',
|
||||
endpoint,
|
||||
request: {
|
||||
method: 'POST',
|
||||
body: requestBody,
|
||||
},
|
||||
status: 'pending',
|
||||
});
|
||||
|
||||
try {
|
||||
const response = await fetchAPI(endpoint, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(requestBody),
|
||||
});
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
addLog?.({
|
||||
function: 'generateSingleIdea',
|
||||
endpoint,
|
||||
request: {
|
||||
method: 'POST',
|
||||
body: requestBody,
|
||||
},
|
||||
response: {
|
||||
status: 200,
|
||||
data: response,
|
||||
},
|
||||
status: 'success',
|
||||
duration,
|
||||
});
|
||||
|
||||
return response;
|
||||
} catch (error: any) {
|
||||
const duration = Date.now() - startTime;
|
||||
|
||||
// Parse error message to extract error type
|
||||
let errorType = 'UNKNOWN_ERROR';
|
||||
let errorMessage = error.message || 'Unknown error';
|
||||
|
||||
if (errorMessage.includes('OperationalError')) {
|
||||
errorType = 'DATABASE_ERROR';
|
||||
errorMessage = errorMessage.replace(/API Error \(\d+\): /, '').replace(/ - .*OperationalError.*/, ' - Database operation failed');
|
||||
} else if (errorMessage.includes('ValidationError')) {
|
||||
errorType = 'VALIDATION_ERROR';
|
||||
} else if (errorMessage.includes('PermissionDenied')) {
|
||||
errorType = 'PERMISSION_ERROR';
|
||||
} else if (errorMessage.match(/API Error \(\d+\): ([^-]+)/)) {
|
||||
const match = errorMessage.match(/API Error \(\d+\): ([^-]+)/);
|
||||
if (match) {
|
||||
errorType = match[1].trim();
|
||||
errorMessage = errorMessage.replace(/API Error \(\d+\): [^-]+ - /, '');
|
||||
}
|
||||
}
|
||||
|
||||
addLog?.({
|
||||
function: 'generateSingleIdea',
|
||||
endpoint,
|
||||
request: {
|
||||
method: 'POST',
|
||||
body: requestBody,
|
||||
},
|
||||
response: {
|
||||
status: 500,
|
||||
error: errorMessage,
|
||||
errorType,
|
||||
},
|
||||
status: 'error',
|
||||
duration,
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
@@ -1051,161 +919,33 @@ export async function bulkUpdateTasksStatus(ids: number[], status: string): Prom
|
||||
}
|
||||
|
||||
export async function autoGenerateContent(ids: number[]): Promise<{ success: boolean; task_id?: string; tasks_updated?: number; message?: string; error?: string }> {
|
||||
const startTime = Date.now();
|
||||
const { useAIRequestLogsStore } = await import('../store/aiRequestLogsStore').catch(() => ({ useAIRequestLogsStore: null }));
|
||||
const addLog = useAIRequestLogsStore?.getState().addLog;
|
||||
|
||||
const endpoint = `/v1/writer/tasks/auto_generate_content/`;
|
||||
const requestBody = { ids };
|
||||
|
||||
addLog?.({
|
||||
function: 'autoGenerateContent',
|
||||
endpoint,
|
||||
request: {
|
||||
method: 'POST',
|
||||
body: requestBody,
|
||||
},
|
||||
status: 'pending',
|
||||
});
|
||||
|
||||
try {
|
||||
const response = await fetchAPI(endpoint, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(requestBody),
|
||||
});
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
addLog({
|
||||
function: 'autoGenerateContent',
|
||||
endpoint,
|
||||
request: {
|
||||
method: 'POST',
|
||||
body: requestBody,
|
||||
},
|
||||
response: {
|
||||
status: 200,
|
||||
data: response,
|
||||
},
|
||||
status: 'success',
|
||||
duration,
|
||||
});
|
||||
|
||||
return response;
|
||||
} catch (error: any) {
|
||||
const duration = Date.now() - startTime;
|
||||
|
||||
// Parse error message to extract error type
|
||||
let errorType = 'UNKNOWN_ERROR';
|
||||
let errorMessage = error.message || 'Unknown error';
|
||||
|
||||
if (errorMessage.includes('OperationalError')) {
|
||||
errorType = 'DATABASE_ERROR';
|
||||
errorMessage = errorMessage.replace(/API Error \(\d+\): /, '').replace(/ - .*OperationalError.*/, ' - Database operation failed');
|
||||
} else if (errorMessage.includes('ValidationError')) {
|
||||
errorType = 'VALIDATION_ERROR';
|
||||
} else if (errorMessage.match(/API Error \(\d+\): ([^-]+)/)) {
|
||||
const match = errorMessage.match(/API Error \(\d+\): ([^-]+)/);
|
||||
if (match) {
|
||||
errorType = match[1].trim();
|
||||
errorMessage = errorMessage.replace(/API Error \(\d+\): [^-]+ - /, '');
|
||||
}
|
||||
}
|
||||
|
||||
addLog?.({
|
||||
function: 'autoGenerateContent',
|
||||
endpoint,
|
||||
request: {
|
||||
method: 'POST',
|
||||
body: requestBody,
|
||||
},
|
||||
response: {
|
||||
status: 500,
|
||||
error: errorMessage,
|
||||
errorType,
|
||||
},
|
||||
status: 'error',
|
||||
duration,
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export async function autoGenerateImages(taskIds: number[]): Promise<{ success: boolean; task_id?: string; images_created?: number; message?: string; error?: string }> {
|
||||
const startTime = Date.now();
|
||||
const { useAIRequestLogsStore } = await import('../store/aiRequestLogsStore').catch(() => ({ useAIRequestLogsStore: null }));
|
||||
const addLog = useAIRequestLogsStore?.getState().addLog;
|
||||
|
||||
const endpoint = `/v1/writer/tasks/auto_generate_images/`;
|
||||
const requestBody = { task_ids: taskIds };
|
||||
|
||||
addLog?.({
|
||||
function: 'autoGenerateImages',
|
||||
endpoint,
|
||||
request: {
|
||||
method: 'POST',
|
||||
body: requestBody,
|
||||
},
|
||||
status: 'pending',
|
||||
});
|
||||
|
||||
try {
|
||||
const response = await fetchAPI(endpoint, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(requestBody),
|
||||
});
|
||||
|
||||
const duration = Date.now() - startTime;
|
||||
addLog({
|
||||
function: 'autoGenerateImages',
|
||||
endpoint,
|
||||
request: {
|
||||
method: 'POST',
|
||||
body: requestBody,
|
||||
},
|
||||
response: {
|
||||
status: 200,
|
||||
data: response,
|
||||
},
|
||||
status: 'success',
|
||||
duration,
|
||||
});
|
||||
|
||||
return response;
|
||||
} catch (error: any) {
|
||||
const duration = Date.now() - startTime;
|
||||
|
||||
// Parse error message to extract error type
|
||||
let errorType = 'UNKNOWN_ERROR';
|
||||
let errorMessage = error.message || 'Unknown error';
|
||||
|
||||
if (errorMessage.includes('OperationalError')) {
|
||||
errorType = 'DATABASE_ERROR';
|
||||
errorMessage = errorMessage.replace(/API Error \(\d+\): /, '').replace(/ - .*OperationalError.*/, ' - Database operation failed');
|
||||
} else if (errorMessage.includes('ValidationError')) {
|
||||
errorType = 'VALIDATION_ERROR';
|
||||
} else if (errorMessage.match(/API Error \(\d+\): ([^-]+)/)) {
|
||||
const match = errorMessage.match(/API Error \(\d+\): ([^-]+)/);
|
||||
if (match) {
|
||||
errorType = match[1].trim();
|
||||
errorMessage = errorMessage.replace(/API Error \(\d+\): [^-]+ - /, '');
|
||||
}
|
||||
}
|
||||
|
||||
addLog?.({
|
||||
function: 'autoGenerateImages',
|
||||
endpoint,
|
||||
request: {
|
||||
method: 'POST',
|
||||
body: requestBody,
|
||||
},
|
||||
response: {
|
||||
status: 500,
|
||||
error: errorMessage,
|
||||
errorType,
|
||||
},
|
||||
status: 'error',
|
||||
duration,
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,8 +40,6 @@ import BulkStatusUpdateModal from '../components/common/BulkStatusUpdateModal';
|
||||
import { CompactPagination } from '../components/ui/pagination';
|
||||
import SectorSelector from '../components/common/SectorSelector';
|
||||
import { usePageSizeStore } from '../store/pageSizeStore';
|
||||
// DEPRECATED: Frontend debug logging removed - now using backend console logging
|
||||
// import { useAIRequestLogsStore } from '../store/aiRequestLogsStore';
|
||||
import ToggleTableRow, { ToggleButton } from '../components/common/ToggleTableRow';
|
||||
|
||||
interface ColumnConfig {
|
||||
|
||||
Reference in New Issue
Block a user