alot of othe mess fro autoamtion overview an ddetiaeld run apge sonly

This commit is contained in:
IGNY8 VPS (Salman)
2026-01-17 10:13:08 +00:00
parent 6b1fa0c1ee
commit 0435a5cf70
14 changed files with 1727 additions and 470 deletions

View File

@@ -2,7 +2,7 @@
* Automation Run Detail Page
* Comprehensive view of a single automation run
*/
import React, { useState, useEffect } from 'react';
import React, { useEffect, useRef, useState } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import { useSiteStore } from '../../store/siteStore';
import { automationService } from '../../services/automationService';
@@ -20,29 +20,74 @@ const AutomationRunDetail: React.FC = () => {
const { runId } = useParams<{ runId: string }>();
const navigate = useNavigate();
const { activeSite } = useSiteStore();
const toast = useToast();
const { error: toastError } = useToast();
const [loading, setLoading] = useState(true);
const [runDetail, setRunDetail] = useState<RunDetailResponse | null>(null);
const [error, setError] = useState<string | null>(null);
const lastRequestKey = useRef<string | null>(null);
useEffect(() => {
loadRunDetail();
}, [runId, activeSite]);
const loadRunDetail = async () => {
if (!activeSite || !runId) return;
const decodeTitle = (value: string | undefined | null) => {
if (!value) return '';
try {
setLoading(true);
const data = await automationService.getRunDetail(activeSite.id, runId);
setRunDetail(data);
} catch (error: any) {
console.error('Failed to load run detail', error);
toast.error(error.message || 'Failed to load run detail');
} finally {
setLoading(false);
return decodeURIComponent(value);
} catch {
return value;
}
};
const getDisplayTitle = () => {
const run = runDetail?.run;
if (!run) return 'Automation Run';
if (run.site_name) return run.site_name;
if (run.site_domain) return run.site_domain.replace('www.', '');
const decoded = decodeTitle(run.run_title);
if (decoded) return decoded;
if (run.run_number) return `Run #${run.run_number}`;
return 'Automation Run';
};
useEffect(() => {
const loadRunDetail = async () => {
if (!runId) {
setError('Missing run id');
setLoading(false);
return;
}
if (!activeSite) {
setError('Please select a site to view automation run details.');
setLoading(false);
return;
}
const requestKey = `${activeSite.id}-${runId}`;
if (lastRequestKey.current === requestKey) {
return;
}
lastRequestKey.current = requestKey;
try {
setLoading(true);
setError(null);
const data = await automationService.getRunDetail(activeSite.id, runId);
setRunDetail(data);
} catch (err: any) {
console.error('Failed to load run detail', err);
const message = err?.message === 'Internal server error'
? 'Run detail is temporarily unavailable (server error). Please try again later.'
: err?.message || 'Failed to load run detail';
setError(message);
toastError(message);
lastRequestKey.current = null;
} finally {
setLoading(false);
}
};
loadRunDetail();
}, [runId, activeSite, toastError]);
if (!activeSite) {
return (
<div className="p-6">
@@ -59,6 +104,14 @@ const AutomationRunDetail: React.FC = () => {
);
}
if (error) {
return (
<div className="p-6">
<p className="text-gray-600 dark:text-gray-400">{error}</p>
</div>
);
}
if (!runDetail) {
return (
<div className="p-6">
@@ -67,26 +120,71 @@ const AutomationRunDetail: React.FC = () => {
);
}
const displayTitle = getDisplayTitle();
const breadcrumbLabel = runDetail.run?.run_number ? `Run #${runDetail.run.run_number}` : displayTitle;
const normalizedRun = runDetail.run ? { ...runDetail.run, run_title: displayTitle } : null;
const stageSummary = (runDetail.stages || []).reduce(
(acc, stage) => {
acc.itemsProcessed += stage.items_processed || 0;
acc.itemsCreated += stage.items_created || 0;
if (stage.stage_number === 4) acc.contentCreated += stage.items_created || 0;
if (stage.stage_number === 6) acc.imagesGenerated += stage.items_created || 0;
return acc;
},
{ itemsProcessed: 0, itemsCreated: 0, contentCreated: 0, imagesGenerated: 0 }
);
const derivedInsights = [] as RunDetailResponse['insights'];
if (normalizedRun) {
if ((normalizedRun.total_credits_used || 0) > 0 && stageSummary.itemsCreated === 0) {
derivedInsights.push({
type: 'warning',
severity: 'warning',
message: 'Credits were spent but no outputs were recorded. Review stage errors and retry failed steps.',
});
}
if (normalizedRun.status === 'running') {
derivedInsights.push({
type: 'success',
severity: 'info',
message: `Run is currently active in stage ${normalizedRun.current_stage || 1}.`,
});
}
}
if ((runDetail.stages || []).some(stage => stage.status === 'failed')) {
const failedStage = runDetail.stages.find(stage => stage.status === 'failed');
derivedInsights.push({
type: 'error',
severity: 'error',
message: `Stage ${failedStage?.stage_number} failed. Review the stage details and error message for remediation.`,
});
}
const combinedInsights = runDetail.insights && runDetail.insights.length > 0
? [...runDetail.insights, ...derivedInsights]
: derivedInsights;
return (
<>
<PageMeta
title={`Run Detail - ${runDetail.run?.run_title || 'Automation Run'}`}
title={`Run Detail - ${displayTitle}`}
description="Detailed automation run analysis"
/>
<div className="space-y-6">
<PageHeader
title={runDetail.run?.run_title || 'Automation Run'}
breadcrumb={`Automation / Runs / ${runDetail.run?.run_title || 'Detail'}`}
title={displayTitle}
breadcrumb={`Automation / Runs / ${breadcrumbLabel || 'Detail'}`}
description="Comprehensive run analysis with stage breakdown and performance metrics"
/>
{/* Run Summary */}
{runDetail.run && <RunSummaryCard run={runDetail.run} />}
{normalizedRun && <RunSummaryCard run={normalizedRun} summary={stageSummary} />}
{/* Insights Panel */}
{runDetail.insights && runDetail.insights.length > 0 && (
<InsightsPanel insights={runDetail.insights} />
{combinedInsights.length > 0 && (
<InsightsPanel insights={combinedInsights} />
)}
{/* Two Column Layout */}