From 9f364b56d497e71e0f3da7daf72d686c40889116 Mon Sep 17 00:00:00 2001 From: Vijayan Balasubramanian Date: Wed, 22 Mar 2023 16:55:29 -0700 Subject: [PATCH] Add support to draw rectangle shape to filter documents (#348) * Add rectangle ui tool bar Signed-off-by: Vijayan Balasubramanian (cherry picked from commit a42c9155636b4d5a60dca45b61f613c07ded4795) --- CHANGELOG.md | 1 + common/index.ts | 4 + .../filter_by_rectangle.test.tsx.snap | 113 ++++++++++++++++++ .../filter_toolbar.test.tsx.snap | 8 ++ .../spatial_filter/draw_filter_shape.tsx | 24 +++- .../toolbar/spatial_filter/draw_tooltip.tsx | 4 + .../filter_by_rectangle.test.tsx | 23 ++++ .../spatial_filter/filter_by_rectangle.tsx | 90 ++++++++++++++ .../toolbar/spatial_filter/filter_toolbar.tsx | 5 + 9 files changed, 266 insertions(+), 6 deletions(-) create mode 100644 public/components/toolbar/spatial_filter/__snapshots__/filter_by_rectangle.test.tsx.snap create mode 100644 public/components/toolbar/spatial_filter/filter_by_rectangle.test.tsx create mode 100644 public/components/toolbar/spatial_filter/filter_by_rectangle.tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index 860ac652..1eaf3f96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), * Update max supported layer count ([#332](https://github.com/opensearch-project/dashboards-maps/pull/332)) * BWC for document layer label textType ([#340](https://github.com/opensearch-project/dashboards-maps/pull/340)) * Add mapbox-gl draw mode ([#347](https://github.com/opensearch-project/dashboards-maps/pull/347)) +* Add support to draw rectangle shape to filter documents ([#348](https://github.com/opensearch-project/dashboards-maps/pull/348)) * Avoid trigger tooltip from label ([#350](https://github.com/opensearch-project/dashboards-maps/pull/350)) ### Bug Fixes diff --git a/common/index.ts b/common/index.ts index 7ecb3a21..c6160e8c 100644 --- a/common/index.ts +++ b/common/index.ts @@ -158,12 +158,14 @@ export enum TOOLTIP_STATE { export enum FILTER_DRAW_MODE { NONE = 'none', // draw filter is inactive POLYGON = 'polygon', // Filter is active and set to draw polygon + RECTANGLE = 'rectangle', // Filter is active and set to draw rectangle } export const MAPBOX_GL_DRAW_CREATE_LISTENER = 'draw.create'; export enum MAPBOX_GL_DRAW_MODES { DRAW_POLYGON = 'draw_polygon', + DRAW_RECTANGLE = 'draw_rectangle', SIMPLE_SELECT = 'simple_select', } @@ -175,5 +177,7 @@ export interface DrawFilterProperties { export const DRAW_FILTER_SHAPE_TITLE = 'DRAW SHAPE'; export const DRAW_FILTER_POLYGON_DEFAULT_LABEL = 'polygon'; +export const DRAW_FILTER_RECTANGLE_DEFAULT_LABEL = 'rectangle'; export const DRAW_FILTER_POLYGON = 'Draw Polygon'; +export const DRAW_FILTER_RECTANGLE = 'Draw Rectangle'; export const DRAW_FILTER_SPATIAL_RELATIONS = ['intersects', 'disjoint', 'within']; diff --git a/public/components/toolbar/spatial_filter/__snapshots__/filter_by_rectangle.test.tsx.snap b/public/components/toolbar/spatial_filter/__snapshots__/filter_by_rectangle.test.tsx.snap new file mode 100644 index 00000000..3dc50dad --- /dev/null +++ b/public/components/toolbar/spatial_filter/__snapshots__/filter_by_rectangle.test.tsx.snap @@ -0,0 +1,113 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`renders filter by rectangle button 1`] = ` + + + + } + closePopover={[Function]} + data-test-subj="drawRectanglePopOver" + display="inlineBlock" + hasArrow={true} + id="drawRectangleId" + isOpen={false} + ownFocus={true} + panelPaddingSize="none" +> + , + "id": 0, + "title": "DRAW SHAPE", + }, + ] + } + size="m" + /> + +`; + +exports[`renders filter by rectangle in middle of drawing 1`] = ` + + + + } + closePopover={[Function]} + data-test-subj="drawRectanglePopOver" + display="inlineBlock" + hasArrow={true} + id="drawRectangleId" + isOpen={false} + ownFocus={true} + panelPaddingSize="none" +> + , + "id": 0, + "title": "DRAW SHAPE", + }, + ] + } + size="m" + /> + +`; diff --git a/public/components/toolbar/spatial_filter/__snapshots__/filter_toolbar.test.tsx.snap b/public/components/toolbar/spatial_filter/__snapshots__/filter_toolbar.test.tsx.snap index fbafe8dd..edb9097b 100644 --- a/public/components/toolbar/spatial_filter/__snapshots__/filter_toolbar.test.tsx.snap +++ b/public/components/toolbar/spatial_filter/__snapshots__/filter_toolbar.test.tsx.snap @@ -12,6 +12,10 @@ exports[`renders spatial filter before drawing 1`] = ` isDrawActive={false} setDrawFilterProperties={[MockFunction]} /> + `; @@ -36,6 +40,10 @@ exports[`renders spatial filter while drawing 1`] = ` isDrawActive={true} setDrawFilterProperties={[MockFunction]} /> + `; diff --git a/public/components/toolbar/spatial_filter/draw_filter_shape.tsx b/public/components/toolbar/spatial_filter/draw_filter_shape.tsx index 567d049f..36f384c2 100644 --- a/public/components/toolbar/spatial_filter/draw_filter_shape.tsx +++ b/public/components/toolbar/spatial_filter/draw_filter_shape.tsx @@ -13,6 +13,7 @@ import { MAPBOX_GL_DRAW_MODES, MAPBOX_GL_DRAW_CREATE_LISTENER, } from '../../../../common'; +import { DrawRectangle } from '../../draw/modes/rectangle'; interface DrawFilterShapeProps { filterProperties: DrawFilterProperties; @@ -20,6 +21,17 @@ interface DrawFilterShapeProps { updateFilterProperties: (properties: DrawFilterProperties) => void; } +function getMapboxDrawMode(mode: FILTER_DRAW_MODE): string { + switch (mode) { + case FILTER_DRAW_MODE.POLYGON: + return MAPBOX_GL_DRAW_MODES.DRAW_POLYGON; + case FILTER_DRAW_MODE.RECTANGLE: + return MAPBOX_GL_DRAW_MODES.DRAW_RECTANGLE; + default: + return MAPBOX_GL_DRAW_MODES.SIMPLE_SELECT; + } +} + export const DrawFilterShape = ({ filterProperties, map, @@ -33,6 +45,10 @@ export const DrawFilterShape = ({ const mapboxDrawRef = useRef( new MapboxDraw({ displayControlsDefault: false, + modes: { + ...MapboxDraw.modes, + [MAPBOX_GL_DRAW_MODES.DRAW_RECTANGLE]: DrawRectangle, + }, }) ); @@ -51,12 +67,8 @@ export const DrawFilterShape = ({ }, []); useEffect(() => { - if (filterProperties.mode === FILTER_DRAW_MODE.POLYGON) { - mapboxDrawRef.current.changeMode(MAPBOX_GL_DRAW_MODES.DRAW_POLYGON); - } else { - // default mode - mapboxDrawRef.current.changeMode(MAPBOX_GL_DRAW_MODES.SIMPLE_SELECT); - } + const mapboxDrawMode: string = getMapboxDrawMode(filterProperties.mode); + mapboxDrawRef.current.changeMode(mapboxDrawMode); }, [filterProperties.mode]); return ; diff --git a/public/components/toolbar/spatial_filter/draw_tooltip.tsx b/public/components/toolbar/spatial_filter/draw_tooltip.tsx index bcb25a1f..ee42e317 100644 --- a/public/components/toolbar/spatial_filter/draw_tooltip.tsx +++ b/public/components/toolbar/spatial_filter/draw_tooltip.tsx @@ -22,6 +22,10 @@ const getTooltipContent = (mode: FILTER_DRAW_MODE): string => { return i18n.translate('maps.drawFilterPolygon.tooltipContent', { defaultMessage: 'Click to start shape. Click for vertex. Double click to finish.', }); + case FILTER_DRAW_MODE.RECTANGLE: + return i18n.translate('maps.drawFilterRectangle.tooltipContent', { + defaultMessage: 'Click and drag to draw rectangle.', + }); default: return i18n.translate('maps.drawFilterDefault.tooltipContent', { defaultMessage: 'Click to start shape. Double click to finish.', diff --git a/public/components/toolbar/spatial_filter/filter_by_rectangle.test.tsx b/public/components/toolbar/spatial_filter/filter_by_rectangle.test.tsx new file mode 100644 index 00000000..8b100b67 --- /dev/null +++ b/public/components/toolbar/spatial_filter/filter_by_rectangle.test.tsx @@ -0,0 +1,23 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ +import { shallow } from 'enzyme'; +import React from 'react'; +import { FilterByRectangle } from './filter_by_rectangle'; + +it('renders filter by rectangle button', () => { + const mockCallback = jest.fn(); + const component = shallow( + + ); + expect(component).toMatchSnapshot(); +}); + +it('renders filter by rectangle in middle of drawing', () => { + const mockCallback = jest.fn(); + const component = shallow( + + ); + expect(component).toMatchSnapshot(); +}); diff --git a/public/components/toolbar/spatial_filter/filter_by_rectangle.tsx b/public/components/toolbar/spatial_filter/filter_by_rectangle.tsx new file mode 100644 index 00000000..d018917e --- /dev/null +++ b/public/components/toolbar/spatial_filter/filter_by_rectangle.tsx @@ -0,0 +1,90 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import React, { useState } from 'react'; +import { EuiPopover, EuiContextMenu, EuiPanel, EuiButtonIcon } from '@elastic/eui'; +import { FilterInputPanel } from './filter_input_panel'; +// TODO: replace with rectangle image file once available +import rectangle from '../../../images/polygon.svg'; +import { + DrawFilterProperties, + DRAW_FILTER_SPATIAL_RELATIONS, + DRAW_FILTER_SHAPE_TITLE, + DRAW_FILTER_RECTANGLE, + DRAW_FILTER_RECTANGLE_DEFAULT_LABEL, +} from '../../../../common'; +import { FILTER_DRAW_MODE } from '../../../../common'; + +interface FilterByRectangleProps { + setDrawFilterProperties: (properties: DrawFilterProperties) => void; + isDrawActive: boolean; +} + +export const FilterByRectangle = ({ + setDrawFilterProperties, + isDrawActive, +}: FilterByRectangleProps) => { + const [isPopoverOpen, setPopover] = useState(false); + + const onClick = () => { + setPopover(!isPopoverOpen); + }; + + const closePopover = () => { + setPopover(false); + }; + + const onSubmit = (input: { relation: string; label: string; mode: FILTER_DRAW_MODE }) => { + setDrawFilterProperties({ + mode: input.mode, + relation: input.relation, + filterLabel: input.label, + }); + closePopover(); + }; + + const panels = [ + { + id: 0, + title: DRAW_FILTER_SHAPE_TITLE, + content: ( + + ), + }, + ]; + + const drawRectangleButton = ( + + + + ); + return ( + + + + ); +}; diff --git a/public/components/toolbar/spatial_filter/filter_toolbar.tsx b/public/components/toolbar/spatial_filter/filter_toolbar.tsx index 9fc6bbaa..747dd7bf 100644 --- a/public/components/toolbar/spatial_filter/filter_toolbar.tsx +++ b/public/components/toolbar/spatial_filter/filter_toolbar.tsx @@ -7,6 +7,7 @@ import React from 'react'; import { EuiButton, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { FilterByPolygon } from './filter_by_polygon'; import { FILTER_DRAW_MODE, DrawFilterProperties } from '../../../../common'; +import {FilterByRectangle} from "./filter_by_rectangle"; interface SpatialFilterToolBarProps { setFilterProperties: (properties: DrawFilterProperties) => void; @@ -25,6 +26,10 @@ export const SpatialFilterToolbar = ({ const filterIconGroups = ( + ); if (isDrawActive) {