Skip to content

Commit

Permalink
Add ability to shown options for several different fields in same fil…
Browse files Browse the repository at this point in the history
…ter (#1179)

* Add ability to shown options for several different fields in same filter select

* Update changelog

* Introduce test cases
  • Loading branch information
bevacqua authored Sep 10, 2018
1 parent f149b02 commit 1da565f
Show file tree
Hide file tree
Showing 5 changed files with 460 additions and 11 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

- Added `maxWidth` prop to `EuiModal` ([#1165](https://github.com/elastic/eui/pull/1165))
- Support field names with `_` characters in search queries ([#1180](https://github.com/elastic/eui/pull/1180))
- Added ability to include multiple fields in a value selection filter for `EuiSearchBar` ([#1179](https://github.com/elastic/eui/pull/1179))

**Bug fixes**

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ exports[`EuiSearchFilters render - with filters 1`] = `
key="filter_1"
>
<FieldValueSelectionFilter
autoClose={true}
config={
Object {
"field": "tag",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,189 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`FieldValueSelectionFilter active - field is global 1`] = `
<EuiPopover
anchorPosition="downCenter"
button={
<EuiFilterButton
color="text"
grow={true}
hasActiveFilters={true}
iconSide="right"
iconType="arrowDown"
onClick={[Function]}
type="button"
>
Tag
</EuiFilterButton>
}
closePopover={[Function]}
hasArrow={true}
id="field_value_selection_0"
isOpen={false}
ownFocus={true}
panelClassName="euiFilterGroup__popoverPanel"
panelPaddingSize="none"
withTitle={null}
>
<div
className="euiFilterSelect__note"
>
<div
className="euiFilterSelect__noteContent"
>
<EuiLoadingChart
mono={false}
size="m"
/>
<EuiSpacer
size="xs"
/>
<p>
Loading...
</p>
</div>
</div>
</EuiPopover>
`;

exports[`FieldValueSelectionFilter active - fields in options 1`] = `
<EuiPopover
anchorPosition="downCenter"
button={
<EuiFilterButton
color="text"
grow={true}
hasActiveFilters={true}
iconSide="right"
iconType="arrowDown"
onClick={[Function]}
type="button"
>
Tag
</EuiFilterButton>
}
closePopover={[Function]}
hasArrow={true}
id="field_value_selection_0"
isOpen={false}
ownFocus={true}
panelClassName="euiFilterGroup__popoverPanel"
panelPaddingSize="none"
withTitle={null}
>
<div
className="euiFilterSelect__note"
>
<div
className="euiFilterSelect__noteContent"
>
<EuiLoadingChart
mono={false}
size="m"
/>
<EuiSpacer
size="xs"
/>
<p>
Loading...
</p>
</div>
</div>
</EuiPopover>
`;

exports[`FieldValueSelectionFilter inactive - field is global 1`] = `
<EuiPopover
anchorPosition="downCenter"
button={
<EuiFilterButton
color="text"
grow={true}
hasActiveFilters={false}
iconSide="right"
iconType="arrowDown"
onClick={[Function]}
type="button"
>
Tag
</EuiFilterButton>
}
closePopover={[Function]}
hasArrow={true}
id="field_value_selection_0"
isOpen={false}
ownFocus={true}
panelClassName="euiFilterGroup__popoverPanel"
panelPaddingSize="none"
withTitle={null}
>
<div
className="euiFilterSelect__note"
>
<div
className="euiFilterSelect__noteContent"
>
<EuiLoadingChart
mono={false}
size="m"
/>
<EuiSpacer
size="xs"
/>
<p>
Loading...
</p>
</div>
</div>
</EuiPopover>
`;

exports[`FieldValueSelectionFilter inactive - fields in options 1`] = `
<EuiPopover
anchorPosition="downCenter"
button={
<EuiFilterButton
color="text"
grow={true}
hasActiveFilters={false}
iconSide="right"
iconType="arrowDown"
onClick={[Function]}
type="button"
>
Tag
</EuiFilterButton>
}
closePopover={[Function]}
hasArrow={true}
id="field_value_selection_0"
isOpen={false}
ownFocus={true}
panelClassName="euiFilterGroup__popoverPanel"
panelPaddingSize="none"
withTitle={null}
>
<div
className="euiFilterSelect__note"
>
<div
className="euiFilterSelect__noteContent"
>
<EuiLoadingChart
mono={false}
size="m"
/>
<EuiSpacer
size="xs"
/>
<p>
Loading...
</p>
</div>
</div>
</EuiPopover>
`;

exports[`FieldValueSelectionFilter render - all configurations 1`] = `
<EuiPopover
anchorPosition="downCenter"
Expand Down Expand Up @@ -46,6 +230,52 @@ exports[`FieldValueSelectionFilter render - all configurations 1`] = `
</EuiPopover>
`;

exports[`FieldValueSelectionFilter render - fields in options 1`] = `
<EuiPopover
anchorPosition="downCenter"
button={
<EuiFilterButton
color="text"
grow={true}
hasActiveFilters={false}
iconSide="right"
iconType="arrowDown"
onClick={[Function]}
type="button"
>
Tag
</EuiFilterButton>
}
closePopover={[Function]}
hasArrow={true}
id="field_value_selection_0"
isOpen={false}
ownFocus={true}
panelClassName="euiFilterGroup__popoverPanel"
panelPaddingSize="none"
withTitle={null}
>
<div
className="euiFilterSelect__note"
>
<div
className="euiFilterSelect__noteContent"
>
<EuiLoadingChart
mono={false}
size="m"
/>
<EuiSpacer
size="xs"
/>
<p>
Loading...
</p>
</div>
</div>
</EuiPopover>
`;

exports[`FieldValueSelectionFilter render - multi-select OR 1`] = `
<EuiPopover
anchorPosition="downCenter"
Expand Down
53 changes: 42 additions & 11 deletions src/components/search_bar/filters/field_value_selection_filter.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { EuiIcon } from '../../icon/icon';
import { Query } from '../query';

const FieldValueOptionType = PropTypes.shape({
field: PropTypes.string,
value: PropTypes.any.isRequired,
name: PropTypes.string,
view: PropTypes.node
Expand All @@ -25,7 +26,8 @@ const FieldValueOptionsType = PropTypes.oneOfType([

export const FieldValueSelectionFilterConfigType = PropTypes.shape({
type: EuiPropTypes.is('field_value_selection').isRequired,
field: PropTypes.string.isRequired,
field: PropTypes.string,
autoClose: PropTypes.boolean,
name: PropTypes.string.isRequired,
options: FieldValueOptionsType.isRequired,
cache: PropTypes.number,
Expand Down Expand Up @@ -56,6 +58,10 @@ export class FieldValueSelectionFilter extends Component {

static propTypes = FieldValueSelectionFilterPropTypes;

static defaultProps = {
autoClose: true,
}

constructor(props) {
super(props);
this.selectItems = [];
Expand Down Expand Up @@ -154,24 +160,30 @@ export class FieldValueSelectionFilter extends Component {

onOptionClick(field, value, checked) {
const multiSelect = this.resolveMultiSelect();
if (!multiSelect) {
// we're closing popover only if the user can only select one item... if the
// user can select more, we'll leave it open so she can continue selecting
const { autoClose } = this.props;

// we're closing popover only if the user can only select one item... if the
// user can select more, we'll leave it open so she can continue selecting

if (!multiSelect && autoClose) {
this.closePopover();
const query = checked ?
this.props.query.removeSimpleFieldClauses(field) :
this.props.query.removeSimpleFieldClauses(field).addSimpleFieldValue(field, value);

this.props.onChange(query);
} else {
if (multiSelect === 'or') {
const query = checked ?
this.props.query.removeOrFieldValue(field, value) :
this.props.query.addOrFieldValue(field, value);

this.props.onChange(query);
} else {
const query = checked ?
this.props.query.removeSimpleFieldValue(field, value) :
this.props.query.addSimpleFieldValue(field, value);

this.props.onChange(query);
}
}
Expand Down Expand Up @@ -209,9 +221,14 @@ export class FieldValueSelectionFilter extends Component {
render() {
const { index, query, config } = this.props;
const multiSelect = this.resolveMultiSelect();
const active = multiSelect === 'or' ?
query.hasOrFieldClause(config.field) :
query.hasSimpleFieldClause(config.field);

const activeTop = this.isActiveField(config.field);
const activeItem = this.state.options
? this.state.options.all.some(item => this.isActiveField(item.field))
: false;

const active = activeTop || activeItem;

const button = (
<EuiFilterButton
iconType="arrowDown"
Expand All @@ -224,7 +241,6 @@ export class FieldValueSelectionFilter extends Component {
</EuiFilterButton>
);


const searchBox = this.renderSearchBox();
const content = this.renderContent(config.field, query, config, multiSelect);
const threshold = this.props.config.searchThreshold || defaults.config.searchThreshold;
Expand Down Expand Up @@ -277,14 +293,18 @@ export class FieldValueSelectionFilter extends Component {
return this.renderNoOptions();
}
const items = this.state.options.shown.reduce((items, option, index) => {
const optionField = option.field || field;

const clause = multiSelect === 'or' ?
query.getOrFieldClause(field, option.value) :
query.getSimpleFieldClause(field, option.value);
query.getOrFieldClause(optionField, option.value) :
query.getSimpleFieldClause(optionField, option.value);

const checked = this.resolveChecked(clause);
const onClick = () => {
// clicking a checked item will uncheck it and effective remove the filter (value = undefined)
this.onOptionClick(field, option.value, checked);
this.onOptionClick(optionField, option.value, checked);
};

const item = (
<EuiFilterSelectItem
key={index}
Expand Down Expand Up @@ -355,4 +375,15 @@ export class FieldValueSelectionFilter extends Component {
</div>
);
}

isActiveField(field) {
const { query } = this.props;
const multiSelect = this.resolveMultiSelect();

if (multiSelect === 'or') {
return query.hasOrFieldClause(field);
}

return query.hasSimpleFieldClause(field);
}
}
Loading

0 comments on commit 1da565f

Please sign in to comment.