feat: add detailed view for prompt component (#7036)

* Changed prompt component to show the prompt with more details

* Fix classes for edit node

* Fixed test

---------

Co-authored-by: Rodrigo Nader <rodrigosilvanader@gmail.com>
This commit is contained in:
Lucas Oliveira 2025-03-14 16:49:06 -03:00 • committed by GitHub
commit b6333d0e49
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 36 additions and 81 deletions

View file

@ -1,48 +1,18 @@
import { GRADIENT_CLASS } from "@/constants/constants"; import SanitizedHTMLWrapper from "@/components/common/sanitizedHTMLWrapper";
import { regexHighlight } from "@/constants/constants";
import PromptModal from "@/modals/promptModal"; import PromptModal from "@/modals/promptModal";
import { cn } from "../../../../../utils/utils"; import { cn } from "../../../../../utils/utils";
import IconComponent from "../../../../common/genericIconComponent";
import { Button } from "../../../../ui/button"; import { Button } from "../../../../ui/button";
import { getPlaceholder } from "../../helpers/get-placeholder-disabled"; import { getPlaceholder } from "../../helpers/get-placeholder-disabled";
import { InputProps, PromptAreaComponentType } from "../../types"; import { InputProps, PromptAreaComponentType } from "../../types";
const promptContentClasses = { const promptContentClasses = {
base: "overflow-hidden text-clip whitespace-nowrap bg-background", base: "overflow-hidden text-clip whitespace-nowrap bg-background h-fit max-h-28",
editNode: "input-edit-node input-dialog", editNode: "input-edit-node input-dialog py-2",
normal: "primary-input text-muted-foreground", normal: "primary-input text-primary",
disabled: "disabled-state", disabled: "disabled-state",
}; };
const externalLinkIconClasses = {
gradient: ({
disabled,
editNode,
}: {
disabled: boolean;
editNode: boolean;
}) =>
disabled
? ""
: editNode
? "gradient-fade-input-edit-node "
: "gradient-fade-input ",
background: ({
disabled,
editNode,
}: {
disabled: boolean;
editNode: boolean;
}) =>
disabled
? ""
: editNode
? "background-fade-input-edit-node "
: "background-fade-input",
icon: "icons-parameters-comp absolute right-3 h-4 w-4 shrink-0",
editNodeTop: "top-[0.375rem]",
normalTop: "top-2.5",
};
export default function PromptAreaComponent({ export default function PromptAreaComponent({
field_name, field_name,
nodeClass, nodeClass,
@ -54,6 +24,24 @@ export default function PromptAreaComponent({
id = "", id = "",
readonly = false, readonly = false,
}: InputProps<string, PromptAreaComponentType>): JSX.Element { }: InputProps<string, PromptAreaComponentType>): JSX.Element {
const coloredContent = (typeof value === "string" ? value : "")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(regexHighlight, (match, p1, p2) => {
// Decide which group was matched. If p1 is not undefined, do nothing
// we don't want to change the text. If p2 is not undefined, then we
// have a variable, so we should highlight it.
// ! This will not work with multiline or indented json yet
if (p1 !== undefined) {
return match;
} else if (p2 !== undefined) {
return `<span class="chat-message-highlight">{${p2}}</span>`;
}
return match;
})
.replace(/\n/g, "<br />");
const renderPromptText = () => ( const renderPromptText = () => (
<span <span
id={id} id={id}
@ -64,50 +52,20 @@ export default function PromptAreaComponent({
disabled && !editNode && promptContentClasses.disabled, disabled && !editNode && promptContentClasses.disabled,
)} )}
> >
{value !== "" {value !== "" ? (
? value <SanitizedHTMLWrapper
: getPlaceholder(disabled, "Type your prompt here...")} className="m-0 whitespace-pre-wrap p-0 text-xs"
content={coloredContent}
suppressWarning={true}
/>
) : (
<span className="text-sm text-muted-foreground">
{getPlaceholder(disabled, "Type your prompt here...")}
</span>
)}
</span> </span>
); );
const renderExternalLinkIcon = () => (
<>
<div
className={cn(
externalLinkIconClasses.gradient({ disabled, editNode }),
editNode
? externalLinkIconClasses.editNodeTop
: externalLinkIconClasses.normalTop,
)}
style={{
pointerEvents: "none",
background: disabled ? "" : GRADIENT_CLASS,
}}
aria-hidden="true"
/>
<div
className={cn(
externalLinkIconClasses.background({ disabled, editNode }),
editNode
? externalLinkIconClasses.editNodeTop
: externalLinkIconClasses.normalTop,
disabled && "bg-border",
)}
aria-hidden="true"
/>
<IconComponent
name={disabled ? "lock" : "Scan"}
className={cn(
externalLinkIconClasses.icon,
editNode
? externalLinkIconClasses.editNodeTop
: externalLinkIconClasses.normalTop,
disabled ? "text-placeholder-foreground" : "text-foreground",
)}
/>
</>
);
return ( return (
<div className={cn("w-full", disabled && "pointer-events-none")}> <div className={cn("w-full", disabled && "pointer-events-none")}>
<PromptModal <PromptModal
@ -124,10 +82,7 @@ export default function PromptAreaComponent({
className="w-full" className="w-full"
data-testid="button_open_prompt_modal" data-testid="button_open_prompt_modal"
> >
<div className="relative w-full"> <div className="relative w-full">{renderPromptText()}</div>
{renderPromptText()}
{renderExternalLinkIcon()}
</div>
</Button> </Button>
</PromptModal> </PromptModal>
</div> </div>

View file

@ -76,7 +76,7 @@ test(
await page.getByTestId("button_open_prompt_modal").click(); await page.getByTestId("button_open_prompt_modal").click();
await page.getByTestId("edit-prompt-sanitized").first().click(); await page.getByTestId("edit-prompt-sanitized").last().click();
await page await page
.getByTestId("modal-promptarea_prompt_template") .getByTestId("modal-promptarea_prompt_template")