link actions to their screenshots - frontend (#4403)
This commit is contained in:
@@ -328,6 +328,7 @@ export type ActionApiResponse = {
|
|||||||
option: Option | null;
|
option: Option | null;
|
||||||
file_url: string | null;
|
file_url: string | null;
|
||||||
created_by: string | null;
|
created_by: string | null;
|
||||||
|
screenshot_artifact_id?: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Action = {
|
export type Action = {
|
||||||
@@ -339,6 +340,7 @@ export type Action = {
|
|||||||
stepId: string;
|
stepId: string;
|
||||||
index: number;
|
index: number;
|
||||||
created_by: string | null;
|
created_by: string | null;
|
||||||
|
screenshotArtifactId?: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type EvalKind = "workflow" | "task";
|
export type EvalKind = "workflow" | "task";
|
||||||
@@ -464,6 +466,7 @@ export type ActionsApiResponse = {
|
|||||||
response: string | null;
|
response: string | null;
|
||||||
created_by: string | null;
|
created_by: string | null;
|
||||||
text: string | null;
|
text: string | null;
|
||||||
|
screenshot_artifact_id?: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TaskV2 = {
|
export type TaskV2 = {
|
||||||
|
|||||||
@@ -9,18 +9,37 @@ import { statusIsNotFinalized } from "../types";
|
|||||||
import { apiPathPrefix } from "@/util/env";
|
import { apiPathPrefix } from "@/util/env";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
artifactId?: string;
|
||||||
stepId: string;
|
stepId: string;
|
||||||
index: number;
|
index: number;
|
||||||
taskStatus?: Status; // to give a hint that screenshot may not be available if task is not finalized
|
taskStatus?: Status; // to give a hint that screenshot may not be available if task is not finalized
|
||||||
};
|
};
|
||||||
|
|
||||||
function ActionScreenshot({ stepId, index, taskStatus }: Props) {
|
function ActionScreenshot({ artifactId, stepId, index, taskStatus }: Props) {
|
||||||
const credentialGetter = useCredentialGetter();
|
const credentialGetter = useCredentialGetter();
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: artifactById,
|
||||||
|
isLoading: isLoadingArtifactById,
|
||||||
|
isFetching: isFetchingArtifactById,
|
||||||
|
} = useQuery<ArtifactApiResponse>({
|
||||||
|
queryKey: ["artifact", artifactId],
|
||||||
|
queryFn: async () => {
|
||||||
|
const client = await getClient(credentialGetter);
|
||||||
|
return client
|
||||||
|
.get(`${apiPathPrefix}/artifacts/${artifactId}`)
|
||||||
|
.then((response) => response.data);
|
||||||
|
},
|
||||||
|
enabled: Boolean(artifactId),
|
||||||
|
refetchOnWindowFocus: false,
|
||||||
|
refetchOnMount: false,
|
||||||
|
retry: 1,
|
||||||
|
});
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: artifacts,
|
data: artifacts,
|
||||||
isLoading,
|
isLoading: isLoadingStepArtifacts,
|
||||||
isFetching,
|
isFetching: isFetchingStepArtifacts,
|
||||||
} = useQuery<Array<ArtifactApiResponse>>({
|
} = useQuery<Array<ArtifactApiResponse>>({
|
||||||
queryKey: ["step", stepId, "artifacts"],
|
queryKey: ["step", stepId, "artifacts"],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
@@ -39,14 +58,19 @@ function ActionScreenshot({ stepId, index, taskStatus }: Props) {
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
enabled: !artifactId, // fallback path only when explicit artifact id is absent
|
||||||
});
|
});
|
||||||
|
|
||||||
const actionScreenshots = artifacts?.filter(
|
const actionScreenshots = artifacts?.filter(
|
||||||
(artifact) => artifact.artifact_type === ArtifactType.ActionScreenshot,
|
(artifact) => artifact.artifact_type === ArtifactType.ActionScreenshot,
|
||||||
);
|
);
|
||||||
|
|
||||||
// action screenshots are reverse ordered w.r.t action order
|
const screenshotFromStep =
|
||||||
const screenshot = actionScreenshots?.[actionScreenshots.length - index - 1];
|
actionScreenshots?.[actionScreenshots.length - index - 1];
|
||||||
|
const screenshot = artifactById ?? screenshotFromStep;
|
||||||
|
|
||||||
|
const isLoading = isLoadingArtifactById || isLoadingStepArtifacts;
|
||||||
|
const isFetching = isFetchingArtifactById || isFetchingStepArtifacts;
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -237,6 +237,7 @@ function TaskActions() {
|
|||||||
{activeSelection === "stream" ? getStream() : null}
|
{activeSelection === "stream" ? getStream() : null}
|
||||||
{typeof activeSelection === "number" && activeAction ? (
|
{typeof activeSelection === "number" && activeAction ? (
|
||||||
<ActionScreenshot
|
<ActionScreenshot
|
||||||
|
artifactId={activeAction.screenshotArtifactId ?? undefined}
|
||||||
stepId={activeAction.stepId}
|
stepId={activeAction.stepId}
|
||||||
index={activeAction.index}
|
index={activeAction.index}
|
||||||
taskStatus={task?.status}
|
taskStatus={task?.status}
|
||||||
|
|||||||
@@ -127,6 +127,7 @@ function useActions({ id }: Props): {
|
|||||||
stepId: action.step_id ?? "",
|
stepId: action.step_id ?? "",
|
||||||
index: index,
|
index: index,
|
||||||
created_by: action.created_by,
|
created_by: action.created_by,
|
||||||
|
screenshotArtifactId: action.screenshot_artifact_id ?? undefined,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -122,6 +122,7 @@ function WorkflowRunOverview() {
|
|||||||
!showStreamingBrowser &&
|
!showStreamingBrowser &&
|
||||||
isAction(selection) && (
|
isAction(selection) && (
|
||||||
<ActionScreenshot
|
<ActionScreenshot
|
||||||
|
artifactId={selection.screenshot_artifact_id ?? undefined}
|
||||||
index={selection.action_order ?? 0}
|
index={selection.action_order ?? 0}
|
||||||
stepId={selection.step_id ?? ""}
|
stepId={selection.step_id ?? ""}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user