refactor: parameter component, edit node modal and api modal (#2928)

* changed column defs to receive handleOnNewValue and use it to change Advanced variable

* Exported function isTargetHandleConnected

* Refactored types of setNodeClass

* Exported type of handleOnNewValue

* Refactored useHandleNodeClass to only handle changes to node data

* Refactored toggleCellRender to handle advanced values by itself with the handleOnNewValue

* changed setNodeClass types and disabled hook

* changed handleNodeClass on parametercomponent

* changed handleNodeClass on the two components that used it

* refactor: Update handleNodeClass to accept newNodeClass and type only

* Refactor EditNodeModal component to use new handleNodeClass and columnDefs

* Changed columnDefs to receive new handleNodeClass and not receive useless parameters

* changed cellTypeStr to strRender

* Refactored inputFileComponent to use the new handleOnNewValue

* Refactored keypairList to convert values on the fly

* added parameterRenderComponent that renders all parameters in one place

* Exported parameterRenderComponent

* Changed tableNodeCellRender to use ParameterRenderComponent

* changed parameterredercomponent to receive name

* changed strrendercomponent to receive name

* changed nodecellrender to pass name and to check if value is undefined before assigning on templateData

* chore: Refactor use-handle-new-value to handle undefined values in changes

* Used ParameterRenderComponent at parameterComponent

* Refactored parameterRenderComponent to include refresh button

* Created refresh parameter component

* Added nodeId to parameterrendercomponent call

* Removed unused variable

* Refactored refreshButton

* Fixed parameters not showing when they dont have a value

* Created a tweakComplnent that renders the tweak individually, with the same table as the EditNode

* Created tweaks component, that renders all tweaks

* Changed tableNodeCellRender to pass setNode as well

* changed handleOnNewValue to use custom setNode if specified

* added editNodeComponent that handles the table and rowData and columnDefs

* changed editNodeModal to use editNodeComponent instead of table

* changed columndefs type to handle setNode and hideVisibility optional parameters

* changed useRowData to not use myData, and just use nodeClass

* Changed codeTabsPropsType tweaks property to include only the ncessary

* changed codeTabsComponent to use TweaksComponent and handle an internal nodes state

* changed apiModal to handle the tweaks build by finding the differences between old and current node

* fix bug on API modal that refresh tweaks table all the time

* Created new tweaks store type

* Added tweaks store with all of the logic needed to get the tweaks on the API page

* refactored TweakComponent to hold an temporary state to prevent the table from rerendering

* Added TweakComponent into TweaksComponent

* Removed external state on tableAdvancedToggle, making every state come from the Stores

* Removed external state from TableNodeCellRender and added isTweaks to choose which store to use

* Added SetNode type on HandleOnNewValue

* Added custom setNode to handleNodeClass

* Removed unused logic from apiModal

* removed unused old code

* Changed type of getChangesTypes

* Transformed string into object on get codes

* Changed getNodesWithDefaultValue to return nodes that will appear on Tweaks, as well as just the allowed parameters

* added hasTweaks to tabs

* added check of template keys to update the local nodeClass state, allowing the table to be updated just when the number of parameters changes

* passed isTweaks to columnDefs

* removed unused state and passed isTweaks to value getters

* Removed unused state

* updated tabsArrayType with hasTweaks and removed unused types

* Added local nodes tweaks state to the codetabscomponent and refactored conditions of display

* removed unused console.log

* changed advanced toggle to use parameterid given by the value

* changed nodecellrender to use parameter id given by the value

* passed parameter id by value to the renderers

* removed nodeClass from columnDefs definition

* Fixed isTargetHandleConnected returning error if field is undefined

* Fix performance issues on edit node modal

* Fixed scroll overflow issues on tweaksComponent

* Revert "Revert "refactor: update template api, handleonnewvalue and handlenodeclass hooks (#2628)""

This reverts commit 236ae82cabba2fa1128f498d781099facd222b57.

* 📝 (tweaksTest.spec.ts): remove redundant code and improve readability by simplifying the interaction with elements in the test case

* added custom id for tests

* ✨ (frontend): Add unique id prop to input components for better testability and accessibility.

✨ (Hierarchical Tasks Agent.spec.ts): Update dropdown element IDs to improve clarity and consistency
✨ (Memory Chatbot.spec.ts): Update dropdown element IDs to improve clarity and consistency
✨ (Sequential Tasks Agent.spec.ts): Update dropdown element IDs to improve clarity and consistency
✨ (chatInputOutputUser-shard-0.spec.ts): Update dropdown element IDs to improve clarity and consistency
✨ (chatInputOutputUser-shard-1.spec.ts): Update dropdown element IDs to improve clarity and consistency
✨ (chatInputOutputUser-shard-2.spec.ts): Update dropdown element IDs to improve clarity and consistency
✨ (decisionFlow.spec.ts): Update input list element IDs to improve clarity and consistency
✨ (decisionFlow.spec.ts): Update prompt area element IDs to improve clarity and consistency
✨ (decisionFlow.spec.ts): Update dropdown element IDs to improve clarity and consistency
✨ (freeze-path.spec.ts): Update dropdown element IDs to improve clarity and consistency
✨ (generalBugs-shard-0.spec.ts): Update dropdown element IDs to improve clarity and consistency
✨ (generalBugs-shard-1.spec.ts): Update dropdown element IDs to improve clarity and consistency
✨ (generalBugs-shard-3.spec.ts): Update dropdown element IDs to improve clarity and consistency

🔧 (logs.spec.ts, textInputOutput.spec.ts): update dropdown test selectors to match changes in the frontend codebase

* Fixed prompt not holding the value when validating

* Fixed range spec on int component

* Fixed OpenAI Model max tokens range spec

* ✨ (dropdownComponent.spec.ts): Update dropdown test cases to use more descriptive test IDs for better clarity and maintainability
📝 (fileUploadComponent.spec.ts): Add explicit wait for "Run Flow" button to ensure it is loaded before clicking
📝 (folders.spec.ts): Update file path in readFileSync function to use an absolute path for better reliability
📝 (freeze-path.spec.ts): Refactor test code to remove commented out code and improve readability by using more descriptive test IDs and removing unnecessary code snippets

✨ (inputListComponent.spec.ts): Update test file to use consistent naming convention for input elements in the InputListComponent
📝 (intComponent.spec.ts): Refactor test file to use consistent naming convention for input elements in the IntComponent

✨ (nestedComponent.spec.ts): Update test steps and interactions for nestedComponent to improve test coverage and accuracy.

📝 (promptModalComponent.spec.ts): Update test selectors for prompt modal component to improve consistency and readability
📝 (textAreaModalComponent.spec.ts): Update test selectors for text area modal component to improve consistency and readability
📝 (toggleComponent.spec.ts): Update test selectors for toggle component to improve consistency and readability

* 🐛 (intComponent.spec.ts): fix incorrect value comparison in test for IntComponent
🐛 (intComponent.spec.ts): fix missing test step for clicking on a specific element in IntComponent test

* 📝 (Vector Store.spec.ts): increase timeout for waiting for "built successfully" text to improve test reliability and prevent false negatives

* Fixed folders test

---------

Co-authored-by: anovazzi1 <otavio2204@gmail.com>
Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@langflow.org>
Co-authored-by: cristhianzl <cristhian.lousa@gmail.com>
This commit is contained in:
Lucas Oliveira 2024-07-26 13:32:24 -03:00 • committed by GitHub
commit a9863a050e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
80 changed files with 2035 additions and 2932 deletions

View file

@ -1,6 +1,7 @@
import operator
from functools import reduce
from langflow.field_typing.range_spec import RangeSpec
from langchain_openai import ChatOpenAI
from pydantic.v1 import SecretStr
@ -30,6 +31,7 @@ class OpenAIModelComponent(LCModelComponent):
display_name="Max Tokens",
advanced=True,
info="The maximum number of tokens to generate. Set to 0 for unlimited tokens.",
range_spec=RangeSpec(min=0, max=128000),
),
DictInput(name="model_kwargs", display_name="Model Kwargs", advanced=True),
BoolInput(

View file

@ -8,6 +8,7 @@
"name": "langflow",
"version": "0.1.2",
"dependencies": {
"@chakra-ui/number-input": "^2.1.2",
"@headlessui/react": "^2.0.4",
"@hookform/resolvers": "^3.6.0",
"@million/lint": "^1.0.0-rc.26",
@ -765,6 +766,293 @@
"node": ">=6.9.0"
}
},
"node_modules/@chakra-ui/anatomy": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/@chakra-ui/anatomy/-/anatomy-2.2.2.tgz",
"integrity": "sha512-MV6D4VLRIHr4PkW4zMyqfrNS1mPlCTiCXwvYGtDFQYr+xHFfonhAuf9WjsSc0nyp2m0OdkSLnzmVKkZFLo25Tg==",
"license": "MIT",
"peer": true
},
"node_modules/@chakra-ui/color-mode": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@chakra-ui/color-mode/-/color-mode-2.2.0.tgz",
"integrity": "sha512-niTEA8PALtMWRI9wJ4LL0CSBDo8NBfLNp4GD6/0hstcm3IlbBHTVKxN6HwSaoNYfphDQLxCjT4yG+0BJA5tFpg==",
"license": "MIT",
"peer": true,
"dependencies": {
"@chakra-ui/react-use-safe-layout-effect": "2.1.0"
},
"peerDependencies": {
"react": ">=18"
}
},
"node_modules/@chakra-ui/counter": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@chakra-ui/counter/-/counter-2.1.0.tgz",
"integrity": "sha512-s6hZAEcWT5zzjNz2JIWUBzRubo9la/oof1W7EKZVVfPYHERnl5e16FmBC79Yfq8p09LQ+aqFKm/etYoJMMgghw==",
"license": "MIT",
"dependencies": {
"@chakra-ui/number-utils": "2.0.7",
"@chakra-ui/react-use-callback-ref": "2.1.0",
"@chakra-ui/shared-utils": "2.0.5"
},
"peerDependencies": {
"react": ">=18"
}
},
"node_modules/@chakra-ui/form-control": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@chakra-ui/form-control/-/form-control-2.2.0.tgz",
"integrity": "sha512-wehLC1t4fafCVJ2RvJQT2jyqsAwX7KymmiGqBu7nQoQz8ApTkGABWpo/QwDh3F/dBLrouHDoOvGmYTqft3Mirw==",
"license": "MIT",
"dependencies": {
"@chakra-ui/icon": "3.2.0",
"@chakra-ui/react-context": "2.1.0",
"@chakra-ui/react-types": "2.0.7",
"@chakra-ui/react-use-merge-refs": "2.1.0",
"@chakra-ui/shared-utils": "2.0.5"
},
"peerDependencies": {
"@chakra-ui/system": ">=2.0.0",
"react": ">=18"
}
},
"node_modules/@chakra-ui/icon": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/@chakra-ui/icon/-/icon-3.2.0.tgz",
"integrity": "sha512-xxjGLvlX2Ys4H0iHrI16t74rG9EBcpFvJ3Y3B7KMQTrnW34Kf7Da/UC8J67Gtx85mTHW020ml85SVPKORWNNKQ==",
"license": "MIT",
"dependencies": {
"@chakra-ui/shared-utils": "2.0.5"
},
"peerDependencies": {
"@chakra-ui/system": ">=2.0.0",
"react": ">=18"
}
},
"node_modules/@chakra-ui/number-input": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/@chakra-ui/number-input/-/number-input-2.1.2.tgz",
"integrity": "sha512-pfOdX02sqUN0qC2ysuvgVDiws7xZ20XDIlcNhva55Jgm095xjm8eVdIBfNm3SFbSUNxyXvLTW/YQanX74tKmuA==",
"license": "MIT",
"dependencies": {
"@chakra-ui/counter": "2.1.0",
"@chakra-ui/form-control": "2.2.0",
"@chakra-ui/icon": "3.2.0",
"@chakra-ui/react-context": "2.1.0",
"@chakra-ui/react-types": "2.0.7",
"@chakra-ui/react-use-callback-ref": "2.1.0",
"@chakra-ui/react-use-event-listener": "2.1.0",
"@chakra-ui/react-use-interval": "2.1.0",
"@chakra-ui/react-use-merge-refs": "2.1.0",
"@chakra-ui/react-use-safe-layout-effect": "2.1.0",
"@chakra-ui/react-use-update-effect": "2.1.0",
"@chakra-ui/shared-utils": "2.0.5"
},
"peerDependencies": {
"@chakra-ui/system": ">=2.0.0",
"react": ">=18"
}
},
"node_modules/@chakra-ui/number-utils": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/@chakra-ui/number-utils/-/number-utils-2.0.7.tgz",
"integrity": "sha512-yOGxBjXNvLTBvQyhMDqGU0Oj26s91mbAlqKHiuw737AXHt0aPllOthVUqQMeaYLwLCjGMg0jtI7JReRzyi94Dg==",
"license": "MIT"
},
"node_modules/@chakra-ui/object-utils": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@chakra-ui/object-utils/-/object-utils-2.1.0.tgz",
"integrity": "sha512-tgIZOgLHaoti5PYGPTwK3t/cqtcycW0owaiOXoZOcpwwX/vlVb+H1jFsQyWiiwQVPt9RkoSLtxzXamx+aHH+bQ==",
"license": "MIT",
"peer": true
},
"node_modules/@chakra-ui/react-context": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@chakra-ui/react-context/-/react-context-2.1.0.tgz",
"integrity": "sha512-iahyStvzQ4AOwKwdPReLGfDesGG+vWJfEsn0X/NoGph/SkN+HXtv2sCfYFFR9k7bb+Kvc6YfpLlSuLvKMHi2+w==",
"license": "MIT",
"peerDependencies": {
"react": ">=18"
}
},
"node_modules/@chakra-ui/react-types": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/@chakra-ui/react-types/-/react-types-2.0.7.tgz",
"integrity": "sha512-12zv2qIZ8EHwiytggtGvo4iLT0APris7T0qaAWqzpUGS0cdUtR8W+V1BJ5Ocq+7tA6dzQ/7+w5hmXih61TuhWQ==",
"license": "MIT",
"peerDependencies": {
"react": ">=18"
}
},
"node_modules/@chakra-ui/react-use-callback-ref": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@chakra-ui/react-use-callback-ref/-/react-use-callback-ref-2.1.0.tgz",
"integrity": "sha512-efnJrBtGDa4YaxDzDE90EnKD3Vkh5a1t3w7PhnRQmsphLy3g2UieasoKTlT2Hn118TwDjIv5ZjHJW6HbzXA9wQ==",
"license": "MIT",
"peerDependencies": {
"react": ">=18"
}
},
"node_modules/@chakra-ui/react-use-event-listener": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@chakra-ui/react-use-event-listener/-/react-use-event-listener-2.1.0.tgz",
"integrity": "sha512-U5greryDLS8ISP69DKDsYcsXRtAdnTQT+jjIlRYZ49K/XhUR/AqVZCK5BkR1spTDmO9H8SPhgeNKI70ODuDU/Q==",
"license": "MIT",
"dependencies": {
"@chakra-ui/react-use-callback-ref": "2.1.0"
},
"peerDependencies": {
"react": ">=18"
}
},
"node_modules/@chakra-ui/react-use-interval": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@chakra-ui/react-use-interval/-/react-use-interval-2.1.0.tgz",
"integrity": "sha512-8iWj+I/+A0J08pgEXP1J1flcvhLBHkk0ln7ZvGIyXiEyM6XagOTJpwNhiu+Bmk59t3HoV/VyvyJTa+44sEApuw==",
"license": "MIT",
"dependencies": {
"@chakra-ui/react-use-callback-ref": "2.1.0"
},
"peerDependencies": {
"react": ">=18"
}
},
"node_modules/@chakra-ui/react-use-merge-refs": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@chakra-ui/react-use-merge-refs/-/react-use-merge-refs-2.1.0.tgz",
"integrity": "sha512-lERa6AWF1cjEtWSGjxWTaSMvneccnAVH4V4ozh8SYiN9fSPZLlSG3kNxfNzdFvMEhM7dnP60vynF7WjGdTgQbQ==",
"license": "MIT",
"peerDependencies": {
"react": ">=18"
}
},
"node_modules/@chakra-ui/react-use-safe-layout-effect": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@chakra-ui/react-use-safe-layout-effect/-/react-use-safe-layout-effect-2.1.0.tgz",
"integrity": "sha512-Knbrrx/bcPwVS1TorFdzrK/zWA8yuU/eaXDkNj24IrKoRlQrSBFarcgAEzlCHtzuhufP3OULPkELTzz91b0tCw==",
"license": "MIT",
"peerDependencies": {
"react": ">=18"
}
},
"node_modules/@chakra-ui/react-use-update-effect": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@chakra-ui/react-use-update-effect/-/react-use-update-effect-2.1.0.tgz",
"integrity": "sha512-ND4Q23tETaR2Qd3zwCKYOOS1dfssojPLJMLvUtUbW5M9uW1ejYWgGUobeAiOVfSplownG8QYMmHTP86p/v0lbA==",
"license": "MIT",
"peerDependencies": {
"react": ">=18"
}
},
"node_modules/@chakra-ui/react-utils": {
"version": "2.0.12",
"resolved": "https://registry.npmjs.org/@chakra-ui/react-utils/-/react-utils-2.0.12.tgz",
"integrity": "sha512-GbSfVb283+YA3kA8w8xWmzbjNWk14uhNpntnipHCftBibl0lxtQ9YqMFQLwuFOO0U2gYVocszqqDWX+XNKq9hw==",
"license": "MIT",
"peer": true,
"dependencies": {
"@chakra-ui/utils": "2.0.15"
},
"peerDependencies": {
"react": ">=18"
}
},
"node_modules/@chakra-ui/shared-utils": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/@chakra-ui/shared-utils/-/shared-utils-2.0.5.tgz",
"integrity": "sha512-4/Wur0FqDov7Y0nCXl7HbHzCg4aq86h+SXdoUeuCMD3dSj7dpsVnStLYhng1vxvlbUnLpdF4oz5Myt3i/a7N3Q==",
"license": "MIT"
},
"node_modules/@chakra-ui/styled-system": {
"version": "2.9.2",
"resolved": "https://registry.npmjs.org/@chakra-ui/styled-system/-/styled-system-2.9.2.tgz",
"integrity": "sha512-To/Z92oHpIE+4nk11uVMWqo2GGRS86coeMmjxtpnErmWRdLcp1WVCVRAvn+ZwpLiNR+reWFr2FFqJRsREuZdAg==",
"license": "MIT",
"peer": true,
"dependencies": {
"@chakra-ui/shared-utils": "2.0.5",
"csstype": "^3.1.2",
"lodash.mergewith": "4.6.2"
}
},
"node_modules/@chakra-ui/system": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/@chakra-ui/system/-/system-2.6.2.tgz",
"integrity": "sha512-EGtpoEjLrUu4W1fHD+a62XR+hzC5YfsWm+6lO0Kybcga3yYEij9beegO0jZgug27V+Rf7vns95VPVP6mFd/DEQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"@chakra-ui/color-mode": "2.2.0",
"@chakra-ui/object-utils": "2.1.0",
"@chakra-ui/react-utils": "2.0.12",
"@chakra-ui/styled-system": "2.9.2",
"@chakra-ui/theme-utils": "2.0.21",
"@chakra-ui/utils": "2.0.15",
"react-fast-compare": "3.2.2"
},
"peerDependencies": {
"@emotion/react": "^11.0.0",
"@emotion/styled": "^11.0.0",
"react": ">=18"
}
},
"node_modules/@chakra-ui/theme": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/@chakra-ui/theme/-/theme-3.3.1.tgz",
"integrity": "sha512-Hft/VaT8GYnItGCBbgWd75ICrIrIFrR7lVOhV/dQnqtfGqsVDlrztbSErvMkoPKt0UgAkd9/o44jmZ6X4U2nZQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"@chakra-ui/anatomy": "2.2.2",
"@chakra-ui/shared-utils": "2.0.5",
"@chakra-ui/theme-tools": "2.1.2"
},
"peerDependencies": {
"@chakra-ui/styled-system": ">=2.8.0"
}
},
"node_modules/@chakra-ui/theme-tools": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/@chakra-ui/theme-tools/-/theme-tools-2.1.2.tgz",
"integrity": "sha512-Qdj8ajF9kxY4gLrq7gA+Azp8CtFHGO9tWMN2wfF9aQNgG9AuMhPrUzMq9AMQ0MXiYcgNq/FD3eegB43nHVmXVA==",
"license": "MIT",
"peer": true,
"dependencies": {
"@chakra-ui/anatomy": "2.2.2",
"@chakra-ui/shared-utils": "2.0.5",
"color2k": "^2.0.2"
},
"peerDependencies": {
"@chakra-ui/styled-system": ">=2.0.0"
}
},
"node_modules/@chakra-ui/theme-utils": {
"version": "2.0.21",
"resolved": "https://registry.npmjs.org/@chakra-ui/theme-utils/-/theme-utils-2.0.21.tgz",
"integrity": "sha512-FjH5LJbT794r0+VSCXB3lT4aubI24bLLRWB+CuRKHijRvsOg717bRdUN/N1fEmEpFnRVrbewttWh/OQs0EWpWw==",
"license": "MIT",
"peer": true,
"dependencies": {
"@chakra-ui/shared-utils": "2.0.5",
"@chakra-ui/styled-system": "2.9.2",
"@chakra-ui/theme": "3.3.1",
"lodash.mergewith": "4.6.2"
}
},
"node_modules/@chakra-ui/utils": {
"version": "2.0.15",
"resolved": "https://registry.npmjs.org/@chakra-ui/utils/-/utils-2.0.15.tgz",
"integrity": "sha512-El4+jL0WSaYYs+rJbuYFDbjmfCcfGDmRY95GO4xwzit6YAPZBLcR65rOEwLps+XWluZTy1xdMrusg/hW0c1aAA==",
"license": "MIT",
"peer": true,
"dependencies": {
"@types/lodash.mergewith": "4.6.7",
"css-box-model": "1.2.1",
"framesync": "6.1.2",
"lodash.mergewith": "4.6.2"
}
},
"node_modules/@clack/core": {
"version": "0.3.4",
"resolved": "https://registry.npmjs.org/@clack/core/-/core-0.3.4.tgz",
@ -799,6 +1087,195 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@emotion/babel-plugin": {
"version": "11.11.0",
"resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz",
"integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/helper-module-imports": "^7.16.7",
"@babel/runtime": "^7.18.3",
"@emotion/hash": "^0.9.1",
"@emotion/memoize": "^0.8.1",
"@emotion/serialize": "^1.1.2",
"babel-plugin-macros": "^3.1.0",
"convert-source-map": "^1.5.0",
"escape-string-regexp": "^4.0.0",
"find-root": "^1.1.0",
"source-map": "^0.5.7",
"stylis": "4.2.0"
}
},
"node_modules/@emotion/babel-plugin/node_modules/convert-source-map": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
"license": "MIT",
"peer": true
},
"node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
"license": "MIT",
"peer": true,
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@emotion/babel-plugin/node_modules/source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
"integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
"license": "BSD-3-Clause",
"peer": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/@emotion/cache": {
"version": "11.11.0",
"resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz",
"integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"@emotion/memoize": "^0.8.1",
"@emotion/sheet": "^1.2.2",
"@emotion/utils": "^1.2.1",
"@emotion/weak-memoize": "^0.3.1",
"stylis": "4.2.0"
}
},
"node_modules/@emotion/hash": {
"version": "0.9.1",
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz",
"integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==",
"license": "MIT",
"peer": true
},
"node_modules/@emotion/is-prop-valid": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz",
"integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==",
"license": "MIT",
"peer": true,
"dependencies": {
"@emotion/memoize": "^0.8.1"
}
},
"node_modules/@emotion/memoize": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz",
"integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==",
"license": "MIT",
"peer": true
},
"node_modules/@emotion/react": {
"version": "11.11.4",
"resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.4.tgz",
"integrity": "sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==",
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.18.3",
"@emotion/babel-plugin": "^11.11.0",
"@emotion/cache": "^11.11.0",
"@emotion/serialize": "^1.1.3",
"@emotion/use-insertion-effect-with-fallbacks": "^1.0.1",
"@emotion/utils": "^1.2.1",
"@emotion/weak-memoize": "^0.3.1",
"hoist-non-react-statics": "^3.3.1"
},
"peerDependencies": {
"react": ">=16.8.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@emotion/serialize": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.4.tgz",
"integrity": "sha512-RIN04MBT8g+FnDwgvIUi8czvr1LU1alUMI05LekWB5DGyTm8cCBMCRpq3GqaiyEDRptEXOyXnvZ58GZYu4kBxQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"@emotion/hash": "^0.9.1",
"@emotion/memoize": "^0.8.1",
"@emotion/unitless": "^0.8.1",
"@emotion/utils": "^1.2.1",
"csstype": "^3.0.2"
}
},
"node_modules/@emotion/sheet": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz",
"integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==",
"license": "MIT",
"peer": true
},
"node_modules/@emotion/styled": {
"version": "11.11.5",
"resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.11.5.tgz",
"integrity": "sha512-/ZjjnaNKvuMPxcIiUkf/9SHoG4Q196DRl1w82hQ3WCsjo1IUR8uaGWrC6a87CrYAW0Kb/pK7hk8BnLgLRi9KoQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.18.3",
"@emotion/babel-plugin": "^11.11.0",
"@emotion/is-prop-valid": "^1.2.2",
"@emotion/serialize": "^1.1.4",
"@emotion/use-insertion-effect-with-fallbacks": "^1.0.1",
"@emotion/utils": "^1.2.1"
},
"peerDependencies": {
"@emotion/react": "^11.0.0-rc.0",
"react": ">=16.8.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@emotion/unitless": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz",
"integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==",
"license": "MIT",
"peer": true
},
"node_modules/@emotion/use-insertion-effect-with-fallbacks": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz",
"integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==",
"license": "MIT",
"peer": true,
"peerDependencies": {
"react": ">=16.8.0"
}
},
"node_modules/@emotion/utils": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz",
"integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==",
"license": "MIT",
"peer": true
},
"node_modules/@emotion/weak-memoize": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz",
"integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==",
"license": "MIT",
"peer": true
},
"node_modules/@esbuild/aix-ppc64": {
"version": "0.21.5",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
@ -4998,8 +5475,17 @@
"node_modules/@types/lodash": {
"version": "4.17.5",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.5.tgz",
"integrity": "sha512-MBIOHVZqVqgfro1euRDWX7OO0fBVUUMrN6Pwm8LQsz8cWhEpihlvR70ENj3f40j58TNxZaWv2ndSkInykNBBJw==",
"dev": true
"integrity": "sha512-MBIOHVZqVqgfro1euRDWX7OO0fBVUUMrN6Pwm8LQsz8cWhEpihlvR70ENj3f40j58TNxZaWv2ndSkInykNBBJw=="
},
"node_modules/@types/lodash.mergewith": {
"version": "4.6.7",
"resolved": "https://registry.npmjs.org/@types/lodash.mergewith/-/lodash.mergewith-4.6.7.tgz",
"integrity": "sha512-3m+lkO5CLRRYU0fhGRp7zbsGi6+BZj0uTVSwvcKU+nSlhjA9/QRNfuSGnD2mX6hQA7ZbmcCkzk5h4ZYGOtk14A==",
"license": "MIT",
"peer": true,
"dependencies": {
"@types/lodash": "*"
}
},
"node_modules/@types/mathjax": {
"version": "0.0.37",
@ -5028,6 +5514,13 @@
"undici-types": "~5.26.4"
}
},
"node_modules/@types/parse-json": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz",
"integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==",
"license": "MIT",
"peer": true
},
"node_modules/@types/prop-types": {
"version": "15.7.12",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz",
@ -5402,6 +5895,49 @@
"proxy-from-env": "^1.1.0"
}
},
"node_modules/babel-plugin-macros": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz",
"integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==",
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.12.5",
"cosmiconfig": "^7.0.0",
"resolve": "^1.19.0"
},
"engines": {
"node": ">=10",
"npm": ">=6"
}
},
"node_modules/babel-plugin-macros/node_modules/cosmiconfig": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz",
"integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==",
"license": "MIT",
"peer": true,
"dependencies": {
"@types/parse-json": "^4.0.0",
"import-fresh": "^3.2.1",
"parse-json": "^5.0.0",
"path-type": "^4.0.0",
"yaml": "^1.10.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/babel-plugin-macros/node_modules/yaml": {
"version": "1.10.2",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
"integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
"license": "ISC",
"peer": true,
"engines": {
"node": ">= 6"
}
},
"node_modules/babel-plugin-syntax-hermes-parser": {
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/babel-plugin-syntax-hermes-parser/-/babel-plugin-syntax-hermes-parser-0.21.1.tgz",
@ -6358,6 +6894,13 @@
"color-support": "bin.js"
}
},
"node_modules/color2k": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/color2k/-/color2k-2.0.3.tgz",
"integrity": "sha512-zW190nQTIoXcGCaU08DvVNFTmQhUpnJfVuAKfWqUQkflXKpaDdpaYoM0iluLS9lgJNHyBF58KKA2FBEwkD7wog==",
"license": "MIT",
"peer": true
},
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@ -6461,6 +7004,16 @@
"node": ">= 8"
}
},
"node_modules/css-box-model": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz",
"integrity": "sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==",
"license": "MIT",
"peer": true,
"dependencies": {
"tiny-invariant": "^1.0.6"
}
},
"node_modules/css.escape": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz",
@ -7571,6 +8124,13 @@
"node": ">=8"
}
},
"node_modules/find-root": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz",
"integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==",
"license": "MIT",
"peer": true
},
"node_modules/find-up": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
@ -7735,6 +8295,23 @@
}
}
},
"node_modules/framesync": {
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/framesync/-/framesync-6.1.2.tgz",
"integrity": "sha512-jBTqhX6KaQVDyus8muwZbBeGGP0XgujBRbQ7gM7BRdS3CadCZIHiawyzYLnafYcvZIh5j8WE7cxZKFn7dXhu9g==",
"license": "MIT",
"peer": true,
"dependencies": {
"tslib": "2.4.0"
}
},
"node_modules/framesync/node_modules/tslib": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
"integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==",
"license": "0BSD",
"peer": true
},
"node_modules/fs-extra": {
"version": "11.2.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz",
@ -9249,6 +9826,13 @@
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
"dev": true
},
"node_modules/lodash.mergewith": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz",
"integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==",
"license": "MIT",
"peer": true
},
"node_modules/lodash.template": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz",
@ -12228,6 +12812,13 @@
"react": ">=16.13.1"
}
},
"node_modules/react-fast-compare": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz",
"integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==",
"license": "MIT",
"peer": true
},
"node_modules/react-hook-form": {
"version": "7.52.0",
"resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.52.0.tgz",
@ -13637,6 +14228,13 @@
"inline-style-parser": "0.1.1"
}
},
"node_modules/stylis": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz",
"integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==",
"license": "MIT",
"peer": true
},
"node_modules/sucrase": {
"version": "3.35.0",
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",

View file

@ -3,6 +3,7 @@
"version": "0.1.2",
"private": true,
"dependencies": {
"@chakra-ui/number-input": "^2.1.2",
"@headlessui/react": "^2.0.4",
"@hookform/resolvers": "^3.6.0",
"@million/lint": "^1.0.0-rc.26",

View file

@ -1,42 +1,22 @@
import TableNodeComponent from "@/components/TableNodeComponent";
import useHandleNodeClass from "@/CustomNodes/hooks/use-handle-node-class";
import { ParameterRenderComponent } from "@/components/parameterRenderComponent";
import { usePostTemplateValue } from "@/controllers/API/queries/nodes/use-post-template-value";
import useAlertStore from "@/stores/alertStore";
import { cloneDeep } from "lodash";
import { ReactNode, useEffect, useRef, useState } from "react";
import { useHotkeys } from "react-hotkeys-hook";
import { useUpdateNodeInternals } from "reactflow";
import CodeAreaComponent from "../../../../components/codeAreaComponent";
import DictComponent from "../../../../components/dictComponent";
import Dropdown from "../../../../components/dropdownComponent";
import FloatComponent from "../../../../components/floatComponent";
import { default as IconComponent } from "../../../../components/genericIconComponent";
import InputFileComponent from "../../../../components/inputFileComponent";
import InputGlobalComponent from "../../../../components/inputGlobalComponent";
import InputListComponent from "../../../../components/inputListComponent";
import IntComponent from "../../../../components/intComponent";
import KeypairListComponent from "../../../../components/keypairListComponent";
import { Multiselect } from "../../../../components/multiselectComponent";
import PromptAreaComponent from "../../../../components/promptComponent";
import ShadTooltip from "../../../../components/shadTooltipComponent";
import TextAreaComponent from "../../../../components/textAreaComponent";
import ToggleShadComponent from "../../../../components/toggleShadComponent";
import { Button } from "../../../../components/ui/button";
import { RefreshButton } from "../../../../components/ui/refreshButton";
import { LANGFLOW_SUPPORTED_TYPES } from "../../../../constants/constants";
import { Case } from "../../../../shared/components/caseComponent";
import useFlowStore from "../../../../stores/flowStore";
import useFlowsManagerStore from "../../../../stores/flowsManagerStore";
import { useShortcutsStore } from "../../../../stores/shortcuts";
import { useTypesStore } from "../../../../stores/typesStore";
import { APIClassType } from "../../../../types/api";
import { ParameterComponentType } from "../../../../types/components";
import {
debouncedHandleUpdateValues,
handleUpdateValues,
} from "../../../../utils/parameterUtils";
import {
convertObjToArray,
convertValuesToNumbers,
getGroupOutputNodeId,
hasDuplicateKeys,
scapedJSONStringfy,
} from "../../../../utils/reactflowUtils";
import {
@ -49,12 +29,9 @@ import {
} from "../../../../utils/utils";
import useFetchDataOnMount from "../../../hooks/use-fetch-data-on-mount";
import useHandleOnNewValue from "../../../hooks/use-handle-new-value";
import useHandleNodeClass from "../../../hooks/use-handle-node-class";
import useHandleRefreshButtonPress from "../../../hooks/use-handle-refresh-buttons";
import OutputComponent from "../OutputComponent";
import HandleRenderComponent from "../handleRenderComponent";
import OutputModal from "../outputModal";
import { TEXT_FIELD_TYPES } from "./constants";
export default function ParameterComponent({
left,
@ -81,10 +58,12 @@ export default function ParameterComponent({
const edges = useFlowStore((state) => state.edges);
const setNode = useFlowStore((state) => state.setNode);
const myData = useTypesStore((state) => state.data);
const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot);
const [isLoading, setIsLoading] = useState(false);
const postTemplateValue = usePostTemplateValue({
node: data.node!,
nodeId: data.id,
parameterId: name,
});
const updateNodeInternals = useUpdateNodeInternals();
const [errorDuplicateKey, setErrorDuplicateKey] = useState(false);
const setFilterEdge = useFlowStore((state) => state.setFilterEdge);
const [openOutputModal, setOpenOutputModal] = useState(false);
const flowPool = useFlowStore((state) => state.flowPool);
@ -132,29 +111,12 @@ export default function ParameterComponent({
}
}
const setErrorData = useAlertStore((state) => state.setErrorData);
const output = useShortcutsStore((state) => state.output);
useHotkeys(output, handleOutputWShortcut, { preventDefault });
const { handleOnNewValue: handleOnNewValueHook } = useHandleOnNewValue(
data,
name,
takeSnapshot,
handleUpdateValues,
debouncedHandleUpdateValues,
setNode,
setIsLoading,
);
const { handleNodeClass: handleNodeClassHook } = useHandleNodeClass(
data,
name,
takeSnapshot,
setNode,
updateNodeInternals,
);
const { handleRefreshButtonPress: handleRefreshButtonPressHook } =
useHandleRefreshButtonPress(setIsLoading, setNode);
const { handleNodeClass } = useHandleNodeClass(data.id);
let disabled =
edges.some(
@ -168,27 +130,13 @@ export default function ParameterComponent({
edge.sourceHandle === scapedJSONStringfy(proxy ? { ...id, proxy } : id),
) ?? false;
const handleRefreshButtonPress = async (name, data) => {
handleRefreshButtonPressHook(name, data);
};
const { handleOnNewValue } = useHandleOnNewValue({
node: data.node!,
nodeId: data.id,
name,
});
useFetchDataOnMount(data, name, handleUpdateValues, setNode, setIsLoading);
const handleOnNewValue = async (
newValue: string | string[] | boolean | Object[],
dbValue?: boolean,
skipSnapshot: boolean | undefined = false,
): Promise<void> => {
handleOnNewValueHook(newValue, dbValue, skipSnapshot);
};
const handleNodeClass = (
newNodeClass: APIClassType,
code?: string,
type?: string,
): void => {
handleNodeClassHook(newNodeClass, code, type);
};
useFetchDataOnMount(data.node!, handleNodeClass, name, postTemplateValue);
useEffect(() => {
// @ts-ignore
@ -401,301 +349,21 @@ export default function ParameterComponent({
testIdComplement={`${data?.type?.toLowerCase()}-shownode`}
/>
)}
<Case
condition={
left === true &&
TEXT_FIELD_TYPES.includes(type ?? "") &&
!data.node?.template[name]?.options
}
>
<div className="w-full">
<Case condition={data.node?.template[name]?.list}>
<div
className={
// Commenting this out until we have a better
// way to display
// (data.node?.template[name]?.refresh ? "w-5/6 " : "") +
"mt-2 flex-grow"
}
>
<InputListComponent
componentName={name}
disabled={disabled}
value={
!data.node!.template[name]?.value ||
data.node!.template[name]?.value === ""
? [""]
: data.node!.template[name]?.value
}
onChange={handleOnNewValue}
/>
</div>
</Case>
<Case condition={data.node?.template[name]?.multiline}>
<div className="mt-2 flex w-full flex-col">
<div className="flex-grow">
<TextAreaComponent
disabled={disabled}
value={data.node!.template[name]?.value ?? ""}
onChange={handleOnNewValue}
id={"textarea-" + data.node!.template[name]?.name}
data-testid={"textarea-" + data.node!.template[name]?.name}
/>
</div>
{data.node?.template[name]?.refresh_button && (
<div className="flex-grow">
<RefreshButton
isLoading={isLoading}
disabled={disabled}
name={name}
data={data}
button_text={
data.node?.template[name].refresh_button_text
}
className="extra-side-bar-buttons mt-1"
handleUpdateValues={handleRefreshButtonPress}
id={"refresh-button-" + name}
/>
</div>
)}
</div>
</Case>
<Case
condition={
!data.node?.template[name]?.multiline &&
!data.node?.template[name]?.list
}
>
<div className="mt-2 flex w-full items-center">
<div
className={
"flex-grow " +
(data.node?.template[name]?.refresh_button ? "w-5/6" : "")
}
>
<InputGlobalComponent
disabled={disabled}
onChange={handleOnNewValue}
name={name}
data={data.node?.template[name]!}
/>
</div>
{data.node?.template[name]?.refresh_button && (
<div className="w-1/6">
<RefreshButton
isLoading={isLoading}
disabled={disabled}
name={name}
data={data}
button_text={
data.node?.template[name].refresh_button_text
}
className="extra-side-bar-buttons ml-2 mt-1"
handleUpdateValues={handleRefreshButtonPress}
id={"refresh-button-" + name}
/>
</div>
)}
</div>
</Case>
</div>
</Case>
<Case condition={left === true && type === "bool"}>
<div className="mt-2 w-full">
<ToggleShadComponent
id={"toggle-" + name}
disabled={disabled}
enabled={data.node?.template[name]?.value ?? false}
setEnabled={handleOnNewValue}
size="large"
<div className="mt-2 w-full">
{data.node?.template[name] !== undefined && (
<ParameterRenderComponent
handleOnNewValue={handleOnNewValue}
name={name}
nodeId={data.id}
templateData={data.node?.template[name]!}
templateValue={data.node?.template[name].value ?? ""}
editNode={false}
/>
</div>
</Case>
<Case condition={left === true && type === "float"}>
<div className="mt-2 w-full">
<FloatComponent
handleNodeClass={handleNodeClass}
nodeClass={data.node!}
disabled={disabled}
value={data.node?.template[name]?.value ?? ""}
rangeSpec={data.node?.template[name]?.rangeSpec}
onChange={handleOnNewValue}
/>
</div>
</Case>
<Case condition={left === true && type === "table"}>
<div className="mt-2 w-full">
<TableNodeComponent
description={info || "Add or edit data"}
columns={data.node?.template[name]?.table_schema?.columns}
onChange={handleOnNewValue}
tableTitle={data.node?.template[name]?.display_name ?? "Table"}
value={data.node?.template[name]?.value}
/>
</div>
</Case>
<Case
condition={
left === true &&
type === "str" &&
!data.node?.template[name]?.list &&
(data.node?.template[name]?.options ||
data.node?.template[name]?.real_time_refresh)
}
>
<div className="mt-2 flex w-full items-center gap-2">
<div className="flex-1">
<Dropdown
disabled={disabled}
isLoading={isLoading}
options={data.node!.template[name]?.options}
onSelect={handleOnNewValue}
value={data.node!.template[name]?.value}
id={"dropdown-" + name}
/>
</div>
{data.node?.template[name]?.refresh_button && (
<div className="w-1/6">
<RefreshButton
isLoading={isLoading}
disabled={disabled}
name={name}
data={data}
button_text={data.node?.template[name]?.refresh_button_text}
handleUpdateValues={handleRefreshButtonPress}
id={"refresh-button-" + name}
/>
</div>
)}
</div>
</Case>
<Case
condition={
type === "str" &&
!!data.node?.template[name]?.options &&
!!data.node?.template[name]?.list
}
>
<div className="mt-2 flex w-full items-center">
<Multiselect
disabled={disabled}
options={data?.node?.template?.[name]?.options || []}
values={data?.node?.template?.[name]?.value || []}
id={"multiselect-" + name}
onValueChange={handleOnNewValue}
/>
</div>
</Case>
<Case condition={left === true && type === "code"}>
<div className="mt-2 w-full">
<CodeAreaComponent
readonly={
data.node?.flow && data.node.template[name]?.dynamic
? true
: false
}
dynamic={data.node?.template[name]?.dynamic ?? false}
setNodeClass={handleNodeClass}
nodeClass={data.node}
disabled={disabled}
value={data.node?.template[name]?.value ?? ""}
onChange={handleOnNewValue}
id={"code-input-" + name}
/>
</div>
</Case>
<Case condition={left === true && type === "file"}>
<div className="mt-2 w-full">
<InputFileComponent
disabled={disabled}
value={data.node?.template[name]?.value ?? ""}
onChange={handleOnNewValue}
fileTypes={data.node?.template[name]?.fileTypes}
onFileChange={(filePath: string) => {
data.node!.template[name].file_path = filePath;
}}
></InputFileComponent>
</div>
</Case>
<Case condition={left === true && type === "int"}>
<div className="mt-2 w-full">
<IntComponent
rangeSpec={data.node?.template[name]?.rangeSpec}
disabled={disabled}
value={data.node?.template[name]?.value ?? ""}
onChange={handleOnNewValue}
id={"int-input-" + name}
/>
</div>
</Case>
<Case condition={left === true && type === "prompt"}>
<div className="mt-2 w-full">
<PromptAreaComponent
readonly={data.node?.flow ? true : false}
field_name={name}
setNodeClass={handleNodeClass}
nodeClass={data.node}
disabled={disabled}
value={data.node?.template[name]?.value ?? ""}
onChange={handleOnNewValue}
id={"prompt-input-" + name}
data-testid={"prompt-input-" + name}
/>
</div>
</Case>
<Case condition={left === true && type === "NestedDict"}>
<div
className={"mt-2 w-full" + (disabled ? " cursor-not-allowed" : "")}
>
<DictComponent
disabled={disabled}
editNode={false}
value={
!data.node!.template[name]?.value ||
!Object.keys(data.node!.template[name]?.value || {}).length
? {}
: data.node!.template[name]?.value
}
onChange={handleOnNewValue}
id="div-dict-input"
/>
</div>
</Case>
<Case condition={left === true && type === "dict"}>
<div className="mt-2 w-full">
<KeypairListComponent
disabled={disabled}
editNode={false}
value={
!data.node!.template[name]?.value ||
!Object.keys(data.node!.template[name]?.value || {}).length
? [{ "": "" }]
: convertObjToArray(data.node!.template[name]?.value, type!)
}
duplicateKey={errorDuplicateKey}
onChange={(newValue) => {
const valueToNumbers = convertValuesToNumbers(newValue);
setErrorDuplicateKey(hasDuplicateKeys(valueToNumbers));
// if data.node?.template[name]?.list is true, then the value is an array of objects
// else we need to get the first object of the array
if (data.node?.template[name]?.list) {
handleOnNewValue(valueToNumbers);
} else handleOnNewValue(valueToNumbers[0]);
}}
isList={data.node?.template[name]?.list ?? false}
/>
</div>
</Case>
)}
</div>
{openOutputModal && (
<OutputModal
open={openOutputModal}

View file

@ -0,0 +1,44 @@
import {
ERROR_UPDATING_COMPONENT,
SAVE_DEBOUNCE_TIME,
TITLE_ERROR_UPDATING_COMPONENT,
} from "@/constants/constants";
import {
APIClassType,
APITemplateType,
ResponseErrorDetailAPI,
} from "@/types/api";
import { UseMutationResult } from "@tanstack/react-query";
import { cloneDeep, debounce } from "lodash";
export const mutateTemplate = debounce(
async (
newValue,
node: APIClassType,
setNodeClass,
postTemplateValue: UseMutationResult<
APITemplateType | undefined,
ResponseErrorDetailAPI,
any
>,
setErrorData,
) => {
try {
const newNode = cloneDeep(node);
const newTemplate = await postTemplateValue.mutateAsync({
value: newValue,
});
if (newTemplate) {
newNode.template = newTemplate;
}
setNodeClass(newNode);
} catch (e) {
const error = e as ResponseErrorDetailAPI;
setErrorData({
title: TITLE_ERROR_UPDATING_COMPONENT,
list: [error.response?.data?.detail || ERROR_UPDATING_COMPONENT],
});
}
},
SAVE_DEBOUNCE_TIME,
);

View file

@ -1,55 +1,40 @@
import { cloneDeep } from "lodash";
import { useEffect } from "react";
import {
ERROR_UPDATING_COMPONENT,
TITLE_ERROR_UPDATING_COMPONENT,
} from "../../constants/constants";
APIClassType,
APITemplateType,
ResponseErrorDetailAPI,
} from "@/types/api";
import { UseMutationResult } from "@tanstack/react-query";
import { useEffect } from "react";
import useAlertStore from "../../stores/alertStore";
import { ResponseErrorDetailAPI } from "../../types/api";
import { NodeDataType } from "../../types/flow";
import { mutateTemplate } from "../helpers/mutate-template";
const useFetchDataOnMount = (
data: NodeDataType,
node: APIClassType,
setNodeClass: (node: APIClassType) => void,
name: string,
handleUpdateValues: (name: string, data: NodeDataType) => Promise<any>,
setNode: (id: string, callback: (oldNode: any) => any) => void,
setIsLoading: (value: boolean) => void,
postTemplateValue: UseMutationResult<
APITemplateType | undefined,
ResponseErrorDetailAPI,
any
>,
) => {
const setErrorData = useAlertStore((state) => state.setErrorData);
useEffect(() => {
async function fetchData() {
const template = node.template[name];
if (
(data.node?.template[name]?.real_time_refresh ||
data.node?.template[name]?.refresh_button) &&
(template?.real_time_refresh || template?.refresh_button) &&
// options can be undefined but not an empty array
(data.node?.template[name]?.options?.length ?? 0) === 0
(template?.options?.length ?? 0) === 0
) {
setIsLoading(true);
try {
let newTemplate = await handleUpdateValues(name, data);
if (newTemplate) {
setNode(data.id, (oldNode) => {
let newNode = cloneDeep(oldNode);
newNode.data = {
...newNode.data,
};
newNode.data.node.template = newTemplate;
return newNode;
});
}
} catch (error) {
let responseError = error as ResponseErrorDetailAPI;
setErrorData({
title: TITLE_ERROR_UPDATING_COMPONENT,
list: [
responseError?.response?.data?.detail ?? ERROR_UPDATING_COMPONENT,
],
});
}
setIsLoading(false);
mutateTemplate(
template?.value,
node,
setNodeClass,
postTemplateValue,
setErrorData,
);
}
}
fetchData();

View file

@ -1,79 +1,100 @@
import { usePostTemplateValue } from "@/controllers/API/queries/nodes/use-post-template-value";
import useAlertStore from "@/stores/alertStore";
import useFlowStore from "@/stores/flowStore";
import useFlowsManagerStore from "@/stores/flowsManagerStore";
import { APIClassType, InputFieldType } from "@/types/api";
import { NodeType } from "@/types/flow";
import { cloneDeep } from "lodash";
import {
ERROR_UPDATING_COMPONENT,
TITLE_ERROR_UPDATING_COMPONENT,
} from "../../constants/constants";
import useAlertStore from "../../stores/alertStore";
import { ResponseErrorTypeAPI } from "../../types/api";
import { NodeDataType } from "../../types/flow";
import { mutateTemplate } from "../helpers/mutate-template";
export type handleOnNewValueType = (
changes: Partial<InputFieldType>,
options?: {
skipSnapshot?: boolean;
setNodeClass?: (node: APIClassType) => void;
},
) => void;
const useHandleOnNewValue = ({
node,
nodeId,
name,
setNode: setNodeExternal,
}: {
node: APIClassType;
nodeId: string;
name: string;
setNode?: (
id: string,
update: NodeType | ((oldState: NodeType) => NodeType),
) => void;
}) => {
const takeSnapshot = useFlowsManagerStore((state) => state.takeSnapshot);
const setNode = setNodeExternal ?? useFlowStore((state) => state.setNode);
const useHandleOnNewValue = (
data: NodeDataType,
name: string,
takeSnapshot: () => void,
handleUpdateValues: (name: string, data: NodeDataType) => Promise<any>,
debouncedHandleUpdateValues: any,
setNode: (id: string, callback: (oldNode: any) => any) => void,
setIsLoading: (value: boolean) => void,
) => {
const setErrorData = useAlertStore((state) => state.setErrorData);
const handleOnNewValue = async (newValue, dbValue, skipSnapshot = false) => {
const nodeTemplate = data.node!.template[name];
const currentValue = nodeTemplate.value;
const postTemplateValue = usePostTemplateValue({
parameterId: name,
nodeId: nodeId,
node: node,
});
if (currentValue !== newValue && !skipSnapshot) {
takeSnapshot();
const handleOnNewValue: handleOnNewValueType = async (changes, options?) => {
const newNode = cloneDeep(node);
const template = newNode.template;
if (!template) {
setErrorData({ title: "Template not found in the component" });
return;
}
const parameter = template[name];
if (!parameter) {
setErrorData({ title: "Parameter not found in the template" });
return;
}
if (!options?.skipSnapshot) takeSnapshot();
Object.entries(changes).forEach(([key, value]) => {
if (value !== undefined) parameter[key] = value;
});
const shouldUpdate =
data.node?.template[name].real_time_refresh &&
!data.node?.template[name].refresh_button &&
currentValue !== newValue;
parameter.real_time_refresh && !parameter.refresh_button;
const typeToDebounce = nodeTemplate.type;
const setNodeClass = (newNodeClass: APIClassType) => {
options?.setNodeClass && options.setNodeClass(newNodeClass);
setNode(nodeId, (oldNode) => {
const newData = cloneDeep(oldNode.data);
newData.node = newNodeClass;
return {
...oldNode,
data: newData,
};
});
};
nodeTemplate.value = newValue;
let newTemplate;
if (shouldUpdate) {
setIsLoading(true);
try {
if (["int"].includes(typeToDebounce)) {
newTemplate = await handleUpdateValues(name, data);
} else {
newTemplate = await debouncedHandleUpdateValues(name, data);
}
} catch (error) {
let responseError = error as ResponseErrorTypeAPI;
setErrorData({
title: TITLE_ERROR_UPDATING_COMPONENT,
list: [
responseError?.response?.data?.detail.error ??
ERROR_UPDATING_COMPONENT,
],
});
}
setIsLoading(false);
if (shouldUpdate && changes.value) {
mutateTemplate(
changes.value,
newNode,
setNodeClass,
postTemplateValue,
setErrorData,
);
}
setNode(data.id, (oldNode) => {
const newNode = cloneDeep(oldNode);
newNode.data = {
...newNode.data,
setNode(nodeId, (oldNode) => {
const newData = cloneDeep(oldNode.data);
newData.node = newNode;
return {
...oldNode,
data: newData,
};
if (dbValue !== undefined) {
newNode.data.node.template[name].load_from_db = dbValue;
}
if (data.node?.template[name].real_time_refresh && newTemplate) {
newNode.data.node.template = newTemplate;
} else {
newNode.data.node.template[name].value = newValue;
}
return newNode;
});
};

View file

@ -1,37 +1,30 @@
import useFlowStore from "@/stores/flowStore";
import { NodeType } from "@/types/flow";
import { cloneDeep } from "lodash";
import { NodeDataType } from "../../types/flow";
const useHandleNodeClass = (
data: NodeDataType,
name: string,
takeSnapshot: () => void,
setNode: (id: string, callback: (oldNode: any) => any) => void,
updateNodeInternals: (id: string) => void,
nodeId: string,
setMyNode?: (
id: string,
update: NodeType | ((oldState: NodeType) => NodeType),
) => void,
) => {
const handleNodeClass = (newNodeClass, code, type?: string) => {
if (!data.node) return;
if (data.node!.template[name].value !== code) {
takeSnapshot();
}
const setNode = setMyNode ?? useFlowStore((state) => state.setNode);
setNode(data.id, (oldNode) => {
const handleNodeClass = (newNodeClass, type?: string) => {
setNode(nodeId, (oldNode) => {
let newNode = cloneDeep(oldNode);
newNode.data = {
...newNode.data,
node: newNodeClass,
description: newNodeClass.description ?? data.node!.description,
display_name: newNodeClass.display_name ?? data.node!.display_name,
node: cloneDeep(newNodeClass),
};
if (type) {
newNode.data.type = type;
}
newNode.data.node.template[name].value = code;
return newNode;
});
updateNodeInternals(data.id);
};
return { handleNodeClass };

View file

@ -1,47 +0,0 @@
import { cloneDeep } from "lodash";
import {
ERROR_UPDATING_COMPONENT,
TITLE_ERROR_UPDATING_COMPONENT,
} from "../../constants/constants";
import useAlertStore from "../../stores/alertStore";
import { ResponseErrorDetailAPI } from "../../types/api";
import { handleUpdateValues } from "../../utils/parameterUtils";
const useHandleRefreshButtonPress = (
setIsLoading: (value: boolean) => void,
setNode: (id: string, callback: (oldNode: any) => any) => void,
) => {
const setErrorData = useAlertStore((state) => state.setErrorData);
const handleRefreshButtonPress = async (name, data) => {
setIsLoading(true);
try {
let newTemplate = await handleUpdateValues(name, data);
if (newTemplate) {
setNode(data.id, (oldNode) => {
let newNode = cloneDeep(oldNode);
newNode.data = {
...newNode.data,
};
newNode.data.node.template = newTemplate;
return newNode;
});
}
} catch (error) {
let responseError = error as ResponseErrorDetailAPI;
setErrorData({
title: TITLE_ERROR_UPDATING_COMPONENT,
list: [
responseError?.response?.data?.detail ?? ERROR_UPDATING_COMPONENT,
],
});
}
setIsLoading(false);
};
return { handleRefreshButtonPress };
};
export default useHandleRefreshButtonPress;

View file

@ -0,0 +1,49 @@
import AccordionComponent from "@/components/accordionComponent";
import ShadTooltip from "@/components/shadTooltipComponent";
import { EditNodeComponent } from "@/modals/editNodeModal/components/editNodeComponent";
import { APIClassType } from "@/types/api";
import { NodeType } from "@/types/flow";
import { customStringify } from "@/utils/reactflowUtils";
import { useEffect, useState } from "react";
export function TweakComponent({
open,
node,
}: {
open: boolean;
node: NodeType;
}) {
const [nodeClass, setNodeClass] = useState<APIClassType | undefined>(
node.data?.node,
);
useEffect(() => {
if (
customStringify(Object.keys(node.data?.node?.template ?? {})) ===
customStringify(Object.keys(nodeClass?.template ?? {}))
)
return;
setNodeClass(node.data?.node);
}, [node.data?.node]);
return node && node.data && nodeClass ? (
<AccordionComponent
trigger={
<ShadTooltip side="top" styleClasses="z-50" content={node.data.id}>
<div>{node.data.node?.display_name}</div>
</ShadTooltip>
}
keyValue={node.data.id}
>
<EditNodeComponent
open={open}
autoHeight
hideVisibility
nodeClass={nodeClass}
isTweaks
nodeId={node.data.id}
/>
</AccordionComponent>
) : (
<></>
);
}

View file

@ -0,0 +1,16 @@
import { useTweaksStore } from "@/stores/tweaksStore";
import { NodeType } from "@/types/flow";
import { TweakComponent } from "../tweakComponent";
export function TweaksComponent({ open }: { open: boolean }) {
const nodes = useTweaksStore((state) => state.nodes);
return (
<div className="h-full w-full overflow-y-auto overflow-x-hidden rounded-lg bg-muted custom-scroll">
{nodes?.map((node: NodeType, i) => (
<div className="px-3" key={i}>
<TweakComponent open={open} node={node} />
</div>
))}
</div>
);
}

View file

@ -1,82 +1,34 @@
import { cloneDeep } from "lodash";
import { useEffect, useState } from "react";
import { useTweaksStore } from "@/stores/tweaksStore";
import { useState } from "react";
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
import { oneDark } from "react-syntax-highlighter/dist/cjs/styles/prism";
import CodeAreaComponent from "../../components/codeAreaComponent";
import Dropdown from "../../components/dropdownComponent";
import FloatComponent from "../../components/floatComponent";
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 { LANGFLOW_SUPPORTED_TYPES } from "../../constants/constants";
import getTabsOrder from "../../modals/apiModal/utils/get-tabs-order";
import { Case } from "../../shared/components/caseComponent";
import { useDarkStore } from "../../stores/darkStore";
import useFlowStore from "../../stores/flowStore";
import { codeTabsPropsType } from "../../types/components";
import {
convertObjToArray,
convertValuesToNumbers,
hasDuplicateKeys,
} from "../../utils/reactflowUtils";
import { classNames, cn } from "../../utils/utils";
import AccordionComponent from "../accordionComponent";
import DictComponent from "../dictComponent";
import { cn } from "../../utils/utils";
import IconComponent from "../genericIconComponent";
import InputComponent from "../inputComponent";
import KeypairListComponent from "../keypairListComponent";
import ShadTooltip from "../shadTooltipComponent";
import { Button } from "../ui/button";
import { Label } from "../ui/label";
import { Switch } from "../ui/switch";
import { TweaksComponent } from "./components/tweaksComponent";
export default function CodeTabsComponent({
flow,
open,
tabs,
activeTab,
setActiveTab,
isMessage,
tweaks,
setActiveTweaks,
activeTweaks,
allowExport = false,
isThereTweaks = false,
isThereWH = false,
}: codeTabsPropsType) {
const [isCopied, setIsCopied] = useState<Boolean>(false);
const [data, setData] = useState(flow ? flow["data"]!["nodes"] : null);
const dark = useDarkStore((state) => state.dark);
const unselectAll = useFlowStore((state) => state.unselectAll);
const [errorDuplicateKey, setErrorDuplicateKey] = useState(false);
useEffect(() => {
if (flow && flow["data"]!["nodes"]) {
setData(flow["data"]!["nodes"]);
}
}, [flow]);
useEffect(() => {
if (tweaks && data) {
unselectAll();
}
}, []);
const nodes = useTweaksStore((state) => state.nodes);
const copyToClipboard = () => {
if (!navigator.clipboard || !navigator.clipboard.writeText) {
@ -92,12 +44,6 @@ export default function CodeTabsComponent({
});
};
const type = (node, templateParam) => {
return node.data.node.template[templateParam].type;
};
const tabsOrder = getTabsOrder(isThereWH, isThereTweaks);
return (
<Tabs
value={activeTab}
@ -130,29 +76,31 @@ export default function CodeTabsComponent({
)}
<div className="float-right mx-2 mb-1 mt-2 flex items-center gap-4">
{tweaks && (
<div className={Number(activeTab) > 2 ? "hidden" : "flex gap-2"}>
<Switch
style={{
transform: `scaleX(${0.7}) scaleY(${0.7})`,
}}
id="tweaks-switch"
onCheckedChange={setActiveTweaks}
autoFocus={false}
/>
<Label
className={cn(
"relative right-1 top-[4px] text-xs font-medium text-muted-foreground",
activeTweaks ? "text-primary" : "",
)}
htmlFor="tweaks-switch"
>
Tweaks
</Label>
</div>
)}
{nodes.length > 0 &&
tabs.find((tab) => tab.name.toLowerCase() === "tweaks") &&
tabs[activeTab].hasTweaks && (
<div className="flex gap-2">
<Switch
style={{
transform: `scaleX(${0.7}) scaleY(${0.7})`,
}}
id="tweaks-switch"
onCheckedChange={setActiveTweaks}
autoFocus={false}
/>
<Label
className={cn(
"relative right-1 top-[4px] text-xs font-medium text-muted-foreground",
activeTweaks ? "text-primary" : "",
)}
htmlFor="tweaks-switch"
>
Tweaks
</Label>
</div>
)}
{Number(activeTab) < 5 && (
{tabs[activeTab].name.toLowerCase !== "tweaks" && (
<>
<Button
variant="ghost"
@ -177,7 +125,7 @@ export default function CodeTabsComponent({
className="api-modal-tabs-content overflow-hidden"
key={idx} // Remember to add a unique key prop
>
{tabsOrder[idx].toLowerCase() !== "tweaks" ? (
{tab.name.toLowerCase() !== "tweaks" ? (
<div className="flex h-full w-full flex-col">
{tab.description && (
<div
@ -193,675 +141,9 @@ export default function CodeTabsComponent({
{tab.code}
</SyntaxHighlighter>
</div>
) : tabsOrder[idx].toLowerCase() === "tweaks" ? (
) : tab.name.toLowerCase() === "tweaks" ? (
<>
<div className="api-modal-according-display">
<div
className={classNames(
"h-[70vh] w-full overflow-y-auto overflow-x-hidden rounded-lg bg-muted custom-scroll",
)}
>
{data?.map((node: any, i) => (
<div className="px-3" key={i}>
{tweaks?.tweaksList!.includes(node["data"]["id"]) && (
<AccordionComponent
trigger={
<ShadTooltip
side="top"
styleClasses="z-50"
content={node["data"]["id"]}
>
<div>{node["data"]["node"]["display_name"]}</div>
</ShadTooltip>
}
keyValue={node["data"]["id"]}
>
<div className="api-modal-table-arrangement">
<Table className="table-fixed bg-muted outline-1">
<TableHeader className="h-10 border-input text-xs font-medium text-ring">
<TableRow className="">
<TableHead className="h-7 text-center">
PARAM
</TableHead>
<TableHead className="h-7 p-0 text-center">
VALUE
</TableHead>
</TableRow>
</TableHeader>
<TableBody className="p-0">
{Object.keys(node["data"]["node"]["template"])
.filter(
(templateField) =>
templateField.charAt(0) !== "_" &&
node.data.node.template[templateField]
.show &&
LANGFLOW_SUPPORTED_TYPES.has(
node.data.node.template[templateField]
.type,
),
)
.map((templateField, indx) => {
return (
<TableRow key={indx} className="h-10">
<TableCell className="p-0 text-center text-sm text-foreground">
{templateField}
</TableCell>
<TableCell className="p-0 text-xs text-foreground">
<div className="m-auto w-[250px]">
<Case
condition={
type(node, templateField) ===
"str" &&
!node.data.node.template[
templateField
].options
}
>
<Case
condition={
node.data.node.template[
templateField
]?.list
}
>
<InputListComponent
componentName={templateField}
editNode={true}
disabled={false}
value={
!node.data.node.template[
templateField
].value ||
node.data.node.template[
templateField
].value === ""
? [""]
: node.data.node.template[
templateField
].value
}
onChange={(target) => {
setData((old) => {
let newInputList =
cloneDeep(old);
newInputList![
i
].data.node.template[
templateField
].value = target;
return newInputList;
});
tweaks?.buildTweakObject!(
node["data"]["id"],
target,
node.data.node.template[
templateField
],
);
}}
/>
</Case>
<Case
condition={
node.data.node.template[
templateField
].multiline
}
>
<div>
<TextAreaComponent
disabled={false}
editNode={true}
value={
!node.data.node.template[
templateField
].value ||
node.data.node.template[
templateField
].value === ""
? ""
: node.data.node
.template[
templateField
].value
}
onChange={(target) => {
setData((old) => {
let newInputList =
cloneDeep(old);
newInputList![
i
].data.node.template[
templateField
].value = target;
return newInputList;
});
tweaks?.buildTweakObject!(
node["data"]["id"],
target,
node.data.node.template[
templateField
],
);
}}
/>
</div>
</Case>
<Case
condition={
!node.data.node.template[
templateField
].multiline &&
!node.data.node.template[
templateField
].list
}
>
<InputComponent
editNode={true}
disabled={false}
password={
node.data.node.template[
templateField
].password ?? false
}
value={
!node.data.node.template[
templateField
].value ||
node.data.node.template[
templateField
].value === ""
? ""
: node.data.node.template[
templateField
].value
}
onChange={(target) => {
setData((old) => {
let newInputList =
cloneDeep(old);
newInputList![
i
].data.node.template[
templateField
].value = target;
return newInputList;
});
tweaks?.buildTweakObject!(
node["data"]["id"],
target,
node.data.node.template[
templateField
],
);
}}
/>
</Case>
</Case>
<Case
condition={
type(node, templateField) ===
"bool"
}
>
<div className="ml-auto">
{" "}
<ToggleShadComponent
enabled={
node.data.node.template[
templateField
].value
}
setEnabled={(e) => {
setData((old) => {
let newInputList =
cloneDeep(old);
newInputList![
i
].data.node.template[
templateField
].value = e;
return newInputList;
});
tweaks?.buildTweakObject!(
node["data"]["id"],
e,
node.data.node.template[
templateField
],
);
}}
size="small"
disabled={false}
/>
</div>
</Case>
<Case
condition={
type(node, templateField) ===
"file"
}
>
<div className="mx-auto">
<InputFileComponent
editNode={true}
disabled={false}
value={
node.data.node.template[
templateField
].value ?? ""
}
onChange={(target: any) => {}}
fileTypes={
node.data.node.template[
templateField
].fileTypes
}
onFileChange={(
value: any,
) => {
node.data.node.template[
templateField
].file_path = value;
}}
></InputFileComponent>
</div>
</Case>
<Case
condition={
type(node, templateField) ===
"float"
}
>
<div className="mx-auto">
<FloatComponent
disabled={false}
editNode={true}
value={
!node.data.node.template[
templateField
].value ||
node.data.node.template[
templateField
].value === ""
? ""
: node.data.node.template[
templateField
].value
}
rangeSpec={
node.data.node.template[
templateField
].rangeSpec
}
onChange={(target) => {
setData((old) => {
let newInputList =
cloneDeep(old);
newInputList![
i
].data.node.template[
templateField
].value = target;
return newInputList;
});
tweaks?.buildTweakObject!(
node["data"]["id"],
target,
node.data.node.template[
templateField
],
);
}}
/>
</div>
</Case>
<Case
condition={
type(node, templateField) ===
"str" &&
node.data.node.template[
templateField
].options
}
>
<div className="mx-auto">
<Dropdown
editNode={true}
options={
node.data.node.template[
templateField
].options
}
onSelect={(target) => {
setData((old) => {
let newInputList =
cloneDeep(old);
newInputList![
i
].data.node.template[
templateField
].value = target;
return newInputList;
});
tweaks?.buildTweakObject!(
node["data"]["id"],
target,
node.data.node.template[
templateField
],
);
}}
value={
!node.data.node.template[
templateField
].value ||
node.data.node.template[
templateField
].value === ""
? ""
: node.data.node.template[
templateField
].value
}
></Dropdown>
</div>
</Case>
<Case
condition={
type(node, templateField) ===
"int"
}
>
<div className="mx-auto">
<IntComponent
disabled={false}
editNode={true}
rangeSpec={
node.data.node.template[
templateField
].rangeSpec
}
value={
!node.data.node.template[
templateField
].value ||
node.data.node.template[
templateField
].value === ""
? ""
: node.data.node.template[
templateField
].value
}
onChange={(target) => {
setData((old) => {
let newInputList =
cloneDeep(old);
newInputList![
i
].data.node.template[
templateField
].value = target;
return newInputList;
});
tweaks?.buildTweakObject!(
node["data"]["id"],
target,
node.data.node.template[
templateField
],
);
}}
/>
</div>
</Case>
<Case
condition={
type(node, templateField) ===
"prompt"
}
>
<div className="mx-auto">
<PromptAreaComponent
readonly={true}
editNode={true}
disabled={false}
value={
!node.data.node.template[
templateField
].value ||
node.data.node.template[
templateField
].value === ""
? ""
: node.data.node.template[
templateField
].value
}
onChange={(target) => {
setData((old) => {
let newInputList =
cloneDeep(old);
newInputList![
i
].data.node.template[
templateField
].value = target;
return newInputList;
});
tweaks?.buildTweakObject!(
node["data"]["id"],
target,
node.data.node.template[
templateField
],
);
}}
/>
</div>
</Case>
<Case
condition={
type(node, templateField) ===
"code"
}
>
<div className="mx-auto">
<CodeAreaComponent
disabled={false}
editNode={true}
readonly={true}
value={
!node.data.node.template[
templateField
].value ||
node.data.node.template[
templateField
].value === ""
? ""
: node.data.node.template[
templateField
].value
}
onChange={(target) => {
setData((old) => {
let newInputList =
cloneDeep(old);
newInputList![
i
].data.node.template[
templateField
].value = target;
return newInputList;
});
tweaks?.buildTweakObject!(
node["data"]["id"],
target,
node.data.node.template[
templateField
],
);
}}
/>
</div>
</Case>
<Case
condition={
type(node, templateField) ===
"dict"
}
>
<div className="mx-auto overflow-auto custom-scroll">
<KeypairListComponent
disabled={false}
editNode={true}
value={
node.data.node!.template[
templateField
].value?.length === 0 ||
!node.data.node!.template[
templateField
].value
? [{ "": "" }]
: convertObjToArray(
node.data.node!
.template[
templateField
].value,
type(
node,
templateField,
),
)
}
duplicateKey={
errorDuplicateKey
}
onChange={(target) => {
const valueToNumbers =
convertValuesToNumbers(
target,
);
node.data.node!.template[
templateField
].value = valueToNumbers;
setErrorDuplicateKey(
hasDuplicateKeys(
valueToNumbers,
),
);
setData((old) => {
let newInputList =
cloneDeep(old);
newInputList![
i
].data.node.template[
templateField
].value = target;
return newInputList;
});
tweaks?.buildTweakObject!(
node["data"]["id"],
target,
node.data.node.template[
templateField
],
);
}}
isList={
node.data.node!.template[
templateField
]?.list ?? false
}
/>
</div>
</Case>
<Case
condition={
type(node, templateField) ===
"NestedDict"
}
>
<div className="mx-auto">
<DictComponent
disabled={false}
editNode={true}
value={
node.data.node!.template[
templateField
].value?.toString() === "{}"
? {}
: node.data.node!
.template[
templateField
].value
}
onChange={(target) => {
setData((old) => {
let newInputList =
cloneDeep(old);
newInputList![
i
].data.node.template[
templateField
].value = target;
return newInputList;
});
tweaks?.buildTweakObject!(
node["data"]["id"],
target,
node.data.node.template[
templateField
],
);
}}
/>
</div>
</Case>
<Case
condition={
type(node, templateField) ===
"Any"
}
>
<>-</>
</Case>
</div>
</TableCell>
</TableRow>
);
})}
</TableBody>
</Table>
</div>
</AccordionComponent>
)}
{tweaks?.tweaksList!.length === 0 && (
<>
<div className="pt-3">
No tweaks are available for this flow.
</div>
</>
)}
</div>
))}
</div>
</div>
<TweaksComponent open={open} />
</>
) : null}
</TabsContent>

View file

@ -4,7 +4,6 @@ import {
CONSOLE_ERROR_MSG,
INVALID_FILE_ALERT,
} from "../../constants/alerts_constants";
import { uploadFile } from "../../controllers/API";
import useAlertStore from "../../stores/alertStore";
import useFlowsManagerStore from "../../stores/flowsManagerStore";
import { FileComponentType } from "../../types/components";
@ -13,25 +12,22 @@ import { Button } from "../ui/button";
export default function InputFileComponent({
value,
onChange,
handleOnNewValue,
disabled,
fileTypes,
onFileChange,
editNode = false,
id,
}: FileComponentType): JSX.Element {
const currentFlowId = useFlowsManagerStore((state) => state.currentFlowId);
const [myValue, setMyValue] = useState(value);
const [loading, setLoading] = useState(false);
const setErrorData = useAlertStore((state) => state.setErrorData);
// Clear component state
useEffect(() => {
if (disabled && value !== "") {
setMyValue("");
onChange("", undefined, true);
onFileChange("");
handleOnNewValue({ value: "", file_path: "" }, { skipSnapshot: true });
}
}, [disabled, onChange]);
}, [disabled, handleOnNewValue]);
function checkFileType(fileName: string): boolean {
if (fileTypes === undefined) return true;
@ -43,10 +39,6 @@ export default function InputFileComponent({
return false;
}
useEffect(() => {
setMyValue(value);
}, [value]);
const { mutate } = usePostUploadFile();
const handleButtonClick = (): void => {
@ -74,11 +66,9 @@ export default function InputFileComponent({
const { file_path } = data;
// sets the value that goes to the backend
onFileChange(file_path);
// Update the state and on with the name of the file
// sets the value to the user
setMyValue(file.name);
onChange(file.name);
handleOnNewValue({ value: file.name, file_path });
setLoading(false);
},
onError: () => {
@ -107,6 +97,7 @@ export default function InputFileComponent({
<div className={disabled ? "input-component-div" : "w-full"}>
<div className="input-file-component gap-3">
<span
data-testid={id}
onClick={handleButtonClick}
className={
editNode
@ -116,7 +107,7 @@ export default function InputFileComponent({
: "input-dialog primary-input text-muted-foreground"
}
>
{myValue !== "" ? myValue : "No file"}
{value !== "" ? value : "No file"}
</span>
{!editNode && (
<Button

View file

@ -14,6 +14,7 @@ export default function InputListComponent({
editNode = false,
componentName,
playgroundDisabled,
id,
}: InputListComponentType): JSX.Element {
useEffect(() => {
if (disabled && value.length > 0 && value[0] !== "") {
@ -49,10 +50,7 @@ export default function InputListComponent({
newInputList[idx] = event.target.value;
onChange(newInputList);
}}
data-testid={
`input-list-input${editNode ? "-edit" : ""}_${componentName}-` +
idx
}
data-testid={`${id}_` + idx}
/>
{idx === 0 ? (
<Button

View file

@ -1,10 +1,14 @@
import { useEffect } from "react";
import { IntComponentType } from "../../types/components";
import { cn } from "@/utils/utils";
import {
handleKeyDown,
handleOnlyIntegerInput,
} from "../../utils/reactflowUtils";
import { Input } from "../ui/input";
NumberDecrementStepper,
NumberIncrementStepper,
NumberInput,
NumberInputField,
NumberInputStepper,
} from "@chakra-ui/number-input";
import { useEffect, useRef, useState } from "react";
import { IntComponentType } from "../../types/components";
import { handleKeyDown } from "../../utils/reactflowUtils";
export default function IntComponent({
value,
@ -15,7 +19,6 @@ export default function IntComponent({
id = "",
}: IntComponentType): JSX.Element {
const min = -Infinity;
// Clear component state
useEffect(() => {
if (disabled && value !== "") {
@ -23,32 +26,54 @@ export default function IntComponent({
}
}, [disabled, onChange]);
const [cursor, setCursor] = useState<number | null>(null);
const ref = useRef<HTMLInputElement>(null);
useEffect(() => {
ref.current?.setSelectionRange(cursor, cursor);
}, [ref, cursor, value]);
const handleChangeInput = (e: React.ChangeEvent<HTMLInputElement>) => {
setCursor(e.target.selectionStart);
onChange(e.target.value);
};
return (
<div className="w-full">
<Input
<NumberInput
id={id}
onKeyDown={(event) => {
handleOnlyIntegerInput(event);
handleKeyDown(event, value, "");
}}
type="number"
step={rangeSpec?.step ?? 1}
step={(Number.isInteger(rangeSpec?.step) ? rangeSpec?.step : 1) ?? 1}
min={rangeSpec?.min ?? min}
max={rangeSpec?.max ?? undefined}
onInput={(event: React.ChangeEvent<HTMLInputElement>) => {
if (Number(event.target.value) < min) {
event.target.value = min.toString();
}
onChange={(value) => {
onChange(value);
}}
value={value ?? ""}
className={editNode ? "input-edit-node" : ""}
disabled={disabled}
placeholder={editNode ? "Integer number" : "Type an integer number"}
onChange={(event) => {
onChange(event.target.value);
}}
data-testid={id}
/>
>
<NumberInputField
className={cn(
editNode ? "input-edit-node" : "",
"nopan nodelete nodrag noflow primary-input",
)}
onChange={handleChangeInput}
onKeyDown={(event) => {
handleKeyDown(event, value, "");
}}
onInput={(event: React.ChangeEvent<HTMLInputElement>) => {
if (Number(event.target.value) < min) {
event.target.value = min.toString();
}
}}
disabled={disabled}
placeholder={editNode ? "Integer number" : "Type an integer number"}
data-testid={id}
ref={ref}
/>
<NumberInputStepper paddingRight={10}>
<NumberIncrementStepper fontSize={8} marginTop={6} />
<NumberDecrementStepper fontSize={8} marginBottom={6} />
</NumberInputStepper>
</NumberInput>
</div>
);
}

View file

@ -1,6 +1,11 @@
import { useEffect, useRef, useState } from "react";
import { useEffect, useState } from "react";
import { KeyPairListComponentType } from "../../types/components";
import {
convertObjToArray,
convertValuesToNumbers,
hasDuplicateKeys,
} from "@/utils/reactflowUtils";
import { cloneDeep } from "lodash";
import { classNames } from "../../utils/utils";
import IconComponent from "../genericIconComponent";
@ -11,8 +16,8 @@ export default function KeypairListComponent({
onChange,
disabled,
editNode = false,
duplicateKey,
isList = true,
id,
}: KeyPairListComponentType): JSX.Element {
useEffect(() => {
if (disabled && value.length > 0 && value[0] !== "") {
@ -20,7 +25,22 @@ export default function KeypairListComponent({
}
}, [disabled]);
const myValue = Array.isArray(value) ? value : [value];
const [duplicateKey, setDuplicateKey] = useState(false);
const myValue =
Object.keys(value || {})?.length === 0 || !value
? [{ "": "" }]
: convertObjToArray(value, "dict");
Array.isArray(value) ? value : [value];
const handleNewValue = (newValue: any) => {
const valueToNumbers = convertValuesToNumbers(newValue);
setDuplicateKey(hasDuplicateKeys(valueToNumbers));
if (isList) {
onChange(valueToNumbers);
} else onChange(valueToNumbers[0]);
};
const handleChangeKey = (event, idx) => {
const oldKey = Object.keys(myValue[idx])[0];
@ -29,7 +49,7 @@ export default function KeypairListComponent({
const newValue = cloneDeep(myValue);
newValue[idx] = updatedObj;
onChange(newValue);
handleNewValue(newValue);
};
const handleChangeValue = (event, idx) => {
@ -39,7 +59,7 @@ export default function KeypairListComponent({
const newValue = cloneDeep(myValue);
newValue[idx] = updatedObj;
onChange(newValue);
handleNewValue(newValue);
};
return (
@ -100,11 +120,7 @@ export default function KeypairListComponent({
? "editNodeplusbtn" + index.toString()
: "plusbtn" + index.toString()
}
data-testid={
editNode
? "editNodeplusbtn" + index.toString()
: "plusbtn" + index.toString()
}
data-testid={id}
>
<IconComponent
name="Plus"

View file

@ -0,0 +1,46 @@
import { RefreshButton } from "@/components/ui/refreshButton";
import { usePostTemplateValue } from "@/controllers/API/queries/nodes/use-post-template-value";
import { mutateTemplate } from "@/CustomNodes/helpers/mutate-template";
import useAlertStore from "@/stores/alertStore";
export function RefreshParameterComponent({
children,
templateData,
disabled,
nodeClass,
handleNodeClass,
nodeId,
name,
}) {
const postTemplateValue = usePostTemplateValue({
parameterId: name,
nodeId: nodeId,
node: nodeClass,
});
const setErrorData = useAlertStore((state) => state.setErrorData);
const handleRefreshButtonPress = () =>
mutateTemplate(
templateData.value,
nodeClass,
handleNodeClass,
postTemplateValue,
setErrorData,
);
return (
<div className="flex w-full items-center gap-2">
<div className="w-full">{children}</div>
{templateData.refresh_button && (
<div className="w-1/6">
<RefreshButton
isLoading={postTemplateValue.isPending}
disabled={disabled}
button_text={templateData.refresh_button_text}
handleUpdateValues={handleRefreshButtonPress}
id={"refresh-button-" + name}
/>
</div>
)}
</div>
);
}

View file

@ -0,0 +1,73 @@
import Dropdown from "../../../dropdownComponent";
import InputGlobalComponent from "../../../inputGlobalComponent";
import InputListComponent from "../../../inputListComponent";
import { Multiselect } from "../../../multiselectComponent";
import TextAreaComponent from "../../../textAreaComponent";
export function StrRenderComponent({
templateData,
value,
name,
disabled,
handleOnNewValue,
editNode,
id,
}) {
const onChange = (value: any, dbValue?: boolean, skipSnapshot?: boolean) => {
handleOnNewValue({ value, load_from_db: dbValue }, { skipSnapshot });
};
if (!templateData.options) {
return templateData?.list ? (
<InputListComponent
componentName={name ?? undefined}
editNode={editNode}
disabled={disabled}
value={!value || value === "" ? [""] : value}
onChange={onChange}
id={`inputlist_${id}`}
/>
) : templateData.multiline ? (
<TextAreaComponent
id={`textarea_${id}`}
disabled={disabled}
editNode={editNode}
value={value ?? ""}
onChange={onChange}
/>
) : (
<InputGlobalComponent
disabled={disabled}
editNode={editNode}
onChange={onChange}
name={name}
data={templateData}
/>
);
}
if (!!templateData.options && !!templateData?.list) {
return (
<Multiselect
editNode={editNode}
disabled={disabled}
options={templateData.options || []}
values={[value ?? "Choose an option"]}
id={`multiselect_${id}`}
onValueChange={onChange}
/>
);
}
if (!!templateData.options) {
return (
<Dropdown
editNode={editNode}
options={templateData.options}
onSelect={onChange}
value={value ?? "Choose an option"}
id={`dropdown_${id}`}
/>
);
}
}

View file

@ -0,0 +1,149 @@
import { TEXT_FIELD_TYPES } from "@/CustomNodes/GenericNode/components/parameterComponent/constants";
import { handleOnNewValueType } from "@/CustomNodes/hooks/use-handle-new-value";
import { APIClassType, InputFieldType } from "@/types/api";
import CodeAreaComponent from "../codeAreaComponent";
import DictComponent from "../dictComponent";
import FloatComponent from "../floatComponent";
import InputFileComponent from "../inputFileComponent";
import IntComponent from "../intComponent";
import KeypairListComponent from "../keypairListComponent";
import PromptAreaComponent from "../promptComponent";
import ToggleShadComponent from "../toggleShadComponent";
import { RefreshParameterComponent } from "./component/refreshParameterComponent";
import { StrRenderComponent } from "./component/strRenderComponent";
export function ParameterRenderComponent({
handleOnNewValue,
name,
nodeId,
templateData,
templateValue,
editNode,
handleNodeClass,
nodeClass,
disabled,
}: {
handleOnNewValue: handleOnNewValueType;
name: string;
nodeId: string;
templateData: Partial<InputFieldType>;
templateValue: any;
editNode: boolean;
handleNodeClass: (value: any, code?: string, type?: string) => void;
nodeClass: APIClassType;
disabled: boolean;
}) {
const onChange = (value: any) => {
handleOnNewValue({ value });
};
const id = (
templateData.type +
"_" +
(editNode ? "edit_" : "") +
templateData.name
).toLowerCase();
return (
<RefreshParameterComponent
templateData={templateData}
disabled={disabled}
nodeId={nodeId}
nodeClass={nodeClass}
handleNodeClass={handleNodeClass}
name={name}
>
{TEXT_FIELD_TYPES.includes(templateData.type ?? "") ? (
<StrRenderComponent
templateData={templateData}
value={templateValue}
name={name}
disabled={disabled}
handleOnNewValue={handleOnNewValue}
id={id}
editNode={editNode}
/>
) : templateData.type === "NestedDict" ? (
<DictComponent
disabled={disabled}
editNode={editNode}
value={(templateValue || "").toString() === "{}" ? {} : templateValue}
onChange={onChange}
id={`dict_${id}`}
/>
) : templateData.type === "dict" ? (
<KeypairListComponent
disabled={disabled}
editNode={editNode}
value={templateValue}
onChange={onChange}
isList={templateData.list ?? false}
id={`keypair_${id}`}
/>
) : templateData.type === "bool" ? (
<ToggleShadComponent
id={`toggle_${id}`}
disabled={disabled}
enabled={templateValue}
setEnabled={onChange}
size={editNode ? "small" : "large"}
/>
) : templateData.type === "float" ? (
<FloatComponent
disabled={disabled}
editNode={editNode}
rangeSpec={templateData.range_spec}
value={templateValue ?? ""}
onChange={onChange}
id={`float_${id}`}
/>
) : templateData.type === "int" ? (
<IntComponent
rangeSpec={templateData.range_spec}
id={`int_${id}`}
disabled={disabled}
editNode={editNode}
value={templateValue ?? ""}
onChange={onChange}
/>
) : templateData.type === "file" ? (
<InputFileComponent
editNode={editNode}
disabled={disabled}
value={templateValue ?? ""}
handleOnNewValue={handleOnNewValue}
fileTypes={templateData.fileTypes}
id={`inputfile_${id}`}
/>
) : templateData.type === "prompt" ? (
<PromptAreaComponent
readonly={nodeClass.flow ? true : false}
field_name={name}
editNode={editNode}
disabled={disabled}
nodeClass={nodeClass}
setNodeClass={handleNodeClass}
value={templateValue ?? ""}
onChange={onChange}
id={`promptarea_${id}`}
/>
) : templateData.type === "code" ? (
<CodeAreaComponent
readonly={nodeClass.flow && templateData.dynamic ? true : false}
dynamic={templateData.dynamic ?? false}
setNodeClass={handleNodeClass}
nodeClass={nodeClass}
disabled={disabled}
editNode={editNode}
value={templateValue ?? ""}
onChange={onChange}
id={`codearea_${id}`}
/>
) : templateData.type === "Any" ? (
<>-</>
) : (
String(templateValue)
)}
</RefreshParameterComponent>
);
}

View file

@ -0,0 +1,56 @@
import useHandleOnNewValue from "@/CustomNodes/hooks/use-handle-new-value";
import ShadTooltip from "@/components/shadTooltipComponent";
import useFlowStore from "@/stores/flowStore";
import { isTargetHandleConnected } from "@/utils/reactflowUtils";
import { CustomCellRendererProps } from "ag-grid-react";
import ToggleShadComponent from "../../../toggleShadComponent";
export default function TableAdvancedToggleCellRender({
value: { nodeId, parameterId },
}: CustomCellRendererProps) {
const edges = useFlowStore((state) => state.edges);
const node = useFlowStore((state) => state.getNode(nodeId));
const parameter = node?.data?.node?.template?.[parameterId];
const disabled = isTargetHandleConnected(
edges,
parameterId,
parameter,
nodeId,
);
const { handleOnNewValue } = useHandleOnNewValue({
node: node?.data.node,
nodeId,
name: parameterId,
});
return (
parameter && (
<ShadTooltip
content={
disabled
? "Cannot change visibility of connected handles"
: "Change visibility of the field"
}
styleClasses="z-50"
>
<div>
<div className="flex h-full items-center">
<ToggleShadComponent
id={"show" + parameterId}
disabled={disabled}
enabled={!parameter?.advanced ?? true}
setEnabled={(e) => {
console.log(e, parameter);
handleOnNewValue({ advanced: !e });
}}
size="small"
editNode={true}
/>
</div>
</div>
</ShadTooltip>
)
);
}

Some files were not shown because too many files have changed in this diff Show more