feat(platform): Updates to Runner Output UI (#8717)
* feat(platform): Updates to Runner Output UI * add copy text button to output boxes * prettier --------- Co-authored-by: Aarushi <50577581+aarushik93@users.noreply.github.com>zamilmajdy/secrt-1000-add-capability-for-the-admin-to-log-in-as-other-users^2
parent
19095be249
commit
63e3244e7e
|
@ -1,4 +1,4 @@
|
||||||
import React from "react";
|
import React, { useEffect, useRef } from "react";
|
||||||
import {
|
import {
|
||||||
Sheet,
|
Sheet,
|
||||||
SheetContent,
|
SheetContent,
|
||||||
|
@ -10,6 +10,9 @@ import { ScrollArea } from "@/components/ui/scroll-area";
|
||||||
import { BlockIORootSchema } from "@/lib/autogpt-server-api/types";
|
import { BlockIORootSchema } from "@/lib/autogpt-server-api/types";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Clipboard } from "lucide-react";
|
||||||
|
import { useToast } from "@/components/ui/use-toast";
|
||||||
|
|
||||||
export interface BlockOutput {
|
export interface BlockOutput {
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -29,11 +32,20 @@ interface OutputModalProps {
|
||||||
const formatOutput = (output: any): string => {
|
const formatOutput = (output: any): string => {
|
||||||
if (typeof output === "object") {
|
if (typeof output === "object") {
|
||||||
try {
|
try {
|
||||||
|
if (
|
||||||
|
Array.isArray(output) &&
|
||||||
|
output.every((item) => typeof item === "string")
|
||||||
|
) {
|
||||||
|
return output.join("\n").replace(/\\n/g, "\n");
|
||||||
|
}
|
||||||
return JSON.stringify(output, null, 2);
|
return JSON.stringify(output, null, 2);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return `Error formatting output: ${(error as Error).message}`;
|
return `Error formatting output: ${(error as Error).message}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (typeof output === "string") {
|
||||||
|
return output.replace(/\\n/g, "\n");
|
||||||
|
}
|
||||||
return String(output);
|
return String(output);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -42,11 +54,28 @@ export function RunnerOutputUI({
|
||||||
onClose,
|
onClose,
|
||||||
blockOutputs,
|
blockOutputs,
|
||||||
}: OutputModalProps) {
|
}: OutputModalProps) {
|
||||||
|
const { toast } = useToast();
|
||||||
|
|
||||||
|
const copyOutput = (name: string, output: any) => {
|
||||||
|
const formattedOutput = formatOutput(output);
|
||||||
|
navigator.clipboard.writeText(formattedOutput).then(() => {
|
||||||
|
toast({
|
||||||
|
title: `"${name}" output copied to clipboard!`,
|
||||||
|
duration: 2000,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const adjustTextareaHeight = (textarea: HTMLTextAreaElement) => {
|
||||||
|
textarea.style.height = "auto";
|
||||||
|
textarea.style.height = `${textarea.scrollHeight}px`;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Sheet open={isOpen} onOpenChange={onClose}>
|
<Sheet open={isOpen} onOpenChange={onClose}>
|
||||||
<SheetContent
|
<SheetContent
|
||||||
side="right"
|
side="right"
|
||||||
className="flex h-full w-full flex-col overflow-hidden sm:max-w-[500px]"
|
className="flex h-full w-full flex-col overflow-hidden sm:max-w-[600px]"
|
||||||
>
|
>
|
||||||
<SheetHeader className="px-2 py-2">
|
<SheetHeader className="px-2 py-2">
|
||||||
<SheetTitle className="text-xl">Run Outputs</SheetTitle>
|
<SheetTitle className="text-xl">Run Outputs</SheetTitle>
|
||||||
|
@ -70,11 +99,38 @@ export function RunnerOutputUI({
|
||||||
</Label>
|
</Label>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="rounded-md bg-gray-100 p-2">
|
<div className="group relative rounded-md bg-gray-100 p-2">
|
||||||
|
<Button
|
||||||
|
className="absolute right-1 top-1 z-10 m-1 hidden p-2 group-hover:block"
|
||||||
|
variant="outline"
|
||||||
|
size="icon"
|
||||||
|
onClick={() =>
|
||||||
|
copyOutput(
|
||||||
|
block.hardcodedValues.name || "Unnamed Output",
|
||||||
|
block.result,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
title="Copy Output"
|
||||||
|
>
|
||||||
|
<Clipboard size={18} />
|
||||||
|
</Button>
|
||||||
<Textarea
|
<Textarea
|
||||||
readOnly
|
readOnly
|
||||||
value={formatOutput(block.result ?? "No output yet")}
|
value={formatOutput(block.result ?? "No output yet")}
|
||||||
className="resize-none whitespace-pre-wrap break-words border-none bg-transparent text-sm"
|
className="w-full resize-none whitespace-pre-wrap break-words border-none bg-transparent text-sm"
|
||||||
|
style={{
|
||||||
|
height: "auto",
|
||||||
|
minHeight: "2.5rem",
|
||||||
|
maxHeight: "400px",
|
||||||
|
}}
|
||||||
|
ref={(el) => {
|
||||||
|
if (el) {
|
||||||
|
adjustTextareaHeight(el);
|
||||||
|
if (el.scrollHeight > 400) {
|
||||||
|
el.style.height = "400px";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue