Feature/Indexing (#1802)

* indexing

* fix for multiple files upsert

* fix default Postgres port

* fix SQLite node description

* add MySQLRecordManager node

* fix MySQL unique index

* add upsert history

* update jsx ui

* lint-fix

* update dialog details

* update llamaindex pinecone

---------

Co-authored-by: chungyau97 <chungyau97@gmail.com>
This commit is contained in:
Henry Heng
2024-04-02 23:47:19 +01:00
committed by GitHub
parent 957694a912
commit e422ce287b
67 changed files with 3006 additions and 246 deletions
+5 -1
View File
@@ -1,7 +1,11 @@
import client from './client'
const upsertVectorStore = (id, input) => client.post(`/vector/internal-upsert/${id}`, input)
const getUpsertHistory = (id, params = {}) => client.get(`/upsert-history/${id}`, { params: { order: 'DESC', ...params } })
const deleteUpsertHistory = (ids) => client.patch(`/upsert-history`, { ids })
export default {
upsertVectorStore
getUpsertHistory,
upsertVectorStore,
deleteUpsertHistory
}
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.0 KiB

+17 -1
View File
@@ -1,5 +1,13 @@
// assets
import { IconTrash, IconFileUpload, IconFileExport, IconCopy, IconMessage, IconAdjustmentsHorizontal } from '@tabler/icons'
import {
IconTrash,
IconFileUpload,
IconFileExport,
IconCopy,
IconMessage,
IconDatabaseExport,
IconAdjustmentsHorizontal
} from '@tabler/icons'
// constant
const icons = {
@@ -8,6 +16,7 @@ const icons = {
IconFileExport,
IconCopy,
IconMessage,
IconDatabaseExport,
IconAdjustmentsHorizontal
}
@@ -25,6 +34,13 @@ const settings = {
url: '',
icon: icons.IconMessage
},
{
id: 'viewUpsertHistory',
title: 'Upsert History',
type: 'item',
url: '',
icon: icons.IconDatabaseExport
},
{
id: 'chatflowConfiguration',
title: 'Configuration',
+5
View File
@@ -355,6 +355,11 @@ export const getUpsertDetails = (nodes, edges) => {
innerNodes.push(nodes.find((node) => node.data.id === embeddingsId))
}
if (vsNode.data.inputs.recordManager) {
const recordManagerId = vsNode.data.inputs.recordManager.replace(/{{|}}/g, '').split('.')[0]
innerNodes.push(nodes.find((node) => node.data.id === recordManagerId))
}
for (const doc of connectedDocs) {
const docId = doc.replace(/{{|}}/g, '').split('.')[0]
const docNode = nodes.find((node) => node.data.id === docId)
@@ -16,6 +16,7 @@ import SaveChatflowDialog from '@/ui-component/dialog/SaveChatflowDialog'
import APICodeDialog from '@/views/chatflows/APICodeDialog'
import ViewMessagesDialog from '@/ui-component/dialog/ViewMessagesDialog'
import ChatflowConfigurationDialog from '@/ui-component/dialog/ChatflowConfigurationDialog'
import UpsertHistoryDialog from '@/views/vectorstore/UpsertHistoryDialog'
// API
import chatflowsApi from '@/api/chatflows'
@@ -45,6 +46,8 @@ const CanvasHeader = ({ chatflow, handleSaveFlow, handleDeleteFlow, handleLoadFl
const [apiDialogProps, setAPIDialogProps] = useState({})
const [viewMessagesDialogOpen, setViewMessagesDialogOpen] = useState(false)
const [viewMessagesDialogProps, setViewMessagesDialogProps] = useState({})
const [upsertHistoryDialogOpen, setUpsertHistoryDialogOpen] = useState(false)
const [upsertHistoryDialogProps, setUpsertHistoryDialogProps] = useState({})
const [chatflowConfigurationDialogOpen, setChatflowConfigurationDialogOpen] = useState(false)
const [chatflowConfigurationDialogProps, setChatflowConfigurationDialogProps] = useState({})
@@ -62,6 +65,12 @@ const CanvasHeader = ({ chatflow, handleSaveFlow, handleDeleteFlow, handleLoadFl
chatflow: chatflow
})
setViewMessagesDialogOpen(true)
} else if (setting === 'viewUpsertHistory') {
setUpsertHistoryDialogProps({
title: 'View Upsert History',
chatflow: chatflow
})
setUpsertHistoryDialogOpen(true)
} else if (setting === 'chatflowConfiguration') {
setChatflowConfigurationDialogProps({
title: 'Chatflow Configuration',
@@ -387,6 +396,11 @@ const CanvasHeader = ({ chatflow, handleSaveFlow, handleDeleteFlow, handleLoadFl
dialogProps={viewMessagesDialogProps}
onCancel={() => setViewMessagesDialogOpen(false)}
/>
<UpsertHistoryDialog
show={upsertHistoryDialogOpen}
dialogProps={upsertHistoryDialogProps}
onCancel={() => setUpsertHistoryDialogOpen(false)}
/>
<ChatflowConfigurationDialog
key='chatflowConfiguration'
show={chatflowConfigurationDialogOpen}
@@ -406,6 +406,10 @@ export const ChatMessage = ({ open, chatflowid, isDialog, previews, setPreviews
if (response.data) {
const data = response.data
if (data.executionError) {
handleError(data.msg)
return
}
setMessages((prevMessages) => {
let allMessages = [...cloneDeep(prevMessages)]
@@ -0,0 +1,453 @@
import PropTypes from 'prop-types'
import { createPortal } from 'react-dom'
import { useDispatch, useSelector } from 'react-redux'
import { useEffect, useState, forwardRef } from 'react'
import DatePicker from 'react-datepicker'
import moment from 'moment/moment'
// MUI
import {
Stack,
Box,
Paper,
Table,
TableBody,
TableContainer,
TableHead,
TableRow,
TableCell,
IconButton,
Button,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
ListItemButton,
Collapse,
Accordion,
AccordionSummary,
Typography,
AccordionDetails,
Checkbox
} from '@mui/material'
import { useTheme } from '@mui/material/styles'
import ExpandMoreIcon from '@mui/icons-material/ExpandMore'
import { IconChevronsUp, IconChevronsDown, IconTrash, IconX } from '@tabler/icons'
// Project imports
import { TableViewOnly } from '@/ui-component/table/Table'
import { TooltipWithParser } from '@/ui-component/tooltip/TooltipWithParser'
import HistoryEmptySVG from '@/assets/images/upsert_history_empty.svg'
// Api
import vectorstoreApi from '@/api/vectorstore'
import useApi from '@/hooks/useApi'
// Store
import { HIDE_CANVAS_DIALOG, SHOW_CANVAS_DIALOG } from '@/store/actions'
import { baseURL } from '@/store/constant'
import useNotifier from '@/utils/useNotifier'
import { enqueueSnackbar as enqueueSnackbarAction, closeSnackbar as closeSnackbarAction } from '@/store/actions'
const DatePickerCustomInput = forwardRef(function DatePickerCustomInput({ value, onClick }, ref) {
return (
<ListItemButton style={{ borderRadius: 15, border: '1px solid #e0e0e0' }} onClick={onClick} ref={ref}>
{value}
</ListItemButton>
)
})
DatePickerCustomInput.propTypes = {
value: PropTypes.string,
onClick: PropTypes.func
}
function UpsertHistoryRow(props) {
const [open, setOpen] = useState(false)
const [nodeConfigExpanded, setNodeConfigExpanded] = useState({})
const handleAccordionChange = (nodeLabel) => (event, isExpanded) => {
const accordianNodes = { ...nodeConfigExpanded }
accordianNodes[nodeLabel] = isExpanded
setNodeConfigExpanded(accordianNodes)
}
const isItemSelected = props.selected.indexOf(props.upsertHistory.id) !== -1
return (
<>
<TableRow sx={{ '&:last-child td, &:last-child th': { border: 0 } }}>
<TableCell padding='checkbox'>
<Checkbox
color='primary'
checked={isItemSelected}
onChange={(event) => props.handleSelect(event, props.upsertHistory.id)}
inputProps={{
'aria-labelledby': props.upsertHistory.id
}}
/>
</TableCell>
<TableCell>{moment(props.upsertHistory.date).format('MMMM Do YYYY, h:mm:ss a')}</TableCell>
<TableCell>{props.upsertHistory.result?.numAdded ?? '0'}</TableCell>
<TableCell>{props.upsertHistory.result?.numUpdated ?? '0'}</TableCell>
<TableCell>{props.upsertHistory.result?.numSkipped ?? '0'}</TableCell>
<TableCell>{props.upsertHistory.result?.numDeleted ?? '0'}</TableCell>
<TableCell>
<IconButton aria-label='expand row' size='small' color='inherit' onClick={() => setOpen(!open)}>
{open ? <IconChevronsUp /> : <IconChevronsDown />}
</IconButton>
</TableCell>
</TableRow>
{open && (
<TableRow sx={{ '& td': { border: 0 } }}>
<TableCell sx={{ pb: 0, pt: 0 }} colSpan={6}>
<Collapse in={open} timeout='auto' unmountOnExit>
<Box sx={{ mt: 1, mb: 2 }}>
{(props.upsertHistory.flowData ?? []).map((node, index) => {
return (
<Accordion
expanded={nodeConfigExpanded[node.id] || false}
onChange={handleAccordionChange(node.id)}
key={index}
disableGutters
>
<AccordionSummary
expandIcon={<ExpandMoreIcon />}
aria-controls={`nodes-accordian-${node.name}`}
id={`nodes-accordian-header-${node.name}`}
>
<div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
<div
style={{
width: 40,
height: 40,
marginRight: 10,
borderRadius: '50%',
backgroundColor: 'white'
}}
>
<img
style={{
width: '100%',
height: '100%',
padding: 7,
borderRadius: '50%',
objectFit: 'contain'
}}
alt={node.name}
src={`${baseURL}/api/v1/node-icon/${node.name}`}
/>
</div>
<Typography variant='h5'>{node.label}</Typography>
<div
style={{
display: 'flex',
flexDirection: 'row',
width: 'max-content',
borderRadius: 15,
background: 'rgb(254,252,191)',
padding: 5,
paddingLeft: 10,
paddingRight: 10,
marginLeft: 10
}}
>
<span style={{ color: 'rgb(116,66,16)', fontSize: '0.825rem' }}>{node.id}</span>
</div>
</div>
</AccordionSummary>
<AccordionDetails>
<TableViewOnly
sx={{ minWidth: 150 }}
rows={node.paramValues}
columns={Object.keys(node.paramValues[0])}
/>
</AccordionDetails>
</Accordion>
)
})}
</Box>
</Collapse>
</TableCell>
</TableRow>
)}
</>
)
}
UpsertHistoryRow.propTypes = {
upsertHistory: PropTypes.object,
theme: PropTypes.any,
isDarkMode: PropTypes.bool,
selected: PropTypes.array,
handleSelect: PropTypes.func
}
const UpsertHistoryDialog = ({ show, dialogProps, onCancel }) => {
const portalElement = document.getElementById('portal')
const dispatch = useDispatch()
const customization = useSelector((state) => state.customization)
const theme = useTheme()
const getUpsertHistoryApi = useApi(vectorstoreApi.getUpsertHistory)
useNotifier()
const enqueueSnackbar = (...args) => dispatch(enqueueSnackbarAction(...args))
const closeSnackbar = (...args) => dispatch(closeSnackbarAction(...args))
const [chatflowUpsertHistory, setChatflowUpsertHistory] = useState([])
const [startDate, setStartDate] = useState(new Date().setMonth(new Date().getMonth() - 1))
const [endDate, setEndDate] = useState(new Date())
const [selected, setSelected] = useState([])
const onSelectAllClick = (event) => {
if (event.target.checked) {
const newSelected = chatflowUpsertHistory.map((n) => n.id)
setSelected(newSelected)
return
}
setSelected([])
}
const onStartDateSelected = (date) => {
setStartDate(date)
getUpsertHistoryApi.request(dialogProps.chatflow.id, {
startDate: date,
endDate: endDate
})
}
const onEndDateSelected = (date) => {
setEndDate(date)
getUpsertHistoryApi.request(dialogProps.chatflow.id, {
endDate: date,
startDate: startDate
})
}
const handleSelect = (event, id) => {
const selectedIndex = selected.indexOf(id)
let newSelected = []
if (selectedIndex === -1) {
newSelected = newSelected.concat(selected, id)
} else if (selectedIndex === 0) {
newSelected = newSelected.concat(selected.slice(1))
} else if (selectedIndex === selected.length - 1) {
newSelected = newSelected.concat(selected.slice(0, -1))
} else if (selectedIndex > 0) {
newSelected = newSelected.concat(selected.slice(0, selectedIndex), selected.slice(selectedIndex + 1))
}
setSelected(newSelected)
}
const handleRemoveHistory = async () => {
try {
await vectorstoreApi.deleteUpsertHistory(selected)
enqueueSnackbar({
message: 'Succesfully deleted upsert history',
options: {
key: new Date().getTime() + Math.random(),
variant: 'success',
action: (key) => (
<Button style={{ color: 'white' }} onClick={() => closeSnackbar(key)}>
<IconX />
</Button>
)
}
})
setChatflowUpsertHistory(chatflowUpsertHistory.filter((hist) => !selected.includes(hist.id)))
setSelected([])
} catch (error) {
enqueueSnackbar({
message: 'Error deleting upsert history',
options: {
key: new Date().getTime() + Math.random(),
variant: 'error',
persist: true,
action: (key) => (
<Button style={{ color: 'white' }} onClick={() => closeSnackbar(key)}>
<IconX />
</Button>
)
}
})
}
}
useEffect(() => {
if (getUpsertHistoryApi.data) {
setChatflowUpsertHistory(getUpsertHistoryApi.data)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [getUpsertHistoryApi.data])
useEffect(() => {
if (dialogProps.chatflow) {
getUpsertHistoryApi.request(dialogProps.chatflow.id)
}
return () => {
setChatflowUpsertHistory([])
setStartDate(new Date().setMonth(new Date().getMonth() - 1))
setEndDate(new Date())
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [dialogProps])
useEffect(() => {
if (show) dispatch({ type: SHOW_CANVAS_DIALOG })
else dispatch({ type: HIDE_CANVAS_DIALOG })
return () => dispatch({ type: HIDE_CANVAS_DIALOG })
}, [show, dispatch])
const component = show ? (
<Dialog
onClose={onCancel}
open={show}
fullWidth
maxWidth='lg'
aria-labelledby='upsert-history-dialog-title'
aria-describedby='upsert-history-dialog-description'
>
<DialogTitle sx={{ fontSize: '1rem' }} id='upsert-history-dialog-title'>
{dialogProps.title}
</DialogTitle>
<DialogContent>
<>
<div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center', width: '100%', marginBottom: 10 }}>
<div style={{ marginRight: 10 }}>
<b style={{ marginRight: 10 }}>From Date</b>
<DatePicker
selected={startDate}
onChange={(date) => onStartDateSelected(date)}
selectsStart
startDate={startDate}
endDate={endDate}
customInput={<DatePickerCustomInput />}
/>
</div>
<div style={{ marginRight: 10 }}>
<b style={{ marginRight: 10 }}>To Date</b>
<DatePicker
selected={endDate}
onChange={(date) => onEndDateSelected(date)}
selectsEnd
startDate={startDate}
endDate={endDate}
minDate={startDate}
maxDate={new Date()}
customInput={<DatePickerCustomInput />}
/>
</div>
</div>
{selected.length > 0 && (
<Button
sx={{ mt: 1, mb: 2 }}
variant='outlined'
onClick={handleRemoveHistory}
color='error'
startIcon={<IconTrash />}
>
Delete {selected.length} {selected.length === 1 ? 'row' : 'rows'}
</Button>
)}
{chatflowUpsertHistory.length <= 0 && (
<Stack sx={{ alignItems: 'center', justifyContent: 'center' }} flexDirection='column'>
<Box sx={{ p: 7, height: 'auto' }}>
<img
style={{ objectFit: 'cover', height: '20vh', width: 'auto' }}
src={HistoryEmptySVG}
alt='HistoryEmptySVG'
/>
</Box>
<div>No Upsert History Yet</div>
</Stack>
)}
{chatflowUpsertHistory.length > 0 && (
<TableContainer component={Paper}>
<Table sx={{ minWidth: 650 }} aria-label='simple table'>
<TableHead>
<TableRow>
<TableCell padding='checkbox'>
<Checkbox
color='primary'
checked={selected.length === chatflowUpsertHistory.length}
onChange={onSelectAllClick}
inputProps={{
'aria-label': 'select all'
}}
/>
</TableCell>
<TableCell>Date</TableCell>
<TableCell>
Added{' '}
<TooltipWithParser
style={{ marginBottom: 2, marginLeft: 10 }}
title={'Number of vector embeddings added to Vector Store'}
/>
</TableCell>
<TableCell>
Updated{' '}
<TooltipWithParser
style={{ marginBottom: 2, marginLeft: 10 }}
title={
'Updated existing vector embeddings. Only works when a Record Manager is connected to the Vector Store'
}
/>
</TableCell>
<TableCell>
Skipped{' '}
<TooltipWithParser
style={{ marginBottom: 2, marginLeft: 10 }}
title={
'Number of same vector embeddings that exists, and were skipped re-upserting again. Only works when a Record Manager is connected to the Vector Store'
}
/>
</TableCell>
<TableCell>
Deleted{' '}
<TooltipWithParser
style={{ marginBottom: 2, marginLeft: 10 }}
title={
'Deleted vector embeddings. Only works when a Record Manager with a Cleanup method is connected to the Vector Store'
}
/>
</TableCell>
<TableCell>Details</TableCell>
</TableRow>
</TableHead>
<TableBody>
{chatflowUpsertHistory.map((upsertHistory, index) => (
<UpsertHistoryRow
key={index}
upsertHistory={upsertHistory}
theme={theme}
isDarkMode={customization.isDarkMode}
selected={selected}
handleSelect={handleSelect}
/>
))}
</TableBody>
</Table>
</TableContainer>
)}
</>
</DialogContent>
<DialogActions>
<Button onClick={onCancel}>Close</Button>
</DialogActions>
</Dialog>
) : null
return createPortal(component, portalElement)
}
UpsertHistoryDialog.propTypes = {
show: PropTypes.bool,
dialogProps: PropTypes.object,
onCancel: PropTypes.func
}
export default UpsertHistoryDialog
@@ -0,0 +1,94 @@
import PropTypes from 'prop-types'
import { createPortal } from 'react-dom'
import { useDispatch, useSelector } from 'react-redux'
import { useEffect } from 'react'
import ReactJson from 'flowise-react-json-view'
import { Typography, Card, CardContent, Button, Dialog, DialogActions, DialogContent, DialogTitle } from '@mui/material'
import StatsCard from '@/ui-component/cards/StatsCard'
import { HIDE_CANVAS_DIALOG, SHOW_CANVAS_DIALOG } from '@/store/actions'
const UpsertResultDialog = ({ show, dialogProps, onCancel }) => {
const portalElement = document.getElementById('portal')
const dispatch = useDispatch()
const customization = useSelector((state) => state.customization)
useEffect(() => {
if (show) dispatch({ type: SHOW_CANVAS_DIALOG })
else dispatch({ type: HIDE_CANVAS_DIALOG })
return () => dispatch({ type: HIDE_CANVAS_DIALOG })
}, [show, dispatch])
const component = show ? (
<Dialog
onClose={onCancel}
open={show}
fullWidth
maxWidth='sm'
aria-labelledby='upsert-result-dialog-title'
aria-describedby='upsert-result-dialog-description'
>
<DialogTitle sx={{ fontSize: '1rem' }} id='upsert-result-dialog-title'>
Upsert Record
</DialogTitle>
<DialogContent>
<>
<div
style={{
display: 'grid',
gridTemplateColumns: 'repeat(4, minmax(0, 1fr))',
gap: 5
}}
>
<StatsCard title='Added' stat={dialogProps.numAdded ?? 0} />
<StatsCard title='Updated' stat={dialogProps.numUpdated ?? 0} />
<StatsCard title='Skipped' stat={dialogProps.numSkipped ?? 0} />
<StatsCard title='Deleted' stat={dialogProps.numDeleted ?? 0} />
</div>
{dialogProps.addedDocs && dialogProps.addedDocs.length > 0 && (
<Typography sx={{ mt: 2, mb: 2, fontWeight: 500 }}>{dialogProps.numAdded} Added Documents</Typography>
)}
{dialogProps.addedDocs &&
dialogProps.addedDocs.length > 0 &&
dialogProps.addedDocs.map((docs, index) => {
return (
<Card
key={index}
sx={{ border: '1px solid #e0e0e0', borderRadius: `${customization.borderRadius}px`, mb: 1 }}
>
<CardContent>
<Typography sx={{ fontSize: 14 }} color='text.primary' gutterBottom>
{docs.pageContent}
</Typography>
<ReactJson
theme={customization.isDarkMode ? 'ocean' : 'rjv-default'}
style={{ padding: 10, borderRadius: 10 }}
src={docs.metadata}
name={null}
quotesOnKeys={false}
enableClipboard={false}
displayDataTypes={false}
collapsed={true}
/>
</CardContent>
</Card>
)
})}
</>
</DialogContent>
<DialogActions>
<Button onClick={onCancel}>Close</Button>
</DialogActions>
</Dialog>
) : null
return createPortal(component, portalElement)
}
UpsertResultDialog.propTypes = {
show: PropTypes.bool,
dialogProps: PropTypes.object,
onCancel: PropTypes.func,
onSave: PropTypes.func
}
export default UpsertResultDialog
@@ -78,7 +78,7 @@ function a11yProps(index) {
}
}
const VectorStoreDialog = ({ show, dialogProps, onCancel }) => {
const VectorStoreDialog = ({ show, dialogProps, onCancel, onIndexResult }) => {
const portalElement = document.getElementById('portal')
const { reactFlowInstance } = useContext(flowContext)
const dispatch = useDispatch()
@@ -276,7 +276,7 @@ query(formData).then((response) => {
const onUpsertClicked = async (vectorStoreNode) => {
setLoading(true)
try {
await vectorstoreApi.upsertVectorStore(dialogProps.chatflowid, { stopNodeId: vectorStoreNode.data.id })
const res = await vectorstoreApi.upsertVectorStore(dialogProps.chatflowid, { stopNodeId: vectorStoreNode.data.id })
enqueueSnackbar({
message: 'Succesfully upserted vector store. You can start chatting now!',
options: {
@@ -290,6 +290,7 @@ query(formData).then((response) => {
}
})
setLoading(false)
if (res && res.data && typeof res.data === 'object') onIndexResult(res.data)
} catch (error) {
enqueueSnackbar({
message: error.response.data.message,
@@ -549,7 +550,8 @@ query(formData).then((response) => {
VectorStoreDialog.propTypes = {
show: PropTypes.bool,
dialogProps: PropTypes.object,
onCancel: PropTypes.func
onCancel: PropTypes.func,
onIndexResult: PropTypes.func
}
export default VectorStoreDialog
@@ -1,33 +1,19 @@
import { useState, useRef, useEffect } from 'react'
import { useDispatch } from 'react-redux'
import PropTypes from 'prop-types'
import { Button } from '@mui/material'
import { IconDatabaseImport, IconX } from '@tabler/icons'
// project import
import { StyledFab } from '@/ui-component/button/StyledFab'
import VectorStoreDialog from './VectorStoreDialog'
// api
import vectorstoreApi from '@/api/vectorstore'
// Hooks
import useNotifier from '@/utils/useNotifier'
// Const
import { enqueueSnackbar as enqueueSnackbarAction, closeSnackbar as closeSnackbarAction } from '@/store/actions'
import UpsertResultDialog from './UpsertResultDialog'
export const VectorStorePopUp = ({ chatflowid }) => {
const dispatch = useDispatch()
useNotifier()
const enqueueSnackbar = (...args) => dispatch(enqueueSnackbarAction(...args))
const closeSnackbar = (...args) => dispatch(closeSnackbarAction(...args))
const [open, setOpen] = useState(false)
const [showExpandDialog, setShowExpandDialog] = useState(false)
const [expandDialogProps, setExpandDialogProps] = useState({})
const [showUpsertResultDialog, setShowUpsertResultDialog] = useState(false)
const [upsertResultDialogProps, setUpsertResultDialogProps] = useState({})
const anchorRef = useRef(null)
const prevOpen = useRef(open)
@@ -43,38 +29,6 @@ export const VectorStorePopUp = ({ chatflowid }) => {
setShowExpandDialog(true)
}
const onUpsert = async () => {
try {
await vectorstoreApi.upsertVectorStore(chatflowid, {})
enqueueSnackbar({
message: 'Succesfully upserted vector store',
options: {
key: new Date().getTime() + Math.random(),
variant: 'success',
action: (key) => (
<Button style={{ color: 'white' }} onClick={() => closeSnackbar(key)}>
<IconX />
</Button>
)
}
})
} catch (error) {
enqueueSnackbar({
message: error.response.data.message,
options: {
key: new Date().getTime() + Math.random(),
variant: 'error',
persist: true,
action: (key) => (
<Button style={{ color: 'white' }} onClick={() => closeSnackbar(key)}>
<IconX />
</Button>
)
}
})
}
}
useEffect(() => {
if (prevOpen.current === true && open === false) {
anchorRef.current.focus()
@@ -100,12 +54,24 @@ export const VectorStorePopUp = ({ chatflowid }) => {
<VectorStoreDialog
show={showExpandDialog}
dialogProps={expandDialogProps}
onUpsert={onUpsert}
onCancel={() => {
setShowExpandDialog(false)
setOpen((prevopen) => !prevopen)
}}
onIndexResult={(indexRes) => {
setShowExpandDialog(false)
setShowUpsertResultDialog(true)
setUpsertResultDialogProps({ ...indexRes })
}}
></VectorStoreDialog>
<UpsertResultDialog
show={showUpsertResultDialog}
dialogProps={upsertResultDialogProps}
onCancel={() => {
setShowUpsertResultDialog(false)
setOpen(false)
}}
></UpsertResultDialog>
</>
)
}