diff --git a/src/frontend/package-lock.json b/src/frontend/package-lock.json index acf9a1865..1bd962f0a 100644 --- a/src/frontend/package-lock.json +++ b/src/frontend/package-lock.json @@ -37,7 +37,7 @@ "base64-js": "^1.5.1", "class-variance-authority": "^0.6.0", "clsx": "^1.2.1", - "dompurify": "^3.0.3", + "dompurify": "^3.0.4", "esbuild": "^0.17.18", "lodash": "^4.17.21", "lucide-react": "^0.233.0", @@ -5142,9 +5142,9 @@ } }, "node_modules/dompurify": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.3.tgz", - "integrity": "sha512-axQ9zieHLnAnHh0sfAamKYiqXMJAVwu+LM/alQ7WDagoWessyWvMSFyW65CqF3owufNu8HBcE4cM2Vflu7YWcQ==" + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.4.tgz", + "integrity": "sha512-ae0mA+Qiqp6C29pqZX3fQgK+F91+F7wobM/v8DRzDqJdZJELXiFUx4PP4pK/mzUS0xkiSEx3Ncd9gr69jg3YsQ==" }, "node_modules/electron-to-chromium": { "version": "1.4.440", diff --git a/src/frontend/package.json b/src/frontend/package.json index b856cd5b6..aab383997 100644 --- a/src/frontend/package.json +++ b/src/frontend/package.json @@ -32,7 +32,7 @@ "base64-js": "^1.5.1", "class-variance-authority": "^0.6.0", "clsx": "^1.2.1", - "dompurify": "^3.0.3", + "dompurify": "^3.0.4", "esbuild": "^0.17.18", "lodash": "^4.17.21", "lucide-react": "^0.233.0", diff --git a/src/frontend/src/components/ShadTooltipComponent/index.tsx b/src/frontend/src/components/ShadTooltipComponent/index.tsx index 362be6842..e106eb4f6 100644 --- a/src/frontend/src/components/ShadTooltipComponent/index.tsx +++ b/src/frontend/src/components/ShadTooltipComponent/index.tsx @@ -1,4 +1,4 @@ -import { ShadTooltipProps } from "../../types/components"; +import { RadialProgressType, ShadToolTipType } from "../../types/components"; import { Tooltip, TooltipContent, @@ -6,20 +6,20 @@ import { TooltipTrigger, } from "../ui/tooltip"; -const ShadTooltip = ({ - delayDuration = 500, - side, +export default function ShadTooltip({ content, + side, + asChild = true, children, - style, -}: ShadTooltipProps) => { + delayDuration +}: ShadToolTipType) { + return ( - {children} + {children} ); -}; +} -export default ShadTooltip; diff --git a/src/frontend/src/constants.tsx b/src/frontend/src/constants.tsx index d48bcdf2e..60d63d974 100644 --- a/src/frontend/src/constants.tsx +++ b/src/frontend/src/constants.tsx @@ -523,3 +523,9 @@ export const NOUNS: string[] = [ * */ export const USER_PROJECTS_HEADER = "My Collection"; +/** + * CSS for highlight HTML + * @constant + * + */ +export const HIGHLIGH_CSS = "block pl-3 pr-14 py-2 w-full h-full text-sm outline-0 border-0 break-all"; \ No newline at end of file diff --git a/src/frontend/src/modals/codeAreaModal/index.tsx b/src/frontend/src/modals/codeAreaModal/index.tsx index df4e015a6..a04d5dbba 100644 --- a/src/frontend/src/modals/codeAreaModal/index.tsx +++ b/src/frontend/src/modals/codeAreaModal/index.tsx @@ -102,7 +102,7 @@ export default function CodeAreaModal({ return ( - + Edit Code @@ -115,7 +115,7 @@ export default function CodeAreaModal({ {CODE_PROMPT_DIALOG_SUBTITLE} -
+
{ setCode(value); }} - className="h-[300px] w-full rounded-lg border-[1px] border-ring custom-scroll " + className="w-full rounded-lg h-full custom-scroll border-[1px] border-gray-300 dark:border-gray-600" />
diff --git a/src/frontend/src/modals/genericModal/index.tsx b/src/frontend/src/modals/genericModal/index.tsx index 8be3f8aaa..f6f8434cc 100644 --- a/src/frontend/src/modals/genericModal/index.tsx +++ b/src/frontend/src/modals/genericModal/index.tsx @@ -1,4 +1,4 @@ -import { useContext, useRef, useState } from "react"; +import { useContext, useRef, useState, useEffect } from "react"; import { PopUpContext } from "../../contexts/popUpContext"; import { darkContext } from "../../contexts/darkContext"; import { postValidatePrompt } from "../../controllers/API"; @@ -14,9 +14,31 @@ import { } from "../../components/ui/dialog"; import { Button } from "../../components/ui/button"; import { Textarea } from "../../components/ui/textarea"; -import { PROMPT_DIALOG_SUBTITLE, TEXT_DIALOG_SUBTITLE } from "../../constants"; +import { + HIGHLIGH_CSS, + PROMPT_DIALOG_SUBTITLE, + TEXT_DIALOG_SUBTITLE, +} from "../../constants"; import { FileText } from "lucide-react"; import { APIClassType } from "../../types/api"; +import { + INVALID_CHARACTERS, + TypeModal, + classNames, + getRandomKeyByssmm, + regexHighlight, + varHighlightHTML, +} from "../../utils"; +import { Badge } from "../../components/ui/badge"; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "../../components/ui/tooltip"; +import ShadTooltip from "../../components/ShadTooltipComponent"; +import { set } from "lodash"; +import DOMPurify from "dompurify"; export default function GenericModal({ field_name = "", @@ -41,7 +63,10 @@ export default function GenericModal({ const [myModalTitle] = useState(modalTitle); const [myModalType] = useState(type); const [open, setOpen] = useState(true); - const [myValue, setMyValue] = useState(value); + const [inputValue, setInputValue] = useState(value); + const [isEdit, setIsEdit] = useState(true); + const [wordsHighlightInvalid, setWordsHighlightInvalid] = useState([]); + const [wordsHighlight, setWordsHighlight] = useState([]); const { dark } = useContext(darkContext); const { setErrorData, setSuccessData } = useContext(alertContext); const { closePopUp, setCloseEdit } = useContext(PopUpContext); @@ -54,10 +79,108 @@ export default function GenericModal({ } } + function checkVariables(valueToCheck) { + const regex = /\{([^{}]+)\}/g; + const matches = []; + let match; + while ((match = regex.exec(valueToCheck))) { + matches.push(`{${match[1]}}`); + } + + let invalid_chars = []; + let fixed_variables = []; + let input_variables = matches; + for (let variable of input_variables) { + let new_var = variable; + for (let char of INVALID_CHARACTERS) { + if (variable.includes(char)) { + invalid_chars.push(new_var); + } + } + fixed_variables.push(new_var); + if (new_var !== variable) { + const index = input_variables.indexOf(variable); + if (index !== -1) { + input_variables.splice(index, 1, new_var); + } + } + } + + const filteredWordsHighlight = matches.filter( + (word) => !invalid_chars.includes(word) + ); + + setWordsHighlightInvalid(invalid_chars); + setWordsHighlight(filteredWordsHighlight); + } + + useEffect(() => { + if (type == TypeModal.PROMPT && inputValue && inputValue != "") { + checkVariables(inputValue); + } + }, []); + + const coloredContent = (inputValue || "") + .replace(//g, ">") + .replace(regexHighlight, varHighlightHTML({ name: "$1" })) + .replace(/\n/g, "
"); + + const TextAreaContentView = () => { + return ( +
{ + setIsEdit(true); + }} + /> + ); + }; + + function validatePrompt(closeModal: boolean) { + postValidatePrompt(field_name, inputValue, nodeClass) + .then((apiReturn) => { + if (apiReturn.data) { + setNodeClass(apiReturn.data.frontend_node); + setModalOpen(closeModal); + + let inputVariables = apiReturn.data.input_variables; + if (inputVariables.length === 0) { + setIsEdit(true); + setErrorData({ + title: + "The template you are attempting to use does not contain any variables for data entry.", + }); + } else { + setIsEdit(false); + setSuccessData({ + title: "Prompt is ready", + }); + setModalOpen(closeModal); + setValue(inputValue); + } + } else { + setIsEdit(true); + setErrorData({ + title: "Something went wrong, please try again", + }); + } + }) + .catch((error) => { + setIsEdit(true); + return setErrorData({ + title: "There is something wrong with this prompt, please review it", + list: [error.response.data.detail], + }); + }); + } + return ( - + {myModalTitle} @@ -83,17 +206,78 @@ export default function GenericModal({ -
-