From 14a0669c992adead98719eccfc300175768de7ab Mon Sep 17 00:00:00 2001 From: Lucas Oliveira Date: Mon, 17 Jul 2023 13:27:04 -0300 Subject: [PATCH] Normailzed code modals --- .../components/codeTabsComponent/index.tsx | 524 +++++++++++++++++ src/frontend/src/index.css | 2 +- src/frontend/src/modals/ApiModal/index.tsx | 553 +----------------- .../modals/formModal/chatMessage/index.tsx | 20 +- 4 files changed, 565 insertions(+), 534 deletions(-) create mode 100644 src/frontend/src/components/codeTabsComponent/index.tsx diff --git a/src/frontend/src/components/codeTabsComponent/index.tsx b/src/frontend/src/components/codeTabsComponent/index.tsx new file mode 100644 index 000000000..744e0e171 --- /dev/null +++ b/src/frontend/src/components/codeTabsComponent/index.tsx @@ -0,0 +1,524 @@ +import { Check, Clipboard, Download } from "lucide-react"; +import { useState } from "react"; +import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; +import { oneDark } from "react-syntax-highlighter/dist/cjs/styles/prism"; +import AccordionComponent from "../../components/AccordionComponent"; +import ShadTooltip from "../../components/ShadTooltipComponent"; +import CodeAreaComponent from "../../components/codeAreaComponent"; +import Dropdown from "../../components/dropdownComponent"; +import FloatComponent from "../../components/floatComponent"; +import InputComponent from "../../components/inputComponent"; +import InputFileComponent from "../../components/inputFileComponent"; +import InputListComponent from "../../components/inputListComponent"; +import IntComponent from "../../components/intComponent"; +import PromptAreaComponent from "../../components/promptComponent"; +import TextAreaComponent from "../../components/textAreaComponent"; +import ToggleShadComponent from "../../components/toggleShadComponent"; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "../../components/ui/table"; +import { + Tabs, + TabsContent, + TabsList, + TabsTrigger, +} from "../../components/ui/tabs"; +import { FlowType } from "../../types/flow/index"; +import { classNames } from "../../utils"; + +export default function CodeTabsComponent({ + flow, + tabs, + activeTab, + setActiveTab, + tweaks: { tweak, tweaksList, buildContent, getValue, buildTweakObject }, +}: { + flow?: FlowType; + tabs: any; + activeTab: string; + setActiveTab: any; + tweaks?: any; +}) { + const [isCopied, setIsCopied] = useState(false); + const [openAccordion, setOpenAccordion] = useState([]); + + const copyToClipboard = () => { + if (!navigator.clipboard || !navigator.clipboard.writeText) { + return; + } + + navigator.clipboard.writeText(tabs[activeTab].code).then(() => { + setIsCopied(true); + + setTimeout(() => { + setIsCopied(false); + }, 2000); + }); + }; + + const downloadAsFile = () => { + const fileExtension = tabs[activeTab].language || ".txt"; + const suggestedFileName = `${"generated-code."}${fileExtension}`; + const fileName = window.prompt("Enter the file name.", suggestedFileName); + + if (!fileName) { + // user pressed cancel on prompt + return; + } + + const blob = new Blob([tabs[activeTab].code], { type: "text/plain" }); + const url = URL.createObjectURL(blob); + const link = document.createElement("a"); + link.download = fileName; + link.href = url; + link.style.display = "none"; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + URL.revokeObjectURL(url); + }; + + function openAccordions() { + let accordionsToOpen = []; + tweak.current.forEach((el) => { + Object.keys(el).forEach((key) => { + if (Object.keys(el[key]).length > 0) { + accordionsToOpen.push(key); + setOpenAccordion(accordionsToOpen); + } + }); + }); + + if (accordionsToOpen.length == 0) { + setOpenAccordion([]); + } + } + return ( + { + setActiveTab(value); + if (value === "3") { + openAccordions(); + } + }} + > +
+ + {tabs.map((tab, index) => ( + + {tab.name} + + ))} + + {Number(activeTab) < 3 && ( +
+ + +
+ )} +
+ + {tabs.map((tab, index) => ( + + {index < 3 ? ( + + {tab.code} + + ) : index === 3 ? ( + <> +
+
+ {flow["data"]["nodes"].map((t: any, index) => ( +
+ {tweaksList.current.includes(t["data"]["id"]) && ( + +
+ + + + + PARAM + + + VALUE + + + + + {Object.keys(t["data"]["node"]["template"]) + .filter( + (n) => + n.charAt(0) !== "_" && + t.data.node.template[n].show && + (t.data.node.template[n].type === "str" || + t.data.node.template[n].type === + "bool" || + t.data.node.template[n].type === + "float" || + t.data.node.template[n].type === + "code" || + t.data.node.template[n].type === + "prompt" || + t.data.node.template[n].type === + "file" || + t.data.node.template[n].type === "int") + ) + .map((n, i) => { + //console.log(t.data.node.template[n]); + + return ( + + + {n} + + +
+ {t.data.node.template[n].type === + "str" && + !t.data.node.template[n].options ? ( +
+ {t.data.node.template[n] + .list ? ( + {}} + onAddInput={(k) => { + buildTweakObject( + t["data"]["id"], + k, + t.data.node.template[n] + ); + }} + /> + ) : t.data.node.template[n] + .multiline ? ( + +
+ { + buildTweakObject( + t["data"]["id"], + k, + t.data.node + .template[n] + ); + }} + /> +
+
+ ) : ( + { + buildTweakObject( + t["data"]["id"], + k, + t.data.node.template[n] + ); + }} + /> + )} +
+ ) : t.data.node.template[n].type === + "bool" ? ( +
+ {" "} + { + t.data.node.template[ + n + ].value = e; + buildTweakObject( + t["data"]["id"], + e, + t.data.node.template[n] + ); + }} + size="small" + disabled={false} + /> +
+ ) : t.data.node.template[n].type === + "file" ? ( + +
+ {}} + fileTypes={ + t.data.node.template[n] + .fileTypes + } + suffixes={ + t.data.node.template[n] + .suffixes + } + onFileChange={( + k: any + ) => {}} + > +
+
+ ) : t.data.node.template[n].type === + "float" ? ( +
+ { + buildTweakObject( + t["data"]["id"], + k, + t.data.node.template[n] + ); + }} + /> +
+ ) : t.data.node.template[n].type === + "str" && + t.data.node.template[n] + .options ? ( +
+ { + buildTweakObject( + t["data"]["id"], + k, + t.data.node.template[n] + ); + }} + value={getValue( + t.data.node.template[n] + .value, + t.data, + t.data.node.template[n] + )} + > +
+ ) : t.data.node.template[n].type === + "int" ? ( +
+ { + buildTweakObject( + t["data"]["id"], + k, + t.data.node.template[n] + ); + }} + /> +
+ ) : t.data.node.template[n].type === + "prompt" ? ( + +
+ { + buildTweakObject( + t["data"]["id"], + k, + t.data.node.template[n] + ); + }} + /> +
+
+ ) : t.data.node.template[n].type === + "code" ? ( + +
+ { + buildTweakObject( + t["data"]["id"], + k, + t.data.node.template[n] + ); + }} + /> +
+
+ ) : t.data.node.template[n].type === + "Any" ? ( + "-" + ) : ( +
+ )} +
+
+
+ ); + })} +
+
+
+
+ )} + + {tweaksList.current.length === 0 && ( + <> +
+ No tweaks are available for this flow. +
+ + )} +
+ ))} +
+
+ + ) : null} +
+ ))} +
+ ); +} diff --git a/src/frontend/src/index.css b/src/frontend/src/index.css index 15556b27c..c81038284 100644 --- a/src/frontend/src/index.css +++ b/src/frontend/src/index.css @@ -904,7 +904,7 @@ The cursor: default; property value restores the browser's default cursor style } .api-modal-tabs { - @apply lg:w-full h-full overflow-hidden text-center bg-muted rounded-md border sm:w-[75vw] + @apply lg:w-full h-full flex flex-col overflow-hidden text-center bg-muted rounded-md border sm:w-[75vw] } .api-modal-tablist-div { @apply flex items-center justify-between px-2 diff --git a/src/frontend/src/modals/ApiModal/index.tsx b/src/frontend/src/modals/ApiModal/index.tsx index 1d530ca6d..c4571bf26 100644 --- a/src/frontend/src/modals/ApiModal/index.tsx +++ b/src/frontend/src/modals/ApiModal/index.tsx @@ -11,35 +11,8 @@ import { useState, } from "react"; // import "ace-builds/webpack-resolver"; -import { Check, Clipboard, Code2 } from "lucide-react"; -import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; -import { oneDark } from "react-syntax-highlighter/dist/cjs/styles/prism"; -import AccordionComponent from "../../components/AccordionComponent"; -import ShadTooltip from "../../components/ShadTooltipComponent"; -import CodeAreaComponent from "../../components/codeAreaComponent"; -import Dropdown from "../../components/dropdownComponent"; -import FloatComponent from "../../components/floatComponent"; -import InputComponent from "../../components/inputComponent"; -import InputFileComponent from "../../components/inputFileComponent"; -import InputListComponent from "../../components/inputListComponent"; -import IntComponent from "../../components/intComponent"; -import PromptAreaComponent from "../../components/promptComponent"; -import TextAreaComponent from "../../components/textAreaComponent"; -import ToggleShadComponent from "../../components/toggleShadComponent"; -import { - Table, - TableBody, - TableCell, - TableHead, - TableHeader, - TableRow, -} from "../../components/ui/table"; -import { - Tabs, - TabsContent, - TabsList, - TabsTrigger, -} from "../../components/ui/tabs"; +import { Code2 } from "lucide-react"; +import CodeTabsComponent from "../../components/codeTabsComponent"; import { EXPORT_CODE_DIALOG, getCurlCode, @@ -48,7 +21,7 @@ import { } from "../../constants"; import { TabsContext } from "../../contexts/tabsContext"; import { FlowType } from "../../types/flow/index"; -import { buildTweaks, classNames } from "../../utils"; +import { buildTweaks } from "../../utils"; import BaseModal from "../baseModal"; const ApiModal = forwardRef( @@ -62,27 +35,11 @@ const ApiModal = forwardRef( }, ref ) => { - const [activeTab, setActiveTab] = useState("0"); const [open, setOpen] = useState(false); - const [isCopied, setIsCopied] = useState(false); - const [openAccordion, setOpenAccordion] = useState([]); + const [activeTab, setActiveTab] = useState("0"); const tweak = useRef([]); const tweaksList = useRef([]); const { setTweak, getTweak, tabsState } = useContext(TabsContext); - - const copyToClipboard = () => { - if (!navigator.clipboard || !navigator.clipboard.writeText) { - return; - } - - navigator.clipboard.writeText(tabs[activeTab].code).then(() => { - setIsCopied(true); - - setTimeout(() => { - setIsCopied(false); - }, 2000); - }); - }; const pythonApiCode = getPythonApiCode(flow, tweak.current, tabsState); const curl_code = getCurlCode(flow, tweak.current, tabsState); const pythonCode = getPythonCode(flow, tweak.current, tabsState); @@ -92,6 +49,7 @@ const ApiModal = forwardRef( name: "cURL", mode: "bash", image: "https://curl.se/logo/curl-symbol-transparent.png", + language: "sh", code: curl_code, }, { @@ -99,12 +57,14 @@ const ApiModal = forwardRef( mode: "python", image: "https://images.squarespace-cdn.com/content/v1/5df3d8c5d2be5962e4f87890/1628015119369-OY4TV3XJJ53ECO0W2OLQ/Python+API+Training+Logo.png?format=1000w", + language: "py", code: pythonApiCode, }, { name: "Python Code", mode: "python", image: "https://cdn-icons-png.flaticon.com/512/5968/5968350.png", + language: "py", code: pythonCode, }, ]); @@ -133,6 +93,7 @@ const ApiModal = forwardRef( name: "cURL", mode: "bash", image: "https://curl.se/logo/curl-symbol-transparent.png", + language: "sh", code: curl_code, }, { @@ -140,11 +101,13 @@ const ApiModal = forwardRef( mode: "python", image: "https://images.squarespace-cdn.com/content/v1/5df3d8c5d2be5962e4f87890/1628015119369-OY4TV3XJJ53ECO0W2OLQ/Python+API+Training+Logo.png?format=1000w", + language: "py", code: pythonApiCode, }, { name: "Python Code", mode: "python", + language: "py", image: "https://cdn-icons-png.flaticon.com/512/5968/5968350.png", code: pythonCode, }, @@ -152,6 +115,7 @@ const ApiModal = forwardRef( name: "Tweaks", mode: "python", image: "https://cdn-icons-png.flaticon.com/512/5968/5968350.png", + language: "py", code: pythonCode, }, ]); @@ -161,6 +125,7 @@ const ApiModal = forwardRef( name: "cURL", mode: "bash", image: "https://curl.se/logo/curl-symbol-transparent.png", + language: "sh", code: curl_code, }, { @@ -168,12 +133,14 @@ const ApiModal = forwardRef( mode: "python", image: "https://images.squarespace-cdn.com/content/v1/5df3d8c5d2be5962e4f87890/1628015119369-OY4TV3XJJ53ECO0W2OLQ/Python+API+Training+Logo.png?format=1000w", + language: "py", code: pythonApiCode, }, { name: "Python Code", mode: "python", image: "https://cdn-icons-png.flaticon.com/512/5968/5968350.png", + language: "py", code: pythonCode, }, ]); @@ -206,7 +173,6 @@ const ApiModal = forwardRef( return self.indexOf(value) === index; }); } - function buildTweakObject(tw, changes, template) { if (template.type === "float") { changes = parseFloat(changes); @@ -286,22 +252,6 @@ const ApiModal = forwardRef( return returnValue; } - function openAccordions() { - let accordionsToOpen = []; - tweak.current.forEach((el) => { - Object.keys(el).forEach((key) => { - if (Object.keys(el[key]).length > 0) { - accordionsToOpen.push(key); - setOpenAccordion(accordionsToOpen); - } - }); - }); - - if (accordionsToOpen.length == 0) { - setOpenAccordion([]); - } - } - return ( {children} @@ -314,470 +264,19 @@ const ApiModal = forwardRef( /> - { - setActiveTab(value); - if (value === "3") { - openAccordions(); - } + -
- - {tabs.map((tab, index) => ( - - {tab.name} - - ))} - - {Number(activeTab) < 3 && ( -
- -
- )} -
- - {tabs.map((tab, index) => ( - - {index < 3 ? ( - - {tab.code} - - ) : index === 3 ? ( - <> -
-
- {flow["data"]["nodes"].map((t: any, index) => ( -
- {tweaksList.current.includes(t["data"]["id"]) && ( - -
- - - - - PARAM - - - VALUE - - - - - {Object.keys( - t["data"]["node"]["template"] - ) - .filter( - (n) => - n.charAt(0) !== "_" && - t.data.node.template[n].show && - (t.data.node.template[n].type === - "str" || - t.data.node.template[n].type === - "bool" || - t.data.node.template[n].type === - "float" || - t.data.node.template[n].type === - "code" || - t.data.node.template[n].type === - "prompt" || - t.data.node.template[n].type === - "file" || - t.data.node.template[n].type === - "int") - ) - .map((n, i) => { - //console.log(t.data.node.template[n]); - - return ( - - - {n} - - -
- {t.data.node.template[n] - .type === "str" && - !t.data.node.template[n] - .options ? ( -
- {t.data.node.template[n] - .list ? ( - {}} - onAddInput={(k) => { - buildTweakObject( - t["data"]["id"], - k, - t.data.node - .template[n] - ); - }} - /> - ) : t.data.node.template[ - n - ].multiline ? ( - -
- { - buildTweakObject( - t["data"][ - "id" - ], - k, - t.data.node - .template[n] - ); - }} - /> -
-
- ) : ( - { - buildTweakObject( - t["data"]["id"], - k, - t.data.node - .template[n] - ); - }} - /> - )} -
- ) : t.data.node.template[n] - .type === "bool" ? ( -
- {" "} - { - t.data.node.template[ - n - ].value = e; - buildTweakObject( - t["data"]["id"], - e, - t.data.node - .template[n] - ); - }} - size="small" - disabled={false} - /> -
- ) : t.data.node.template[n] - .type === "file" ? ( - -
- {}} - fileTypes={ - t.data.node - .template[n] - .fileTypes - } - suffixes={ - t.data.node - .template[n] - .suffixes - } - onFileChange={( - k: any - ) => {}} - > -
-
- ) : t.data.node.template[n] - .type === "float" ? ( -
- { - buildTweakObject( - t["data"]["id"], - k, - t.data.node - .template[n] - ); - }} - /> -
- ) : t.data.node.template[n] - .type === "str" && - t.data.node.template[n] - .options ? ( -
- { - buildTweakObject( - t["data"]["id"], - k, - t.data.node - .template[n] - ); - }} - value={getValue( - t.data.node.template[ - n - ].value, - t.data, - t.data.node.template[ - n - ] - )} - > -
- ) : t.data.node.template[n] - .type === "int" ? ( -
- { - buildTweakObject( - t["data"]["id"], - k, - t.data.node - .template[n] - ); - }} - /> -
- ) : t.data.node.template[n] - .type === "prompt" ? ( - -
- { - buildTweakObject( - t["data"]["id"], - k, - t.data.node - .template[n] - ); - }} - /> -
-
- ) : t.data.node.template[n] - .type === "code" ? ( - -
- { - buildTweakObject( - t["data"]["id"], - k, - t.data.node - .template[n] - ); - }} - /> -
-
- ) : t.data.node.template[n] - .type === "Any" ? ( - "-" - ) : ( -
- )} -
-
-
- ); - })} -
-
-
-
- )} - - {tweaksList.current.length === 0 && ( - <> -
- No tweaks are available for this flow. -
- - )} -
- ))} -
-
- - ) : null} -
- ))} -
+ />
); diff --git a/src/frontend/src/modals/formModal/chatMessage/index.tsx b/src/frontend/src/modals/formModal/chatMessage/index.tsx index 953aed530..31b389efb 100644 --- a/src/frontend/src/modals/formModal/chatMessage/index.tsx +++ b/src/frontend/src/modals/formModal/chatMessage/index.tsx @@ -8,11 +8,11 @@ import remarkMath from "remark-math"; import MaleTechnology from "../../../assets/male-technologist.png"; import Robot from "../../../assets/robot.png"; import SanitizedHTMLWrapper from "../../../components/SanitizedHTMLWrapper"; +import CodeTabsComponent from "../../../components/codeTabsComponent"; import { THOUGHTS_ICON } from "../../../constants"; import { ChatMessageType } from "../../../types/chat"; import { classNames } from "../../../utils"; import FileCard from "../fileComponent"; -import { CodeBlock } from "./codeBlock"; export default function ChatMessage({ chat, lockChat, @@ -110,11 +110,19 @@ export default function ChatMessage({ ); return !inline ? ( - {}} /> ) : (