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

filterWith option for field_value_selection filters #1328

Merged
merged 5 commits into from
Nov 27, 2018
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
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- Adjusted `EuiDatePickerRange` to allow for deeper customization ([#1219](https://github.com/elastic/eui/pull/1219))
- Added `contentProps` and `textProps` to `EuiButton` and `EuiButtonEmpty` ([#1219](https://github.com/elastic/eui/pull/1219))
- TypeScript types are now published to a `eui.d.ts` top-level file ([#1304](https://github.com/elastic/eui/pull/1304))
- Added `filterWith` option for `EuiSearchBar` filters of type `field_value_selection` ([#1328](https://github.com/elastic/eui/pull/1328))

**Bug fixes**

Expand Down Expand Up @@ -162,7 +163,7 @@
**Bug fixes**

- Fixed an issue in `EuiTooltip` because IE1 didn't support `document.contains()` ([#1190](https://github.com/elastic/eui/pull/1190))
- Fixed some issues around parsing string values in EuiSearchBar / EuiQuery ([#1189](https://github.com/elastic/eui/pull/1189))
- Fixed some issues around parsing string values in `EuiSearchBar` and `EuiQuery` ([#1189](https://github.com/elastic/eui/pull/1189))

## [`4.0.0`](https://github.com/elastic/eui/tree/v4.0.0)

Expand Down
24 changes: 24 additions & 0 deletions src-docs/src/views/search_bar/search_bar_example.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,17 @@ import {

import { SearchBar } from './search_bar';
import { ControlledSearchBar } from './controlled_search_bar';
import { SearchBarFilters } from './search_bar_filters';

const searchBarSource = require('!!raw-loader!./search_bar');
const searchBarHtml = renderToHtml(SearchBar);

const controlledSearchBarSource = require('!!raw-loader!./controlled_search_bar');
const controlledSearchBarHtml = renderToHtml(ControlledSearchBar);

const searchBarFiltersSource = require('!!raw-loader!./search_bar_filters');
const searchBarFiltersHtml = renderToHtml(SearchBarFilters);

export const SearchBarExample = {
title: 'Search Bar',
sections: [
Expand Down Expand Up @@ -116,6 +120,26 @@ export const SearchBarExample = {
</div>
),
demo: <ControlledSearchBar/>
},
{
title: 'Search Bar Filters',
source: [
{
type: GuideSectionTypes.JS,
code: searchBarFiltersSource,
}, {
type: GuideSectionTypes.HTML,
code: searchBarFiltersHtml,
}
],
text: (
<div>
<p>
A <EuiCode>EuiSearchBar</EuiCode> can have custom filter drop downs that control how a user can search.
</p>
</div>
),
demo: <SearchBarFilters/>
}
],
};
300 changes: 300 additions & 0 deletions src-docs/src/views/search_bar/search_bar_filters.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,300 @@
import React, { Component, Fragment } from 'react';
import { times } from 'lodash';
import { Random } from '../../../../src/services/random';
import {
EuiHealth,
EuiCallOut,
EuiSpacer,
EuiFlexGroup,
EuiFlexItem,
EuiCodeBlock,
EuiTitle,
EuiBasicTable,
EuiSearchBar,
} from '../../../../src/components';

const random = new Random();

const tags = [
{ name: 'marketing', color: 'danger' },
{ name: 'finance', color: 'success' },
{ name: 'eng', color: 'success' },
{ name: 'sales', color: 'warning' },
{ name: 'ga', color: 'success' },
{ name: 'presales', color: 'success' },
{ name: 'product', color: 'warning' },
{ name: 'engineering', color: 'success' },
{ name: 'design', color: 'warning' },
{ name: 'earlybirds', color: 'success' },
{ name: 'people-ops', color: 'danger' },
{ name: 'solutions', color: 'success' },
{ name: 'elasticsearch', color: 'success' },
{ name: 'kibana', color: 'success' },
{ name: 'cloud', color: 'danger' },
{ name: 'logstash', color: 'warning' },
{ name: 'beats', color: 'warning' },
{ name: 'legal', color: 'danger' },
{ name: 'revenue', color: 'success' },
{ name: 'public-relations', color: 'success' },
{ name: 'social-media-management', color: 'warning' },
];

const types = [
'dashboard',
'visualization',
'watch',
];

const users = [
'dewey',
'wanda',
'carrie',
'jmack',
'gabic',
];

const items = times(10, (id) => {
return {
id,
status: random.oneOf(['open', 'closed']),
type: random.oneOf(types),
tag: random.setOf(tags.map(tag => tag.name), { min: 0, max: 3 }),
active: random.boolean(),
owner: random.oneOf(users),
followers: random.integer({ min: 0, max: 20 }),
comments: random.integer({ min: 0, max: 10 }),
stars: random.integer({ min: 0, max: 5 })
};
});

const initialQuery = EuiSearchBar.Query.MATCH_ALL;

export class SearchBarFilters extends Component {

constructor(props) {
super(props);
this.state = {
query: initialQuery,
result: items,
error: null
};
}

onChange = ({ query, error }) => {
if (error) {
this.setState({ error });
} else {
this.setState({
error: null,
result: EuiSearchBar.Query.execute(query, items, { defaultFields: ['owner', 'tag', 'type'] }),
query
});
}
};

renderSearch() {
const filters = [
{
type: 'field_value_selection',
field: 'tag',
name: 'Tag ("prefix" filter, default)',
multiSelect: 'or',
options: tags.map(tag => ({
value: tag.name,
view: <EuiHealth color={tag.color}>{tag.name}</EuiHealth>
}))
},
{
type: 'field_value_selection',
field: 'tag',
name: 'Tag ("includes" filter)',
filterWith: 'includes',
multiSelect: 'or',
options: tags.map(tag => ({
value: tag.name,
view: <EuiHealth color={tag.color}>{tag.name}</EuiHealth>
}))
},
{
type: 'field_value_selection',
field: 'tag',
name: 'Tag (custom filter)',
filterWith: () => Math.random() > 0.5,
multiSelect: 'or',
options: tags.map(tag => ({
value: tag.name,
view: <EuiHealth color={tag.color}>{tag.name}</EuiHealth>
}))
}
];

const schema = {
strict: true,
fields: {
active: {
type: 'boolean'
},
status: {
type: 'string'
},
followers: {
type: 'number'
},
comments: {
type: 'number'
},
stars: {
type: 'number'
},
created: {
type: 'date'
},
owner: {
type: 'string'
},
tag: {
type: 'string',
validate: (value) => {
if (!tags.some(tag => tag.name === value)) {
throw new Error(`unknown tag (possible values: ${tags.map(tag => tag.name).join(',')})`);
}
}
}
}
};

return (
<EuiSearchBar
defaultQuery={initialQuery}
box={{
placeholder: 'e.g. type:visualization -is:active joe',
incremental: true,
schema
}}
filters={filters}
onChange={this.onChange}
/>
);
}

renderError() {
const { error } = this.state;
if (!error) {
return;
}
return (
<Fragment>
<EuiCallOut
iconType="faceSad"
color="danger"
title={`Invalid search: ${error.message}`}
/>
<EuiSpacer size="l"/>
</Fragment>
);
}

renderTable() {
const columns = [
{
name: 'Type',
field: 'type'
},
{
name: 'Open',
field: 'status',
render: (status) => status === 'open' ? 'Yes' : 'No'
},
{
name: 'Active',
field: 'active',
dataType: 'boolean'
},
{
name: 'Tags',
field: 'tag'
},
{
name: 'Owner',
field: 'owner'
},
{
name: 'Stats',
width: '150px',
render: (item) => {
return (
<div>
<div>{`${item.stars} Stars`}</div>
<div>{`${item.followers} Followers`}</div>
<div>{`${item.comments} Comments`}</div>
</div>
);
}
}
];

const queriedItems = EuiSearchBar.Query.execute(this.state.query, items, {
defaultFields: ['owner', 'tag', 'type']
});

return (
<EuiBasicTable
items={queriedItems}
columns={columns}
/>
);
}

render() {
const {
query,
} = this.state;

const esQueryDsl = EuiSearchBar.Query.toESQuery(query);
const esQueryString = EuiSearchBar.Query.toESQueryString(query);

const content = this.renderError() || (
<EuiFlexGroup>
<EuiFlexItem grow={4}>

<EuiTitle size="s">
<h3>Elasticsearch Query String</h3>
</EuiTitle>
<EuiSpacer size="s"/>
<EuiCodeBlock language="js">
{esQueryString ? esQueryString : ''}
</EuiCodeBlock>

<EuiSpacer size="l"/>

<EuiTitle size="s">
<h3>Elasticsearch Query DSL</h3>
</EuiTitle>
<EuiSpacer size="s"/>
<EuiCodeBlock language="js">
{esQueryDsl ? JSON.stringify(esQueryDsl, null, 2) : ''}
</EuiCodeBlock>

</EuiFlexItem>

<EuiFlexItem grow={6}>
<EuiTitle size="s">
<h3>JS execution</h3>
</EuiTitle>

<EuiSpacer size="s"/>

{this.renderTable()}
</EuiFlexItem>
</EuiFlexGroup>
);

return (
<Fragment>
{this.renderSearch()}
<EuiSpacer size="l"/>
{content}
</Fragment>
);
}
}
Loading