Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add shape filter UI button #329

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,22 @@ export const LAYER_ICON_TYPE_MAP: { [key: string]: string } = {

export enum TOOLTIP_STATE {
DISPLAY_FEATURES = 'DISPLAY_FEATURES',
FILTER_DRAW_SHAPE = 'FILTER_DRAW_SHAPE',
}

export enum FILTER_DRAW_MODE {
NONE = 'none', // draw filter is inactive
POLYGON = 'polygon', // Filter is active and set to draw polygon
}

export interface DrawFilterProperties {
relation?: string;
mode: FILTER_DRAW_MODE;
filterLabel?: string;
}
Comment on lines +151 to +160
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about introduce a prop isDrawActive, the mode only contains different type of draw.

enum FILTER_DRAW_MODE {
  POLYGON = 'polygon', // Filter is active and set to draw polygon
  CIRCLE='circle',
}

export interface DrawFilterProperties {
  relation?: string;
  isDrawActive: boolean
  mode: FILTER_DRAW_MODE;
  filterLabel?: string;
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good suggestion. Then we have to maintain two variable for 1 behavior. For ex: if draw is false, then i have to reset mode to null, similarly if we want to enable draw behavior, we have to set to true and set mode accordingly.


export const DRAW_FILTER_SHAPE_TITLE = 'DRAW SHAPE';
export const DRAW_FILTER_POLYGON_DEFAULT_LABEL = 'polygon';
export const DRAW_FILTER_POLYGON = 'Draw Polygon';
export const DRAW_FILTER_POLYGON_RELATIONS = ['intersects', 'disjoint', 'within'];

1 change: 0 additions & 1 deletion public/components/layer_config/layer_basic_settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import {
MAP_LAYER_DEFAULT_OPACITY_STEP,
MAX_LAYER_NAME_LIMIT,
} from '../../../common';
import { layersTypeNameMap } from '../../model/layersFunctions';

interface Props {
selectedLayerConfig: MapLayerSpecification;
Expand Down
7 changes: 7 additions & 0 deletions public/components/map_container/map_container.scss
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,10 @@
bottom: $euiSizeM;
right: $euiSizeS;
}

.SpatialFilterToolbar-container {
z-index: 1;
position: absolute;
top: ($euiSizeM + $euiSizeS) + ($euiSizeXL * 5);
right: $euiSizeS;
}
24 changes: 22 additions & 2 deletions public/components/map_container/map_container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { Map as Maplibre, NavigationControl } from 'maplibre-gl';
import { debounce, throttle } from 'lodash';
import { LayerControlPanel } from '../layer_control_panel';
import './map_container.scss';
import { DASHBOARDS_MAPS_LAYER_TYPE, MAP_INITIAL_STATE } from '../../../common';
import { DASHBOARDS_MAPS_LAYER_TYPE, DrawFilterProperties, FILTER_DRAW_MODE, MAP_INITIAL_STATE } from '../../../common';
import { MapLayerSpecification } from '../../model/mapLayerType';
import {
Filter,
Expand All @@ -34,7 +34,8 @@ import {
} from '../../model/layersFunctions';
import { MapsFooter } from './maps_footer';
import { DisplayFeatures } from '../tooltip/display_features';
import { TOOLTIP_STATE } from '../../../common/index';
import { TOOLTIP_STATE } from '../../../common';
import { SpatialFilterToolbar } from '../toolbar/spatial_filter/filter_toolbar';

interface MapContainerProps {
setLayers: (layers: MapLayerSpecification[]) => void;
Expand Down Expand Up @@ -78,6 +79,9 @@ export const MapContainer = ({
>();
// start with display feature
const [tooltipState, setTooltipState] = useState<TOOLTIP_STATE>(TOOLTIP_STATE.DISPLAY_FEATURES);
const [filterProperties, setFilterProperties] = useState<DrawFilterProperties>({
mode: FILTER_DRAW_MODE.NONE,
});

useEffect(() => {
if (!mapContainer.current) return;
Expand Down Expand Up @@ -212,6 +216,14 @@ export const MapContainer = ({
}
}, [layers, mounted, timeRange, filters, query, mapState, isReadOnlyMode]);

useEffect(() => {
const currentTooltipState: TOOLTIP_STATE =
filterProperties?.mode === FILTER_DRAW_MODE.NONE
? TOOLTIP_STATE.DISPLAY_FEATURES
: TOOLTIP_STATE.FILTER_DRAW_SHAPE;
setTooltipState(currentTooltipState);
}, [filterProperties]);

const updateIndexPatterns = async () => {
if (!selectedLayerConfig) {
return;
Expand Down Expand Up @@ -253,6 +265,14 @@ export const MapContainer = ({
{mounted && tooltipState === TOOLTIP_STATE.DISPLAY_FEATURES && (
<DisplayFeatures map={maplibreRef.current!} layers={layers} />
)}
<div className="SpatialFilterToolbar-container">
{mounted && (
<SpatialFilterToolbar
setFilterProperties={setFilterProperties}
isDrawActive={filterProperties.mode !== FILTER_DRAW_MODE.NONE}
/>
)}
</div>
<div className="map-container" ref={mapContainer} />
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`renders filter by polygon button 1`] = `
<EuiPopover
anchorPosition="leftUp"
button={
<EuiPanel
className="spatialFilterToolbar__shape"
paddingSize="none"
>
<EuiButtonIcon
aria-label="draw_filter_polygon"
color="text"
iconType={Object {}}
isDisabled={false}
onClick={[Function]}
size="s"
title="Draw Polygon"
/>
</EuiPanel>
}
closePopover={[Function]}
data-test-subj="drawPolygonPopOver"
display="inlineBlock"
hasArrow={true}
id="drawPolygonId"
isOpen={false}
ownFocus={true}
panelPaddingSize="none"
>
<EuiContextMenu
initialPanelId={0}
panels={
Array [
Object {
"content": <FilterInputPanel
defaultFilterLabel="polygon"
drawLabel="Draw Polygon"
mode="polygon"
onSubmit={[Function]}
relations={
Array [
"intersects",
"disjoint",
"within",
]
}
/>,
"id": 0,
"title": "DRAW SHAPE",
},
]
}
size="m"
/>
</EuiPopover>
`;

exports[`renders filter by polygon in middle of drawing 1`] = `
<EuiPopover
anchorPosition="leftUp"
button={
<EuiPanel
className="spatialFilterToolbar__shape"
paddingSize="none"
>
<EuiButtonIcon
aria-label="draw_filter_polygon"
color="text"
iconType={Object {}}
isDisabled={true}
onClick={[Function]}
size="s"
title="Draw Polygon"
/>
</EuiPanel>
}
closePopover={[Function]}
data-test-subj="drawPolygonPopOver"
display="inlineBlock"
hasArrow={true}
id="drawPolygonId"
isOpen={false}
ownFocus={true}
panelPaddingSize="none"
>
<EuiContextMenu
initialPanelId={0}
panels={
Array [
Object {
"content": <FilterInputPanel
defaultFilterLabel="polygon"
drawLabel="Draw Polygon"
mode="polygon"
onSubmit={[Function]}
relations={
Array [
"intersects",
"disjoint",
"within",
]
}
/>,
"id": 0,
"title": "DRAW SHAPE",
},
]
}
size="m"
/>
</EuiPopover>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`renders spatial filter before drawing 1`] = `
<EuiFlexGroup
alignItems="flexStart"
direction="column"
gutterSize="s"
responsive={false}
>
<EuiFlexItem>
<FilterByPolygon
isDrawActive={false}
setDrawFilterProperties={[MockFunction]}
/>
</EuiFlexItem>
</EuiFlexGroup>
`;

exports[`renders spatial filter while drawing 1`] = `
<EuiFlexGroup
gutterSize="s"
>
<EuiFlexItem
grow={false}
>
<EuiButton
fill={true}
onClick={[Function]}
size="s"
>
Cancel
</EuiButton>
</EuiFlexItem>
<EuiFlexItem>
<FilterByPolygon
isDrawActive={true}
setDrawFilterProperties={[MockFunction]}
/>
</EuiFlexItem>
</EuiFlexGroup>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/
import { shallow } from 'enzyme';
import React from 'react';
import { FilterByPolygon } from './filter_by_polygon';

it('renders filter by polygon button', () => {
const mockCallback = jest.fn();
const polygonComponent = shallow(
<FilterByPolygon setDrawFilterProperties={mockCallback} isDrawActive={false} />
);
expect(polygonComponent).toMatchSnapshot();
});

it('renders filter by polygon in middle of drawing', () => {
const mockCallback = jest.fn();
const polygonComponent = shallow(
<FilterByPolygon setDrawFilterProperties={mockCallback} isDrawActive={true} />
);
expect(polygonComponent).toMatchSnapshot();
});
89 changes: 89 additions & 0 deletions public/components/toolbar/spatial_filter/filter_by_polygon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* 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';
import polygon from '../../../images/polygon.svg';
import {
DrawFilterProperties,
DRAW_FILTER_POLYGON,
DRAW_FILTER_POLYGON_DEFAULT_LABEL,
DRAW_FILTER_POLYGON_RELATIONS,
DRAW_FILTER_SHAPE_TITLE,
} from '../../../../common';
import { FILTER_DRAW_MODE } from '../../../../common';

interface FilterByPolygonProps {
setDrawFilterProperties: (properties: DrawFilterProperties) => void;
isDrawActive: boolean;
}

export const FilterByPolygon = ({
setDrawFilterProperties,
isDrawActive,
}: FilterByPolygonProps) => {
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: (
<FilterInputPanel
drawLabel={DRAW_FILTER_POLYGON}
defaultFilterLabel={DRAW_FILTER_POLYGON_DEFAULT_LABEL}
relations={DRAW_FILTER_POLYGON_RELATIONS}
onSubmit={onSubmit}
mode={FILTER_DRAW_MODE.POLYGON}
/>
),
},
];

const drawPolygonButton = (
<EuiPanel paddingSize="none" className="spatialFilterToolbar__shape">
<EuiButtonIcon
color="text"
size={'s'}
iconType={polygon}
onClick={onClick}
aria-label={'draw_filter_polygon'}
title={DRAW_FILTER_POLYGON}
isDisabled={isDrawActive}
/>
</EuiPanel>
);
return (
<EuiPopover
id="drawPolygonId"
button={drawPolygonButton}
isOpen={isPopoverOpen}
closePopover={closePopover}
panelPaddingSize="none"
anchorPosition="leftUp"
data-test-subj="drawPolygonPopOver"
>
<EuiContextMenu initialPanelId={0} panels={panels} />
</EuiPopover>
);
};
Loading