Merge branch 'modalRefactor' into python_custom_node_component

This commit is contained in:
Lucas Oliveira 2023-07-16 17:09:56 -03:00
commit 8e6e2e9708
30 changed files with 1625 additions and 1894 deletions

View file

@ -147,9 +147,9 @@
}
},
"node_modules/@babel/compat-data": {
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.6.tgz",
"integrity": "sha512-29tfsWTq2Ftu7MXmimyC0C5FDZv5DYxOZkh3XD3+QW4V/BYuv/LyEsjj3c0hqedEaDt6DBfDvexMKU8YevdqFg==",
"version": "7.22.9",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz",
"integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==",
"engines": {
"node": ">=6.9.0"
}
@ -194,10 +194,18 @@
"node": ">=6.9.0"
}
},
"node_modules/@babel/core/node_modules/@nicolo-ribaudo/semver-v6": {
"version": "6.3.3",
"resolved": "https://registry.npmjs.org/@nicolo-ribaudo/semver-v6/-/semver-v6-6.3.3.tgz",
"integrity": "sha512-3Yc1fUTs69MG/uZbJlLSI3JISMn2UV2rg+1D/vROUqZyh3l6iYHCs7GMp+M40ZD7yOdDbYjJcU1oTJhrc+dGKg==",
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/@babel/generator": {
"version": "7.22.7",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.7.tgz",
"integrity": "sha512-p+jPjMG+SI8yvIaxGgeW24u7q9+5+TGpZh8/CuB7RhBKd7RCy8FayNEFNNKrNK/eUcY/4ExQqLmyrvBXKsIcwQ==",
"version": "7.22.9",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.9.tgz",
"integrity": "sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw==",
"dependencies": {
"@babel/types": "^7.22.5",
"@jridgewell/gen-mapping": "^0.3.2",
@ -209,15 +217,15 @@
}
},
"node_modules/@babel/helper-compilation-targets": {
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.6.tgz",
"integrity": "sha512-534sYEqWD9VfUm3IPn2SLcH4Q3P86XL+QvqdC7ZsFrzyyPF3T4XGiVghF6PTYNdWg6pXuoqXxNQAhbYeEInTzA==",
"version": "7.22.9",
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.9.tgz",
"integrity": "sha512-7qYrNM6HjpnPHJbopxmb8hSPoZ0gsX8IvUS32JGVoy+pU9e5N0nLr1VjJoR6kA4d9dmGLxNYOjeB8sUDal2WMw==",
"dependencies": {
"@babel/compat-data": "^7.22.6",
"@babel/compat-data": "^7.22.9",
"@babel/helper-validator-option": "^7.22.5",
"@nicolo-ribaudo/semver-v6": "^6.3.3",
"browserslist": "^4.21.9",
"lru-cache": "^5.1.1"
"lru-cache": "^5.1.1",
"semver": "^6.3.1"
},
"engines": {
"node": ">=6.9.0"
@ -226,6 +234,14 @@
"@babel/core": "^7.0.0"
}
},
"node_modules/@babel/helper-compilation-targets/node_modules/semver": {
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/@babel/helper-environment-visitor": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
@ -269,21 +285,21 @@
}
},
"node_modules/@babel/helper-module-transforms": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.5.tgz",
"integrity": "sha512-+hGKDt/Ze8GFExiVHno/2dvG5IdstpzCq0y4Qc9OJ25D4q3pKfiIP/4Vp3/JvhDkLKsDK2api3q3fpIgiIF5bw==",
"version": "7.22.9",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz",
"integrity": "sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==",
"dependencies": {
"@babel/helper-environment-visitor": "^7.22.5",
"@babel/helper-module-imports": "^7.22.5",
"@babel/helper-simple-access": "^7.22.5",
"@babel/helper-split-export-declaration": "^7.22.5",
"@babel/helper-validator-identifier": "^7.22.5",
"@babel/template": "^7.22.5",
"@babel/traverse": "^7.22.5",
"@babel/types": "^7.22.5"
"@babel/helper-split-export-declaration": "^7.22.6",
"@babel/helper-validator-identifier": "^7.22.5"
},
"engines": {
"node": ">=6.9.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0"
}
},
"node_modules/@babel/helper-simple-access": {
@ -1149,12 +1165,12 @@
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
},
"node_modules/@mui/private-theming": {
"version": "5.13.1",
"resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.13.1.tgz",
"integrity": "sha512-HW4npLUD9BAkVppOUZHeO1FOKUJWAwbpy0VQoGe3McUYTlck1HezGHQCfBQ5S/Nszi7EViqiimECVl9xi+/WjQ==",
"version": "5.13.7",
"resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.13.7.tgz",
"integrity": "sha512-qbSr+udcij5F9dKhGX7fEdx2drXchq7htLNr2Qg2Ma+WJ6q0ERlEqGSBiPiVDJkptcjeVL4DGmcf1wl5+vD4EA==",
"dependencies": {
"@babel/runtime": "^7.21.0",
"@mui/utils": "^5.13.1",
"@babel/runtime": "^7.22.5",
"@mui/utils": "^5.13.7",
"prop-types": "^15.8.1"
},
"engines": {
@ -1175,9 +1191,9 @@
}
},
"node_modules/@mui/private-theming/node_modules/@babel/runtime": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.5.tgz",
"integrity": "sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==",
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz",
"integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==",
"dependencies": {
"regenerator-runtime": "^0.13.11"
},
@ -1185,6 +1201,33 @@
"node": ">=6.9.0"
}
},
"node_modules/@mui/private-theming/node_modules/@mui/utils": {
"version": "5.13.7",
"resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.13.7.tgz",
"integrity": "sha512-/3BLptG/q0u36eYED7Nhf4fKXmcKb6LjjT7ZMwhZIZSdSxVqDqSTmATW3a56n3KEPQUXCU9TpxAfCBQhs6brVA==",
"dependencies": {
"@babel/runtime": "^7.22.5",
"@types/prop-types": "^15.7.5",
"@types/react-is": "^18.2.1",
"prop-types": "^15.8.1",
"react-is": "^18.2.0"
},
"engines": {
"node": ">=12.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/mui"
},
"peerDependencies": {
"react": "^17.0.0 || ^18.0.0"
}
},
"node_modules/@mui/private-theming/node_modules/react-is": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
},
"node_modules/@mui/styled-engine": {
"version": "5.13.2",
"resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.13.2.tgz",
@ -1217,9 +1260,9 @@
}
},
"node_modules/@mui/styled-engine/node_modules/@babel/runtime": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.5.tgz",
"integrity": "sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==",
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz",
"integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==",
"dependencies": {
"regenerator-runtime": "^0.13.11"
},
@ -1272,9 +1315,9 @@
}
},
"node_modules/@mui/system/node_modules/@babel/runtime": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.5.tgz",
"integrity": "sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==",
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz",
"integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==",
"dependencies": {
"regenerator-runtime": "^0.13.11"
},
@ -1323,9 +1366,9 @@
}
},
"node_modules/@mui/utils/node_modules/@babel/runtime": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.5.tgz",
"integrity": "sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==",
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz",
"integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==",
"dependencies": {
"regenerator-runtime": "^0.13.11"
},
@ -1338,14 +1381,6 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
},
"node_modules/@nicolo-ribaudo/semver-v6": {
"version": "6.3.3",
"resolved": "https://registry.npmjs.org/@nicolo-ribaudo/semver-v6/-/semver-v6-6.3.3.tgz",
"integrity": "sha512-3Yc1fUTs69MG/uZbJlLSI3JISMn2UV2rg+1D/vROUqZyh3l6iYHCs7GMp+M40ZD7yOdDbYjJcU1oTJhrc+dGKg==",
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@ -3542,7 +3577,7 @@
"version": "16.18.12",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.12.tgz",
"integrity": "sha512-vzLe5NaNMjIE3mcddFVGlAXN1LEWueUsMsOJWaT6wWMJGyljHAWHznqfnKUQWGzu7TLPrGvWdNAsvQYW+C0xtw==",
"devOptional": true
"dev": true
},
"node_modules/@types/parse-json": {
"version": "4.0.0",
@ -5094,9 +5129,9 @@
"integrity": "sha512-ae0mA+Qiqp6C29pqZX3fQgK+F91+F7wobM/v8DRzDqJdZJELXiFUx4PP4pK/mzUS0xkiSEx3Ncd9gr69jg3YsQ=="
},
"node_modules/electron-to-chromium": {
"version": "1.4.440",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.440.tgz",
"integrity": "sha512-r6dCgNpRhPwiWlxbHzZQ/d9swfPaEJGi8ekqRBwQYaR3WmA5VkqQfBWSDDjuJU1ntO+W9tHx8OHV/96Q8e0dVw=="
"version": "1.4.457",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.457.tgz",
"integrity": "sha512-/g3UyNDmDd6ebeWapmAoiyy+Sy2HyJ+/X8KyvNeHfKRFfHaA2W8oF5fxD5F3tjBDcjpwo0iek6YNgxNXDBoEtA=="
},
"node_modules/emoji-regex": {
"version": "8.0.0",
@ -5588,6 +5623,7 @@
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"dev": true,
"hasInstallScript": true,
"optional": true,
"os": [
@ -8025,9 +8061,9 @@
}
},
"node_modules/node-releases": {
"version": "2.0.12",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.12.tgz",
"integrity": "sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ=="
"version": "2.0.13",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
"integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ=="
},
"node_modules/normalize-path": {
"version": "3.0.0",

View file

@ -1,3 +1,4 @@
import { cloneDeep } from "lodash";
import { Info } from "lucide-react";
import React, { useContext, useEffect, useRef, useState } from "react";
import { Handle, Position, useUpdateNodeInternals } from "reactflow";
@ -13,7 +14,6 @@ import PromptAreaComponent from "../../../../components/promptComponent";
import TextAreaComponent from "../../../../components/textAreaComponent";
import ToggleShadComponent from "../../../../components/toggleShadComponent";
import { MAX_LENGTH_TO_SCROLL_TOOLTIP } from "../../../../constants";
import { PopUpContext } from "../../../../contexts/popUpContext";
import { TabsContext } from "../../../../contexts/tabsContext";
import { typesContext } from "../../../../contexts/typesContext";
import { ParameterComponentType } from "../../../../types/components";
@ -32,6 +32,7 @@ export default function ParameterComponent({
left,
id,
data,
setData,
tooltipTitle,
title,
color,
@ -47,7 +48,6 @@ export default function ParameterComponent({
const infoHtml = useRef(null);
const updateNodeInternals = useUpdateNodeInternals();
const [position, setPosition] = useState(0);
const { closePopUp } = useContext(PopUpContext);
const { setTabsState, tabId, save } = useContext(TabsContext);
useEffect(() => {
@ -61,15 +61,16 @@ export default function ParameterComponent({
updateNodeInternals(data.id);
}, [data.id, position, updateNodeInternals]);
useEffect(() => {}, [closePopUp, data.node.template]);
const { reactFlowInstance } = useContext(typesContext);
let disabled =
reactFlowInstance?.getEdges().some((e) => e.targetHandle === id) ?? false;
const [myData, setMyData] = useState(useContext(typesContext).data);
const { data: myData } = useContext(typesContext);
const handleOnNewValue = (newValue: any) => {
data.node.template[name].value = newValue;
let newData = cloneDeep(data);
newData.node.template[name].value = newValue;
setData(newData);
// Set state to pending
setTabsState((prev) => {
return {

View file

@ -5,9 +5,7 @@ import ShadTooltip from "../../components/ShadTooltipComponent";
import Tooltip from "../../components/TooltipComponent";
import { useSSE } from "../../contexts/SSEContext";
import { alertContext } from "../../contexts/alertContext";
import { PopUpContext } from "../../contexts/popUpContext";
import { typesContext } from "../../contexts/typesContext";
import NodeModal from "../../modals/NodeModal";
import NodeToolbarComponent from "../../pages/FlowPage/components/nodeToolbarComponent";
import { NodeDataType } from "../../types/flow";
import {
@ -19,17 +17,16 @@ import {
import ParameterComponent from "./components/parameterComponent";
export default function GenericNode({
data,
data: olddata,
selected,
}: {
data: NodeDataType;
selected: boolean;
}) {
const [data, setData] = useState(olddata);
const { setErrorData } = useContext(alertContext);
const showError = useRef(true);
const { types, deleteNode } = useContext(typesContext);
const { closePopUp, openPopUp } = useContext(PopUpContext);
const { types, deleteNode, reactFlowInstance } = useContext(typesContext);
// any to avoid type conflict
const Icon: any =
nodeIconsLucide[data.type] || nodeIconsLucide[types[data.type]];
@ -37,12 +34,9 @@ export default function GenericNode({
// State for outline color
const { sseData, isBuilding } = useSSE();
const refHtml = useRef(null);
// useEffect(() => {
// if (reactFlowInstance) {
// setParams(Object.values(reactFlowInstance.toObject()));
// }
// }, [save]);
useEffect(() => {
olddata.node = data.node;
}, [data, reactFlowInstance]);
// New useEffect to watch for changes in sseData and update validation status
useEffect(() => {
@ -67,13 +61,12 @@ export default function GenericNode({
deleteNode(data.id);
return;
}
useEffect(() => {}, [closePopUp, data.node.template]);
return (
<>
<NodeToolbar>
<NodeToolbarComponent
data={data}
openPopUp={openPopUp}
setData={setData}
deleteNode={deleteNode}
></NodeToolbarComponent>
</NodeToolbar>
@ -101,15 +94,6 @@ export default function GenericNode({
</ShadTooltip>
</div>
</div>
<div className="round-button-div">
<button
className="relative"
onClick={(event) => {
event.preventDefault();
openPopUp(<NodeModal data={data} />);
}}
></button>
</div>
<div className="round-button-div">
<div>
<Tooltip
@ -198,6 +182,7 @@ export default function GenericNode({
!data.node.template[t].advanced ? (
<ParameterComponent
data={data}
setData={setData}
color={
nodeColors[types[data.node.template[t].type]] ??
nodeColors[data.node.template[t].type] ??
@ -242,21 +227,23 @@ export default function GenericNode({
>
{" "}
</div>
{data.node.base_classes?.length > 0 && (
<ParameterComponent
data={data}
color={nodeColors[types[data.type]] ?? nodeColors.unknown}
title={
data.node.output_types && data.node.output_types.length > 0
? data.node.output_types.join("|")
: data.type
}
tooltipTitle={data.node.base_classes.join("\n")}
id={[data.type, data.id, ...data.node.base_classes].join("|")}
type={data.node.base_classes.join("|")}
left={false}
/>
)}
{/* <div className="px-5 py-2 mt-2 text-center">
Output
</div> */}
<ParameterComponent
data={data}
setData={setData}
color={nodeColors[types[data.type]] ?? nodeColors.unknown}
title={
data.node.output_types && data.node.output_types.length > 0
? data.node.output_types.join("|")
: data.type
}
tooltipTitle={data.node.base_classes.join("\n")}
id={[data.type, data.id, ...data.node.base_classes].join("|")}
type={data.node.base_classes.join("|")}
left={false}
/>
</>
</div>
</div>

View file

@ -16,6 +16,8 @@ export default function AccordionComponent({
open.length === 0 ? "" : getOpenAccordion()
);
console.log(open);
function getOpenAccordion() {
let value = "";
open.forEach((el) => {

View file

@ -62,7 +62,10 @@ export const EditFlowSettings: React.FC<InputProps> = ({
/>
</Label>
<Label>
<span className="font-medium">Description (optional)</span>
<div className="edit-flow-arrangement mt-3">
<span className="font-medium ">Description (optional)</span>
</div>
<Textarea
name="description"
id="description"

View file

@ -1,6 +1,5 @@
import { useContext, useEffect, useState } from "react";
import { PopUpContext } from "../../contexts/popUpContext";
import CodeAreaModal from "../../modals/codeAreaModal/v2";
import { useEffect, useState } from "react";
import CodeAreaModal from "../../modals/codeAreaModal";
import { CodeAreaComponentType } from "../../types/components";
import { ExternalLink } from "lucide-react";
@ -11,11 +10,12 @@ export default function CodeAreaComponent({
disabled,
editNode = false,
nodeClass,
setNodeClass,
dynamic,
setNodeClass,
}: CodeAreaComponentType) {
const [myValue, setMyValue] = useState(value);
const { openPopUp } = useContext(PopUpContext);
const [myValue, setMyValue] = useState(
typeof value == "string" ? value : JSON.stringify(value)
);
useEffect(() => {
if (disabled) {
setMyValue("");
@ -28,61 +28,36 @@ export default function CodeAreaComponent({
}, [value]);
return (
<div
className={
disabled ? "pointer-events-none w-full cursor-not-allowed" : "w-full"
}
>
<div className="flex w-full items-center">
<span
onClick={() => {
openPopUp(
<CodeAreaModal
dynamic={dynamic}
value={myValue}
nodeClass={nodeClass}
setNodeClass={setNodeClass}
setValue={(t: string) => {
setMyValue(t);
onChange(t);
}}
/>
);
}}
className={
editNode
? "input-edit-node input-dialog "
: "input-dialog input-primary " +
(disabled ? "input-disable" : "")
}
>
{myValue !== "" ? myValue : "Type something..."}
</span>
<button
onClick={() => {
openPopUp(
<CodeAreaModal
key={myValue}
dynamic={dynamic}
setNodeClass={setNodeClass}
value={myValue}
nodeClass={nodeClass}
setValue={(t: string) => {
setMyValue(t);
onChange(t);
}}
/>
);
}}
>
<div className={disabled ? "pointer-events-none w-full " : " w-full"}>
<CodeAreaModal
dynamic={dynamic}
value={myValue}
nodeClass={nodeClass}
setNodeClass={setNodeClass}
setValue={(t: string) => {
setMyValue(t);
onChange(t);
}}
>
<div className="flex w-full items-center">
<span
className={
editNode
? "input-edit-node input-dialog"
: (disabled ? " input-disable input-ring " : "") +
" input-primary text-muted-foreground "
}
>
{myValue !== "" ? myValue : "Type something..."}
</span>
{!editNode && (
<ExternalLink
strokeWidth={1.5}
className="ml-3 h-6 w-6 hover:text-accent-foreground"
/>
)}
</button>
</div>
</div>
</CodeAreaModal>
</div>
);
}

View file

@ -1,7 +1,6 @@
import { Listbox, Transition } from "@headlessui/react";
import { Check, ChevronsUpDown } from "lucide-react";
import { Fragment, useContext, useEffect, useState } from "react";
import { PopUpContext } from "../../contexts/popUpContext";
import { Fragment, useEffect, useState } from "react";
import { DropDownComponentType } from "../../types/components";
import { classNames } from "../../utils";
@ -13,15 +12,13 @@ export default function Dropdown({
numberOfOptions = 0,
apiModal = false,
}: DropDownComponentType) {
const { closePopUp } = useContext(PopUpContext);
let [internalValue, setInternalValue] = useState(
value === "" || !value ? "Choose an option" : value
);
useEffect(() => {
setInternalValue(value === "" || !value ? "Choose an option" : value);
}, [closePopUp]);
}, [value]);
return (
<>

View file

@ -1,5 +1,4 @@
import { useContext, useEffect, useState } from "react";
import { PopUpContext } from "../../contexts/popUpContext";
import { useContext, useEffect } from "react";
import { TabsContext } from "../../contexts/tabsContext";
import { FloatComponentType } from "../../types/components";
@ -10,9 +9,7 @@ export default function FloatComponent({
disabled,
editNode = false,
}: FloatComponentType) {
const [myValue, setMyValue] = useState(value ?? "");
const { setDisableCopyPaste } = useContext(TabsContext);
const { closePopUp } = useContext(PopUpContext);
const step = 0.1;
const min = 0;
@ -20,15 +17,10 @@ export default function FloatComponent({
useEffect(() => {
if (disabled) {
setMyValue("");
onChange("");
}
}, [disabled, onChange]);
useEffect(() => {
setMyValue(value);
}, [closePopUp]);
return (
<div className={"w-full " + (disabled ? "float-component-pointer" : "")}>
<input
@ -50,7 +42,7 @@ export default function FloatComponent({
}
}}
max={max}
value={myValue}
value={value ?? ""}
className={
editNode
? "input-edit-node"
@ -60,7 +52,6 @@ export default function FloatComponent({
editNode ? "Number 0 to 1" : "Type a number from zero to one"
}
onChange={(e) => {
setMyValue(e.target.value);
onChange(e.target.value);
}}
/>

View file

@ -6,8 +6,7 @@ import {
Settings2,
Undo,
} from "lucide-react";
import { useContext } from "react";
import { PopUpContext } from "../../../../contexts/popUpContext";
import { useContext, useState } from "react";
import { TabsContext } from "../../../../contexts/tabsContext";
import {
DropdownMenu,
@ -26,8 +25,8 @@ import { Button } from "../../../ui/button";
export const MenuBar = ({ flows, tabId }) => {
const { updateFlow, setTabId, addFlow } = useContext(TabsContext);
const { setErrorData } = useContext(alertContext);
const { openPopUp } = useContext(PopUpContext);
const { undo, redo } = useContext(undoRedoContext);
const [openSettings, setOpenSettings] = useState(false);
const navigate = useNavigate();
@ -69,15 +68,17 @@ export const MenuBar = ({ flows, tabId }) => {
<Plus className="header-menu-options" />
New
</DropdownMenuItem>
<DropdownMenuItem
onClick={() => {
openPopUp(<FlowSettingsModal />);
setOpenSettings(true);
}}
className="cursor-pointer"
>
<Settings2 className="header-menu-options " />
Settings
</DropdownMenuItem>
<DropdownMenuItem
onClick={() => {
undo();
@ -96,32 +97,12 @@ export const MenuBar = ({ flows, tabId }) => {
<Redo className="header-menu-options " />
Redo
</DropdownMenuItem>
{/* <DropdownMenuSeparator /> */}
{/* <DropdownMenuLabel>Projects</DropdownMenuLabel> */}
{/* <DropdownMenuRadioGroup className="max-h-full overflow-scroll"
value={tabId}
onValueChange={(value) => {
setTabId(value);
}}
>
{flows.map((flow, idx) => {
return (
<Link
to={"/flow/" + flow.id}
className="flex w-full items-center"
>
<DropdownMenuRadioItem
value={flow.id}
className="flex-1 w-full inline-block truncate break-words mr-2"
>
{flow.name}
</DropdownMenuRadioItem>
</Link>
);
})}
</DropdownMenuRadioGroup> */}
</DropdownMenuContent>
</DropdownMenu>
<FlowSettingsModal
open={openSettings}
setOpen={setOpenSettings}
></FlowSettingsModal>
</div>
</div>
);

View file

@ -1,5 +1,4 @@
import { useContext, useEffect, useState } from "react";
import { PopUpContext } from "../../contexts/popUpContext";
import { TabsContext } from "../../contexts/tabsContext";
import { InputComponentType } from "../../types/components";
import { classNames } from "../../utils";
@ -12,26 +11,19 @@ export default function InputComponent({
password,
editNode = false,
}: InputComponentType) {
const [myValue, setMyValue] = useState(value ?? "");
const [pwdVisible, setPwdVisible] = useState(false);
const { setDisableCopyPaste } = useContext(TabsContext);
const { closePopUp } = useContext(PopUpContext);
useEffect(() => {
if (disabled) {
setMyValue("");
onChange("");
}
}, [disabled, onChange]);
useEffect(() => {
setMyValue(value ?? "");
}, [closePopUp]);
return (
<div className={disabled ? "input-component-div" : "relative"}>
<input
value={myValue}
value={value}
onFocus={() => {
if (disableCopyPaste) setDisableCopyPaste(true);
}}
@ -40,16 +32,13 @@ export default function InputComponent({
}}
className={classNames(
disabled ? " input-disable " : "",
password && !pwdVisible && myValue !== ""
? " text-clip password "
: "",
password && !pwdVisible && value !== "" ? " text-clip password " : "",
editNode ? " input-edit-node " : " input-primary ",
password && editNode ? "pr-8" : "",
password && !editNode ? "pr-10" : ""
)}
placeholder={password && editNode ? "Key" : "Type something..."}
onChange={(e) => {
setMyValue(e.target.value);
onChange(e.target.value);
}}
/>

View file

@ -1,9 +1,8 @@
import { useContext, useEffect, useState } from "react";
import { useEffect, useState } from "react";
import { InputListComponentType } from "../../types/components";
import _ from "lodash";
import { Plus, X } from "lucide-react";
import { PopUpContext } from "../../contexts/popUpContext";
export default function InputListComponent({
value,
@ -13,7 +12,12 @@ export default function InputListComponent({
onAddInput,
}: InputListComponentType) {
const [inputList, setInputList] = useState(value ?? [""]);
const { closePopUp } = useContext(PopUpContext);
useEffect(() => {
if (value) {
setInputList(value);
}
}, [value]);
useEffect(() => {
if (disabled) {
@ -22,10 +26,6 @@ export default function InputListComponent({
}
}, [disabled, onChange]);
useEffect(() => {
setInputList(value);
}, [closePopUp]);
return (
<div
className={

View file

@ -1,5 +1,4 @@
import { useContext, useEffect, useState } from "react";
import { PopUpContext } from "../../contexts/popUpContext";
import { useContext, useEffect } from "react";
import { TabsContext } from "../../contexts/tabsContext";
import { FloatComponentType } from "../../types/components";
@ -10,22 +9,15 @@ export default function IntComponent({
disabled,
editNode = false,
}: FloatComponentType) {
const [myValue, setMyValue] = useState(value ?? "");
const { setDisableCopyPaste } = useContext(TabsContext);
const min = 0;
const { closePopUp } = useContext(PopUpContext);
useEffect(() => {
if (disabled) {
setMyValue("");
onChange("");
}
}, [disabled, onChange]);
useEffect(() => {
setMyValue(value);
}, [closePopUp]);
return (
<div
className={
@ -66,7 +58,7 @@ export default function IntComponent({
e.target.value = min.toString();
}
}}
value={myValue}
value={value ?? ""}
className={
editNode
? " input-edit-node "
@ -74,7 +66,6 @@ export default function IntComponent({
}
placeholder={editNode ? "Integer number" : "Type an integer number"}
onChange={(e) => {
setMyValue(e.target.value);
onChange(e.target.value);
}}
/>

View file

@ -1,8 +1,6 @@
import { useContext, useEffect, useState } from "react";
import { PopUpContext } from "../../contexts/popUpContext";
import GenericModal from "../../modals/genericModal";
import { TextAreaComponentType } from "../../types/components";
import { TypeModal } from "../../utils";
import { ExternalLink } from "lucide-react";
import { typesContext } from "../../contexts/typesContext";
@ -18,7 +16,6 @@ export default function PromptAreaComponent({
editNode = false,
}: TextAreaComponentType) {
const [myValue, setMyValue] = useState(value);
const { openPopUp } = useContext(PopUpContext);
const { reactFlowInstance } = useContext(typesContext);
useEffect(() => {
if (disabled) {
@ -39,72 +36,31 @@ export default function PromptAreaComponent({
}
}, [value, reactFlowInstance]);
// useEffect(() => {
// if (value !== "" && myValue !== value && reactFlowInstance) {
// // only executed once
// setMyValue(value);
// postValidatePrompt(field_name, value, nodeClass)
// .then((apiReturn) => {
// if (apiReturn.data) {
// setNodeClass(apiReturn.data.frontend_node);
// // need to update reactFlowInstance to re-render the nodes.
// reactFlowInstance.setEdges(
// _.cloneDeep(reactFlowInstance.getEdges())
// );
// }
// })
// .catch((error) => {});
// }
// }, [reactFlowInstance, field_name, myValue, nodeClass, setNodeClass, value]);
return (
<div className={disabled ? "pointer-events-none w-full " : " w-full"}>
<div className="flex w-full items-center">
<span
onClick={() => {
openPopUp(
<GenericModal
type={TypeModal.PROMPT}
value={myValue}
buttonText="Check & Save"
modalTitle="Edit Prompt"
setValue={(t: string) => {
setMyValue(t);
onChange(t);
}}
nodeClass={nodeClass}
setNodeClass={setNodeClass}
/>
);
}}
className={
editNode
? "input-edit-node input-dialog"
: (disabled ? " input-disable text-ring " : "") +
" input-primary text-muted-foreground "
}
>
{myValue !== "" ? myValue : "Type your prompt here"}
</span>
<button
onClick={() => {
openPopUp(
<GenericModal
field_name={field_name}
type={TypeModal.PROMPT}
value={myValue}
buttonText="Check & Save"
modalTitle="Edit Prompt"
setValue={(t: string) => {
setMyValue(t);
onChange(t);
}}
nodeClass={nodeClass}
setNodeClass={setNodeClass}
/>
);
}}
>
<GenericModal
type={"prompt"}
value={myValue}
buttonText="Check & Save"
modalTitle="Edit Prompt"
setValue={(t: string) => {
setMyValue(t);
onChange(t);
}}
nodeClass={nodeClass}
setNodeClass={setNodeClass}
>
<div className="flex w-full items-center">
<span
className={
editNode
? "input-edit-node input-dialog"
: (disabled ? " input-disable text-ring " : "") +
" input-primary text-muted-foreground "
}
>
{myValue !== "" ? myValue : "Type your prompt here..."}
</span>
{!editNode && (
<ExternalLink
strokeWidth={1.5}
@ -114,8 +70,8 @@ export default function PromptAreaComponent({
}
/>
)}
</button>
</div>
</div>
</GenericModal>
</div>
);
}

View file

@ -1,8 +1,6 @@
import { useContext, useEffect, useState } from "react";
import { PopUpContext } from "../../contexts/popUpContext";
import { useContext, useEffect } from "react";
import GenericModal from "../../modals/genericModal";
import { TextAreaComponentType } from "../../types/components";
import { TypeModal } from "../../utils";
import { ExternalLink } from "lucide-react";
import { TabsContext } from "../../contexts/tabsContext";
@ -13,26 +11,19 @@ export default function TextAreaComponent({
disabled,
editNode = false,
}: TextAreaComponentType) {
const [myValue, setMyValue] = useState(value);
const { openPopUp, closePopUp } = useContext(PopUpContext);
const { setDisableCopyPaste } = useContext(TabsContext);
useEffect(() => {
if (disabled) {
setMyValue("");
onChange("");
}
}, [disabled, onChange]);
useEffect(() => {
setMyValue(value);
}, [closePopUp]);
return (
<div className={disabled ? "pointer-events-none w-full " : " w-full"}>
<div className="flex w-full items-center">
<input
value={myValue}
value={value}
onFocus={() => {
setDisableCopyPaste(true);
}}
@ -40,43 +31,37 @@ export default function TextAreaComponent({
setDisableCopyPaste(false);
}}
className={
editNode
(editNode
? " input-edit-node "
: " input-primary " + (disabled ? " input-disable" : "")
: " input-primary " + (disabled ? " input-disable" : "")) +
" w-full"
}
placeholder={"Type something..."}
onChange={(e) => {
setMyValue(e.target.value);
onChange(e.target.value);
}}
/>
<button
onClick={() => {
openPopUp(
<GenericModal
type={TypeModal.TEXT}
buttonText="Finishing Editing"
modalTitle="Edit Text"
value={myValue}
setValue={(t: string) => {
setMyValue(t);
onChange(t);
}}
<div>
<GenericModal
type={"text"}
buttonText="Finishing Editing"
modalTitle="Edit Text"
value={value}
setValue={(t: string) => {
onChange(t);
}}
>
{!editNode && (
<ExternalLink
strokeWidth={1.5}
className={
"icons-parameters-comp" +
(disabled ? " text-ring" : " hover:text-accent-foreground")
}
/>
);
}}
>
{!editNode && (
<ExternalLink
strokeWidth={1.5}
className={
"icons-parameters-comp" +
(disabled ? " text-ring" : " hover:text-accent-foreground")
}
/>
)}
</button>
)}
</GenericModal>
</div>
</div>
</div>
);

View file

@ -212,11 +212,11 @@ The cursor: default; property value restores the browser's default cursor style
@apply focus:placeholder-transparent focus:ring-ring focus:border-ring
}
.input-primary {
@apply bg-background block border-border form-input px-3 placeholder:text-muted-foreground rounded-md shadow-sm sm:text-sm truncate w-full;
@apply bg-background text-left block border-border form-input px-3 placeholder:text-muted-foreground rounded-md shadow-sm sm:text-sm truncate w-full;
}
.input-edit-node{
@apply input-primary border-border placeholder:text-center pt-0.5 pb-0.5 text-center
@apply input-primary border-border pt-0.5 pb-0.5
}
.input-search{
@apply input-primary pr-7 mx-2
@ -904,7 +904,7 @@ The cursor: default; property value restores the browser's default cursor style
}
.api-modal-tabs {
@apply w-full h-full overflow-hidden text-center bg-muted rounded-md border
@apply lg:w-full h-full overflow-hidden text-center bg-muted rounded-md border sm:w-[75vw]
}
.api-modal-tablist-div {
@apply flex items-center justify-between px-2

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,6 @@
import { cloneDeep } from "lodash";
import { Variable } from "lucide-react";
import { useContext, useRef, useState } from "react";
import { ReactNode, forwardRef, useContext, useEffect, useState } from "react";
import CodeAreaComponent from "../../components/codeAreaComponent";
import Dropdown from "../../components/dropdownComponent";
import FloatComponent from "../../components/floatComponent";
@ -12,15 +13,6 @@ import TextAreaComponent from "../../components/textAreaComponent";
import ToggleShadComponent from "../../components/toggleShadComponent";
import { Badge } from "../../components/ui/badge";
import { Button } from "../../components/ui/button";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "../../components/ui/dialog";
import {
Table,
TableBody,
@ -29,313 +21,307 @@ import {
TableHeader,
TableRow,
} from "../../components/ui/table";
import { PopUpContext } from "../../contexts/popUpContext";
import { TabsContext } from "../../contexts/tabsContext";
import { typesContext } from "../../contexts/typesContext";
import { NodeDataType } from "../../types/flow";
import { classNames, limitScrollFieldsModal } from "../../utils";
import BaseModal from "../baseModal";
export default function EditNodeModal({ data }: { data: NodeDataType }) {
const [open, setOpen] = useState(true);
const [nodeLength, setNodeLength] = useState(
Object.keys(data.node.template).filter(
(t) =>
t.charAt(0) !== "_" &&
data.node.template[t].show &&
(data.node.template[t].type === "str" ||
data.node.template[t].type === "bool" ||
data.node.template[t].type === "float" ||
data.node.template[t].type === "code" ||
data.node.template[t].type === "prompt" ||
data.node.template[t].type === "file" ||
data.node.template[t].type === "int")
).length
);
const [nodeValue, setNodeValue] = useState(null);
const { closePopUp } = useContext(PopUpContext);
const { types } = useContext(typesContext);
const ref = useRef();
const { setTabsState, tabId } = useContext(TabsContext);
const { reactFlowInstance } = useContext(typesContext);
const EditNodeModal = forwardRef(
(
{
data,
setData,
nodeLength,
children,
}: {
data: NodeDataType;
setData: (data: NodeDataType) => void;
nodeLength: number;
children: ReactNode;
},
ref
) => {
const [modalOpen, setModalOpen] = useState(false);
const [myData, setMyData] = useState(data);
const { setTabsState, tabId } = useContext(TabsContext);
const { reactFlowInstance } = useContext(typesContext);
let disabled =
reactFlowInstance?.getEdges().some((e) => e.targetHandle === data.id) ??
false;
if (nodeLength == 0) {
closePopUp();
}
let disabled =
reactFlowInstance?.getEdges().some((e) => e.targetHandle === data.id) ??
false;
function setModalOpen(x: boolean) {
setOpen(x);
if (x === false) {
closePopUp();
function changeAdvanced(n) {
setMyData((old) => {
let newData = cloneDeep(old);
newData.node.template[n].advanced = !newData.node.template[n].advanced;
return newData;
});
}
}
function changeAdvanced(node) {
Object.keys(data.node.template).map((n, i) => {
if (n === node.name) {
data.node.template[n].advanced = !data.node.template[n].advanced;
}
return n;
});
setNodeValue(!nodeValue);
}
const handleOnNewValue = (newValue: any, name) => {
setMyData((old) => {
let newData = cloneDeep(old);
newData.node.template[name].value = newValue;
return newData;
});
};
const handleOnNewValue = (newValue: any, name) => {
data.node.template[name].value = newValue;
// Set state to pending
setTabsState((prev) => {
return {
...prev,
[tabId]: {
...prev[tabId],
isPending: true,
},
};
});
};
useEffect(() => {
setMyData(data); // reset data to what it is on node when opening modal
}, [modalOpen]);
return (
<Dialog open={true} onOpenChange={setModalOpen}>
<DialogTrigger asChild></DialogTrigger>
<DialogContent className="sm:max-w-[600px] lg:max-w-[700px]">
<DialogHeader>
<DialogTitle className="flex items-center">
<span className="pr-2">{data.type}</span>
<Badge variant="secondary">ID: {data.id}</Badge>
</DialogTitle>
<DialogDescription asChild>
<div>
{data.node?.description}
<div className="flex pt-3">
<Variable className="edit-node-modal-variable "></Variable>
<span className="edit-node-modal-span">Parameters</span>
</div>
</div>
</DialogDescription>
</DialogHeader>
return (
<BaseModal size="large-h-full" open={modalOpen} setOpen={setModalOpen}>
<BaseModal.Trigger>{children}</BaseModal.Trigger>
<BaseModal.Header description={myData.node?.description}>
<span className="pr-2">{myData.type}</span>
<Badge variant="secondary">ID: {myData.id}</Badge>
</BaseModal.Header>
<BaseModal.Content>
<div className="flex pb-2">
<Variable className="edit-node-modal-variable "></Variable>
<span className="edit-node-modal-span">Parameters</span>
</div>
<div className="edit-node-modal-arrangement">
<div
className={classNames(
"edit-node-modal-box",
nodeLength > limitScrollFieldsModal
? "overflow-scroll overflow-x-hidden custom-scroll"
: "overflow-hidden"
)}
>
{nodeLength > 0 && (
<div className="edit-node-modal-table">
<Table className="table-fixed bg-muted outline-1">
<TableHeader className="edit-node-modal-table-header">
<TableRow className="">
<TableHead className="h-7 text-center">PARAM</TableHead>
<TableHead className="h-7 p-0 text-center">
VALUE
</TableHead>
<TableHead className="h-7 text-center">SHOW</TableHead>
</TableRow>
</TableHeader>
<TableBody className="p-0">
{Object.keys(data.node.template)
.filter(
(t) =>
t.charAt(0) !== "_" &&
data.node.template[t].show &&
(data.node.template[t].type === "str" ||
data.node.template[t].type === "bool" ||
data.node.template[t].type === "float" ||
data.node.template[t].type === "code" ||
data.node.template[t].type === "prompt" ||
data.node.template[t].type === "file" ||
data.node.template[t].type === "int")
)
.map((n, i) => (
<TableRow key={i} className="h-10">
<TableCell className="truncate p-0 text-center text-sm text-foreground sm:px-3">
{data.node.template[n].name
? data.node.template[n].name
: data.node.template[n].display_name}
</TableCell>
<TableCell className="w-[300px] p-0 text-center text-xs text-foreground ">
{data.node.template[n].type === "str" &&
!data.node.template[n].options ? (
<div className="mx-auto">
{data.node.template[n].list ? (
<InputListComponent
editNode={true}
<div className="edit-node-modal-arrangement">
<div
className={classNames(
"edit-node-modal-box",
nodeLength > limitScrollFieldsModal
? "overflow-scroll overflow-x-hidden custom-scroll"
: "overflow-hidden"
)}
>
{nodeLength > 0 && (
<div className="edit-node-modal-table">
<Table className="table-fixed bg-muted outline-1">
<TableHeader className="edit-node-modal-table-header">
<TableRow className="">
<TableHead className="h-7 text-center">PARAM</TableHead>
<TableHead className="h-7 p-0 text-center">
VALUE
</TableHead>
<TableHead className="h-7 text-center">SHOW</TableHead>
</TableRow>
</TableHeader>
<TableBody className="p-0">
{Object.keys(myData.node.template)
.filter(
(t) =>
t.charAt(0) !== "_" &&
myData.node.template[t].show &&
(myData.node.template[t].type === "str" ||
myData.node.template[t].type === "bool" ||
myData.node.template[t].type === "float" ||
myData.node.template[t].type === "code" ||
myData.node.template[t].type === "prompt" ||
myData.node.template[t].type === "file" ||
myData.node.template[t].type === "int")
)
.map((n, i) => (
<TableRow key={i} className="h-10">
<TableCell className="truncate p-0 text-center text-sm text-foreground sm:px-3">
{myData.node.template[n].name
? myData.node.template[n].name
: myData.node.template[n].display_name}
</TableCell>
<TableCell className="w-[300px] p-0 text-center text-xs text-foreground ">
{myData.node.template[n].type === "str" &&
!myData.node.template[n].options ? (
<div className="mx-auto">
{myData.node.template[n].list ? (
<InputListComponent
editNode={true}
disabled={disabled}
value={
!myData.node.template[n].value ||
myData.node.template[n].value === ""
? [""]
: myData.node.template[n].value
}
onChange={(t: string[]) => {
handleOnNewValue(t, n);
}}
/>
) : myData.node.template[n].multiline ? (
<TextAreaComponent
disabled={disabled}
editNode={true}
value={
myData.node.template[n].value ?? ""
}
onChange={(t: string) => {
handleOnNewValue(t, n);
}}
/>
) : (
<InputComponent
editNode={true}
disabled={disabled}
password={
myData.node.template[n].password ??
false
}
value={
myData.node.template[n].value ?? ""
}
onChange={(t) => {
handleOnNewValue(t, n);
}}
/>
)}
</div>
) : myData.node.template[n].type === "bool" ? (
<div className="ml-auto">
{" "}
<ToggleShadComponent
disabled={disabled}
value={
!data.node.template[n].value ||
data.node.template[n].value === ""
? [""]
: data.node.template[n].value
}
onChange={(t: string[]) => {
enabled={myData.node.template[n].value}
setEnabled={(t) => {
handleOnNewValue(t, n);
}}
size="small"
/>
) : data.node.template[n].multiline ? (
<TextAreaComponent
</div>
) : myData.node.template[n].type === "float" ? (
<div className="mx-auto">
<FloatComponent
disabled={disabled}
editNode={true}
value={data.node.template[n].value ?? ""}
onChange={(t: string) => {
handleOnNewValue(t, n);
}}
/>
) : (
<InputComponent
editNode={true}
disabled={disabled}
password={
data.node.template[n].password ?? false
}
value={data.node.template[n].value ?? ""}
value={myData.node.template[n].value ?? ""}
onChange={(t) => {
handleOnNewValue(t, n);
}}
/>
)}
</div>
) : data.node.template[n].type === "bool" ? (
<div className="ml-auto">
{" "}
</div>
) : myData.node.template[n].type === "str" &&
myData.node.template[n].options ? (
<div className="mx-auto">
<Dropdown
numberOfOptions={nodeLength}
editNode={true}
options={myData.node.template[n].options}
onSelect={(t) => handleOnNewValue(t, n)}
value={
myData.node.template[n].value ??
"Choose an option"
}
></Dropdown>
</div>
) : myData.node.template[n].type === "int" ? (
<div className="mx-auto">
<IntComponent
disabled={disabled}
editNode={true}
value={myData.node.template[n].value ?? ""}
onChange={(t) => {
handleOnNewValue(t, n);
}}
/>
</div>
) : myData.node.template[n].type === "file" ? (
<div className="mx-auto">
<InputFileComponent
editNode={true}
disabled={disabled}
value={myData.node.template[n].value ?? ""}
onChange={(t: string) => {
handleOnNewValue(t, n);
}}
fileTypes={
myData.node.template[n].fileTypes
}
suffixes={myData.node.template[n].suffixes}
onFileChange={(t: string) => {
handleOnNewValue(t, n);
}}
></InputFileComponent>
</div>
) : myData.node.template[n].type === "prompt" ? (
<div className="mx-auto">
<PromptAreaComponent
field_name={n}
editNode={true}
disabled={disabled}
nodeClass={myData.node}
setNodeClass={(nodeClass) => {
myData.node = nodeClass;
}}
value={myData.node.template[n].value ?? ""}
onChange={(t: string) => {
handleOnNewValue(t, n);
}}
/>
</div>
) : myData.node.template[n].type === "code" ? (
<div className="mx-auto">
<CodeAreaComponent
dynamic={
data.node.template[n].dynamic ?? false
}
setNodeClass={(nodeClass) => {
data.node = nodeClass;
}}
nodeClass={data.node}
disabled={disabled}
editNode={true}
value={myData.node.template[n].value ?? ""}
onChange={(t: string) => {
handleOnNewValue(t, n);
}}
/>
</div>
) : myData.node.template[n].type === "Any" ? (
"-"
) : (
<div className="hidden"></div>
)}
</TableCell>
<TableCell className="p-0 text-right">
<div className="items-center text-center">
<ToggleShadComponent
enabled={!myData.node.template[n].advanced}
setEnabled={(e) => changeAdvanced(n)}
disabled={disabled}
enabled={data.node.template[n].value}
setEnabled={(t) => {
handleOnNewValue(t, n);
}}
size="small"
/>
</div>
) : data.node.template[n].type === "float" ? (
<div className="mx-auto">
<FloatComponent
disabled={disabled}
editNode={true}
value={data.node.template[n].value ?? ""}
onChange={(t) => {
data.node.template[n].value = t;
}}
/>
</div>
) : data.node.template[n].type === "str" &&
data.node.template[n].options ? (
<div className="mx-auto">
<Dropdown
numberOfOptions={nodeLength}
editNode={true}
options={data.node.template[n].options}
onSelect={(t) => handleOnNewValue(t, n)}
value={
data.node.template[n].value ??
"Choose an option"
}
></Dropdown>
</div>
) : data.node.template[n].type === "int" ? (
<div className="mx-auto">
<IntComponent
disabled={disabled}
editNode={true}
value={data.node.template[n].value ?? ""}
onChange={(t) => {
handleOnNewValue(t, n);
}}
/>
</div>
) : data.node.template[n].type === "file" ? (
<div className="mx-auto">
<InputFileComponent
editNode={true}
disabled={disabled}
value={data.node.template[n].value ?? ""}
onChange={(t: string) => {
handleOnNewValue(t, n);
}}
fileTypes={data.node.template[n].fileTypes}
suffixes={data.node.template[n].suffixes}
onFileChange={(t: string) => {
handleOnNewValue(t, n);
}}
></InputFileComponent>
</div>
) : data.node.template[n].type === "prompt" ? (
<div className="mx-auto">
<PromptAreaComponent
field_name={n}
editNode={true}
disabled={disabled}
nodeClass={data.node}
setNodeClass={(nodeClass) => {
data.node = nodeClass;
}}
value={data.node.template[n].value ?? ""}
onChange={(t: string) => {
handleOnNewValue(t, n);
}}
/>
</div>
) : data.node.template[n].type === "code" ? (
<div className="mx-auto">
<CodeAreaComponent
dynamic={
data.node.template[n].dynamic ?? false
}
setNodeClass={(nodeClass) => {
data.node = nodeClass;
}}
nodeClass={data.node}
disabled={false}
editNode={true}
value={data.node.template[n].value ?? ""}
onChange={(t: string) => {
handleOnNewValue(t, n);
}}
/>
</div>
) : data.node.template[n].type === "Any" ? (
"-"
) : (
<div className="hidden"></div>
)}
</TableCell>
<TableCell className="p-0 text-right">
<div className="items-center text-center">
<ToggleShadComponent
enabled={!data.node.template[n].advanced}
setEnabled={(e) =>
changeAdvanced(data.node.template[n])
}
disabled={disabled}
size="small"
/>
</div>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
)}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
)}
</div>
</div>
</div>
</BaseModal.Content>
<DialogFooter>
<BaseModal.Footer>
<Button
className="mt-3"
onClick={() => {
setData(cloneDeep(myData)); //saves data with actual state of modal
setTabsState((prev) => {
return {
...prev,
[tabId]: {
...prev[tabId],
isPending: true,
},
};
});
setModalOpen(false);
}}
type="submit"
>
Save Changes
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
}
</BaseModal.Footer>
</BaseModal>
);
}
);
export default EditNodeModal;

View file

@ -1,7 +1,6 @@
import { Dialog, Transition } from "@headlessui/react";
import { X } from "lucide-react";
import { Fragment, useContext, useRef, useState } from "react";
import { PopUpContext } from "../../contexts/popUpContext";
import { typesContext } from "../../contexts/typesContext";
import { NodeDataType } from "../../types/flow";
import {
@ -14,150 +13,139 @@ import {
import ModalField from "./components/ModalField";
export default function NodeModal({ data }: { data: NodeDataType }) {
const [open, setOpen] = useState(true);
const { closePopUp } = useContext(PopUpContext);
const [modalOpen, setModalOpen] = useState(false);
const { types } = useContext(typesContext);
const ref = useRef();
function setModalOpen(x: boolean) {
setOpen(x);
if (x === false) {
setTimeout(() => {
closePopUp();
}, 300);
}
}
// any to avoid type conflict
const Icon: any = nodeIconsLucide[types[data.type]];
return (
<Transition.Root show={open} appear={true} as={Fragment}>
<Dialog
as="div"
className="relative z-10"
onClose={setModalOpen}
initialFocus={ref}
<Dialog
open={modalOpen}
as="div"
className="relative z-10"
onClose={setModalOpen}
initialFocus={ref}
>
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-200"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div className="node-modal-div" />
</Transition.Child>
<div className="node-modal-div" />
</Transition.Child>
<div className="node-modal-dialog-arrangement">
<div className="node-modal-dialog-div">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
enterTo="opacity-100 translate-y-0 sm:scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
>
<Dialog.Panel className="node-modal-dialog-panel">
<div className=" node-modal-dialog-panel-div">
<button
type="button"
className="node-modal-dialog-button"
onClick={() => {
setModalOpen(false);
<div className="node-modal-dialog-arrangement">
<div className="node-modal-dialog-div">
<Transition.Child
as={Fragment}
enter="ease-out duration-300"
enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
enterTo="opacity-100 translate-y-0 sm:scale-100"
leave="ease-in duration-200"
leaveFrom="opacity-100 translate-y-0 sm:scale-100"
leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
>
<Dialog.Panel className="node-modal-dialog-panel">
<div className=" node-modal-dialog-panel-div">
<button
type="button"
className="node-modal-dialog-button"
onClick={() => {
setModalOpen(false);
}}
>
<span className="sr-only">Close</span>
<X className="h-6 w-6" aria-hidden="true" />
</button>
</div>
<div className="node-modal-dialog-icon-div">
<div className="node-modal-icon-arrangement">
<Icon
strokeWidth={1.5}
className="node-modal-icon"
style={{
color: nodeColors[types[data.type]] ?? nodeColors.unknown,
}}
>
<span className="sr-only">Close</span>
<X className="h-6 w-6" aria-hidden="true" />
</button>
</div>
<div className="node-modal-dialog-icon-div">
<div className="node-modal-icon-arrangement">
<Icon
strokeWidth={1.5}
className="node-modal-icon"
style={{
color:
nodeColors[types[data.type]] ?? nodeColors.unknown,
}}
/>
<div className="node-modal-title-div">
<Dialog.Title as="h3" className="node-modal-title">
{data.type}
</Dialog.Title>
</div>
/>
<div className="node-modal-title-div">
<Dialog.Title as="h3" className="node-modal-title">
{data.type}
</Dialog.Title>
</div>
<div className="node-modal-template-div">
<div className="flex-max-width h-[445px]">
<div
className={classNames(
"node-modal-template",
Object.keys(data.node.template).filter(
</div>
<div className="node-modal-template-div">
<div className="flex-max-width h-[445px]">
<div
className={classNames(
"node-modal-template",
Object.keys(data.node.template).filter(
(t) =>
t.charAt(0) !== "_" &&
data.node.template[t].advanced &&
data.node.template[t].show
).length > limitScrollFieldsModal
? "overflow-scroll overflow-x-hidden custom-scroll"
: "overflow-hidden"
)}
>
<div className="node-modal-template-column">
{Object.keys(data.node.template)
.filter(
(t) =>
t.charAt(0) !== "_" &&
data.node.template[t].advanced &&
data.node.template[t].show
).length > limitScrollFieldsModal
? "overflow-scroll overflow-x-hidden custom-scroll"
: "overflow-hidden"
)}
>
<div className="node-modal-template-column">
{Object.keys(data.node.template)
.filter(
(t) =>
t.charAt(0) !== "_" &&
data.node.template[t].advanced &&
data.node.template[t].show
)
.map((t: string, idx) => {
return (
<ModalField
key={idx}
data={data}
title={
data.node.template[t].display_name
? data.node.template[t].display_name
: data.node.template[t].name
? toTitleCase(data.node.template[t].name)
: toTitleCase(t)
}
required={data.node.template[t].required}
id={
data.node.template[t].type +
"|" +
t +
"|" +
data.id
}
name={t}
type={data.node.template[t].type}
index={idx}
/>
);
})}
</div>
)
.map((t: string, idx) => {
return (
<ModalField
key={idx}
data={data}
title={
data.node.template[t].display_name
? data.node.template[t].display_name
: data.node.template[t].name
? toTitleCase(data.node.template[t].name)
: toTitleCase(t)
}
required={data.node.template[t].required}
id={
data.node.template[t].type +
"|" +
t +
"|" +
data.id
}
name={t}
type={data.node.template[t].type}
index={idx}
/>
);
})}
</div>
</div>
</div>
<div className="node-modal-button-box">
<button
type="button"
className="node-modal-button"
onClick={() => {
setModalOpen(false);
}}
>
Done
</button>
</div>
</div>
</Dialog.Panel>
</Transition.Child>
</div>
<div className="node-modal-button-box">
<button
type="button"
className="node-modal-button"
onClick={() => {
setModalOpen(false);
}}
>
Done
</button>
</div>
</div>
</Dialog.Panel>
</Transition.Child>
</div>
</Dialog>
</Transition.Root>
</div>
</Dialog>
);
}

View file

@ -1,4 +1,4 @@
import { ReactNode, useContext } from "react";
import { ReactNode } from "react";
import React from "react";
import {
@ -9,14 +9,18 @@ import {
DialogTitle,
DialogTrigger,
} from "../../components/ui/dialog";
import { PopUpContext } from "../../contexts/popUpContext";
type ContentProps = { children: ReactNode };
type HeaderProps = { children: ReactNode; description: string };
type FooterProps = { children: ReactNode };
type TriggerProps = { children: ReactNode };
const Content: React.FC<ContentProps> = ({ children }) => {
return <div className="h-full w-full">{children}</div>;
};
const Trigger: React.FC<ContentProps> = ({ children }) => {
return <>{children}</>;
};
const Header: React.FC<{ children: ReactNode; description: string }> = ({
children,
@ -29,36 +33,80 @@ const Header: React.FC<{ children: ReactNode; description: string }> = ({
</DialogHeader>
);
};
interface BaseModalProps {
children: [React.ReactElement<ContentProps>, React.ReactElement<HeaderProps>];
open: boolean;
setOpen: (open: boolean) => void;
}
function BaseModal({ open, setOpen, children }: BaseModalProps) {
const { closePopUp, setCloseEdit } = useContext(PopUpContext);
function setModalOpen(x: boolean) {
setOpen(x);
if (x === false) {
setTimeout(() => {
setCloseEdit("editcode");
closePopUp();
}, 300);
}
}
const Footer: React.FC<{ children: ReactNode }> = ({ children }) => {
return <>{children}</>;
};
interface BaseModalProps {
children: [
React.ReactElement<ContentProps>,
React.ReactElement<HeaderProps>,
React.ReactElement<TriggerProps>?,
React.ReactElement<FooterProps>?
];
open?: boolean;
setOpen?: (open: boolean) => void;
size?: "smaller" | "small" | "medium" | "large" | "large-h-full";
}
function BaseModal({
open,
setOpen,
children,
size = "large",
}: BaseModalProps) {
const headerChild = React.Children.toArray(children).find(
(child) => (child as React.ReactElement).type === Header
);
const triggerChild = React.Children.toArray(children).find(
(child) => (child as React.ReactElement).type === Trigger
);
const ContentChild = React.Children.toArray(children).find(
(child) => (child as React.ReactElement).type === Content
);
const ContentFooter = React.Children.toArray(children).find(
(child) => (child as React.ReactElement).type === Footer
);
let minWidth: string;
let height: string;
switch (size) {
case "smaller":
minWidth = "min-w-[40vw]";
height = "h-[25vh]";
break;
case "small":
minWidth = "min-w-[40vw]";
height = "h-[40vh]";
break;
case "medium":
minWidth = "min-w-[60vw]";
height = "h-[60vh]";
break;
case "large":
minWidth = "min-w-[80vw]";
height = "h-[80vh]";
break;
case "large-h-full":
minWidth = "min-w-[80vw]";
break;
default:
minWidth = "min-w-[80vw]";
height = "h-[80vh]";
break;
}
//UPDATE COLORS AND STYLE CLASSSES
return (
<Dialog open={true} onOpenChange={setModalOpen}>
<DialogTrigger className="hidden"></DialogTrigger>
<DialogContent className="min-w-[80vw]">
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger className="w-full" hidden={triggerChild ? false : true}>
{triggerChild}
</DialogTrigger>
<DialogContent className={minWidth}>
{headerChild}
<div className="mt-2 flex h-[80vh] w-full ">{ContentChild}</div>
<div className={`mt-2 flex ${height} w-full `}>{ContentChild}</div>
<div className="flex flex-row-reverse">{ContentFooter}</div>
</DialogContent>
</Dialog>
);
@ -66,4 +114,6 @@ function BaseModal({ open, setOpen, children }: BaseModalProps) {
BaseModal.Content = Content;
BaseModal.Header = Header;
BaseModal.Trigger = Trigger;
BaseModal.Footer = Footer;
export default BaseModal;

View file

@ -1,7 +1,4 @@
// organize-imports-ignore
import { useContext, useEffect, useRef, useState } from "react";
import { PopUpContext } from "../../contexts/popUpContext";
import AceEditor from "react-ace";
import "ace-builds/src-noconflict/ace";
import "ace-builds/src-noconflict/ext-language_tools";
import "ace-builds/src-noconflict/mode-python";
import "ace-builds/src-noconflict/theme-github";
@ -10,7 +7,7 @@ import "ace-builds/src-noconflict/ext-language_tools";
import "ace-builds/src-noconflict/ace";
// import "ace-builds/webpack-resolver";
import { TerminalSquare } from "lucide-react";
import { useContext, useState } from "react";
import { ReactNode, useContext, useEffect, useState } from "react";
import AceEditor from "react-ace";
import { Button } from "../../components/ui/button";
import { CODE_PROMPT_DIALOG_SUBTITLE } from "../../constants";
@ -24,48 +21,39 @@ import {
TabsList,
TabsTrigger,
} from "../../components/ui/tabs";
import BaseModal from "../baseModal";
export default function CodeAreaModal({
value,
setValue,
nodeClass,
setNodeClass,
children,
dynamic,
}: {
setValue: (value: string) => void;
value: string;
nodeClass: APIClassType;
children: ReactNode;
setNodeClass: (Class: APIClassType) => void;
dynamic?: boolean;
}) {
const [code, setCode] = useState(value);
const { dark } = useContext(darkContext);
const [height, setHeight] = useState(null);
const { setErrorData, setSuccessData } = useContext(alertContext);
const [activeTab, setActiveTab] = useState("0");
const [error, setError] = useState<{
detail: { error: string; traceback: string };
}>(null);
const { closePopUp, setCloseEdit } = useContext(PopUpContext);
const { setErrorData, setSuccessData } = useContext(alertContext);
function setModalOpen(x: boolean) {
if (x === false) {
setCloseEdit("codearea");
closePopUp();
}
}
console.log(dynamic);
useEffect(() => {
setValue(code);
}, [code, setValue]);
handleClick();
}, [])
function handleClick() {
setLoading(true);
if (!dynamic) {
postValidateCode(code)
.then((apiReturn) => {
setLoading(false);
if (apiReturn.data) {
let importsErrors = apiReturn.data.imports.errors;
let funcErrors = apiReturn.data.function.errors;
@ -95,7 +83,6 @@ export default function CodeAreaModal({
}
})
.catch((_) => {
setLoading(false);
setErrorData({
title: "There is something wrong with this code, please review it",
});
@ -106,109 +93,71 @@ export default function CodeAreaModal({
const { data } = apiReturn;
if (data) {
setNodeClass(data);
setModalOpen(false);
setOpen(false);
}
})
.catch((err) => {
setErrorData({
title:
"There is something wrong with this code, please see the error on the errors tab",
});
console.log(err.response.data);
setError(err.response.data);
});
}
// axios.get("/api/v1/custom_component_error").catch((err) => {
// })
}
const tabs = [{ name: "code" }, { name: "errors" }];
useEffect(() => {
// Function to be executed after the state changes
const delayedFunction = setTimeout(() => {
if (error?.detail.error !== undefined) {
//trigger to update the height, does not really apply any height
setHeight("90%");
}
//600 to happen after the transition of 500ms
}, 600);
// Cleanup function to clear the timeout if the component unmounts or the state changes again
return () => {
clearTimeout(delayedFunction);
};
}, [error, setHeight]);
const [open, setOpen] = useState(false);
return (
<Dialog open={true} onOpenChange={setModalOpen}>
<DialogTrigger></DialogTrigger>
<DialogContent className="min-w-[80vw]">
<DialogHeader>
<DialogTitle className="flex items-center">
<span className="pr-2">Edit Code</span>
<TerminalSquare
strokeWidth={1.5}
className="h-6 w-6 pl-1 text-primary "
aria-hidden="true"
<BaseModal open={open} setOpen={setOpen}>
<BaseModal.Trigger>{children}</BaseModal.Trigger>
<BaseModal.Header description={CODE_PROMPT_DIALOG_SUBTITLE}>
<span className="pr-2">Edit Code</span>
<TerminalSquare
strokeWidth={1.5}
className="h-6 w-6 pl-1 text-primary "
aria-hidden="true"
/>
</BaseModal.Header>
<BaseModal.Content>
<div className="flex h-full w-full flex-col transition-all">
<div className="h-full w-full">
<AceEditor
value={code}
mode="python"
height={height ?? "100%"}
highlightActiveLine={true}
showPrintMargin={false}
fontSize={14}
showGutter
enableLiveAutocompletion
theme={dark ? "twilight" : "github"}
name="CodeEditor"
onChange={(value) => {
setCode(value);
}}
className="h-full w-full rounded-lg border-[1px] border-border custom-scroll"
/>
</DialogTitle>
<DialogDescription>{CODE_PROMPT_DIALOG_SUBTITLE}</DialogDescription>
</DialogHeader>
<Tabs
defaultValue={"0"}
className="h-full w-full overflow-hidden rounded-md border bg-muted text-center"
onValueChange={(value) => setActiveTab(value)}
>
<div className="flex h-72 flex-col items-start px-2">
<TabsList>
{tabs.map((tab, index) => (
<TabsTrigger
disabled={index === 1 && error?.detail.error === undefined}
key={index}
value={index.toString()}
>
<span
className={
error?.detail.error !== undefined && index === 1
? "text-destructive"
: ""
}
>
{tab.name}
</span>
</TabsTrigger>
))}
</TabsList>
{tabs.map((tab, index) => (
<TabsContent
value={index.toString()}
className="mt-1 h-full w-full overflow-hidden px-4 pb-4"
>
{tab.name === "code" ? (
<div className="h-full w-full">
<AceEditor
value={code}
mode="python"
highlightActiveLine={true}
showPrintMargin={false}
fontSize={14}
showGutter
enableLiveAutocompletion
theme={dark ? "twilight" : "github"}
name="CodeEditor"
onChange={(value) => {
setCode(value);
}}
className="h-full w-full rounded-lg border-[1px] border-gray-300 custom-scroll dark:border-gray-600"
/>
</div>
) : (
<div className="flex h-full w-full flex-col overflow-scroll bg-red-200 p-2 text-left custom-scroll">
<h1 className="text-lg text-red-600">
{error?.detail?.error}
</h1>
<span className="w-full border border-red-300"></span>
<div className="text-sm text-red-500">
{error?.detail?.traceback}
</div>
</div>
)}
</TabsContent>
))}
</div>
</Tabs>
<DialogFooter>
<Button className="mt-3" onClick={handleClick} type="submit">
{/* {loading?(<Loading/>):'Check & Save'} */}
Check & Save
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
<div className="flex h-fit w-full justify-end">
<Button className="mt-3" onClick={handleClick} type="submit">
Check & Save
</Button>
</div>
</div>
</BaseModal.Content>
</BaseModal>
);
}

View file

@ -1,60 +1,34 @@
import { Download } from "lucide-react";
import { useContext, useRef, useState } from "react";
import { ReactNode, forwardRef, useContext, useState } from "react";
import EditFlowSettings from "../../components/EditFlowSettingsComponent";
import { Button } from "../../components/ui/button";
import { Checkbox } from "../../components/ui/checkbox";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "../../components/ui/dialog";
import { EXPORT_DIALOG_SUBTITLE } from "../../constants";
import { alertContext } from "../../contexts/alertContext";
import { PopUpContext } from "../../contexts/popUpContext";
import { TabsContext } from "../../contexts/tabsContext";
import { removeApiKeys } from "../../utils";
import BaseModal from "../baseModal";
export default function ExportModal() {
const [open, setOpen] = useState(true);
const { closePopUp } = useContext(PopUpContext);
const ref = useRef();
const { setErrorData } = useContext(alertContext);
const ExportModal = forwardRef((props: { children: ReactNode }, ref) => {
const { flows, tabId, updateFlow, downloadFlow, saveFlow } =
useContext(TabsContext);
const [isMaxLength, setIsMaxLength] = useState(false);
function setModalOpen(x: boolean) {
setOpen(x);
if (x === false) {
setTimeout(() => {
closePopUp();
}, 300);
}
}
const [checked, setChecked] = useState(false);
const [name, setName] = useState(flows.find((f) => f.id === tabId).name);
const [description, setDescription] = useState(
flows.find((f) => f.id === tabId).description
);
const [open, setOpen] = useState(false);
return (
<Dialog open={true} onOpenChange={setModalOpen}>
<DialogTrigger asChild></DialogTrigger>
<DialogContent className="h-[420px] lg:max-w-[600px] ">
<DialogHeader>
<DialogTitle className="flex items-center">
<span className="pr-2">Export</span>
<Download
strokeWidth={1.5}
className="h-6 w-6 pl-1 text-foreground"
aria-hidden="true"
/>
</DialogTitle>
<DialogDescription>{EXPORT_DIALOG_SUBTITLE}</DialogDescription>
</DialogHeader>
<BaseModal size="smaller" open={open} setOpen={setOpen}>
<BaseModal.Trigger>{props.children}</BaseModal.Trigger>
<BaseModal.Header description={EXPORT_DIALOG_SUBTITLE}>
<span className="pr-2">Export</span>
<Download
strokeWidth={1.5}
className="h-6 w-6 pl-1 text-primary "
aria-hidden="true"
/>
</BaseModal.Header>
<BaseModal.Content>
<EditFlowSettings
name={name}
description={description}
@ -64,42 +38,42 @@ export default function ExportModal() {
setDescription={setDescription}
updateFlow={updateFlow}
/>
<div className="flex items-center space-x-2">
<div className="mt-3 flex items-center space-x-2">
<Checkbox
id="terms"
onCheckedChange={(event: boolean) => {
setChecked(event);
}}
/>
<label htmlFor="terms" className="export-modal-save-api text-sm">
<label htmlFor="terms" className="export-modal-save-api text-sm ">
Save with my API keys
</label>
</div>
</BaseModal.Content>
<DialogFooter>
<Button
onClick={() => {
if (checked)
downloadFlow(
flows.find((f) => f.id === tabId),
name,
description
);
else
downloadFlow(
removeApiKeys(flows.find((f) => f.id === tabId)),
name,
description
);
closePopUp();
}}
type="submit"
>
Download Flow
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
<BaseModal.Footer>
<Button
onClick={() => {
if (checked)
downloadFlow(
flows.find((f) => f.id === tabId),
name,
description
);
else
downloadFlow(
removeApiKeys(flows.find((f) => f.id === tabId)),
name,
description
);
setOpen(false);
}}
type="submit"
>
Download Flow
</Button>
</BaseModal.Footer>
</BaseModal>
);
}
});
export default ExportModal;

View file

@ -2,23 +2,18 @@ import { Settings2 } from "lucide-react";
import { useContext, useRef, useState } from "react";
import EditFlowSettings from "../../components/EditFlowSettingsComponent";
import { Button } from "../../components/ui/button";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "../../components/ui/dialog";
import { SETTINGS_DIALOG_SUBTITLE } from "../../constants";
import { alertContext } from "../../contexts/alertContext";
import { PopUpContext } from "../../contexts/popUpContext";
import { TabsContext } from "../../contexts/tabsContext";
import BaseModal from "../baseModal";
export default function FlowSettingsModal() {
const [open, setOpen] = useState(true);
const { closePopUp } = useContext(PopUpContext);
export default function FlowSettingsModal({
open,
setOpen,
}: {
open: boolean;
setOpen: (open: boolean) => void;
}) {
const { setErrorData, setSuccessData } = useContext(alertContext);
const ref = useRef();
const { flows, tabId, updateFlow, setTabsState, saveFlow } =
@ -28,34 +23,25 @@ export default function FlowSettingsModal() {
const [description, setDescription] = useState(
flows.find((f) => f.id === tabId).description
);
function setModalOpen(x: boolean) {
setOpen(x);
if (x === false) {
setTimeout(() => {
closePopUp();
}, 300);
}
}
function handleClick() {
let savedFlow = flows.find((f) => f.id === tabId);
savedFlow.name = name;
savedFlow.description = description;
saveFlow(savedFlow);
setSuccessData({ title: "Changes saved successfully" });
closePopUp();
setOpen(false);
}
return (
<Dialog open={true} onOpenChange={setModalOpen}>
<DialogTrigger asChild></DialogTrigger>
<DialogContent className="h-[390px] lg:max-w-[600px]">
<DialogHeader>
<DialogTitle className="flex items-center">
<span className="pr-2">Settings </span>
<Settings2 className="mr-2 h-4 w-4 " />
</DialogTitle>
<DialogDescription>{SETTINGS_DIALOG_SUBTITLE}</DialogDescription>
</DialogHeader>
<BaseModal open={open} setOpen={setOpen} size="smaller">
<BaseModal.Header description={SETTINGS_DIALOG_SUBTITLE}>
<span className="pr-2">Settings</span>
<Settings2
strokeWidth={1.5}
className="h-6 w-6 pl-1 text-primary "
aria-hidden="true"
/>
</BaseModal.Header>
<BaseModal.Content>
<EditFlowSettings
name={name}
description={description}
@ -65,13 +51,13 @@ export default function FlowSettingsModal() {
setDescription={setDescription}
updateFlow={updateFlow}
/>
</BaseModal.Content>
<DialogFooter>
<Button onClick={handleClick} type="submit">
Save
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
<BaseModal.Footer>
<Button onClick={handleClick} type="submit">
Save
</Button>
</BaseModal.Footer>
</BaseModal>
);
}

View file

@ -36,7 +36,7 @@ export default function FormModal({
setOpen,
}: {
open: boolean;
setOpen: Function;
setOpen: (open: boolean) => void;
flow: FlowType;
}) {
const { tabsState, setTabsState } = useContext(TabsContext);
@ -389,8 +389,8 @@ export default function FormModal({
}
}
return (
<Dialog open={open} onOpenChange={setModalOpen}>
<DialogTrigger className="hidden"></DialogTrigger>
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger hidden></DialogTrigger>
{tabsState[flow.id].formKeysData && (
<DialogContent className="min-w-[80vw]">
<DialogHeader>

View file

@ -1,10 +1,9 @@
import { FileText, Variable } from "lucide-react";
import { useContext, useEffect, useRef, useState } from "react";
import { ReactNode, useContext, useEffect, useRef, useState } from "react";
import SanitizedHTMLWrapper from "../../components/SanitizedHTMLWrapper";
import ShadTooltip from "../../components/ShadTooltipComponent";
import { Badge } from "../../components/ui/badge";
import { Button } from "../../components/ui/button";
import { DialogTitle } from "../../components/ui/dialog";
import { Textarea } from "../../components/ui/textarea";
import {
MAX_WORDS_HIGHLIGHT,
@ -12,13 +11,10 @@ import {
TEXT_DIALOG_SUBTITLE,
} from "../../constants";
import { alertContext } from "../../contexts/alertContext";
import { darkContext } from "../../contexts/darkContext";
import { PopUpContext } from "../../contexts/popUpContext";
import { postValidatePrompt } from "../../controllers/API";
import { APIClassType } from "../../types/api";
import {
INVALID_CHARACTERS,
TypeModal,
classNames,
getRandomKeyByssmm,
regexHighlight,
@ -35,13 +31,15 @@ export default function GenericModal({
type,
nodeClass,
setNodeClass,
children,
}: {
field_name?: string;
setValue: (value: string) => void;
value: string;
buttonText: string;
modalTitle: string;
type: number;
type: "prompt" | "text";
children: ReactNode;
nodeClass?: APIClassType;
setNodeClass?: (Class: APIClassType) => void;
}) {
@ -51,17 +49,9 @@ export default function GenericModal({
const [inputValue, setInputValue] = useState(value);
const [isEdit, setIsEdit] = useState(true);
const [wordsHighlight, setWordsHighlight] = useState([]);
const { dark } = useContext(darkContext);
const { setErrorData, setSuccessData, setNoticeData } =
useContext(alertContext);
const { closePopUp, setCloseEdit } = useContext(PopUpContext);
const ref = useRef();
function setModalOpen(x: boolean) {
if (x === false) {
setCloseEdit("generic");
closePopUp();
}
}
const divRef = useRef(null);
const divRefPrompt = useRef(null);
@ -100,7 +90,7 @@ export default function GenericModal({
}
useEffect(() => {
if (type === TypeModal.PROMPT && inputValue && inputValue != "") {
if (type === "prompt" && inputValue && inputValue != "") {
checkVariables(inputValue);
}
}, [inputValue, type]);
@ -170,8 +160,11 @@ export default function GenericModal({
});
}
const [modalOpen, setModalOpen] = useState(false);
return (
<BaseModal open={true} setOpen={setModalOpen}>
<BaseModal open={modalOpen} setOpen={setModalOpen}>
<BaseModal.Trigger>{children}</BaseModal.Trigger>
<BaseModal.Header
description={(() => {
switch (myModalTitle) {
@ -186,14 +179,12 @@ export default function GenericModal({
}
})()}
>
<DialogTitle className="flex items-center">
<span className="pr-2">{myModalTitle}</span>
<FileText
strokeWidth={1.5}
className="h-6 w-6 pl-1 text-primary "
aria-hidden="true"
/>
</DialogTitle>
<span className="pr-2">{myModalTitle}</span>
<FileText
strokeWidth={1.5}
className="h-6 w-6 pl-1 text-primary "
aria-hidden="true"
/>
</BaseModal.Header>
<BaseModal.Content>
<div className="flex h-full flex-col">
@ -203,7 +194,7 @@ export default function GenericModal({
"flex h-full w-full"
)}
>
{type === TypeModal.PROMPT && isEdit ? (
{type === "prompt" && isEdit ? (
<Textarea
ref={divRefPrompt}
className="form-input h-full w-full rounded-lg custom-scroll focus-visible:ring-1"
@ -218,9 +209,9 @@ export default function GenericModal({
}}
placeholder="Type message here."
/>
) : type === TypeModal.PROMPT && !isEdit ? (
) : type === "prompt" && !isEdit ? (
<TextAreaContentView />
) : type !== TypeModal.PROMPT ? (
) : type !== "prompt" ? (
<Textarea
ref={ref}
className="form-input h-full w-full rounded-lg focus-visible:ring-1"
@ -237,7 +228,7 @@ export default function GenericModal({
<div className="mt-6 flex h-fit w-full items-end justify-between">
<div className="mb-auto flex-1">
{type === TypeModal.PROMPT && (
{type === "prompt" && (
<div className=" mr-2">
<div
ref={divRef}
@ -274,7 +265,7 @@ export default function GenericModal({
))}
</div>
</div>
<span className="mt-1 text-xs text-muted-foreground">
<span className="mt-2 text-xs text-muted-foreground">
Prompt variables can be created with any chosen name inside
curly brackets, e.g. {"{variable_name}"}
</span>
@ -284,11 +275,11 @@ export default function GenericModal({
<Button
onClick={() => {
switch (myModalType) {
case 1:
case "text":
setValue(inputValue);
setModalOpen(false);
break;
case 2:
case "prompt":
!inputValue || inputValue === ""
? setModalOpen(false)
: validatePrompt(false);

View file

@ -17,7 +17,6 @@ import {
} from "../../components/ui/dialog";
import { IMPORT_DIALOG_SUBTITLE } from "../../constants";
import { alertContext } from "../../contexts/alertContext";
import { PopUpContext } from "../../contexts/popUpContext";
import { TabsContext } from "../../contexts/tabsContext";
import { getExamples } from "../../controllers/API";
import { FlowType } from "../../types/flow";
@ -27,20 +26,11 @@ import ButtonBox from "./buttonBox";
export default function ImportModal() {
const [open, setOpen] = useState(true);
const { setErrorData } = useContext(alertContext);
const { closePopUp } = useContext(PopUpContext);
const ref = useRef();
const [showExamples, setShowExamples] = useState(false);
const [loadingExamples, setLoadingExamples] = useState(false);
const [examples, setExamples] = useState<FlowType[]>([]);
const { uploadFlow, addFlow } = useContext(TabsContext);
function setModalOpen(x: boolean) {
setOpen(x);
if (x === false) {
setTimeout(() => {
closePopUp();
}, 300);
}
}
function handleExamples() {
setLoadingExamples(true);
@ -57,8 +47,10 @@ export default function ImportModal() {
);
}
const [modalOpen, setModalOpen] = useState(false);
return (
<Dialog open={true} onOpenChange={setModalOpen}>
<Dialog open={modalOpen} onOpenChange={setModalOpen}>
<DialogTrigger></DialogTrigger>
<DialogContent
className={classNames(

View file

@ -3,7 +3,6 @@ import { useContext, useState } from "react";
import ShadTooltip from "../../../../components/ShadTooltipComponent";
import { Separator } from "../../../../components/ui/separator";
import { alertContext } from "../../../../contexts/alertContext";
import { PopUpContext } from "../../../../contexts/popUpContext";
import { TabsContext } from "../../../../contexts/tabsContext";
import { typesContext } from "../../../../contexts/typesContext";
import ApiModal from "../../../../modals/ApiModal";
@ -19,7 +18,6 @@ import DisclosureComponent from "../DisclosureComponent";
export default function ExtraSidebar() {
const { data } = useContext(typesContext);
const { openPopUp } = useContext(PopUpContext);
const { flows, tabId, uploadFlow, tabsState, saveFlow } =
useContext(TabsContext);
const { setSuccessData, setErrorData } = useContext(alertContext);
@ -56,6 +54,7 @@ export default function ExtraSidebar() {
return ret;
});
}
const flow = flows.find((f) => f.id === tabId);
return (
<div className="side-bar-arrangement">
@ -64,7 +63,6 @@ export default function ExtraSidebar() {
<button
className="extra-side-bar-buttons"
onClick={() => {
// openPopUp(<ImportModal />);
uploadFlow();
}}
>
@ -76,34 +74,33 @@ export default function ExtraSidebar() {
</ShadTooltip>
<ShadTooltip content="Export" side="top">
<button
className={classNames("extra-side-bar-buttons")}
onClick={(event) => {
openPopUp(<ExportModal />);
}}
>
<FileDown
strokeWidth={1.5}
className="side-bar-button-size"
></FileDown>
</button>
<ExportModal>
<div className={classNames("extra-side-bar-buttons")}>
<FileDown
strokeWidth={1.5}
className="side-bar-button-size"
></FileDown>
</div>
</ExportModal>
</ShadTooltip>
<ShadTooltip content="Code" side="top">
<button
className={classNames("extra-side-bar-buttons")}
onClick={(event) => {
openPopUp(<ApiModal flow={flows.find((f) => f.id === tabId)} />);
}}
>
<Code2 strokeWidth={1.5} className="side-bar-button-size"></Code2>
</button>
{flow && flow.data && (
<ApiModal flow={flow}>
<div className={classNames("extra-side-bar-buttons")}>
<Code2
strokeWidth={1.5}
className="side-bar-button-size"
></Code2>
</div>
</ApiModal>
)}
</ShadTooltip>
<ShadTooltip content="Save" side="top">
<button
className="extra-side-bar-buttons"
onClick={(event) => {
saveFlow(flows.find((f) => f.id === tabId));
saveFlow(flow);
setSuccessData({ title: "Changes saved successfully" });
}}
disabled={!isPending}

View file

@ -6,24 +6,24 @@ import { TabsContext } from "../../../../contexts/tabsContext";
import EditNodeModal from "../../../../modals/EditNodeModal";
import { classNames } from "../../../../utils";
const NodeToolbarComponent = (props) => {
export default function NodeToolbarComponent({ data, setData, deleteNode }) {
const [nodeLength, setNodeLength] = useState(
Object.keys(props.data.node.template).filter(
Object.keys(data.node.template).filter(
(t) =>
t.charAt(0) !== "_" &&
props.data.node.template[t].show &&
(props.data.node.template[t].type === "str" ||
props.data.node.template[t].type === "bool" ||
props.data.node.template[t].type === "float" ||
props.data.node.template[t].type === "code" ||
props.data.node.template[t].type === "prompt" ||
props.data.node.template[t].type === "file" ||
props.data.node.template[t].type === "Any" ||
props.data.node.template[t].type === "int")
data.node.template[t].show &&
(data.node.template[t].type === "str" ||
data.node.template[t].type === "bool" ||
data.node.template[t].type === "float" ||
data.node.template[t].type === "code" ||
data.node.template[t].type === "prompt" ||
data.node.template[t].type === "file" ||
data.node.template[t].type === "Any" ||
data.node.template[t].type === "int")
).length
);
const { setLastCopiedSelection, paste } = useContext(TabsContext);
const { paste } = useContext(TabsContext);
const reactFlowInstance = useReactFlow();
return (
<>
@ -33,7 +33,7 @@ const NodeToolbarComponent = (props) => {
<button
className="relative inline-flex items-center rounded-l-md bg-background px-2 py-2 text-foreground shadow-md ring-1 ring-inset ring-ring transition-all duration-500 ease-in-out hover:bg-muted focus:z-10"
onClick={() => {
props.deleteNode(props.data.id);
deleteNode(data.id);
}}
>
<Trash2 className="h-4 w-4"></Trash2>
@ -49,14 +49,14 @@ const NodeToolbarComponent = (props) => {
event.preventDefault();
paste(
{
nodes: [reactFlowInstance.getNode(props.data.id)],
nodes: [reactFlowInstance.getNode(data.id)],
edges: [],
},
{
x: 50,
y: 10,
paneX: reactFlowInstance.getNode(props.data.id).position.x,
paneY: reactFlowInstance.getNode(props.data.id).position.y,
paneX: reactFlowInstance.getNode(data.id).position.x,
paneY: reactFlowInstance.getNode(data.id).position.y,
}
);
}}
@ -67,25 +67,23 @@ const NodeToolbarComponent = (props) => {
<ShadTooltip
content={
props.data.node.documentation === ""
? "Coming Soon"
: "Documentation"
data.node.documentation === "" ? "Coming Soon" : "Documentation"
}
side="top"
>
<a
className={classNames(
"relative -ml-px inline-flex items-center bg-background px-2 py-2 text-foreground shadow-md ring-1 ring-inset ring-ring transition-all duration-500 ease-in-out hover:bg-muted focus:z-10" +
(props.data.node.documentation === ""
(data.node.documentation === ""
? " text-muted-foreground"
: " text-foreground")
)}
target="_blank"
rel="noopener noreferrer"
href={props.data.node.documentation}
href={data.node.documentation}
// deactivate link if no documentation is provided
onClick={(event) => {
if (props.data.node.documentation === "") {
if (data.node.documentation === "") {
event.preventDefault();
}
}}
@ -95,121 +93,25 @@ const NodeToolbarComponent = (props) => {
</ShadTooltip>
<ShadTooltip content="Edit" side="top">
<button
className={classNames(
"relative -ml-px inline-flex items-center rounded-r-md bg-background px-2 py-2 text-foreground shadow-md ring-1 ring-inset ring-ring transition-all duration-500 ease-in-out hover:bg-muted focus:z-10" +
(nodeLength == 0
? " text-muted-foreground"
: " text-foreground")
)}
onClick={(event) => {
if (nodeLength == 0) {
event.preventDefault();
}
event.preventDefault();
props.openPopUp(<EditNodeModal data={props.data} />);
}}
<EditNodeModal
data={data}
setData={setData}
nodeLength={nodeLength}
>
<Settings2 className="h-4 w-4 "></Settings2>
</button>
</ShadTooltip>
{/*
<Menu as="div" className="relative inline-block text-left z-100">
<button className="hover:dark:hover:bg-[#242f47] text-gray-700 transition-all duration-500 ease-in-out dark:bg-gray-800 dark:text-gray-300 shadow-md relative -ml-px inline-flex items-center bg-white px-2 py-2 ring-1 ring-inset ring-gray-300 hover:bg-muted focus:z-10 rounded-r-md">
<div>
<Menu.Button className="flex items-center">
<EllipsisVerticalIcon
className="w-5 h-5 "
aria-hidden="true"
/>
</Menu.Button>
</div>
<Transition
as={Fragment}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
<div
className={classNames(
"relative -ml-px inline-flex items-center rounded-r-md bg-background px-2 py-2 text-foreground shadow-md ring-1 ring-inset ring-ring transition-all duration-500 ease-in-out hover:bg-muted focus:z-10" +
(nodeLength == 0
? " text-muted-foreground"
: " text-foreground")
)}
>
<Menu.Items className="absolute z-40 mt-2 w-56 origin-top-right rounded-md bg-background shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none top-[28px]">
<div className="py-1">
<Menu.Item>
{({ active }) => (
<button
onClick={(event) => {
event.preventDefault();
props.openPopUp(
<EditNodeModal data={props.data} />
);
}}
className={classNames(
active
? "bg-muted text-gray-900"
: "text-foreground",
"w-full group flex items-center px-4 py-2 text-sm"
)}
>
<Settings
className="mr-3 h-5 w-5 text-gray-400 group-hover:text-gray-500"
aria-hidden="true"
/>
Edit
</button>
)}
</Menu.Item>
<Menu.Item>
{({ active }) => (
<button
onClick={(event) => {
event.preventDefault();
console.log(
reactFlowInstance.getNode(props.data.id)
);
paste(
{
nodes: [
reactFlowInstance.getNode(props.data.id),
],
edges: [],
},
{
x: 50,
y: 10,
paneX: reactFlowInstance.getNode(props.data.id)
.position.x,
paneY: reactFlowInstance.getNode(props.data.id)
.position.y,
}
);
}}
className={classNames(
active
? "bg-muted text-gray-900"
: "text-foreground",
"w-full group flex items-center px-4 py-2 text-sm"
)}
>
<DocumentDuplicateIcon
className="mr-3 h-5 w-5 text-gray-400 group-hover:text-gray-500"
aria-hidden="true"
/>
Duplicate
</button>
)}
</Menu.Item>
</div>
</Menu.Items>
</Transition>
</button>
</Menu> */}
<Settings2 className="h-4 w-4 "></Settings2>
</div>
</EditNodeModal>
</ShadTooltip>
</span>
</div>
</>
);
};
export default NodeToolbarComponent;
}

View file

@ -28,6 +28,7 @@ export type DropDownComponentType = {
};
export type ParameterComponentType = {
data: NodeDataType;
setData: (value: NodeDataType) => void;
title: string;
id: string;
color: string;

View file

@ -59,11 +59,6 @@ export function classNames(...classes: Array<string>) {
export const limitScrollFieldsModal = 10;
export enum TypeModal {
TEXT = 1,
PROMPT = 2,
}
export const textColors = {
white: "text-white",
red: "text-red-700",

View file

@ -132,7 +132,7 @@ module.exports = {
keyframes: {
slideDown: {
from: { height: 0 },
to: { height: 100 },
to: { height: "100vh" },
},
slideUp: {
from: { height: "var(--radix-accordion-content-height)" },