Add step logging functionality to ProgressModal and useProgressModal

- Introduced stepLogs to ProgressModal and useProgressModal for enhanced debugging.
- Updated ProgressModal to display step logs with status indicators.
- Modified useProgressModal to manage step logs, collecting and sorting steps from AI requests.
- Adjusted Clusters and Ideas pages to pass stepLogs to ProgressModal for improved user feedback during asynchronous tasks.
- Fixed a typo in Usage.tsx header for clarity.
This commit is contained in:
Desktop
2025-11-10 19:53:51 +05:00
parent c49223f097
commit 2e6aa6f140
5 changed files with 145 additions and 4 deletions

View File

@@ -20,6 +20,13 @@ export interface ProgressModalProps {
onCancel?: () => void;
taskId?: string;
functionId?: string; // AI function ID for tracking (e.g., "ai-cluster-01")
stepLogs?: Array<{
stepNumber: number;
stepName: string;
status: string;
message: string;
timestamp?: number;
}>; // Step logs for debugging
}
// Generate modal instance ID (increments per modal instance)
@@ -40,6 +47,7 @@ export default function ProgressModal({
onCancel,
taskId,
functionId,
stepLogs = [],
}: ProgressModalProps) {
// Generate modal instance ID on first render
const modalInstanceIdRef = React.useRef<string | null>(null);
@@ -170,7 +178,7 @@ export default function ProgressModal({
</div>
{/* Function ID and Task ID (for debugging) */}
{(fullFunctionId || taskId) && import.meta.env.DEV && (
{(fullFunctionId || taskId) && (
<div className="mb-4 space-y-1 text-xs text-gray-400 dark:text-gray-600">
{fullFunctionId && (
<div>Function ID: {fullFunctionId}</div>
@@ -181,6 +189,42 @@ export default function ProgressModal({
</div>
)}
{/* Step Logs / Debug Logs */}
{stepLogs.length > 0 && (
<div className="mb-4 max-h-48 overflow-y-auto bg-gray-50 dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 p-3">
<div className="flex items-center justify-between mb-2">
<h4 className="text-xs font-semibold text-gray-700 dark:text-gray-300">
Step Logs
</h4>
<span className="text-xs text-gray-500 dark:text-gray-400">
{stepLogs.length} step{stepLogs.length !== 1 ? 's' : ''}
</span>
</div>
<div className="space-y-1">
{stepLogs.map((step, index) => (
<div
key={index}
className={`text-xs p-2 rounded border ${
step.status === 'success'
? 'bg-green-50 dark:bg-green-900/20 border-green-200 dark:border-green-800 text-green-800 dark:text-green-300'
: step.status === 'error'
? 'bg-red-50 dark:bg-red-900/20 border-red-200 dark:border-red-800 text-red-800 dark:text-red-300'
: 'bg-blue-50 dark:bg-blue-900/20 border-blue-200 dark:border-blue-800 text-blue-800 dark:text-blue-300'
}`}
>
<div className="flex items-center gap-2">
<span className="font-mono font-semibold">
[{step.stepNumber}]
</span>
<span className="font-semibold">{step.stepName}:</span>
<span>{step.message}</span>
</div>
</div>
))}
</div>
</div>
)}
{/* Footer */}
<div className="flex justify-end gap-3">
{onCancel && status !== 'completed' && status !== 'error' && (

View File

@@ -25,6 +25,13 @@ export interface UseProgressModalReturn {
setError: (errorMessage: string) => void;
reset: () => void;
functionId?: string; // AI function ID for tracking
stepLogs: Array<{
stepNumber: number;
stepName: string;
status: string;
message: string;
timestamp?: number;
}>; // Step logs for debugging
}
export function useProgressModal(): UseProgressModalReturn {
@@ -38,6 +45,15 @@ export function useProgressModal(): UseProgressModalReturn {
status: 'pending',
});
// Step logs state for debugging
const [stepLogs, setStepLogs] = useState<Array<{
stepNumber: number;
stepName: string;
status: string;
message: string;
timestamp?: number;
}>>([]);
// Track displayed percentage and current step for step-based progress
const displayedPercentageRef = useRef(0);
const currentStepRef = useRef<string | null>(null);
@@ -383,6 +399,44 @@ export function useProgressModal(): UseProgressModalReturn {
// Update step logs if available
if (meta.request_steps || meta.response_steps) {
// Collect all steps for display in modal
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 || 'success',
message: step.message || '',
timestamp: step.timestamp,
});
});
}
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 || 'success',
message: step.message || '',
timestamp: step.timestamp,
});
});
}
// 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);
@@ -435,6 +489,44 @@ export function useProgressModal(): UseProgressModalReturn {
// Update final step logs
if (meta.request_steps || meta.response_steps) {
// Collect all steps for display in modal
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 || 'success',
message: step.message || '',
timestamp: step.timestamp,
});
});
}
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 || 'success',
message: step.message || '',
timestamp: step.timestamp,
});
});
}
// 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
@@ -579,6 +671,7 @@ export function useProgressModal(): UseProgressModalReturn {
}
displayedPercentageRef.current = 0;
currentStepRef.current = null;
setStepLogs([]); // Reset step logs when opening modal
setTaskId(newTaskId);
setTitle(newTitle);
setFunctionId(newFunctionId);
@@ -608,6 +701,7 @@ export function useProgressModal(): UseProgressModalReturn {
}
displayedPercentageRef.current = 0;
currentStepRef.current = null;
setStepLogs([]); // Clear step logs when closing modal
setIsOpen(false);
// Clear taskId to stop polling when modal closes
setTaskId(null);
@@ -651,6 +745,7 @@ export function useProgressModal(): UseProgressModalReturn {
title, // Expose title for use in component
taskId, // Expose taskId for use in ProgressModal
functionId, // Expose functionId for use in ProgressModal
stepLogs, // Expose step logs for debugging
};
}

View File

@@ -71,7 +71,7 @@ export default function Usage() {
<div className="p-6">
<PageMeta title="Usage" description="Monitor your plan limits and usage statistics" />
<div className="mb-6">
<h1 className="text-2xl font-bold text-gray-900 dark:text-white">Acoount Limits Usage the End1</h1>
<h1 className="text-2xl font-bold text-gray-900 dark:text-white">Acoount Limits Usagennot </h1>
<p className="text-gray-600 dark:text-gray-400 mt-1">Monitor your plan limits and usage statistics</p>
</div>

View File

@@ -207,7 +207,7 @@ export default function Clusters() {
if (result.success && result.task_id) {
// Async task - show progress modal
progressModal.openModal(result.task_id, 'Generating Ideas', 'ai-generate-ideas-01');
progressModal.openModal(result.task_id, 'Generating Ideas', 'ai-generate-ideas-01-desktop');
} else if (result.success && result.ideas_created) {
// Synchronous completion
toast.success(result.message || 'Ideas generated successfully');
@@ -249,7 +249,7 @@ export default function Clusters() {
if (result.task_id) {
// Async task - open progress modal
hasReloadedRef.current = false;
progressModal.openModal(result.task_id, 'Generating Content Ideas', 'ai-generate-ideas-01');
progressModal.openModal(result.task_id, 'Generating Content Ideas', 'ai-generate-ideas-01-desktop');
// Don't show toast - progress modal will show status
} else {
// Synchronous completion
@@ -482,6 +482,7 @@ export default function Clusters() {
details={progressModal.progress.details}
taskId={progressModal.taskId || undefined}
functionId={progressModal.functionId}
stepLogs={progressModal.stepLogs}
onClose={() => {
progressModal.closeModal();
// Reload once when modal closes if task was completed

View File

@@ -401,6 +401,7 @@ export default function Ideas() {
details={progressModal.progress.details}
taskId={progressModal.taskId || undefined}
functionId={progressModal.functionId}
stepLogs={progressModal.stepLogs}
onClose={() => {
const wasCompleted = progressModal.progress.status === 'completed';
progressModal.closeModal();