add new utilties - customfunction, setter/getter, replace code editor

This commit is contained in:
Henry
2023-12-15 17:15:00 +00:00
parent 1b0b1f13fa
commit 911b4fe7fb
22 changed files with 543 additions and 710 deletions
+8 -3
View File
@@ -8,13 +8,20 @@
"email": "henryheng@flowiseai.com"
},
"dependencies": {
"@codemirror/lang-javascript": "^6.2.1",
"@codemirror/lang-json": "^6.0.1",
"@codemirror/view": "^6.22.3",
"@emotion/cache": "^11.4.0",
"@emotion/react": "^11.10.6",
"@emotion/styled": "^11.10.6",
"@mui/icons-material": "^5.0.3",
"@mui/material": "^5.11.12",
"@mui/lab": "^5.0.0-alpha.156",
"@mui/material": "^5.15.0",
"@mui/x-data-grid": "^6.8.0",
"@tabler/icons": "^1.39.1",
"@uiw/codemirror-theme-sublime": "^4.21.21",
"@uiw/codemirror-theme-vscode": "^4.21.21",
"@uiw/react-codemirror": "^4.21.21",
"clsx": "^1.1.1",
"flowise-embed": "*",
"flowise-embed-react": "*",
@@ -26,7 +33,6 @@
"lodash": "^4.17.21",
"moment": "^2.29.3",
"notistack": "^2.0.4",
"prismjs": "^1.28.0",
"prop-types": "^15.7.2",
"react": "^18.2.0",
"react-code-blocks": "^0.0.9-0",
@@ -39,7 +45,6 @@
"react-redux": "^8.0.5",
"react-router": "~6.3.0",
"react-router-dom": "~6.3.0",
"react-simple-code-editor": "^0.11.2",
"react-syntax-highlighter": "^15.5.0",
"reactflow": "^11.5.6",
"redux": "^4.0.5",
+4 -1
View File
@@ -4,7 +4,10 @@ const getAllNodes = () => client.get('/nodes')
const getSpecificNode = (name) => client.get(`/nodes/${name}`)
const executeCustomFunctionNode = (body) => client.post(`/node-custom-function`, body)
export default {
getAllNodes,
getSpecificNode
getSpecificNode,
executeCustomFunctionNode
}
@@ -2,14 +2,24 @@ import { createPortal } from 'react-dom'
import { useState, useEffect } from 'react'
import { useSelector, useDispatch } from 'react-redux'
import PropTypes from 'prop-types'
import PerfectScrollbar from 'react-perfect-scrollbar'
// MUI
import { Button, Dialog, DialogActions, DialogContent, Typography } from '@mui/material'
import { useTheme } from '@mui/material/styles'
import PerfectScrollbar from 'react-perfect-scrollbar'
import { LoadingButton } from '@mui/lab'
// Project Import
import { StyledButton } from 'ui-component/button/StyledButton'
import { DarkCodeEditor } from 'ui-component/editor/DarkCodeEditor'
import { LightCodeEditor } from 'ui-component/editor/LightCodeEditor'
import { CodeEditor } from 'ui-component/editor/CodeEditor'
// Store
import { HIDE_CANVAS_DIALOG, SHOW_CANVAS_DIALOG } from 'store/actions'
// API
import nodesApi from 'api/nodes'
import useApi from 'hooks/useApi'
import './ExpandTextDialog.css'
const ExpandTextDialog = ({ show, dialogProps, onCancel, onConfirm }) => {
@@ -18,18 +28,30 @@ const ExpandTextDialog = ({ show, dialogProps, onCancel, onConfirm }) => {
const theme = useTheme()
const dispatch = useDispatch()
const customization = useSelector((state) => state.customization)
const languageType = 'json'
const [inputValue, setInputValue] = useState('')
const [inputParam, setInputParam] = useState(null)
const [languageType, setLanguageType] = useState('json')
const [loading, setLoading] = useState(false)
const [codeExecutedResult, setCodeExecutedResult] = useState('')
const executeCustomFunctionNodeApi = useApi(nodesApi.executeCustomFunctionNode)
useEffect(() => {
if (dialogProps.value) setInputValue(dialogProps.value)
if (dialogProps.inputParam) setInputParam(dialogProps.inputParam)
if (dialogProps.inputParam) {
setInputParam(dialogProps.inputParam)
if (dialogProps.inputParam.type === 'code') {
setLanguageType('js')
}
}
return () => {
setInputValue('')
setLoading(false)
setInputParam(null)
setLanguageType('json')
setCodeExecutedResult('')
}
}, [dialogProps])
@@ -39,11 +61,31 @@ const ExpandTextDialog = ({ show, dialogProps, onCancel, onConfirm }) => {
return () => dispatch({ type: HIDE_CANVAS_DIALOG })
}, [show, dispatch])
useEffect(() => {
setLoading(executeCustomFunctionNodeApi.loading)
}, [executeCustomFunctionNodeApi.loading])
useEffect(() => {
if (executeCustomFunctionNodeApi.data) {
setCodeExecutedResult(executeCustomFunctionNodeApi.data)
}
}, [executeCustomFunctionNodeApi.data])
useEffect(() => {
if (executeCustomFunctionNodeApi.error) {
if (typeof executeCustomFunctionNodeApi.error === 'object' && executeCustomFunctionNodeApi.error?.response?.data) {
setCodeExecutedResult(executeCustomFunctionNodeApi.error?.response?.data)
} else if (typeof executeCustomFunctionNodeApi.error === 'string') {
setCodeExecutedResult(executeCustomFunctionNodeApi.error)
}
}
}, [executeCustomFunctionNodeApi.error])
const component = show ? (
<Dialog open={show} fullWidth maxWidth='md' aria-labelledby='alert-dialog-title' aria-describedby='alert-dialog-description'>
<DialogContent>
<div style={{ display: 'flex', flexDirection: 'row' }}>
{inputParam && inputParam.type === 'string' && (
{inputParam && (inputParam.type === 'string' || inputParam.type === 'code') && (
<div style={{ flex: 70 }}>
<Typography sx={{ mb: 2, ml: 1 }} variant='h4'>
{inputParam.label}
@@ -54,42 +96,66 @@ const ExpandTextDialog = ({ show, dialogProps, onCancel, onConfirm }) => {
borderColor: theme.palette.grey['500'],
borderRadius: '12px',
height: '100%',
maxHeight: 'calc(100vh - 220px)',
maxHeight: languageType === 'js' ? 'calc(100vh - 250px)' : 'calc(100vh - 220px)',
overflowX: 'hidden',
backgroundColor: 'white'
}}
>
{customization.isDarkMode ? (
<DarkCodeEditor
disabled={dialogProps.disabled}
value={inputValue}
onValueChange={(code) => setInputValue(code)}
placeholder={inputParam.placeholder}
type={languageType}
style={{
fontSize: '0.875rem',
minHeight: 'calc(100vh - 220px)',
width: '100%'
}}
/>
) : (
<LightCodeEditor
disabled={dialogProps.disabled}
value={inputValue}
onValueChange={(code) => setInputValue(code)}
placeholder={inputParam.placeholder}
type={languageType}
style={{
fontSize: '0.875rem',
minHeight: 'calc(100vh - 220px)',
width: '100%'
}}
/>
)}
<CodeEditor
disabled={dialogProps.disabled}
value={inputValue}
height={languageType === 'js' ? 'calc(100vh - 250px)' : 'calc(100vh - 220px)'}
theme={customization.isDarkMode ? 'dark' : 'light'}
lang={languageType}
placeholder={inputParam.placeholder}
basicSetup={
languageType === 'json'
? { lineNumbers: false, foldGutter: false, autocompletion: false, highlightActiveLine: false }
: {}
}
onValueChange={(code) => setInputValue(code)}
/>
</PerfectScrollbar>
</div>
)}
</div>
{languageType === 'js' && (
<LoadingButton
sx={{
mt: 2,
'&:hover': {
backgroundColor: theme.palette.secondary.main,
backgroundImage: `linear-gradient(rgb(0 0 0/10%) 0 0)`
},
'&:disabled': {
backgroundColor: theme.palette.secondary.main,
backgroundImage: `linear-gradient(rgb(0 0 0/50%) 0 0)`
}
}}
loading={loading}
variant='contained'
fullWidth
color='secondary'
onClick={() => {
setLoading(true)
executeCustomFunctionNodeApi.request({ javascriptFunction: inputValue })
}}
>
Execute
</LoadingButton>
)}
{codeExecutedResult && (
<div style={{ marginTop: '15px' }}>
<CodeEditor
disabled={true}
value={codeExecutedResult}
height='max-content'
theme={customization.isDarkMode ? 'dark' : 'light'}
lang={'js'}
basicSetup={{ lineNumbers: false, foldGutter: false, autocompletion: false, highlightActiveLine: false }}
/>
</div>
)}
</DialogContent>
<DialogActions>
<Button onClick={onCancel}>{dialogProps.cancelButtonName}</Button>
@@ -0,0 +1,48 @@
import PropTypes from 'prop-types'
import CodeMirror from '@uiw/react-codemirror'
import { javascript } from '@codemirror/lang-javascript'
import { json } from '@codemirror/lang-json'
import { vscodeDark } from '@uiw/codemirror-theme-vscode'
import { sublime } from '@uiw/codemirror-theme-sublime'
import { EditorView } from '@codemirror/view'
export const CodeEditor = ({ value, height, theme, lang, placeholder, disabled = false, basicSetup = {}, onValueChange }) => {
const customStyle = EditorView.baseTheme({
'&': {
color: '#191b1f',
padding: '10px'
},
'.cm-placeholder': {
color: 'rgba(120, 120, 120, 0.5)'
}
})
return (
<CodeMirror
placeholder={placeholder}
value={value}
height={height ?? 'calc(100vh - 220px)'}
theme={theme === 'dark' ? (lang === 'js' ? vscodeDark : sublime) : 'none'}
extensions={
lang === 'js'
? [javascript({ jsx: true }), EditorView.lineWrapping, customStyle]
: [json(), EditorView.lineWrapping, customStyle]
}
onChange={onValueChange}
readOnly={disabled}
editable={!disabled}
basicSetup={basicSetup}
/>
)
}
CodeEditor.propTypes = {
value: PropTypes.string,
height: PropTypes.string,
theme: PropTypes.string,
lang: PropTypes.string,
placeholder: PropTypes.string,
disabled: PropTypes.bool,
basicSetup: PropTypes.object,
onValueChange: PropTypes.func
}
@@ -1,43 +0,0 @@
import Editor from 'react-simple-code-editor'
import { highlight, languages } from 'prismjs/components/prism-core'
import 'prismjs/components/prism-clike'
import 'prismjs/components/prism-javascript'
import 'prismjs/components/prism-json'
import 'prismjs/components/prism-markup'
import './prism-dark.css'
import PropTypes from 'prop-types'
import { useTheme } from '@mui/material/styles'
export const DarkCodeEditor = ({ value, placeholder, disabled = false, type, style, onValueChange, onMouseUp, onBlur }) => {
const theme = useTheme()
return (
<Editor
disabled={disabled}
value={value}
placeholder={placeholder}
highlight={(code) => highlight(code, type === 'json' ? languages.json : languages.js)}
padding={10}
onValueChange={onValueChange}
onMouseUp={onMouseUp}
onBlur={onBlur}
tabSize={4}
style={{
...style,
background: theme.palette.codeEditor.main
}}
textareaClassName='editor__textarea'
/>
)
}
DarkCodeEditor.propTypes = {
value: PropTypes.string,
placeholder: PropTypes.string,
disabled: PropTypes.bool,
type: PropTypes.string,
style: PropTypes.object,
onValueChange: PropTypes.func,
onMouseUp: PropTypes.func,
onBlur: PropTypes.func
}
@@ -1,43 +0,0 @@
import Editor from 'react-simple-code-editor'
import { highlight, languages } from 'prismjs/components/prism-core'
import 'prismjs/components/prism-clike'
import 'prismjs/components/prism-javascript'
import 'prismjs/components/prism-json'
import 'prismjs/components/prism-markup'
import './prism-light.css'
import PropTypes from 'prop-types'
import { useTheme } from '@mui/material/styles'
export const LightCodeEditor = ({ value, placeholder, disabled = false, type, style, onValueChange, onMouseUp, onBlur }) => {
const theme = useTheme()
return (
<Editor
disabled={disabled}
value={value}
placeholder={placeholder}
highlight={(code) => highlight(code, type === 'json' ? languages.json : languages.js)}
padding={10}
onValueChange={onValueChange}
onMouseUp={onMouseUp}
onBlur={onBlur}
tabSize={4}
style={{
...style,
background: theme.palette.card.main
}}
textareaClassName='editor__textarea'
/>
)
}
LightCodeEditor.propTypes = {
value: PropTypes.string,
placeholder: PropTypes.string,
disabled: PropTypes.bool,
type: PropTypes.string,
style: PropTypes.object,
onValueChange: PropTypes.func,
onMouseUp: PropTypes.func,
onBlur: PropTypes.func
}
@@ -1,275 +0,0 @@
pre[class*='language-'],
code[class*='language-'] {
color: #d4d4d4;
font-size: 13px;
text-shadow: none;
font-family: Menlo, Monaco, Consolas, 'Andale Mono', 'Ubuntu Mono', 'Courier New', monospace;
direction: ltr;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*='language-']::selection,
code[class*='language-']::selection,
pre[class*='language-'] *::selection,
code[class*='language-'] *::selection {
text-shadow: none;
background: #264f78;
}
@media print {
pre[class*='language-'],
code[class*='language-'] {
text-shadow: none;
}
}
pre[class*='language-'] {
padding: 1em;
margin: 0.5em 0;
overflow: auto;
background: #1e1e1e;
}
:not(pre) > code[class*='language-'] {
padding: 0.1em 0.3em;
border-radius: 0.3em;
color: #db4c69;
background: #1e1e1e;
}
/*********************************************************
* Tokens
*/
.namespace {
opacity: 0.7;
}
.token.doctype .token.doctype-tag {
color: #569cd6;
}
.token.doctype .token.name {
color: #9cdcfe;
}
.token.comment,
.token.prolog {
color: #6a9955;
}
.token.punctuation,
.language-html .language-css .token.punctuation,
.language-html .language-javascript .token.punctuation {
color: #d4d4d4;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.inserted,
.token.unit {
color: #b5cea8;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.deleted {
color: #ce9178;
}
.language-css .token.string.url {
text-decoration: underline;
}
.token.operator,
.token.entity {
color: #d4d4d4;
}
.token.operator.arrow {
color: #569cd6;
}
.token.atrule {
color: #ce9178;
}
.token.atrule .token.rule {
color: #c586c0;
}
.token.atrule .token.url {
color: #9cdcfe;
}
.token.atrule .token.url .token.function {
color: #dcdcaa;
}
.token.atrule .token.url .token.punctuation {
color: #d4d4d4;
}
.token.keyword {
color: #569cd6;
}
.token.keyword.module,
.token.keyword.control-flow {
color: #c586c0;
}
.token.function,
.token.function .token.maybe-class-name {
color: #dcdcaa;
}
.token.regex {
color: #d16969;
}
.token.important {
color: #569cd6;
}
.token.italic {
font-style: italic;
}
.token.constant {
color: #9cdcfe;
}
.token.class-name,
.token.maybe-class-name {
color: #4ec9b0;
}
.token.console {
color: #9cdcfe;
}
.token.parameter {
color: #9cdcfe;
}
.token.interpolation {
color: #9cdcfe;
}
.token.punctuation.interpolation-punctuation {
color: #569cd6;
}
.token.boolean {
color: #569cd6;
}
.token.property,
.token.variable,
.token.imports .token.maybe-class-name,
.token.exports .token.maybe-class-name {
color: #9cdcfe;
}
.token.selector {
color: #d7ba7d;
}
.token.escape {
color: #d7ba7d;
}
.token.tag {
color: #569cd6;
}
.token.tag .token.punctuation {
color: #808080;
}
.token.cdata {
color: #808080;
}
.token.attr-name {
color: #9cdcfe;
}
.token.attr-value,
.token.attr-value .token.punctuation {
color: #ce9178;
}
.token.attr-value .token.punctuation.attr-equals {
color: #d4d4d4;
}
.token.entity {
color: #569cd6;
}
.token.namespace {
color: #4ec9b0;
}
/*********************************************************
* Language Specific
*/
pre[class*='language-javascript'],
code[class*='language-javascript'],
pre[class*='language-jsx'],
code[class*='language-jsx'],
pre[class*='language-typescript'],
code[class*='language-typescript'],
pre[class*='language-tsx'],
code[class*='language-tsx'] {
color: #9cdcfe;
}
pre[class*='language-css'],
code[class*='language-css'] {
color: #ce9178;
}
pre[class*='language-html'],
code[class*='language-html'] {
color: #d4d4d4;
}
.language-regex .token.anchor {
color: #dcdcaa;
}
.language-html .token.punctuation {
color: #808080;
}
/*********************************************************
* Line highlighting
*/
pre[class*='language-'] > code[class*='language-'] {
position: relative;
z-index: 1;
}
.line-highlight.line-highlight {
background: #f7ebc6;
box-shadow: inset 5px 0 0 #f7d87c;
z-index: 0;
}
@@ -1,207 +0,0 @@
code[class*='language-'],
pre[class*='language-'] {
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
color: #90a4ae;
background: #fafafa;
font-family: Roboto Mono, monospace;
font-size: 1em;
line-height: 1.5em;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
code[class*='language-']::-moz-selection,
pre[class*='language-']::-moz-selection,
code[class*='language-'] ::-moz-selection,
pre[class*='language-'] ::-moz-selection {
background: #cceae7;
color: #263238;
}
code[class*='language-']::selection,
pre[class*='language-']::selection,
code[class*='language-'] ::selection,
pre[class*='language-'] ::selection {
background: #cceae7;
color: #263238;
}
:not(pre) > code[class*='language-'] {
white-space: normal;
border-radius: 0.2em;
padding: 0.1em;
}
pre[class*='language-'] {
overflow: auto;
position: relative;
margin: 0.5em 0;
padding: 1.25em 1em;
}
.language-css > code,
.language-sass > code,
.language-scss > code {
color: #f76d47;
}
[class*='language-'] .namespace {
opacity: 0.7;
}
.token.atrule {
color: #7c4dff;
}
.token.attr-name {
color: #39adb5;
}
.token.attr-value {
color: #f6a434;
}
.token.attribute {
color: #f6a434;
}
.token.boolean {
color: #7c4dff;
}
.token.builtin {
color: #39adb5;
}
.token.cdata {
color: #39adb5;
}
.token.char {
color: #39adb5;
}
.token.class {
color: #39adb5;
}
.token.class-name {
color: #6182b8;
}
.token.comment {
color: #aabfc9;
}
.token.constant {
color: #7c4dff;
}
.token.deleted {
color: #e53935;
}
.token.doctype {
color: #aabfc9;
}
.token.entity {
color: #e53935;
}
.token.function {
color: #7c4dff;
}
.token.hexcode {
color: #f76d47;
}
.token.id {
color: #7c4dff;
font-weight: bold;
}
.token.important {
color: #7c4dff;
font-weight: bold;
}
.token.inserted {
color: #39adb5;
}
.token.keyword {
color: #7c4dff;
}
.token.number {
color: #f76d47;
}
.token.operator {
color: #39adb5;
}
.token.prolog {
color: #aabfc9;
}
.token.property {
color: #39adb5;
}
.token.pseudo-class {
color: #f6a434;
}
.token.pseudo-element {
color: #f6a434;
}
.token.punctuation {
color: #39adb5;
}
.token.regex {
color: #6182b8;
}
.token.selector {
color: #e53935;
}
.token.string {
color: #f6a434;
}
.token.symbol {
color: #7c4dff;
}
.token.tag {
color: #e53935;
}
.token.unit {
color: #f76d47;
}
.token.url {
color: #e53935;
}
.token.variable {
color: #e53935;
}
+2 -30
View File
@@ -1,23 +1,10 @@
import { useState, useEffect, useRef } from 'react'
import PropTypes from 'prop-types'
import { FormControl, OutlinedInput, Popover } from '@mui/material'
import ExpandTextDialog from 'ui-component/dialog/ExpandTextDialog'
import SelectVariable from 'ui-component/json/SelectVariable'
import { getAvailableNodesForVariable } from 'utils/genericHelper'
export const Input = ({
inputParam,
value,
nodes,
edges,
nodeId,
onChange,
disabled = false,
showDialog,
dialogProps,
onDialogCancel,
onDialogConfirm
}) => {
export const Input = ({ inputParam, value, nodes, edges, nodeId, onChange, disabled = false }) => {
const [myValue, setMyValue] = useState(value ?? '')
const [anchorEl, setAnchorEl] = useState(null)
const [availableNodesForVariable, setAvailableNodesForVariable] = useState([])
@@ -86,17 +73,6 @@ export const Input = ({
}}
/>
</FormControl>
{showDialog && (
<ExpandTextDialog
show={showDialog}
dialogProps={dialogProps}
onCancel={onDialogCancel}
onConfirm={(newValue, inputParamName) => {
setMyValue(newValue)
onDialogConfirm(newValue, inputParamName)
}}
></ExpandTextDialog>
)}
<div ref={ref}></div>
{inputParam?.acceptVariable && (
<Popover
@@ -131,11 +107,7 @@ Input.propTypes = {
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
onChange: PropTypes.func,
disabled: PropTypes.bool,
showDialog: PropTypes.bool,
dialogProps: PropTypes.object,
nodes: PropTypes.array,
edges: PropTypes.array,
nodeId: PropTypes.string,
onDialogCancel: PropTypes.func,
onDialogConfirm: PropTypes.func
nodeId: PropTypes.string
}
@@ -141,7 +141,12 @@ const SelectVariable = ({ availableNodesForVariable, disabled = false, onSelectA
</ListItemAvatar>
<ListItemText
sx={{ ml: 1 }}
primary={node.data.inputs.chainName ? node.data.inputs.chainName : node.data.id}
primary={
node.data.inputs.chainName ??
node.data.inputs.functionName ??
node.data.inputs.variableName ??
node.data.id
}
secondary={`${selectedOutputAnchor?.label ?? 'output'} from ${node.data.label}`}
/>
</ListItem>
@@ -22,8 +22,11 @@ import { flowContext } from 'store/context/ReactFlowContext'
import { isValidConnection } from 'utils/genericHelper'
import { JsonEditorInput } from 'ui-component/json/JsonEditor'
import { TooltipWithParser } from 'ui-component/tooltip/TooltipWithParser'
import { CodeEditor } from 'ui-component/editor/CodeEditor'
import ToolDialog from 'views/tools/ToolDialog'
import AssistantDialog from 'views/assistants/AssistantDialog'
import ExpandTextDialog from 'ui-component/dialog/ExpandTextDialog'
import FormatPromptValuesDialog from 'ui-component/dialog/FormatPromptValuesDialog'
import CredentialInputHandler from './CredentialInputHandler'
@@ -83,7 +86,7 @@ const NodeInputHandler = ({ inputAnchor, inputParam, data, disabled = false, isA
}
}
}
const onFormatPromptValuesClicked = (value, inputParam) => {
const onEditJSONClicked = (value, inputParam) => {
// Preset values if the field is format prompt values
let inputValue = value
if (inputParam.name === 'promptValues' && !value) {
@@ -255,7 +258,7 @@ const NodeInputHandler = ({ inputAnchor, inputParam, data, disabled = false, isA
{inputParam.description && <TooltipWithParser style={{ marginLeft: 10 }} title={inputParam.description} />}
</Typography>
<div style={{ flexGrow: 1 }}></div>
{inputParam.type === 'string' && inputParam.rows && (
{((inputParam.type === 'string' && inputParam.rows) || inputParam.type === 'code') && (
<IconButton
size='small'
sx={{
@@ -324,6 +327,23 @@ const NodeInputHandler = ({ inputAnchor, inputParam, data, disabled = false, isA
onChange={(newValue) => (data.inputs[inputParam.name] = newValue)}
/>
)}
{inputParam.type === 'code' && (
<>
<div style={{ height: '5px' }}></div>
<div style={{ height: '200px' }}>
<CodeEditor
disabled={disabled}
value={data.inputs[inputParam.name] ?? inputParam.default ?? ''}
height='200px'
theme={customization.isDarkMode ? 'dark' : 'light'}
lang={'js'}
placeholder={inputParam.placeholder}
onValueChange={(code) => (data.inputs[inputParam.name] = code)}
basicSetup={{ highlightActiveLine: false, highlightActiveLineGutter: false }}
/>
</div>
</>
)}
{(inputParam.type === 'string' || inputParam.type === 'password' || inputParam.type === 'number') && (
<Input
key={data.inputs[inputParam.name]}
@@ -334,10 +354,6 @@ const NodeInputHandler = ({ inputAnchor, inputParam, data, disabled = false, isA
nodes={inputParam?.acceptVariable && reactFlowInstance ? reactFlowInstance.getNodes() : []}
edges={inputParam?.acceptVariable && reactFlowInstance ? reactFlowInstance.getEdges() : []}
nodeId={data.id}
showDialog={showExpandDialog}
dialogProps={expandDialogProps}
onDialogCancel={() => setShowExpandDialog(false)}
onDialogConfirm={(newValue, inputParamName) => onExpandDialogSave(newValue, inputParamName)}
/>
)}
{inputParam.type === 'json' && (
@@ -353,11 +369,11 @@ const NodeInputHandler = ({ inputAnchor, inputParam, data, disabled = false, isA
{inputParam?.acceptVariable && (
<>
<Button
sx={{ borderRadius: 25, width: '100%', mb: 2, mt: 2 }}
sx={{ borderRadius: 25, width: '100%', mb: 0, mt: 2 }}
variant='outlined'
onClick={() => onFormatPromptValuesClicked(data.inputs[inputParam.name] ?? '', inputParam)}
onClick={() => onEditJSONClicked(data.inputs[inputParam.name] ?? '', inputParam)}
>
Format Prompt Values
{inputParam.label}
</Button>
<FormatPromptValuesDialog
show={showFormatPromptValuesDialog}
@@ -428,6 +444,12 @@ const NodeInputHandler = ({ inputAnchor, inputParam, data, disabled = false, isA
onCancel={() => setAsyncOptionEditDialog('')}
onConfirm={onConfirmAsyncOption}
></AssistantDialog>
<ExpandTextDialog
show={showExpandDialog}
dialogProps={expandDialogProps}
onCancel={() => setShowExpandDialog(false)}
onConfirm={(newValue, inputParamName) => onExpandDialogSave(newValue, inputParamName)}
></ExpandTextDialog>
</div>
)
}
+9 -30
View File
@@ -12,9 +12,7 @@ import { TooltipWithParser } from 'ui-component/tooltip/TooltipWithParser'
import { GridActionsCellItem } from '@mui/x-data-grid'
import DeleteIcon from '@mui/icons-material/Delete'
import ConfirmDialog from 'ui-component/dialog/ConfirmDialog'
import { DarkCodeEditor } from 'ui-component/editor/DarkCodeEditor'
import { LightCodeEditor } from 'ui-component/editor/LightCodeEditor'
import { useTheme } from '@mui/material/styles'
import { CodeEditor } from 'ui-component/editor/CodeEditor'
// Icons
import { IconX, IconFileExport } from '@tabler/icons'
@@ -56,7 +54,6 @@ try {
const ToolDialog = ({ show, dialogProps, onUseTemplate, onCancel, onConfirm }) => {
const portalElement = document.getElementById('portal')
const theme = useTheme()
const customization = useSelector((state) => state.customization)
const dispatch = useDispatch()
@@ -490,32 +487,14 @@ const ToolDialog = ({ show, dialogProps, onUseTemplate, onCancel, onConfirm }) =
See Example
</Button>
)}
{customization.isDarkMode ? (
<DarkCodeEditor
value={toolFunc}
disabled={dialogProps.type === 'TEMPLATE'}
onValueChange={(code) => setToolFunc(code)}
style={{
fontSize: '0.875rem',
minHeight: 'calc(100vh - 220px)',
width: '100%',
borderRadius: 5
}}
/>
) : (
<LightCodeEditor
value={toolFunc}
disabled={dialogProps.type === 'TEMPLATE'}
onValueChange={(code) => setToolFunc(code)}
style={{
fontSize: '0.875rem',
minHeight: 'calc(100vh - 220px)',
width: '100%',
border: `1px solid ${theme.palette.grey[300]}`,
borderRadius: 5
}}
/>
)}
<CodeEditor
disabled={dialogProps.type === 'TEMPLATE'}
value={toolFunc}
height='calc(100vh - 220px)'
theme={customization.isDarkMode ? 'dark' : 'light'}
lang={'js'}
onValueChange={(code) => setToolFunc(code)}
/>
</Box>
</DialogContent>
<DialogActions>