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

Convert EuiSearchBar to TypeScript #2909

Merged
merged 15 commits into from
Mar 6, 2020
Merged
Show file tree
Hide file tree
Changes from 10 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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
- Added `notification` and `notificationColor` props to `EuiHeaderSectionItemButton` ([#2914](https://github.com/elastic/eui/pull/2914))
- Added `folderCheck`, `folderExclamation`, `push`, `quote`, `reporter` and `users` icons ([#2935](https://github.com/elastic/eui/pull/2935))
- Updated `folderClosed` and `folderOpen` to match new additions and sit better on the pixel grid ([#2935](https://github.com/elastic/eui/pull/2935))
- Converted `EuiSearchBar` to Typescript ([#2909](https://github.com/elastic/eui/pull/2909))

**Bug fixes**

Expand Down
3 changes: 3 additions & 0 deletions src-docs/src/views/search_bar/controlled_search_bar.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,9 @@ export class ControlledSearchBar extends Component {
const schema = {
strict: true,
fields: {
type: {
type: 'string',
},
active: {
type: 'boolean',
},
Expand Down
3 changes: 3 additions & 0 deletions src-docs/src/views/search_bar/search_bar.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,9 @@ export class SearchBar extends Component {
const schema = {
strict: true,
fields: {
type: {
type: 'string',
},
active: {
type: 'boolean',
},
Expand Down
12 changes: 6 additions & 6 deletions src-docs/src/views/search_bar/search_bar_example.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ export const SearchBarExample = {
text: (
<div>
<p>
A <EuiCode>EuiSearchBar</EuiCode> is a toolbar that enables the user
to create/define a search query. This can be done either by entering
the query syntax in a search box or by clicking any of the
An <EuiCode>EuiSearchBar</EuiCode> is a toolbar that enables the
user to create/define a search query. This can be done either by
entering the query syntax in a search box or by clicking any of the
configured filters. The query language is not meant to be full blown
search language for arbitrary data (e.g. as required in the Discover
App in Kibana), yet it does provide some useful features:
Expand Down Expand Up @@ -231,8 +231,8 @@ export const SearchBarExample = {
text: (
<div>
<p>
A <EuiCode>EuiSearchBar</EuiCode> can have its query controlled by a
parent component by passing the <EuiCode>query</EuiCode> prop.
An <EuiCode>EuiSearchBar</EuiCode> can have its query controlled by
a parent component by passing the <EuiCode>query</EuiCode> prop.
Changes to the query will be passed back up through the{' '}
<EuiCode>onChange</EuiCode> callback where the new query must be
stored in state and passed back into the search bar.
Expand All @@ -256,7 +256,7 @@ export const SearchBarExample = {
text: (
<div>
<p>
A <EuiCode>EuiSearchBar</EuiCode> can have custom filter dropdowns
An <EuiCode>EuiSearchBar</EuiCode> can have custom filter dropdowns
that control how a user can search.
</p>
</div>
Expand Down
3 changes: 3 additions & 0 deletions src-docs/src/views/search_bar/search_bar_filters.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ export class SearchBarFilters extends Component {
const schema = {
strict: true,
fields: {
type: {
type: 'string',
},
active: {
type: 'boolean',
},
Expand Down
2 changes: 1 addition & 1 deletion src-docs/src/views/tables/in_memory/in_memory_selection.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export class Table extends Component {
renderToolsLeft() {
const selection = this.state.control_columns;

if (selection.length === 0) {
if (!selection || selection.length === 0) {
return;
}

Expand Down
18 changes: 11 additions & 7 deletions src/components/basic_table/in_memory_table.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,10 @@ import React from 'react';
import { mount, shallow } from 'enzyme';
import { requiredProps } from '../../test';

import {
EuiInMemoryTable,
EuiInMemoryTableProps,
FilterConfig,
} from './in_memory_table';
import { EuiInMemoryTable, EuiInMemoryTableProps } from './in_memory_table';
import { ENTER } from '../../services/key_codes';
import { SortDirection } from '../../services';
import { FilterConfig } from '../search_bar/filters';

interface BasicItem {
id: number | string;
Expand Down Expand Up @@ -652,6 +649,7 @@ describe('EuiInMemoryTable', () => {
pagination: true,
sorting: true,
search: {
onChange: () => {},
defaultQuery: 'name:name1',
box: {
incremental: true,
Expand Down Expand Up @@ -702,7 +700,9 @@ describe('EuiInMemoryTable', () => {
name: 'Name',
},
],
search: {},
search: {
onChange: () => true,
},
className: 'testTable',
};

Expand Down Expand Up @@ -768,7 +768,10 @@ describe('EuiInMemoryTable', () => {
name: 'Name',
},
],
search: { defaultQuery: 'No' },
search: {
onChange: () => {},
defaultQuery: 'No',
},
className: 'testTable',
message: <span className="customMessage">No items found!</span>,
};
Expand Down Expand Up @@ -810,6 +813,7 @@ describe('EuiInMemoryTable', () => {
},
],
search: {
onChange: () => {},
defaultQuery: 'No',
},
className: 'testTable',
Expand Down
155 changes: 21 additions & 134 deletions src/components/basic_table/in_memory_table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,134 +18,16 @@ import {
} from './pagination_bar';
import { isString } from '../../services/predicate';
import { Comparators, Direction } from '../../services/sort';
// @ts-ignore
import { EuiSearchBar } from '../search_bar';
import { EuiSearchBar, Query } from '../search_bar';
import { EuiSpacer } from '../spacer';
import { CommonProps } from '../common';

// Search bar types. Should be moved when it is typescriptified.
interface SearchBoxConfig {
placeholder?: string;
incremental?: boolean;
schema?: SchemaType;
}

interface SchemaType {
strict?: boolean;
fields?: object;
flags?: string[];
}

interface IsFilterConfigType {
type: 'is';
field: string;
name: string;
negatedName?: string;
available?: () => boolean;
}

interface FieldValueOptionType {
field?: string;
value: any;
name?: string;
view?: ReactNode;
}

interface FieldValueSelectionFilterConfigType {
type: 'field_value_selection';
field?: string;
autoClose?: boolean;
name: string;
options:
| FieldValueOptionType[]
| ((query: Query) => Promise<FieldValueOptionType[]>);
filterWith?:
| ((name: string, query: string, options: object) => boolean)
| 'prefix'
| 'includes';
cache?: number;
multiSelect?: boolean | 'and' | 'or';
loadingMessage?: string;
noOptionsMessage?: string;
searchThreshold?: number;
available?: () => boolean;
}

interface FieldValueToggleFilterConfigType {
type: 'field_value_toggle';
field: string;
value: string | number | boolean;
name: string;
negatedName?: string;
available?: () => boolean;
operator?: 'eq' | 'exact' | 'gt' | 'gte' | 'lt' | 'lte';
}

interface FieldValueToggleGroupFilterItem {
value: string | number | boolean;
name: string;
negatedName?: string;
operator?: 'eq' | 'exact' | 'gt' | 'gte' | 'lt' | 'lte';
}

interface FieldValueToggleGroupFilterConfigType {
type: 'field_value_toggle_group';
field: string;
items: FieldValueToggleGroupFilterItem[];
available?: () => boolean;
}

export type FilterConfig =
| IsFilterConfigType
| FieldValueSelectionFilterConfigType
| FieldValueToggleFilterConfigType
| FieldValueToggleGroupFilterConfigType;

type SearchBox = Omit<SearchBoxConfig, 'schema'> & {
schema?: boolean | SchemaType;
};

/* Should point at search_bar/query type when it is converted to typescript */
type Query = any;
import { EuiSearchBarProps } from '../search_bar/search_bar';
import { SchemaType } from '../search_bar/search_box';

interface onChangeArgument {
query: Query;
query: Query | null;
queryText: string;
error: string;
}

interface EuiSearchBarProps {
/**
The initial query the bar will hold when first mounted
*/
defaultQuery?: Query;
/**
If you wish to use the search bar as a controlled component, continuously pass the query
via this prop
*/
query?: Query;
/**
Configures the search box. Set `placeholder` to change the placeholder text in the box and
`incremental` to support incremental (as you type) search.
*/
box?: SearchBox;
/**
An array of search filters.
*/
filters?: FilterConfig[];
/**
* Tools which go to the left of the search bar.
*/
toolsLeft?: React.ReactNode;
/**
* Tools which go to the right of the search bar.
*/
toolsRight?: React.ReactNode;
/**
* Date formatter to use when parsing date values
*/
dateFormat?: object;
onChange?: (values: onChangeArgument) => boolean | void;
error: Error | null;
}

function isEuiSearchBarProps<T>(
Expand Down Expand Up @@ -208,7 +90,7 @@ interface State<T> {
sortName: ReactNode;
sortDirection?: Direction;
};
query: Query;
query: Query | null;
pageIndex: number;
pageSize?: number;
pageSizeOptions?: number[];
Expand All @@ -219,11 +101,13 @@ interface State<T> {
}

const getInitialQuery = (search: Search | undefined) => {
let query: Query | string;
if (!search) {
return;
query = '';
} else {
query = (search as EuiSearchBarProps).defaultQuery || '';
}

const query = (search as EuiSearchBarProps).defaultQuery || '';
return isString(query) ? EuiSearchBar.Query.parse(query) : query;
};

Expand Down Expand Up @@ -382,7 +266,7 @@ export class EuiInMemoryTable<T> extends Component<
pageSizeOptions,
sortName,
sortDirection,
allowNeutralSort: allowNeutralSort === false ? false : true,
allowNeutralSort: allowNeutralSort !== false,
hidePerPageOptions,
};
}
Expand Down Expand Up @@ -444,8 +328,8 @@ export class EuiInMemoryTable<T> extends Component<
};

onQueryChange = ({ query, queryText, error }: onChangeArgument) => {
if (isEuiSearchBarProps(this.props.search)) {
const search = this.props.search;
const { search } = this.props;
if (isEuiSearchBarProps(search)) {
if (search.onChange) {
const shouldQueryInMemory = search.onChange({
query,
Expand All @@ -468,22 +352,25 @@ export class EuiInMemoryTable<T> extends Component<
renderSearchBar() {
const { search } = this.props;
if (search) {
let searchBarProps: EuiSearchBarProps = {};
let searchBarProps: Omit<EuiSearchBarProps, 'onChange'> = {};

if (isEuiSearchBarProps(search)) {
const { onChange, ..._searchBarProps } = search;
pugnascotia marked this conversation as resolved.
Show resolved Hide resolved
searchBarProps = _searchBarProps;

if (searchBarProps.box && searchBarProps.box.schema === true) {
searchBarProps.box.schema = this.resolveSearchSchema();
searchBarProps.box = {
...searchBarProps.box,
schema: this.resolveSearchSchema(),
};
}
}

return <EuiSearchBar onChange={this.onQueryChange} {...searchBarProps} />;
}
}

resolveSearchSchema() {
resolveSearchSchema(): SchemaType {
const { columns } = this.props;
return columns.reduce<{
strict: boolean;
Expand All @@ -501,7 +388,7 @@ export class EuiInMemoryTable<T> extends Component<
);
}

getItemSorter() {
getItemSorter(): (a: T, b: T) => number {
const { sortName, sortDirection } = this.state;

const { columns } = this.props;
Expand All @@ -512,7 +399,7 @@ export class EuiInMemoryTable<T> extends Component<

if (sortColumn == null) {
// can't return a non-function so return a function that says everything is the same
return () => () => 0;
return () => 0;
pugnascotia marked this conversation as resolved.
Show resolved Hide resolved
}

const sortable = sortColumn.sortable;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ exports[`FieldValueSelectionFilter render - all configurations 1`] = `
ownFocus={true}
panelClassName="euiFilterGroup__popoverPanel"
panelPaddingSize="none"
withTitle={null}
withTitle={false}
>
<div
className="euiFilterSelect__note"
Expand Down Expand Up @@ -353,7 +353,7 @@ exports[`FieldValueSelectionFilter render - multi-select OR 1`] = `
ownFocus={true}
panelClassName="euiFilterGroup__popoverPanel"
panelPaddingSize="none"
withTitle={null}
withTitle={false}
>
<div
className="euiFilterSelect__note"
Expand Down Expand Up @@ -397,7 +397,7 @@ exports[`FieldValueSelectionFilter render - options as a function 1`] = `
ownFocus={true}
panelClassName="euiFilterGroup__popoverPanel"
panelPaddingSize="none"
withTitle={null}
withTitle={false}
>
<div
className="euiFilterSelect__note"
Expand Down
Loading