Skip to content

Commit

Permalink
React search box tool bar (#10821)
Browse files Browse the repository at this point in the history
* Add a react tool bar search box

Create basic react toolbar elements and update uiframework docs

* Package.json: put back ngreact (edits got overwritten)

* Add jest tests

* Combine basic tests into one, eliminate helper functions

* Address code review comments

- move tool_bar_footer into it’s own file.
- some stylistic html changes
- comments

* Remove toolbar_with_search_only

It isn’t being used in kibana currently, so we probably don’t need to
support it in our ui_Framework, and the need for the custom
“className="kuiToolBar--searchOnly”” indicates we should resdesign it
if we do need it some day.

* Fix issue with default to named conversion merge

* rename commonHtmlProps = requiredProps
  • Loading branch information
stacey-gammon authored Apr 26, 2017
1 parent 2803fd3 commit 5984a4a
Show file tree
Hide file tree
Showing 23 changed files with 325 additions and 118 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@
"mkdirp": "0.5.1",
"moment": "2.13.0",
"moment-timezone": "0.5.4",
"ngreact": "0.3.0",
"no-ui-slider": "1.2.0",
"node-fetch": "1.3.2",
"node-uuid": "1.4.7",
Expand Down
1 change: 1 addition & 0 deletions src/core_plugins/kibana/public/kibana.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import 'ui/vislib';
import 'ui/agg_response';
import 'ui/agg_types';
import 'ui/timepicker';
import 'ui/react_components';
import { Notifier } from 'ui/notify/notifier';
import 'leaflet';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,11 @@
<div class="kuiViewContentItem kuiControlledTable kuiVerticalRhythm">
<!-- ToolBar -->
<div class="kuiToolBar">
<div class="kuiToolBarSearch">
<div class="kuiToolBarSearchBox">
<div class="kuiToolBarSearchBox__icon kuiIcon fa-search"></div>
<input
class="kuiToolBarSearchBox__input"
type="text"
placeholder="Search..."
aria-label="Filter"
ng-model="listingController.filter"
>
</div>
</div>
<tool-bar-search-box
class="kuiToolBarSection"
filter="listingController.filter"
on-filter="listingController.onFilter"
></tool-bar-search-box>

<div class="kuiToolBarSection">
<!-- Bulk delete button -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import 'ui/pager';

import { SortableProperties } from 'ui_framework/services';

export function VisualizeListingController($injector, $scope) {
export function VisualizeListingController($injector) {
const $filter = $injector.get('$filter');
const confirmModal = $injector.get('confirmModal');
const Notifier = $injector.get('Notifier');
Expand Down Expand Up @@ -76,10 +76,12 @@ export function VisualizeListingController($injector, $scope) {

this.pager = pagerFactory.create(this.items.length, 20, 1);

$scope.$watch(() => this.filter, () => {
this.onFilter = (newFilter) => {
this.filter = newFilter;
deselectAll();
fetchItems();
});
};
fetchItems();

this.toggleAll = function toggleAll() {
if (this.areAllItemsChecked()) {
Expand Down
11 changes: 11 additions & 0 deletions src/ui/public/react_components.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import 'ngreact';

import {
KuiToolBarSearchBox,
} from 'ui_framework/components';

import { uiModules } from 'ui/modules';
const app = uiModules.get('app/kibana', ['react']);
app.directive('toolBarSearchBox', function (reactDirective) {
return reactDirective(KuiToolBarSearchBox);
});
5 changes: 5 additions & 0 deletions ui_framework/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,8 @@ export {
KuiLinkButton,
KuiSubmitButton,
} from './button';
export {
KuiToolBarSearchBox,
KuiToolBar,
KuiToolBarFooter,
} from './tool_bar';
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`renders KuiToolBar 1`] = `
<div
aria-label="aria-label"
class="kuiToolBar testClass1 testClass2"
data-test-subj="test subject string"
>
children
</div>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`renders KuiToolBarFooter 1`] = `
<div
aria-label="aria-label"
class="kuiToolBarFooter testClass1 testClass2"
data-test-subj="test subject string"
>
children
</div>
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`filter initializes search box value 1`] = `
<div
class="kuiToolBarSearch"
>
<div
class="kuiToolBarSearchBox"
>
<div
class="kuiToolBarSearchBox__icon kuiIcon fa-search"
/>
<input
aria-label="Filter"
class="kuiToolBarSearchBox__input"
placeholder="Search..."
type="text"
value="My Query"
/>
</div>
</div>
`;

exports[`renders KuiToolBarSearchBox 1`] = `
<div
aria-label="aria-label"
class="kuiToolBarSearch testClass1 testClass2"
data-test-subj="test subject string"
>
<div
class="kuiToolBarSearchBox"
>
<div
class="kuiToolBarSearchBox__icon kuiIcon fa-search"
/>
<input
aria-label="Filter"
class="kuiToolBarSearchBox__input"
placeholder="Search..."
type="text"
/>
</div>
</div>
`;
3 changes: 3 additions & 0 deletions ui_framework/components/tool_bar/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { KuiToolBarSearchBox } from './tool_bar_search_box';
export { KuiToolBar } from './tool_bar';
export { KuiToolBarFooter } from './tool_bar_footer';
11 changes: 11 additions & 0 deletions ui_framework/components/tool_bar/tool_bar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';
import classNames from 'classnames';

export const KuiToolBar = ({ children, className, ...rest }) => {
const classes = classNames('kuiToolBar', className);
return <div className={classes} {...rest} >{children}</div>;
};
KuiToolBar.propTypes = {
children: React.PropTypes.node,
className: React.PropTypes.string,
};
13 changes: 13 additions & 0 deletions ui_framework/components/tool_bar/tool_bar.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import React from 'react';
import { render } from 'enzyme';
import { requiredProps } from '../../test/required_props';

import {
KuiToolBar,
} from './tool_bar';

test('renders KuiToolBar', () => {
const component = <KuiToolBar { ...requiredProps }>children</KuiToolBar>;
expect(render(component)).toMatchSnapshot();
});

11 changes: 11 additions & 0 deletions ui_framework/components/tool_bar/tool_bar_footer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';
import classNames from 'classnames';

export const KuiToolBarFooter = ({ children, className, ...rest }) => {
const classes = classNames('kuiToolBarFooter', className);
return <div className={classes} {...rest}>{children}</div>;
};
KuiToolBarFooter.propTypes = {
children: React.PropTypes.node,
className: React.PropTypes.string,
};
12 changes: 12 additions & 0 deletions ui_framework/components/tool_bar/tool_bar_footer.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react';
import { render } from 'enzyme';
import { requiredProps } from '../../test/required_props';

import {
KuiToolBarFooter,
} from './tool_bar_footer';

test('renders KuiToolBarFooter', () => {
const component = <KuiToolBarFooter { ...requiredProps }>children</KuiToolBarFooter>;
expect(render(component)).toMatchSnapshot();
});
27 changes: 27 additions & 0 deletions ui_framework/components/tool_bar/tool_bar_search_box.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from 'react';
import classNames from 'classnames';

export function KuiToolBarSearchBox({ filter, onFilter, className, ...rest }) {
function onChange(event) {
onFilter(event.target.value);
}
const classes = classNames('kuiToolBarSearch', className);
return <div className={ classes } { ...rest } >
<div className="kuiToolBarSearchBox">
<div className="kuiToolBarSearchBox__icon kuiIcon fa-search"></div>
<input
className="kuiToolBarSearchBox__input"
type="text"
placeholder="Search..."
aria-label="Filter"
defaultValue={ filter }
onChange={ onChange }
/>
</div>
</div>;
}

KuiToolBarSearchBox.propTypes = {
filter: React.PropTypes.string,
onFilter: React.PropTypes.func.isRequired
};
33 changes: 33 additions & 0 deletions ui_framework/components/tool_bar/tool_bar_search_box.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from 'react';
import { render, mount } from 'enzyme';
import sinon from 'sinon';
import { requiredProps } from '../../test/required_props';

import {
KuiToolBarSearchBox,
} from './tool_bar_search_box';

const onFilter = sinon.spy();

test('renders KuiToolBarSearchBox', () => {
const component = <KuiToolBarSearchBox onFilter={onFilter} { ...requiredProps } />;
expect(render(component)).toMatchSnapshot();
});

describe('onFilter', () => {
test('is called on change event, with the value entered', () => {
const searchBox = mount(<KuiToolBarSearchBox onFilter={onFilter} { ...requiredProps } />);
onFilter.reset();
const event = { target: { value: 'a' } };
searchBox.find('input').simulate('change', event);
sinon.assert.calledWith(onFilter, 'a');
});
});

describe('filter', () => {
test('initializes search box value', () => {
const component = <KuiToolBarSearchBox onFilter={onFilter} filter="My Query" />;
expect(render(component)).toMatchSnapshot();
});
});

48 changes: 0 additions & 48 deletions ui_framework/doc_site/src/views/tool_bar/tool_bar.html

This file was deleted.

59 changes: 59 additions & 0 deletions ui_framework/doc_site/src/views/tool_bar/tool_bar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import React from 'react';

import {
KuiToolBar,
KuiToolBarSearchBox,
KuiButton,
KuiButtonIcon,
KuiButtonGroup,
} from '../../../../components';

export const ToolBar = () => (
<KuiToolBar>
<KuiToolBarSearchBox onFilter={() => {}} />

<div>
<select className="kuiSelect">
<option>Past hour</option>
<option>Past day</option>
<option>Past week</option>
</select>
</div>

<div className="kuiToolBarSection">
<KuiButton
type="primary"
icon={<KuiButtonIcon type="create" />}
>
Create
</KuiButton>

<KuiButton
type="danger"
icon={<KuiButtonIcon type="delete" />}
>
Delete
</KuiButton>
</div>

<div className="kuiToolBarSection">

<div className="kuiToolBarText">
1 &ndash; 20 of 33
</div>

<KuiButtonGroup isUnited>
<KuiButton
type="basic"
icon={<KuiButtonIcon type="previous" />}
>
</KuiButton>
<KuiButton
type="basic"
icon={<KuiButtonIcon type="next" />}
>
</KuiButton>
</KuiButtonGroup>
</div>
</KuiToolBar>
);
Loading

0 comments on commit 5984a4a

Please sign in to comment.