Skip to content

Commit 8b5fedb

Browse files
authored
RI-7293: update vector search routes (#4847)
1 parent 5df430c commit 8b5fedb

File tree

13 files changed

+212
-48
lines changed

13 files changed

+212
-48
lines changed

redisinsight/ui/src/components/main-router/constants/defaultRoutes.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { lazy } from 'react'
22
import { IRoute, FeatureFlags, PageNames, Pages } from 'uiSrc/constants'
33
import {
44
BrowserPage,
5-
VectorSearchPage,
5+
VectorSearchPageRouter,
66
HomePage,
77
InstancePage,
88
RedisCloudDatabasesPage,
@@ -21,9 +21,12 @@ import PipelineManagementPage from 'uiSrc/pages/rdi/pipeline-management'
2121
import { ANALYTICS_ROUTES, RDI_PIPELINE_MANAGEMENT_ROUTES } from './sub-routes'
2222
import COMMON_ROUTES from './commonRoutes'
2323
import { getRouteIncludedByEnv, LAZY_LOAD } from '../config'
24+
import { VECTOR_SEARCH_ROUTES } from './sub-routes/vectorSearchRoutes'
2425

2526
const LazyBrowserPage = lazy(() => import('uiSrc/pages/browser'))
26-
const LazyVectorSearchPage = lazy(() => import('uiSrc/pages/vector-search'))
27+
const LazyVectorSearchPageRouter = lazy(
28+
() => import('uiSrc/pages/vector-search/pages/VectorSearchPageRouter'),
29+
)
2730
const LazyHomePage = lazy(() => import('uiSrc/pages/home'))
2831
const LazyWorkbenchPage = lazy(() => import('uiSrc/pages/workbench'))
2932
const LazyPubSubPage = lazy(() => import('uiSrc/pages/pub-sub'))
@@ -60,7 +63,8 @@ const INSTANCE_ROUTES: IRoute[] = [
6063
{
6164
pageName: PageNames.vectorSearch,
6265
path: Pages.vectorSearch(':instanceId'),
63-
component: LAZY_LOAD ? LazyVectorSearchPage : VectorSearchPage,
66+
component: LAZY_LOAD ? LazyVectorSearchPageRouter : VectorSearchPageRouter,
67+
routes: VECTOR_SEARCH_ROUTES,
6468
},
6569
{
6670
pageName: PageNames.workbench,
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { lazy } from 'react'
2+
3+
import { IRoute, PageNames, Pages } from 'uiSrc/constants'
4+
import { VectorSearchCreateIndexPage, VectorSearchPage } from 'uiSrc/pages'
5+
import { LAZY_LOAD } from '../../config'
6+
7+
const LazyVectorSearchPage = lazy(
8+
() => import('uiSrc/pages/vector-search/pages/VectorSearchPage'),
9+
)
10+
const LazyVectorSearchCreateIndexPage = lazy(
11+
() => import('uiSrc/pages/vector-search/pages/VectorSearchCreateIndexPage'),
12+
)
13+
14+
export const VECTOR_SEARCH_ROUTES: IRoute[] = [
15+
{
16+
pageName: PageNames.vectorSearchCreateIndex,
17+
path: Pages.vectorSearchCreateIndex(':instanceId'),
18+
component: LAZY_LOAD
19+
? LazyVectorSearchCreateIndexPage
20+
: VectorSearchCreateIndexPage,
21+
},
22+
{
23+
pageName: PageNames.vectorSearch,
24+
path: Pages.vectorSearch(':instanceId'),
25+
component: LAZY_LOAD ? LazyVectorSearchPage : VectorSearchPage,
26+
},
27+
]

redisinsight/ui/src/components/navigation-menu/hooks/useNavigation.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ export function useNavigation() {
6666
Pages.rdiPipelineManagement(connectedRdiInstanceId),
6767
)
6868

69+
const isVectorSearchPath = () =>
70+
location.pathname.split('/')[2] === PageNames.vectorSearch
71+
6972
const getAdditionPropsForHighlighting = (
7073
pageName: string,
7174
): Omit<HighlightedFeatureProps, 'children'> => {
@@ -99,7 +102,7 @@ export function useNavigation() {
99102
onClick: () => handleGoPage(Pages.vectorSearch(connectedInstanceId)),
100103
dataTestId: 'vector-search-page-btn',
101104
connectedInstanceId,
102-
isActivePage: activePage === `/${PageNames.vectorSearch}`,
105+
isActivePage: isVectorSearchPath(),
103106
iconType: SlowLogIcon,
104107
},
105108
{

redisinsight/ui/src/constants/pages.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export interface IRoute {
1616
export enum PageNames {
1717
workbench = 'workbench',
1818
vectorSearch = 'vector-search',
19+
vectorSearchCreateIndex = 'create-index',
1920
browser = 'browser',
2021
search = 'search',
2122
slowLog = 'slowlog',
@@ -52,6 +53,8 @@ export const Pages = {
5253
browser: (instanceId: string) => `/${instanceId}/${PageNames.browser}`,
5354
vectorSearch: (instanceId: string) =>
5455
`/${instanceId}/${PageNames.vectorSearch}`,
56+
vectorSearchCreateIndex: (instanceId: string) =>
57+
`/${instanceId}/${PageNames.vectorSearch}/${PageNames.vectorSearchCreateIndex}`,
5558
workbench: (instanceId: string) => `/${instanceId}/${PageNames.workbench}`,
5659
search: (instanceId: string) => `/${instanceId}/${PageNames.search}`,
5760
pubSub: (instanceId: string) => `/${instanceId}/${PageNames.pubSub}`,

redisinsight/ui/src/pages/vector-search/VectorSearchPage.tsx

Lines changed: 0 additions & 30 deletions
This file was deleted.

redisinsight/ui/src/pages/vector-search/create-index/VectorSearchCreateIndex.spec.tsx

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import React from 'react'
2+
import reactRouterDom from 'react-router-dom'
23
import {
34
render,
45
screen,
@@ -8,17 +9,33 @@ import {
89
} from 'uiSrc/utils/test-utils'
910
import { RootState } from 'uiSrc/slices/store'
1011
import { sendEventTelemetry, TelemetryEvent } from 'uiSrc/telemetry'
12+
import { Pages } from 'uiSrc/constants'
13+
import { addErrorNotification } from 'uiSrc/slices/app/notifications'
1114
import { INSTANCE_ID_MOCK } from 'uiSrc/mocks/handlers/analytics/dbAnalysisHistoryHandlers'
12-
import { VectorSearchCreateIndex } from './VectorSearchCreateIndex'
15+
import {
16+
VectorSearchCreateIndex,
17+
VectorSearchCreateIndexProps,
18+
} from './VectorSearchCreateIndex'
1319
import { SampleDataContent, SampleDataType, SearchIndexType } from './types'
20+
import { useCreateIndex } from './hooks/useCreateIndex'
1421

1522
// Mock the telemetry module, so we don't send actual telemetry data during tests
1623
jest.mock('uiSrc/telemetry', () => ({
1724
...jest.requireActual('uiSrc/telemetry'),
1825
sendEventTelemetry: jest.fn(),
1926
}))
2027

21-
const renderVectorSearchCreateIndexComponent = () => {
28+
jest.mock('./hooks/useCreateIndex', () => ({
29+
useCreateIndex: jest.fn(),
30+
}))
31+
32+
const mockedUseCreateIndex = useCreateIndex as jest.MockedFunction<
33+
typeof useCreateIndex
34+
>
35+
36+
const renderVectorSearchCreateIndexComponent = (
37+
props?: VectorSearchCreateIndexProps,
38+
) => {
2239
const testState: RootState = {
2340
...initialStateDefault,
2441
connections: {
@@ -37,13 +54,20 @@ const renderVectorSearchCreateIndexComponent = () => {
3754
},
3855
}
3956
const store = mockStore(testState)
57+
const utils = render(<VectorSearchCreateIndex {...props} />, { store })
4058

41-
return render(<VectorSearchCreateIndex />, { store })
59+
return { ...utils, store }
4260
}
4361

4462
describe('VectorSearchCreateIndex', () => {
4563
beforeEach(() => {
4664
jest.clearAllMocks()
65+
mockedUseCreateIndex.mockReturnValue({
66+
run: jest.fn(),
67+
loading: false,
68+
error: null,
69+
success: false,
70+
} as any)
4771
})
4872

4973
it('should render correctly', () => {
@@ -52,6 +76,43 @@ describe('VectorSearchCreateIndex', () => {
5276
expect(container).toBeInTheDocument()
5377
})
5478

79+
it('should redirect to vector search page after index creation', async () => {
80+
const pushMock = jest.fn()
81+
reactRouterDom.useHistory = jest.fn().mockReturnValue({ push: pushMock })
82+
83+
mockedUseCreateIndex.mockReturnValue({
84+
run: jest.fn(),
85+
loading: false,
86+
error: null,
87+
success: true,
88+
} as any)
89+
90+
renderVectorSearchCreateIndexComponent({ initialStep: 2 })
91+
92+
// Effect should dispatch success notification and navigate
93+
expect(pushMock).toHaveBeenCalledWith(Pages.vectorSearch(INSTANCE_ID_MOCK))
94+
})
95+
96+
it('should dispatch error notification on error', () => {
97+
mockedUseCreateIndex.mockReturnValue({
98+
run: jest.fn(),
99+
loading: false,
100+
error: { message: 'Some error' },
101+
success: false,
102+
} as any)
103+
104+
const { store } = renderVectorSearchCreateIndexComponent({
105+
initialStep: 2,
106+
})
107+
108+
// Should dispatch addErrorNotification
109+
const actions = store?.getActions?.() || []
110+
const hasErrorAction = actions.some(
111+
(a: any) => a.type === addErrorNotification.type,
112+
)
113+
expect(hasErrorAction).toBe(true)
114+
})
115+
55116
describe('Telemetry', () => {
56117
it('should send telemetry events on start step', () => {
57118
renderVectorSearchCreateIndexComponent()

redisinsight/ui/src/pages/vector-search/create-index/VectorSearchCreateIndex.tsx

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React, { useEffect, useState } from 'react'
2-
import { useParams } from 'react-router-dom'
2+
import { useHistory, useParams } from 'react-router-dom'
3+
import { useDispatch } from 'react-redux'
34

45
import { Stepper } from '@redis-ui/components'
56
import { Title } from 'uiSrc/components/base/text'
@@ -25,20 +26,29 @@ import {
2526
collectCreateIndexStepTelemetry,
2627
collectCreateIndexWizardTelemetry,
2728
} from '../telemetry'
29+
import { Pages } from 'uiSrc/constants'
30+
import {
31+
addMessageNotification,
32+
addErrorNotification,
33+
} from 'uiSrc/slices/app/notifications'
34+
import successMessages from 'uiSrc/components/notifications/success-messages'
35+
import { parseCustomError } from 'uiSrc/utils'
2836

2937
const stepNextButtonTexts = [
3038
'Proceed to adding data',
3139
'Proceed to index',
3240
'Create index',
3341
]
3442

35-
type VectorSearchCreateIndexProps = {
43+
export type VectorSearchCreateIndexProps = {
3644
initialStep?: number
3745
}
3846

3947
export const VectorSearchCreateIndex = ({
4048
initialStep = 1,
4149
}: VectorSearchCreateIndexProps) => {
50+
const dispatch = useDispatch()
51+
const history = useHistory()
4252
const { instanceId } = useParams<{ instanceId: string }>()
4353
const [step, setStep] = useState(initialStep)
4454
const [createSearchIndexParameters, setCreateSearchIndexParameters] =
@@ -52,7 +62,7 @@ export const VectorSearchCreateIndex = ({
5262
indexFields: selectedBikesIndexFields,
5363
})
5464

55-
const { run: createIndex, success, loading } = useCreateIndex()
65+
const { run: createIndex, error, success, loading } = useCreateIndex()
5666

5767
const setParameters = (params: Partial<CreateSearchIndexParameters>) => {
5868
setCreateSearchIndexParameters((prev) => ({ ...prev, ...params }))
@@ -81,9 +91,15 @@ export const VectorSearchCreateIndex = ({
8191
})
8292
}, [step])
8393

84-
if (success) {
85-
return <>Success!</>
86-
}
94+
useEffect(() => {
95+
if (error) {
96+
dispatch(addErrorNotification(parseCustomError(error.message) as any))
97+
} else if (success) {
98+
dispatch(addMessageNotification(successMessages.CREATE_INDEX()))
99+
100+
history.push(Pages.vectorSearch(instanceId))
101+
}
102+
}, [success, error])
87103

88104
return (
89105
<VectorSearchScreenWrapper direction="column" justify="between">
Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { VectorSearchPage } from './VectorSearchPage'
2-
3-
export { VectorSearchPage }
4-
export default VectorSearchPage
1+
export { default as VectorSearchCreateIndexPage } from './pages/VectorSearchCreateIndexPage'
2+
export { default as VectorSearchPage } from './pages/VectorSearchPage'
3+
export { default as VectorSearchPageRouter } from './pages/VectorSearchPageRouter'
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import React from 'react'
2+
3+
import { cleanup, render } from 'uiSrc/utils/test-utils'
4+
import VectorSearchCreateIndexPage from './VectorSearchCreateIndexPage'
5+
6+
const renderVectorSearchCreateIndexPageComponent = () =>
7+
render(<VectorSearchCreateIndexPage />)
8+
9+
describe('VectorSearchCreateIndexPage', () => {
10+
beforeEach(() => {
11+
cleanup()
12+
})
13+
14+
it('should render ', () => {
15+
const { container } = renderVectorSearchCreateIndexPageComponent()
16+
17+
expect(container).toBeTruthy()
18+
})
19+
})
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import React from 'react'
2+
import { TelemetryPageView } from 'uiSrc/telemetry'
3+
import { usePageViewTelemetry } from 'uiSrc/telemetry/usePageViewTelemetry'
4+
5+
import { VectorSearchCreateIndex } from './../create-index/VectorSearchCreateIndex'
6+
import { VectorSearchPageWrapper } from './../styles'
7+
8+
const VectorSearchCreateIndexPage = () => {
9+
usePageViewTelemetry({
10+
page: TelemetryPageView.VECTOR_SEARCH_PAGE,
11+
})
12+
13+
return (
14+
<VectorSearchPageWrapper>
15+
<VectorSearchCreateIndex />
16+
</VectorSearchPageWrapper>
17+
)
18+
}
19+
20+
export default VectorSearchCreateIndexPage

0 commit comments

Comments
 (0)