From dde049452cf2856d437903c5b744baeaa1fa551e Mon Sep 17 00:00:00 2001 From: Valentin Kirilov Date: Fri, 11 Jul 2025 13:16:28 +0300 Subject: [PATCH 1/4] RI-7191 Selector tabs component (#4670) * feat: created base wrapper for the "create index" step part of the new vector search * integrate the tab component to serve as a base wrapper * created a minimal implementation for the "use preset index" scenario re #RI-7191 --- .../BuildNewIndexTabTrigger.styles.ts | 7 +++ .../BuildNewIndex/BuildNewIndexTabTrigger.tsx | 9 +++ .../CreateIndexStepWrapper.spec.tsx | 59 +++++++++++++++++++ .../CreateIndexStepWrapper.tsx | 40 +++++++++++++ .../new-index/CreateIndexStep/index.ts | 3 + 5 files changed, 118 insertions(+) create mode 100644 redisinsight/ui/src/components/new-index/CreateIndexStep/BuildNewIndex/BuildNewIndexTabTrigger.styles.ts create mode 100644 redisinsight/ui/src/components/new-index/CreateIndexStep/BuildNewIndex/BuildNewIndexTabTrigger.tsx create mode 100644 redisinsight/ui/src/components/new-index/CreateIndexStep/CreateIndexStepWrapper.spec.tsx create mode 100644 redisinsight/ui/src/components/new-index/CreateIndexStep/CreateIndexStepWrapper.tsx create mode 100644 redisinsight/ui/src/components/new-index/CreateIndexStep/index.ts diff --git a/redisinsight/ui/src/components/new-index/CreateIndexStep/BuildNewIndex/BuildNewIndexTabTrigger.styles.ts b/redisinsight/ui/src/components/new-index/CreateIndexStep/BuildNewIndex/BuildNewIndexTabTrigger.styles.ts new file mode 100644 index 0000000000..5715bf56bf --- /dev/null +++ b/redisinsight/ui/src/components/new-index/CreateIndexStep/BuildNewIndex/BuildNewIndexTabTrigger.styles.ts @@ -0,0 +1,7 @@ +import styled from 'styled-components' + +export const StyledBuildNewIndexTabTrigger = styled.div` + display: flex; + align-items: center; + gap: ${({ theme }) => theme.core.space.space050}; +` diff --git a/redisinsight/ui/src/components/new-index/CreateIndexStep/BuildNewIndex/BuildNewIndexTabTrigger.tsx b/redisinsight/ui/src/components/new-index/CreateIndexStep/BuildNewIndex/BuildNewIndexTabTrigger.tsx new file mode 100644 index 0000000000..4c9eba37e8 --- /dev/null +++ b/redisinsight/ui/src/components/new-index/CreateIndexStep/BuildNewIndex/BuildNewIndexTabTrigger.tsx @@ -0,0 +1,9 @@ +import React from 'react' +import { Badge } from '@redis-ui/components' +import { StyledBuildNewIndexTabTrigger } from './BuildNewIndexTabTrigger.styles' + +export const BuildNewIndexTabTrigger = () => ( + + Build new index + +) diff --git a/redisinsight/ui/src/components/new-index/CreateIndexStep/CreateIndexStepWrapper.spec.tsx b/redisinsight/ui/src/components/new-index/CreateIndexStep/CreateIndexStepWrapper.spec.tsx new file mode 100644 index 0000000000..7865e86d8b --- /dev/null +++ b/redisinsight/ui/src/components/new-index/CreateIndexStep/CreateIndexStepWrapper.spec.tsx @@ -0,0 +1,59 @@ +import React from 'react' +import { fireEvent, render, screen } from 'uiSrc/utils/test-utils' +import { CreateIndexStepWrapper } from './CreateIndexStepWrapper' + +const renderComponent = () => render() + +describe('CreateIndexStepWrapper', () => { + it('should render', () => { + const { container } = renderComponent() + + expect(container).toBeTruthy() + + // Check if the tabs are rendered + const buildNewIndexTabTrigger = screen.getByText('Build new index') + const usePresetIndexTabTrigger = screen.getByText('Use preset index') + + expect(buildNewIndexTabTrigger).toBeInTheDocument() + expect(usePresetIndexTabTrigger).toBeInTheDocument() + + // Check if the "Use preset index" tab content is selected by default + const usePresetIIndexTabContent = screen.queryByTestId( + 'vector-inde-tabs--use-preset-index-content', + ) + expect(usePresetIIndexTabContent).toBeInTheDocument() + }) + + it('should switch to "Use preset index" tab when clicked', () => { + renderComponent() + + const buildNewIndexTabTrigger = screen.getByText('Use preset index') + fireEvent.click(buildNewIndexTabTrigger) + + // Check if the "Use preset index" tab is rendered + const buildNewIndexTabContent = screen.queryByTestId( + 'vector-inde-tabs--use-preset-index-content', + ) + expect(buildNewIndexTabContent).toBeInTheDocument() + }) + + it('shouldn\'t switch to "Build new index" tab when clicked, since it is disabled', () => { + renderComponent() + + const buildNewIndexTabTriggerLabel = screen.getByText('Build new index') + const buildNewIndexTabTriggerButton = + buildNewIndexTabTriggerLabel.closest('[type="button"]') + + expect(buildNewIndexTabTriggerButton).toHaveAttribute('disabled') + expect(buildNewIndexTabTriggerButton).toHaveAttribute('data-disabled') + + // And when clicked, it should not change the active tab + fireEvent.click(buildNewIndexTabTriggerLabel) + + // Check if the "Use preset index" tab is still active + const usePresetIndexTabContent = screen.queryByTestId( + 'vector-inde-tabs--use-preset-index-content', + ) + expect(usePresetIndexTabContent).toBeInTheDocument() + }) +}) diff --git a/redisinsight/ui/src/components/new-index/CreateIndexStep/CreateIndexStepWrapper.tsx b/redisinsight/ui/src/components/new-index/CreateIndexStep/CreateIndexStepWrapper.tsx new file mode 100644 index 0000000000..7dd7073ecb --- /dev/null +++ b/redisinsight/ui/src/components/new-index/CreateIndexStep/CreateIndexStepWrapper.tsx @@ -0,0 +1,40 @@ +import React from 'react' +import { TabsProps } from '@redis-ui/components' +import Tabs, { TabInfo } from 'uiSrc/components/base/layout/tabs' +import { BuildNewIndexTabTrigger } from './BuildNewIndex/BuildNewIndexTabTrigger' + +export enum VectorIndexTab { + BuildNewIndex = 'build-new-index', + UsePresetIndex = 'use-preset-index', +} + +const VECTOR_INDEX_TABS: TabInfo[] = [ + { + value: VectorIndexTab.BuildNewIndex, + label: , + content: null, + disabled: true, + }, + { + value: VectorIndexTab.UsePresetIndex, + label: 'Use preset index', + content: ( +
+ TODO: Add content later +
+ ), + }, +] + +export const CreateIndexStepWrapper = (props: Partial) => { + const { tabs, defaultValue, ...rest } = props + + return ( + + ) +} diff --git a/redisinsight/ui/src/components/new-index/CreateIndexStep/index.ts b/redisinsight/ui/src/components/new-index/CreateIndexStep/index.ts new file mode 100644 index 0000000000..b342bcebad --- /dev/null +++ b/redisinsight/ui/src/components/new-index/CreateIndexStep/index.ts @@ -0,0 +1,3 @@ +import { CreateIndexStepWrapper } from './CreateIndexStepWrapper' + +export default CreateIndexStepWrapper From e32fc59fe8f65ac8f9e574aa4d3277f987b81207 Mon Sep 17 00:00:00 2001 From: Valentin Kirilov Date: Fri, 11 Jul 2025 13:50:32 +0300 Subject: [PATCH 2/4] fix: rename the folder from PascalCase to kebap-case to match the convention re #RI-7091 --- .../CreateIndexStepWrapper.spec.tsx | 6 +++++- .../CreateIndexStepWrapper.tsx | 2 +- .../build-new-index-tab}/BuildNewIndexTabTrigger.styles.ts | 0 .../build-new-index-tab}/BuildNewIndexTabTrigger.tsx | 0 .../{CreateIndexStep => create-index-step}/index.ts | 0 5 files changed, 6 insertions(+), 2 deletions(-) rename redisinsight/ui/src/components/new-index/{CreateIndexStep => create-index-step}/CreateIndexStepWrapper.spec.tsx (94%) rename redisinsight/ui/src/components/new-index/{CreateIndexStep => create-index-step}/CreateIndexStepWrapper.tsx (91%) rename redisinsight/ui/src/components/new-index/{CreateIndexStep/BuildNewIndex => create-index-step/build-new-index-tab}/BuildNewIndexTabTrigger.styles.ts (100%) rename redisinsight/ui/src/components/new-index/{CreateIndexStep/BuildNewIndex => create-index-step/build-new-index-tab}/BuildNewIndexTabTrigger.tsx (100%) rename redisinsight/ui/src/components/new-index/{CreateIndexStep => create-index-step}/index.ts (100%) diff --git a/redisinsight/ui/src/components/new-index/CreateIndexStep/CreateIndexStepWrapper.spec.tsx b/redisinsight/ui/src/components/new-index/create-index-step/CreateIndexStepWrapper.spec.tsx similarity index 94% rename from redisinsight/ui/src/components/new-index/CreateIndexStep/CreateIndexStepWrapper.spec.tsx rename to redisinsight/ui/src/components/new-index/create-index-step/CreateIndexStepWrapper.spec.tsx index 7865e86d8b..a84c28a467 100644 --- a/redisinsight/ui/src/components/new-index/CreateIndexStep/CreateIndexStepWrapper.spec.tsx +++ b/redisinsight/ui/src/components/new-index/create-index-step/CreateIndexStepWrapper.spec.tsx @@ -1,10 +1,14 @@ import React from 'react' -import { fireEvent, render, screen } from 'uiSrc/utils/test-utils' +import { cleanup, fireEvent, render, screen } from 'uiSrc/utils/test-utils' import { CreateIndexStepWrapper } from './CreateIndexStepWrapper' const renderComponent = () => render() describe('CreateIndexStepWrapper', () => { + beforeEach(() => { + cleanup() + }) + it('should render', () => { const { container } = renderComponent() diff --git a/redisinsight/ui/src/components/new-index/CreateIndexStep/CreateIndexStepWrapper.tsx b/redisinsight/ui/src/components/new-index/create-index-step/CreateIndexStepWrapper.tsx similarity index 91% rename from redisinsight/ui/src/components/new-index/CreateIndexStep/CreateIndexStepWrapper.tsx rename to redisinsight/ui/src/components/new-index/create-index-step/CreateIndexStepWrapper.tsx index 7dd7073ecb..3d514b0675 100644 --- a/redisinsight/ui/src/components/new-index/CreateIndexStep/CreateIndexStepWrapper.tsx +++ b/redisinsight/ui/src/components/new-index/create-index-step/CreateIndexStepWrapper.tsx @@ -1,7 +1,7 @@ import React from 'react' import { TabsProps } from '@redis-ui/components' import Tabs, { TabInfo } from 'uiSrc/components/base/layout/tabs' -import { BuildNewIndexTabTrigger } from './BuildNewIndex/BuildNewIndexTabTrigger' +import { BuildNewIndexTabTrigger } from './build-new-index-tab/BuildNewIndexTabTrigger' export enum VectorIndexTab { BuildNewIndex = 'build-new-index', diff --git a/redisinsight/ui/src/components/new-index/CreateIndexStep/BuildNewIndex/BuildNewIndexTabTrigger.styles.ts b/redisinsight/ui/src/components/new-index/create-index-step/build-new-index-tab/BuildNewIndexTabTrigger.styles.ts similarity index 100% rename from redisinsight/ui/src/components/new-index/CreateIndexStep/BuildNewIndex/BuildNewIndexTabTrigger.styles.ts rename to redisinsight/ui/src/components/new-index/create-index-step/build-new-index-tab/BuildNewIndexTabTrigger.styles.ts diff --git a/redisinsight/ui/src/components/new-index/CreateIndexStep/BuildNewIndex/BuildNewIndexTabTrigger.tsx b/redisinsight/ui/src/components/new-index/create-index-step/build-new-index-tab/BuildNewIndexTabTrigger.tsx similarity index 100% rename from redisinsight/ui/src/components/new-index/CreateIndexStep/BuildNewIndex/BuildNewIndexTabTrigger.tsx rename to redisinsight/ui/src/components/new-index/create-index-step/build-new-index-tab/BuildNewIndexTabTrigger.tsx diff --git a/redisinsight/ui/src/components/new-index/CreateIndexStep/index.ts b/redisinsight/ui/src/components/new-index/create-index-step/index.ts similarity index 100% rename from redisinsight/ui/src/components/new-index/CreateIndexStep/index.ts rename to redisinsight/ui/src/components/new-index/create-index-step/index.ts From 9e2c9509e1c5999903b51bcadd9fa980dea7ad9d Mon Sep 17 00:00:00 2001 From: Valentin Kirilov Date: Fri, 11 Jul 2025 13:53:57 +0300 Subject: [PATCH 3/4] feat: created base field box component re #RI-7190 --- .../field-box/FieldBox.spec.tsx | 84 +++++++++++++++++++ .../field-box/FieldBox.styles.ts | 25 ++++++ .../create-index-step/field-box/FieldBox.tsx | 53 ++++++++++++ .../create-index-step/field-box/FieldTag.tsx | 15 ++++ .../create-index-step/field-box/types.ts | 7 ++ .../mocks/mock-vector-index-search.ts | 12 +++ 6 files changed, 196 insertions(+) create mode 100644 redisinsight/ui/src/components/new-index/create-index-step/field-box/FieldBox.spec.tsx create mode 100644 redisinsight/ui/src/components/new-index/create-index-step/field-box/FieldBox.styles.ts create mode 100644 redisinsight/ui/src/components/new-index/create-index-step/field-box/FieldBox.tsx create mode 100644 redisinsight/ui/src/components/new-index/create-index-step/field-box/FieldTag.tsx create mode 100644 redisinsight/ui/src/components/new-index/create-index-step/field-box/types.ts create mode 100644 redisinsight/ui/src/constants/mocks/mock-vector-index-search.ts diff --git a/redisinsight/ui/src/components/new-index/create-index-step/field-box/FieldBox.spec.tsx b/redisinsight/ui/src/components/new-index/create-index-step/field-box/FieldBox.spec.tsx new file mode 100644 index 0000000000..48aa8d50d8 --- /dev/null +++ b/redisinsight/ui/src/components/new-index/create-index-step/field-box/FieldBox.spec.tsx @@ -0,0 +1,84 @@ +import React from 'react' +import { BoxSelectionGroup } from '@redis-ui/components' + +import { FieldTypes } from 'uiSrc/pages/browser/components/create-redisearch-index/constants' +import { MOCK_VECTOR_SEARCH_BOX } from 'uiSrc/constants/mocks/mock-vector-index-search' +import { cleanup, fireEvent, render, screen } from 'uiSrc/utils/test-utils' + +import { FieldBox, FieldBoxProps } from './FieldBox' +import { VectorSearchBox } from './types' + +const renderFieldBoxComponent = (props?: FieldBoxProps) => { + const defaultProps: FieldBoxProps = { + box: MOCK_VECTOR_SEARCH_BOX, + } + + return render( + + + , + ) +} + +describe('CreateIndexStepWrapper', () => { + beforeEach(() => { + cleanup() + }) + + it('should render', () => { + const props: FieldBoxProps = { + box: { + ...MOCK_VECTOR_SEARCH_BOX, + value: 'id', + label: 'id', + text: 'Unique product identifier', + tag: FieldTypes.TAG, + disabled: false, + }, + } + + const { container } = renderFieldBoxComponent(props) + + expect(container).toBeTruthy() + + // Check if the box is rendered with the correct visual elements + const label = screen.getByText(props.box.label!) + const description = screen.getByText(props.box.text!) + const tag = screen.getByText(props.box.tag.toUpperCase()!) + const checkbox = screen.getByRole('checkbox') + + expect(label).toBeInTheDocument() + expect(description).toBeInTheDocument() + expect(tag).toBeInTheDocument() + expect(checkbox).toBeInTheDocument() + }) + + it('should select the box when clicked', () => { + renderFieldBoxComponent() + + const checkbox = screen.getByRole('checkbox') + expect(checkbox).not.toBeChecked() + + const box = screen.getByTestId(`field-box-${MOCK_VECTOR_SEARCH_BOX.value}`) + fireEvent.click(box) + + expect(checkbox).toBeChecked() + }) + + it('should not select the box when clicked if disabled', () => { + const disabledBox: VectorSearchBox = { + ...MOCK_VECTOR_SEARCH_BOX, + disabled: true, + } + + renderFieldBoxComponent({ box: disabledBox }) + + const checkbox = screen.getByRole('checkbox') + expect(checkbox).not.toBeChecked() + + const box = screen.getByTestId(`field-box-${disabledBox.value}`) + fireEvent.click(box) + + expect(checkbox).not.toBeChecked() + }) +}) diff --git a/redisinsight/ui/src/components/new-index/create-index-step/field-box/FieldBox.styles.ts b/redisinsight/ui/src/components/new-index/create-index-step/field-box/FieldBox.styles.ts new file mode 100644 index 0000000000..5028b0511f --- /dev/null +++ b/redisinsight/ui/src/components/new-index/create-index-step/field-box/FieldBox.styles.ts @@ -0,0 +1,25 @@ +import { BoxSelectionGroup } from '@redis-ui/components' +import styled from 'styled-components' + +export const StyledFieldBox = styled(BoxSelectionGroup.Item.Compose)` + display: flex; + flex-direction: column; + justify-content: space-between; + width: 100%; + padding: ${({ theme }) => theme.core.space.space100}; + gap: ${({ theme }) => theme.components.boxSelectionGroup.defaultItem.gap}; +` + +export const BoxHeader = styled.div` + display: flex; + align-items: center; + justify-content: space-between; +` + +export const BoxHeaderActions = styled.div` + display: flex; + align-items: center; + gap: ${({ theme }) => theme.components.boxSelectionGroup.defaultItem.gap}; +` + +export const BoxContent = styled.div`` diff --git a/redisinsight/ui/src/components/new-index/create-index-step/field-box/FieldBox.tsx b/redisinsight/ui/src/components/new-index/create-index-step/field-box/FieldBox.tsx new file mode 100644 index 0000000000..08c016229e --- /dev/null +++ b/redisinsight/ui/src/components/new-index/create-index-step/field-box/FieldBox.tsx @@ -0,0 +1,53 @@ +import React from 'react' +import { + BoxSelectionGroup, + BoxSelectionGroupItemComposeProps, + Checkbox, +} from '@redis-ui/components' + +import { EditIcon } from 'uiSrc/components/base/icons' +import { IconButton } from 'uiSrc/components/base/forms/buttons/IconButton' +import { Text } from 'uiSrc/components/base/text' + +import { + BoxContent, + BoxHeader, + BoxHeaderActions, + StyledFieldBox, +} from './FieldBox.styles' +import { FieldTag } from './FieldTag' +import { VectorSearchBox } from './types' + +export interface FieldBoxProps extends BoxSelectionGroupItemComposeProps { + box: VectorSearchBox +} + +export const FieldBox = ({ box, ...rest }: FieldBoxProps) => { + const { label, text, tag, disabled } = box + + return ( + + + + {(props) => } + + + + + + + + + + {label} + + + {text && ( + + {text} + + )} + + + ) +} diff --git a/redisinsight/ui/src/components/new-index/create-index-step/field-box/FieldTag.tsx b/redisinsight/ui/src/components/new-index/create-index-step/field-box/FieldTag.tsx new file mode 100644 index 0000000000..b35f48ad8c --- /dev/null +++ b/redisinsight/ui/src/components/new-index/create-index-step/field-box/FieldTag.tsx @@ -0,0 +1,15 @@ +import React from 'react' +import { Badge } from '@redis-ui/components' +import { + FIELD_TYPE_OPTIONS, + FieldTypes, +} from 'uiSrc/pages/browser/components/create-redisearch-index/constants' + +// TODO: Add colors mapping for tags when @redis-ui/components v38.6.0 is released +export const FieldTag = ({ tag }: { tag: FieldTypes }) => { + const tagLabel = FIELD_TYPE_OPTIONS.find( + (option) => option.value === tag, + )?.text + + return tagLabel ? : null +} diff --git a/redisinsight/ui/src/components/new-index/create-index-step/field-box/types.ts b/redisinsight/ui/src/components/new-index/create-index-step/field-box/types.ts new file mode 100644 index 0000000000..db9a8111ad --- /dev/null +++ b/redisinsight/ui/src/components/new-index/create-index-step/field-box/types.ts @@ -0,0 +1,7 @@ +import { BoxSelectionGroupBox } from '@redis-ui/components' +import { FieldTypes } from 'uiSrc/pages/browser/components/create-redisearch-index/constants' + +export interface VectorSearchBox extends BoxSelectionGroupBox { + text: string + tag: FieldTypes +} diff --git a/redisinsight/ui/src/constants/mocks/mock-vector-index-search.ts b/redisinsight/ui/src/constants/mocks/mock-vector-index-search.ts new file mode 100644 index 0000000000..994eff57c9 --- /dev/null +++ b/redisinsight/ui/src/constants/mocks/mock-vector-index-search.ts @@ -0,0 +1,12 @@ +import { VectorSearchBox } from 'uiSrc/components/new-index/create-index-step/field-box/types' +import { FieldTypes } from 'uiSrc/pages/browser/components/create-redisearch-index/constants' + +// TODO: Maybe transform this to a factory function, so it can be reused more easily +// TODO: Maybe make the values more dynamic with faker, so we can test more cases +export const MOCK_VECTOR_SEARCH_BOX: VectorSearchBox = { + value: 'field_mock', + label: 'Field Label Mock', + text: 'Field description mock', + tag: FieldTypes.TEXT, + disabled: false, +} From ee4dfbd0b02f7c62e07db5a43cefc9a2f07c1aea Mon Sep 17 00:00:00 2001 From: Valentin Kirilov Date: Fri, 11 Jul 2025 14:01:03 +0300 Subject: [PATCH 4/4] feat: created field boxes group component * used to combine multiple fields boxes in a single group re #RI-7190 --- .../FieldBoxesGroup.spec.tsx | 55 +++++++++++++++++++ .../FieldBoxesGroup.styles.ts | 10 ++++ .../field-boxes-group/FieldBoxesGroup.tsx | 29 ++++++++++ 3 files changed, 94 insertions(+) create mode 100644 redisinsight/ui/src/components/new-index/create-index-step/field-boxes-group/FieldBoxesGroup.spec.tsx create mode 100644 redisinsight/ui/src/components/new-index/create-index-step/field-boxes-group/FieldBoxesGroup.styles.ts create mode 100644 redisinsight/ui/src/components/new-index/create-index-step/field-boxes-group/FieldBoxesGroup.tsx diff --git a/redisinsight/ui/src/components/new-index/create-index-step/field-boxes-group/FieldBoxesGroup.spec.tsx b/redisinsight/ui/src/components/new-index/create-index-step/field-boxes-group/FieldBoxesGroup.spec.tsx new file mode 100644 index 0000000000..20671839e6 --- /dev/null +++ b/redisinsight/ui/src/components/new-index/create-index-step/field-boxes-group/FieldBoxesGroup.spec.tsx @@ -0,0 +1,55 @@ +import React from 'react' + +import { fireEvent, render, screen } from 'uiSrc/utils/test-utils' +import { MOCK_VECTOR_SEARCH_BOX } from 'uiSrc/constants/mocks/mock-vector-index-search' +import { FieldBoxesGroup, FieldBoxesGroupProps } from './FieldBoxesGroup' + +const renderFieldBoxesGroupComponent = ( + props?: Partial, +) => { + const defaultProps: FieldBoxesGroupProps = { + boxes: [MOCK_VECTOR_SEARCH_BOX], + value: [MOCK_VECTOR_SEARCH_BOX.value], + onChange: jest.fn(), + } + + return render() +} + +describe('FieldBoxesGroup', () => { + it('should render', () => { + const { container } = renderFieldBoxesGroupComponent() + + expect(container).toBeTruthy() + + const fieldBoxesGroup = screen.getByTestId('field-boxes-group') + expect(fieldBoxesGroup).toBeInTheDocument() + + const fieldBoxes = screen.getAllByTestId(/field-box-/) + expect(fieldBoxes).toHaveLength(1) + }) + + it('should call onChange when clicking on a box to select it', () => { + const onChangeMock = jest.fn() + const value: string[] = [] + + renderFieldBoxesGroupComponent({ value, onChange: onChangeMock }) + + const box = screen.getByTestId(`field-box-${MOCK_VECTOR_SEARCH_BOX.value}`) + + fireEvent.click(box) + expect(onChangeMock).toHaveBeenCalledWith([MOCK_VECTOR_SEARCH_BOX.value]) + }) + + it('should call onChange when clicking on a box to deselect it', () => { + const onChangeMock = jest.fn() + const value: string[] = [MOCK_VECTOR_SEARCH_BOX.value] + + renderFieldBoxesGroupComponent({ value, onChange: onChangeMock }) + + const box = screen.getByTestId(`field-box-${MOCK_VECTOR_SEARCH_BOX.value}`) + + fireEvent.click(box) + expect(onChangeMock).toHaveBeenCalledWith([]) + }) +}) diff --git a/redisinsight/ui/src/components/new-index/create-index-step/field-boxes-group/FieldBoxesGroup.styles.ts b/redisinsight/ui/src/components/new-index/create-index-step/field-boxes-group/FieldBoxesGroup.styles.ts new file mode 100644 index 0000000000..b535d1369c --- /dev/null +++ b/redisinsight/ui/src/components/new-index/create-index-step/field-boxes-group/FieldBoxesGroup.styles.ts @@ -0,0 +1,10 @@ +import styled from 'styled-components' +import { MultiBoxSelectionGroup } from '@redis-ui/components' + +export const StyledFieldBoxesGroup = styled(MultiBoxSelectionGroup.Compose)` + display: grid; + grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); + gap: ${({ theme }) => theme.core.space.space150}; + align-items: flex-start; + align-self: stretch; +` diff --git a/redisinsight/ui/src/components/new-index/create-index-step/field-boxes-group/FieldBoxesGroup.tsx b/redisinsight/ui/src/components/new-index/create-index-step/field-boxes-group/FieldBoxesGroup.tsx new file mode 100644 index 0000000000..75305c70cb --- /dev/null +++ b/redisinsight/ui/src/components/new-index/create-index-step/field-boxes-group/FieldBoxesGroup.tsx @@ -0,0 +1,29 @@ +import React from 'react' +import { MultiBoxSelectionGroupProps } from '@redis-ui/components' +import { StyledFieldBoxesGroup } from './FieldBoxesGroup.styles' +import { VectorSearchBox } from '../field-box/types' +import { FieldBox } from '../field-box/FieldBox' + +export interface FieldBoxesGroupProps extends MultiBoxSelectionGroupProps { + boxes: VectorSearchBox[] + value: string[] + onChange: (value: string[] | undefined) => void +} + +export const FieldBoxesGroup = ({ + boxes, + value, + onChange, + ...rest +}: FieldBoxesGroupProps) => ( + + {boxes.map((box) => ( + + ))} + +)