Skip to content

Commit b180ec1

Browse files
Vector dimension reset (#594)
* added the vector index API * integrated the create vector index API * added the markdown for alert message * Moved the alert into the connection Modal * fixed the new vector index param * added the vector index dimension to text * Update VectorIndexMisMatchAlert.tsx
1 parent 1073cfa commit b180ec1

File tree

10 files changed

+228
-53
lines changed

10 files changed

+228
-53
lines changed

frontend/src/components/Content.tsx

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { useCredentials } from '../context/UserCredentials';
66
import { useFileContext } from '../context/UsersFiles';
77
import CustomAlert from './UI/Alert';
88
import { extractAPI } from '../utils/FileAPI';
9-
import { ContentProps, CustomFile, OptionType, UserCredentials, alertStateType } from '../types';
9+
import { ContentProps, CustomFile, OptionType, UserCredentials, alertStateType, connectionState } from '../types';
1010
import deleteAPI from '../services/DeleteFiles';
1111
import { postProcessing } from '../services/PostProcessing';
1212
import DeletePopUp from './Popups/DeletePopUp/DeletePopUp';
@@ -33,7 +33,11 @@ const Content: React.FC<ContentProps> = ({
3333
closeSettingModal,
3434
}) => {
3535
const [init, setInit] = useState<boolean>(false);
36-
const [openConnection, setOpenConnection] = useState<boolean>(false);
36+
const [openConnection, setOpenConnection] = useState<connectionState>({
37+
isvectorIndexMatch: true,
38+
openPopUp: false,
39+
novectorindexInDB: true,
40+
});
3741
const [openGraphView, setOpenGraphView] = useState<boolean>(false);
3842
const [inspectedName, setInspectedName] = useState<string>('');
3943
const [connectionStatus, setConnectionStatus] = useState<boolean>(false);
@@ -107,11 +111,11 @@ const Content: React.FC<ContentProps> = ({
107111
port: neo4jConnection.uri.split(':')[2],
108112
});
109113
} else {
110-
setOpenConnection(true);
114+
setOpenConnection((prev) => ({ ...prev, openPopUp: true }));
111115
}
112116
setInit(true);
113117
} else {
114-
setOpenConnection(true);
118+
setOpenConnection((prev) => ({ ...prev, openPopUp: true }));
115119
}
116120
}, []);
117121

@@ -279,11 +283,7 @@ const Content: React.FC<ContentProps> = ({
279283
};
280284

281285
const handleClose = () => {
282-
setalertDetails({
283-
showAlert: false,
284-
alertType: 'info',
285-
alertMessage: '',
286-
});
286+
setalertDetails((prev) => ({ ...prev, showAlert: false, alertMessage: '' }));
287287
};
288288

289289
const handleOpenGraphClick = () => {
@@ -346,14 +346,6 @@ const Content: React.FC<ContentProps> = ({
346346
[selectedfileslength, completedfileNo]
347347
);
348348

349-
// const processingCheck = () => {
350-
// const processingFiles = filesData.some((file) => file.status === 'Processing');
351-
// const selectedRowProcessing = childRef.current?.getSelectedRows().some((row) =>
352-
// filesData.some((file) => file.name === row && file.status === 'Processing')
353-
// );
354-
// return processingFiles || selectedRowProcessing;
355-
// };
356-
357349
const filesForProcessing = useMemo(() => {
358350
let newstatusfiles: CustomFile[] = [];
359351
if (childRef.current?.getSelectedRows().length) {
@@ -417,10 +409,26 @@ const Content: React.FC<ContentProps> = ({
417409
console.log(parsedData.uri);
418410
const response = await connectAPI(parsedData.uri, parsedData.user, parsedData.password, parsedData.database);
419411
if (response?.data?.status === 'Success') {
420-
setConnectionStatus(true);
421-
setOpenConnection(false);
412+
localStorage.setItem(
413+
'neo4j.connection',
414+
JSON.stringify({
415+
...parsedData,
416+
userDbVectorIndex: response.data.data.db_vector_dimension,
417+
})
418+
);
419+
if (response.data.data.application_dimension === response.data.data.db_vector_dimension) {
420+
setConnectionStatus(true);
421+
setOpenConnection((prev) => ({ ...prev, openPopUp: false }));
422+
} else {
423+
setOpenConnection({
424+
isvectorIndexMatch: false,
425+
openPopUp: true,
426+
novectorindexInDB: response.data.data.db_vector_dimension === 0,
427+
});
428+
setConnectionStatus(false);
429+
}
422430
} else {
423-
setOpenConnection(true);
431+
setOpenConnection((prev) => ({ ...prev, openPopUp: true }));
424432
setConnectionStatus(false);
425433
}
426434
})();
@@ -524,9 +532,11 @@ const Content: React.FC<ContentProps> = ({
524532
<div className={`n-bg-palette-neutral-bg-default ${classNameCheck}`}>
525533
<Flex className='w-full' alignItems='center' justifyContent='space-between' flexDirection='row'>
526534
<ConnectionModal
527-
open={openConnection}
535+
open={openConnection.openPopUp}
528536
setOpenConnection={setOpenConnection}
529537
setConnectionStatus={setConnectionStatus}
538+
isVectorIndexMatch={openConnection.isvectorIndexMatch}
539+
noVectorIndexFound={openConnection.novectorindexInDB}
530540
/>
531541
<div className='connectionstatus__container'>
532542
<span className='h6 px-1'>Neo4j connection</span>
@@ -570,7 +580,7 @@ const Content: React.FC<ContentProps> = ({
570580
Graph Enhancement
571581
</ButtonWithToolTip>
572582
{!connectionStatus ? (
573-
<Button className='mr-2.5' onClick={() => setOpenConnection(true)}>
583+
<Button className='mr-2.5' onClick={() => setOpenConnection((prev) => ({ ...prev, openPopUp: true }))}>
574584
{buttonCaptions.connectToNeo4j}
575585
</Button>
576586
) : (

frontend/src/components/DataSources/Local/DropZone.tsx

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,7 @@ const DropZone: FunctionComponent = () => {
7373
};
7474

7575
const handleClose = () => {
76-
setalertDetails({
77-
showAlert: false,
78-
alertMessage: '',
79-
alertType: 'error',
80-
});
76+
setalertDetails((prev) => ({ ...prev, showAlert: false, alertMessage: '' }));
8177
};
8278

8379
useEffect(() => {

frontend/src/components/Layout/PageLayout.tsx

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,7 @@ export default function PageLayoutNew({
6767
});
6868
};
6969
const handleClose = () => {
70-
setalertDetails({
71-
showAlert: false,
72-
alertType: 'info',
73-
alertMessage: '',
74-
});
70+
setalertDetails((prev) => ({ ...prev, showAlert: false, alertMessage: '' }));
7571
};
7672

7773
return (

frontend/src/components/Popups/ConnectionModal/ConnectionModal.tsx

Lines changed: 114 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,43 @@
1-
import { Button, Dialog, TextInput, Dropdown, Banner, Dropzone, Typography, TextLink } from '@neo4j-ndl/react';
1+
import { Button, Dialog, TextInput, Dropdown, Banner, Dropzone, Typography, TextLink, Flex } from '@neo4j-ndl/react';
22
import { Dispatch, SetStateAction, useCallback, useEffect, useMemo, useState } from 'react';
33
import connectAPI from '../../../services/ConnectAPI';
44
import { useCredentials } from '../../../context/UserCredentials';
55
import { useSearchParams } from 'react-router-dom';
66
import { buttonCaptions } from '../../../utils/Constants';
7+
import { createVectorIndex } from '../../../services/vectorIndexCreation';
8+
import { connectionState, UserCredentials } from '../../../types';
9+
import VectorIndexMisMatchAlert from './VectorIndexMisMatchAlert';
710

811
interface Message {
912
type: 'success' | 'info' | 'warning' | 'danger' | 'unknown';
10-
content: string;
13+
content: string | React.ReactNode;
1114
}
1215

1316
interface ConnectionModalProps {
1417
open: boolean;
15-
setOpenConnection: Dispatch<SetStateAction<boolean>>;
18+
setOpenConnection: Dispatch<SetStateAction<connectionState>>;
1619
setConnectionStatus: Dispatch<SetStateAction<boolean>>;
20+
isVectorIndexMatch: boolean;
21+
noVectorIndexFound: boolean;
1722
}
1823

19-
export default function ConnectionModal({ open, setOpenConnection, setConnectionStatus }: ConnectionModalProps) {
24+
export default function ConnectionModal({
25+
open,
26+
setOpenConnection,
27+
setConnectionStatus,
28+
isVectorIndexMatch,
29+
noVectorIndexFound,
30+
}: ConnectionModalProps) {
2031
let prefilledconnection = localStorage.getItem('neo4j.connection');
2132
let initialuri;
2233
let initialdb;
2334
let initialusername;
2435
let initialport;
2536
let initialprotocol;
37+
let initialuserdbvectorindex;
2638
if (prefilledconnection) {
2739
let parsedcontent = JSON.parse(prefilledconnection);
40+
initialuserdbvectorindex = parsedcontent.userDbVectorIndex;
2841
let urisplit = parsedcontent?.uri?.split('://');
2942
initialuri = urisplit[1];
3043
initialdb = parsedcontent?.database;
@@ -40,9 +53,11 @@ export default function ConnectionModal({ open, setOpenConnection, setConnection
4053
const [username, setUsername] = useState<string>(initialusername ?? 'neo4j');
4154
const [password, setPassword] = useState<string>('');
4255
const [connectionMessage, setMessage] = useState<Message | null>({ type: 'unknown', content: '' });
43-
const { setUserCredentials } = useCredentials();
56+
const { setUserCredentials, userCredentials } = useCredentials();
4457
const [isLoading, setIsLoading] = useState<boolean>(false);
4558
const [searchParams, setSearchParams] = useSearchParams();
59+
const [userDbVectorIndex, setUserDbVectorIndex] = useState<number | undefined>(initialuserdbvectorindex ?? undefined);
60+
const [vectorIndexLoading, setVectorIndexLoading] = useState<boolean>(false);
4661

4762
useEffect(() => {
4863
if (searchParams.has('connectURL')) {
@@ -51,8 +66,66 @@ export default function ConnectionModal({ open, setOpenConnection, setConnection
5166
searchParams.delete('connectURL');
5267
setSearchParams(searchParams);
5368
}
69+
return () => {
70+
setUserDbVectorIndex(undefined);
71+
};
5472
}, [open]);
5573

74+
const recreateVectorIndex = useCallback(
75+
async (isNewVectorIndex: boolean) => {
76+
try {
77+
setVectorIndexLoading(true);
78+
const response = await createVectorIndex(userCredentials as UserCredentials, isNewVectorIndex);
79+
setVectorIndexLoading(false);
80+
if (response.data.status === 'Failed') {
81+
throw new Error(response.data.error);
82+
} else {
83+
setMessage({
84+
type: 'success',
85+
content: 'Successfully created the vector index',
86+
});
87+
setConnectionStatus(true);
88+
localStorage.setItem(
89+
'neo4j.connection',
90+
JSON.stringify({
91+
uri: userCredentials?.uri,
92+
user: userCredentials?.userName,
93+
password: userCredentials?.password,
94+
database: userCredentials?.database,
95+
userDbVectorIndex: 384,
96+
})
97+
);
98+
}
99+
} catch (error) {
100+
setVectorIndexLoading(false);
101+
if (error instanceof Error) {
102+
console.log('Error in recreating the vector index', error.message);
103+
setMessage({ type: 'danger', content: error.message });
104+
}
105+
}
106+
setTimeout(() => {
107+
setMessage({ type: 'unknown', content: '' });
108+
setOpenConnection((prev) => ({ ...prev, openPopUp: false }));
109+
}, 3000);
110+
},
111+
[userCredentials, userDbVectorIndex]
112+
);
113+
useEffect(() => {
114+
if (!isVectorIndexMatch) {
115+
setMessage({
116+
type: 'danger',
117+
content: (
118+
<VectorIndexMisMatchAlert
119+
vectorIndexLoading={vectorIndexLoading}
120+
recreateVectorIndex={() => recreateVectorIndex(!noVectorIndexFound)}
121+
isVectorIndexAlreadyExists={!noVectorIndexFound}
122+
userVectorIndexDimension={JSON.parse(localStorage.getItem('neo4j.connection') ?? 'null').userDbVectorIndex}
123+
/>
124+
),
125+
});
126+
}
127+
}, [isVectorIndexMatch, vectorIndexLoading, noVectorIndexFound]);
128+
56129
const parseAndSetURI = (uri: string, urlparams = false) => {
57130
const uriParts: string[] = uri.split('://');
58131
let uriHost: string[] | string;
@@ -131,27 +204,47 @@ export default function ConnectionModal({ open, setOpenConnection, setConnection
131204
setIsLoading(true);
132205
const response = await connectAPI(connectionURI, username, password, database);
133206
if (response?.data?.status === 'Success') {
207+
setUserDbVectorIndex(response.data.data.db_vector_dimension);
208+
if (response.data.data.db_vector_dimension === response.data.data.application_dimension) {
209+
setConnectionStatus(true);
210+
setOpenConnection((prev) => ({ ...prev, openPopUp: false }));
211+
setMessage({
212+
type: 'success',
213+
content: response.data.data.message,
214+
});
215+
} else {
216+
setMessage({
217+
type: 'danger',
218+
content: (
219+
<VectorIndexMisMatchAlert
220+
vectorIndexLoading={vectorIndexLoading}
221+
recreateVectorIndex={() => recreateVectorIndex(response.data.data.db_vector_dimension === 0)}
222+
isVectorIndexAlreadyExists={response.data.data.db_vector_dimension != 0}
223+
userVectorIndexDimension={response.data.data.db_vector_dimension}
224+
/>
225+
),
226+
});
227+
}
134228
localStorage.setItem(
135229
'neo4j.connection',
136-
JSON.stringify({ uri: connectionURI, user: username, password: password, database: database })
230+
JSON.stringify({
231+
uri: connectionURI,
232+
user: username,
233+
password: password,
234+
database: database,
235+
userDbVectorIndex,
236+
})
137237
);
138-
setConnectionStatus(true);
139-
setMessage({
140-
type: 'success',
141-
content: response.data.message,
142-
});
143-
setOpenConnection(false);
144238
} else {
145239
setMessage({ type: 'danger', content: response.data.error });
146-
setOpenConnection(true);
240+
setOpenConnection((prev) => ({ ...prev, openPopUp: true }));
147241
setPassword('');
148242
setConnectionStatus(false);
149243
}
150244
setIsLoading(false);
151245
setTimeout(() => {
152-
setMessage({ type: 'unknown', content: '' });
153246
setPassword('');
154-
}, 3000);
247+
}, 10000);
155248
};
156249

157250
const onClose = useCallback(() => {
@@ -167,7 +260,7 @@ export default function ConnectionModal({ open, setOpenConnection, setConnection
167260
open={open}
168261
aria-labelledby='form-dialog-title'
169262
onClose={() => {
170-
setOpenConnection(false);
263+
setOpenConnection((prev) => ({ ...prev, openPopUp: false }));
171264
setMessage({ type: 'unknown', content: '' });
172265
}}
173266
>
@@ -269,9 +362,11 @@ export default function ConnectionModal({ open, setOpenConnection, setConnection
269362
/>
270363
</div>
271364
</div>
272-
<Button loading={isLoading} disabled={isDisabled} onClick={() => submitConnection()}>
273-
{buttonCaptions.connect}
274-
</Button>
365+
<Flex flexDirection='row' justifyContent='flex-end'>
366+
<Button loading={isLoading} disabled={isDisabled} onClick={() => submitConnection()}>
367+
{buttonCaptions.connect}
368+
</Button>
369+
</Flex>
275370
</Dialog.Content>
276371
</Dialog>
277372
</>
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { Box, Flex } from '@neo4j-ndl/react';
2+
import Markdown from 'react-markdown';
3+
import ButtonWithToolTip from '../../UI/ButtonWithToolTip';
4+
5+
export default function VectorIndexMisMatchAlert({
6+
vectorIndexLoading,
7+
recreateVectorIndex,
8+
isVectorIndexAlreadyExists,
9+
userVectorIndexDimension,
10+
}: {
11+
vectorIndexLoading: boolean;
12+
recreateVectorIndex: () => Promise<void>;
13+
isVectorIndexAlreadyExists: boolean;
14+
userVectorIndexDimension: number;
15+
}) {
16+
return (
17+
<Flex>
18+
<Box>
19+
<Markdown className='whitespace-pre-wrap'>
20+
{isVectorIndexAlreadyExists
21+
? `**Vector Index Incompatibility**
22+
The existing Neo4j vector index dimension (${userVectorIndexDimension}) is incompatible with the supported dimension (384) for this application.
23+
To proceed, please choose one of the following options:
24+
1.**Recreate Vector Index:** Click "Re-Create Vector Index" to generate a compatible vector index.
25+
2.**Use a Different Instance:** Connect to a Neo4j instance with a compatible vector index configuration `
26+
: `**Vector index not found**.
27+
To leverage AI-powered search, please create a vector index.This will enable efficient similarity search within your Neo4j database`}
28+
</Markdown>
29+
</Box>
30+
<Box className='n-size-full n-flex n-flex-col n-items-center n-justify-center'>
31+
<ButtonWithToolTip
32+
text='creates the supported vector index'
33+
label='creates the supported vector index'
34+
placement='top'
35+
loading={vectorIndexLoading}
36+
onClick={() => recreateVectorIndex()}
37+
className='!w-full'
38+
color='danger'
39+
>
40+
{isVectorIndexAlreadyExists ? 'Re-Create Vector Index' : 'Create Vector Index'}
41+
</ButtonWithToolTip>
42+
</Box>
43+
</Flex>
44+
);
45+
}

0 commit comments

Comments
 (0)