chore: clean ups

This commit is contained in:
Lluis Agusti
2026-02-23 20:56:08 +08:00
parent a7c9a3c5ae
commit 1090f90d95
2 changed files with 9 additions and 197 deletions

View File

@@ -1,189 +0,0 @@
import { GraphExecutionMeta, LibraryAgent } from "@/lib/autogpt-server-api";
import {
ComposedChart,
DefaultLegendContentProps,
Legend,
Line,
ResponsiveContainer,
Scatter,
Tooltip,
XAxis,
YAxis,
} from "recharts";
import { differenceInHours, format } from "date-fns";
import { Card } from "@/components/__legacy__/ui/card";
import { cn, hashString } from "@/lib/utils";
import React from "react";
import { FlowRunStatusBadge } from "@/app/(platform)/monitoring/components/FlowRunStatusBadge";
const FlowRunsTimelineChart = ({
flows,
executions,
dataMin,
className,
}: {
flows: LibraryAgent[];
executions: GraphExecutionMeta[];
dataMin: "dataMin" | number;
className?: string;
}) => (
/* TODO: make logarithmic? */
<ResponsiveContainer width="100%" height={120} className={className}>
<ComposedChart>
<XAxis
dataKey="time"
type="number"
domain={[
typeof dataMin == "string"
? dataMin
: dataMin < 0
? Date.now() + dataMin * 1000
: dataMin,
Date.now(),
]}
allowDataOverflow={true}
tickFormatter={(unixTime) => {
const now = new Date();
const time = new Date(unixTime);
return differenceInHours(now, time) < 24
? format(time, "HH:mm")
: format(time, "yyyy-MM-dd HH:mm");
}}
name="Time"
scale="time"
/>
<YAxis
dataKey="_duration"
name="Duration (s)"
tickFormatter={(s) => (s > 90 ? `${Math.round(s / 60)}m` : `${s}s`)}
/>
<Tooltip
content={({ payload }) => {
if (payload && payload.length) {
const data: GraphExecutionMeta & {
time: number;
_duration: number;
} = payload[0].payload;
const flow = flows.find((f) => f.graph_id === data.graph_id);
return (
<Card className="p-2 text-xs leading-normal">
<p>
<strong>Agent:</strong> {flow ? flow.name : "Unknown"}
</p>
<div>
<strong>Status:</strong>&nbsp;
<FlowRunStatusBadge
status={data.status}
className="px-1.5 py-0"
/>
</div>
<p>
<strong>Started:</strong>{" "}
{data.started_at
? format(data.started_at, "yyyy-MM-dd HH:mm:ss")
: "---"}
</p>
{data.stats && (
<p>
<strong>Duration / run time:</strong>{" "}
{formatDuration(data.stats.duration)} /{" "}
{formatDuration(data.stats.node_exec_time)}
</p>
)}
</Card>
);
}
return null;
}}
/>
{flows.map((flow) => (
<Scatter
key={flow.id}
data={executions
.filter((e) => e.graph_id == flow.graph_id && e.started_at)
.map((e) => ({
...e,
time:
(e.started_at?.getTime() ?? 0) +
(e.stats?.node_exec_time ?? 0) * 1000,
_duration: e.stats?.node_exec_time ?? 0,
}))}
name={flow.name}
fill={`hsl(${(hashString(flow.id) * 137.5) % 360}, 70%, 50%)`}
/>
))}
{executions
.filter((e) => e.started_at && e.ended_at)
.map((execution) => (
<Line
key={execution.id}
type="linear"
dataKey="_duration"
data={[
{
...execution,
time: execution.started_at!.getTime(),
_duration: 0,
},
{
...execution,
time: execution.ended_at!.getTime(),
_duration: execution.stats?.node_exec_time ?? 0,
},
]}
stroke={`hsl(${(hashString(execution.graph_id) * 137.5) % 360}, 70%, 50%)`}
strokeWidth={2}
dot={false}
legendType="none"
/>
))}
<Legend
content={<ScrollableLegend />}
wrapperStyle={{
bottom: 0,
left: 0,
right: 0,
width: "100%",
display: "flex",
justifyContent: "center",
}}
/>
</ComposedChart>
</ResponsiveContainer>
);
export default FlowRunsTimelineChart;
const ScrollableLegend: React.FC<
DefaultLegendContentProps & { className?: string }
> = ({ payload, className }) => {
return (
<div
className={cn(
"space-x-3 overflow-x-auto whitespace-nowrap px-4 text-sm",
className,
)}
style={{ scrollbarWidth: "none" }}
>
{payload?.map((entry) => {
if (entry.type == "none") return;
return (
<span key={String(entry.value)} className="inline-flex items-center">
<span
className="mr-1 inline-block size-2.5 rounded-full"
style={{ backgroundColor: entry.color }}
/>
<span>{entry.value}</span>
</span>
);
})}
</div>
);
};
function formatDuration(seconds: number): string {
return (
(seconds < 100 ? seconds.toPrecision(2) : Math.round(seconds)).toString() +
"s"
);
}

View File

@@ -1,4 +1,4 @@
import { useRef, useState } from "react";
import { useEffect, useRef, useState } from "react";
import { z } from "zod";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
@@ -69,9 +69,10 @@ export function HostScopedCredentialsModal({
Array<{ id: string; key: string; value: string }>
>([{ id: crypto.randomUUID(), key: "", value: "" }]);
// Update form values when siblingInputs change (render-time sync instead of useEffect)
// Update form values when siblingInputs change
const prevHostRef = useRef(currentHost);
if (currentHost !== prevHostRef.current) {
useEffect(() => {
if (currentHost === prevHostRef.current) return;
prevHostRef.current = currentHost;
if (currentHost) {
form.setValue("host", currentHost);
@@ -80,7 +81,7 @@ export function HostScopedCredentialsModal({
form.setValue("host", "");
form.setValue("title", "Manual Entry");
}
}
}, [currentHost, form]);
if (
!credentials ||
@@ -92,12 +93,12 @@ export function HostScopedCredentialsModal({
const { provider, providerName, createHostScopedCredentials } = credentials;
const addHeaderPair = () => {
setHeaderPairs([
...headerPairs,
function addHeaderPair() {
setHeaderPairs((prev) => [
...prev,
{ id: crypto.randomUUID(), key: "", value: "" },
]);
};
}
const removeHeaderPair = (index: number) => {
if (headerPairs.length > 1) {