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:
@@ -20,6 +20,13 @@ export interface ProgressModalProps {
|
|||||||
onCancel?: () => void;
|
onCancel?: () => void;
|
||||||
taskId?: string;
|
taskId?: string;
|
||||||
functionId?: string; // AI function ID for tracking (e.g., "ai-cluster-01")
|
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)
|
// Generate modal instance ID (increments per modal instance)
|
||||||
@@ -40,6 +47,7 @@ export default function ProgressModal({
|
|||||||
onCancel,
|
onCancel,
|
||||||
taskId,
|
taskId,
|
||||||
functionId,
|
functionId,
|
||||||
|
stepLogs = [],
|
||||||
}: ProgressModalProps) {
|
}: ProgressModalProps) {
|
||||||
// Generate modal instance ID on first render
|
// Generate modal instance ID on first render
|
||||||
const modalInstanceIdRef = React.useRef<string | null>(null);
|
const modalInstanceIdRef = React.useRef<string | null>(null);
|
||||||
@@ -170,7 +178,7 @@ export default function ProgressModal({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Function ID and Task ID (for debugging) */}
|
{/* 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">
|
<div className="mb-4 space-y-1 text-xs text-gray-400 dark:text-gray-600">
|
||||||
{fullFunctionId && (
|
{fullFunctionId && (
|
||||||
<div>Function ID: {fullFunctionId}</div>
|
<div>Function ID: {fullFunctionId}</div>
|
||||||
@@ -181,6 +189,42 @@ export default function ProgressModal({
|
|||||||
</div>
|
</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 */}
|
{/* Footer */}
|
||||||
<div className="flex justify-end gap-3">
|
<div className="flex justify-end gap-3">
|
||||||
{onCancel && status !== 'completed' && status !== 'error' && (
|
{onCancel && status !== 'completed' && status !== 'error' && (
|
||||||
|
|||||||
@@ -25,6 +25,13 @@ export interface UseProgressModalReturn {
|
|||||||
setError: (errorMessage: string) => void;
|
setError: (errorMessage: string) => void;
|
||||||
reset: () => void;
|
reset: () => void;
|
||||||
functionId?: string; // AI function ID for tracking
|
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 {
|
export function useProgressModal(): UseProgressModalReturn {
|
||||||
@@ -38,6 +45,15 @@ export function useProgressModal(): UseProgressModalReturn {
|
|||||||
status: 'pending',
|
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
|
// Track displayed percentage and current step for step-based progress
|
||||||
const displayedPercentageRef = useRef(0);
|
const displayedPercentageRef = useRef(0);
|
||||||
const currentStepRef = useRef<string | null>(null);
|
const currentStepRef = useRef<string | null>(null);
|
||||||
@@ -383,6 +399,44 @@ export function useProgressModal(): UseProgressModalReturn {
|
|||||||
|
|
||||||
// Update step logs if available
|
// Update step logs if available
|
||||||
if (meta.request_steps || meta.response_steps) {
|
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 { useAIRequestLogsStore } = await import('../store/aiRequestLogsStore').catch(() => ({ useAIRequestLogsStore: null }));
|
||||||
const logs = useAIRequestLogsStore?.getState().logs || [];
|
const logs = useAIRequestLogsStore?.getState().logs || [];
|
||||||
const log = logs.find(l => l.response?.data?.task_id === taskId);
|
const log = logs.find(l => l.response?.data?.task_id === taskId);
|
||||||
@@ -435,6 +489,44 @@ export function useProgressModal(): UseProgressModalReturn {
|
|||||||
|
|
||||||
// Update final step logs
|
// Update final step logs
|
||||||
if (meta.request_steps || meta.response_steps) {
|
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 { useAIRequestLogsStore } = await import('../store/aiRequestLogsStore').catch(() => ({ useAIRequestLogsStore: null }));
|
||||||
const logs = useAIRequestLogsStore?.getState().logs || [];
|
const logs = useAIRequestLogsStore?.getState().logs || [];
|
||||||
// Find log by task_id in response data or by matching the most recent log
|
// 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;
|
displayedPercentageRef.current = 0;
|
||||||
currentStepRef.current = null;
|
currentStepRef.current = null;
|
||||||
|
setStepLogs([]); // Reset step logs when opening modal
|
||||||
setTaskId(newTaskId);
|
setTaskId(newTaskId);
|
||||||
setTitle(newTitle);
|
setTitle(newTitle);
|
||||||
setFunctionId(newFunctionId);
|
setFunctionId(newFunctionId);
|
||||||
@@ -608,6 +701,7 @@ export function useProgressModal(): UseProgressModalReturn {
|
|||||||
}
|
}
|
||||||
displayedPercentageRef.current = 0;
|
displayedPercentageRef.current = 0;
|
||||||
currentStepRef.current = null;
|
currentStepRef.current = null;
|
||||||
|
setStepLogs([]); // Clear step logs when closing modal
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
// Clear taskId to stop polling when modal closes
|
// Clear taskId to stop polling when modal closes
|
||||||
setTaskId(null);
|
setTaskId(null);
|
||||||
@@ -651,6 +745,7 @@ export function useProgressModal(): UseProgressModalReturn {
|
|||||||
title, // Expose title for use in component
|
title, // Expose title for use in component
|
||||||
taskId, // Expose taskId for use in ProgressModal
|
taskId, // Expose taskId for use in ProgressModal
|
||||||
functionId, // Expose functionId for use in ProgressModal
|
functionId, // Expose functionId for use in ProgressModal
|
||||||
|
stepLogs, // Expose step logs for debugging
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ export default function Usage() {
|
|||||||
<div className="p-6">
|
<div className="p-6">
|
||||||
<PageMeta title="Usage" description="Monitor your plan limits and usage statistics" />
|
<PageMeta title="Usage" description="Monitor your plan limits and usage statistics" />
|
||||||
<div className="mb-6">
|
<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>
|
<p className="text-gray-600 dark:text-gray-400 mt-1">Monitor your plan limits and usage statistics</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ export default function Clusters() {
|
|||||||
|
|
||||||
if (result.success && result.task_id) {
|
if (result.success && result.task_id) {
|
||||||
// Async task - show progress modal
|
// 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) {
|
} else if (result.success && result.ideas_created) {
|
||||||
// Synchronous completion
|
// Synchronous completion
|
||||||
toast.success(result.message || 'Ideas generated successfully');
|
toast.success(result.message || 'Ideas generated successfully');
|
||||||
@@ -249,7 +249,7 @@ export default function Clusters() {
|
|||||||
if (result.task_id) {
|
if (result.task_id) {
|
||||||
// Async task - open progress modal
|
// Async task - open progress modal
|
||||||
hasReloadedRef.current = false;
|
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
|
// Don't show toast - progress modal will show status
|
||||||
} else {
|
} else {
|
||||||
// Synchronous completion
|
// Synchronous completion
|
||||||
@@ -482,6 +482,7 @@ export default function Clusters() {
|
|||||||
details={progressModal.progress.details}
|
details={progressModal.progress.details}
|
||||||
taskId={progressModal.taskId || undefined}
|
taskId={progressModal.taskId || undefined}
|
||||||
functionId={progressModal.functionId}
|
functionId={progressModal.functionId}
|
||||||
|
stepLogs={progressModal.stepLogs}
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
progressModal.closeModal();
|
progressModal.closeModal();
|
||||||
// Reload once when modal closes if task was completed
|
// Reload once when modal closes if task was completed
|
||||||
|
|||||||
@@ -401,6 +401,7 @@ export default function Ideas() {
|
|||||||
details={progressModal.progress.details}
|
details={progressModal.progress.details}
|
||||||
taskId={progressModal.taskId || undefined}
|
taskId={progressModal.taskId || undefined}
|
||||||
functionId={progressModal.functionId}
|
functionId={progressModal.functionId}
|
||||||
|
stepLogs={progressModal.stepLogs}
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
const wasCompleted = progressModal.progress.status === 'completed';
|
const wasCompleted = progressModal.progress.status === 'completed';
|
||||||
progressModal.closeModal();
|
progressModal.closeModal();
|
||||||
|
|||||||
Reference in New Issue
Block a user