Spaces:
Configuration error
Configuration error
| import { createPortal } from 'react-dom' | |
| import { useState, useEffect } from 'react' | |
| import { useSelector } from 'react-redux' | |
| import PropTypes from 'prop-types' | |
| import { | |
| Button, | |
| Dialog, | |
| DialogActions, | |
| DialogContent, | |
| Box, | |
| List, | |
| ListItemButton, | |
| ListItem, | |
| ListItemAvatar, | |
| ListItemText, | |
| Typography, | |
| Stack | |
| } from '@mui/material' | |
| import { useTheme } from '@mui/material/styles' | |
| import PerfectScrollbar from 'react-perfect-scrollbar' | |
| import { StyledButton } from 'ui-component/button/StyledButton' | |
| import { DarkCodeEditor } from 'ui-component/editor/DarkCodeEditor' | |
| import { LightCodeEditor } from 'ui-component/editor/LightCodeEditor' | |
| import './EditPromptValuesDialog.css' | |
| import { baseURL } from 'store/constant' | |
| const EditPromptValuesDialog = ({ show, dialogProps, onCancel, onConfirm }) => { | |
| const portalElement = document.getElementById('portal') | |
| const theme = useTheme() | |
| const customization = useSelector((state) => state.customization) | |
| const languageType = 'json' | |
| const [inputValue, setInputValue] = useState('') | |
| const [inputParam, setInputParam] = useState(null) | |
| const [textCursorPosition, setTextCursorPosition] = useState({}) | |
| useEffect(() => { | |
| if (dialogProps.value) setInputValue(dialogProps.value) | |
| if (dialogProps.inputParam) setInputParam(dialogProps.inputParam) | |
| return () => { | |
| setInputValue('') | |
| setInputParam(null) | |
| setTextCursorPosition({}) | |
| } | |
| }, [dialogProps]) | |
| const onMouseUp = (e) => { | |
| if (e.target && e.target.selectionEnd && e.target.value) { | |
| const cursorPosition = e.target.selectionEnd | |
| const textBeforeCursorPosition = e.target.value.substring(0, cursorPosition) | |
| const textAfterCursorPosition = e.target.value.substring(cursorPosition, e.target.value.length) | |
| const body = { | |
| textBeforeCursorPosition, | |
| textAfterCursorPosition | |
| } | |
| setTextCursorPosition(body) | |
| } else { | |
| setTextCursorPosition({}) | |
| } | |
| } | |
| const onSelectOutputResponseClick = (node, isUserQuestion = false) => { | |
| let variablePath = isUserQuestion ? `question` : `${node.id}.data.instance` | |
| if (textCursorPosition) { | |
| let newInput = '' | |
| if (textCursorPosition.textBeforeCursorPosition === undefined && textCursorPosition.textAfterCursorPosition === undefined) | |
| newInput = `${inputValue}${`{{${variablePath}}}`}` | |
| else newInput = `${textCursorPosition.textBeforeCursorPosition}{{${variablePath}}}${textCursorPosition.textAfterCursorPosition}` | |
| setInputValue(newInput) | |
| } | |
| } | |
| 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' && ( | |
| <div style={{ flex: 70 }}> | |
| <Typography sx={{ mb: 2, ml: 1 }} variant='h4'> | |
| {inputParam.label} | |
| </Typography> | |
| <PerfectScrollbar | |
| style={{ | |
| border: '1px solid', | |
| borderColor: theme.palette.grey['500'], | |
| borderRadius: '12px', | |
| height: '100%', | |
| maxHeight: 'calc(100vh - 220px)', | |
| overflowX: 'hidden', | |
| backgroundColor: 'white' | |
| }} | |
| > | |
| {customization.isDarkMode ? ( | |
| <DarkCodeEditor | |
| disabled={dialogProps.disabled} | |
| value={inputValue} | |
| onValueChange={(code) => setInputValue(code)} | |
| placeholder={inputParam.placeholder} | |
| type={languageType} | |
| onMouseUp={(e) => onMouseUp(e)} | |
| onBlur={(e) => onMouseUp(e)} | |
| 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} | |
| onMouseUp={(e) => onMouseUp(e)} | |
| onBlur={(e) => onMouseUp(e)} | |
| style={{ | |
| fontSize: '0.875rem', | |
| minHeight: 'calc(100vh - 220px)', | |
| width: '100%' | |
| }} | |
| /> | |
| )} | |
| </PerfectScrollbar> | |
| </div> | |
| )} | |
| {!dialogProps.disabled && inputParam && inputParam.acceptVariable && ( | |
| <div style={{ flex: 30 }}> | |
| <Stack flexDirection='row' sx={{ mb: 1, ml: 2 }}> | |
| <Typography variant='h4'>Select Variable</Typography> | |
| </Stack> | |
| <PerfectScrollbar style={{ height: '100%', maxHeight: 'calc(100vh - 220px)', overflowX: 'hidden' }}> | |
| <Box sx={{ pl: 2, pr: 2 }}> | |
| <List> | |
| <ListItemButton | |
| sx={{ | |
| p: 0, | |
| borderRadius: `${customization.borderRadius}px`, | |
| boxShadow: '0 2px 14px 0 rgb(32 40 45 / 8%)', | |
| mb: 1 | |
| }} | |
| disabled={dialogProps.disabled} | |
| onClick={() => onSelectOutputResponseClick(null, true)} | |
| > | |
| <ListItem alignItems='center'> | |
| <ListItemAvatar> | |
| <div | |
| style={{ | |
| width: 50, | |
| height: 50, | |
| borderRadius: '50%', | |
| backgroundColor: 'white' | |
| }} | |
| > | |
| <img | |
| style={{ | |
| width: '100%', | |
| height: '100%', | |
| padding: 10, | |
| objectFit: 'contain' | |
| }} | |
| alt='AI' | |
| src='https://raw.githubusercontent.com/zahidkhawaja/langchain-chat-nextjs/main/public/parroticon.png' | |
| /> | |
| </div> | |
| </ListItemAvatar> | |
| <ListItemText | |
| sx={{ ml: 1 }} | |
| primary='question' | |
| secondary={`User's question from chatbox`} | |
| /> | |
| </ListItem> | |
| </ListItemButton> | |
| {dialogProps.availableNodesForVariable && | |
| dialogProps.availableNodesForVariable.length > 0 && | |
| dialogProps.availableNodesForVariable.map((node, index) => { | |
| const selectedOutputAnchor = node.data.outputAnchors[0].options.find( | |
| (ancr) => ancr.name === node.data.outputs['output'] | |
| ) | |
| return ( | |
| <ListItemButton | |
| key={index} | |
| sx={{ | |
| p: 0, | |
| borderRadius: `${customization.borderRadius}px`, | |
| boxShadow: '0 2px 14px 0 rgb(32 40 45 / 8%)', | |
| mb: 1 | |
| }} | |
| disabled={dialogProps.disabled} | |
| onClick={() => onSelectOutputResponseClick(node)} | |
| > | |
| <ListItem alignItems='center'> | |
| <ListItemAvatar> | |
| <div | |
| style={{ | |
| width: 50, | |
| height: 50, | |
| borderRadius: '50%', | |
| backgroundColor: 'white' | |
| }} | |
| > | |
| <img | |
| style={{ | |
| width: '100%', | |
| height: '100%', | |
| padding: 10, | |
| objectFit: 'contain' | |
| }} | |
| alt={node.data.name} | |
| src={`${baseURL}/api/v1/node-icon/${node.data.name}`} | |
| /> | |
| </div> | |
| </ListItemAvatar> | |
| <ListItemText | |
| sx={{ ml: 1 }} | |
| primary={ | |
| node.data.inputs.chainName ? node.data.inputs.chainName : node.data.id | |
| } | |
| secondary={`${selectedOutputAnchor?.label ?? 'output'} from ${ | |
| node.data.label | |
| }`} | |
| /> | |
| </ListItem> | |
| </ListItemButton> | |
| ) | |
| })} | |
| </List> | |
| </Box> | |
| </PerfectScrollbar> | |
| </div> | |
| )} | |
| </div> | |
| </DialogContent> | |
| <DialogActions> | |
| <Button onClick={onCancel}>{dialogProps.cancelButtonName}</Button> | |
| <StyledButton disabled={dialogProps.disabled} variant='contained' onClick={() => onConfirm(inputValue, inputParam.name)}> | |
| {dialogProps.confirmButtonName} | |
| </StyledButton> | |
| </DialogActions> | |
| </Dialog> | |
| ) : null | |
| return createPortal(component, portalElement) | |
| } | |
| EditPromptValuesDialog.propTypes = { | |
| show: PropTypes.bool, | |
| dialogProps: PropTypes.object, | |
| onCancel: PropTypes.func, | |
| onConfirm: PropTypes.func | |
| } | |
| export default EditPromptValuesDialog | |