Merge pull request #4317 from influxdata/feature/filter-protoboards-by-name

Add ability to filter protoboards by name in dashboard step
pull/4318/head
Deniz Kusefoglu 2018-08-29 19:11:49 -07:00 committed by GitHub
commit 3e620a429c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 97 additions and 60 deletions

View File

@ -1,56 +0,0 @@
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import _ from 'lodash'
import {ErrorHandling} from 'src/shared/decorators/errors'
@ErrorHandling
class SearchBar extends Component {
constructor(props) {
super(props)
this.state = {
searchTerm: '',
}
}
componentWillMount() {
this.handleSearch = _.debounce(this.handleSearch, 50)
}
handleSearch = () => {
this.props.onSearch(this.state.searchTerm)
}
handleChange = () => {
this.setState({searchTerm: this.refs.searchInput.value}, this.handleSearch)
}
render() {
const {placeholder, width} = this.props
return (
<div className="search-widget" style={{width: `${width}px`}}>
<input
type="text"
className="form-control input-sm"
placeholder={placeholder}
ref="searchInput"
onChange={this.handleChange}
/>
<span className="icon search" />
</div>
)
}
}
const {func, number, string} = PropTypes
SearchBar.defaultProps = {
width: 260,
}
SearchBar.propTypes = {
width: number,
onSearch: func.isRequired,
placeholder: string.isRequired,
}
export default SearchBar

View File

@ -0,0 +1,61 @@
// Libraries
import React, {PureComponent, ChangeEvent} from 'react'
import _ from 'lodash'
// Decorators
import {ErrorHandling} from 'src/shared/decorators/errors'
interface Props {
width?: number
placeholder: string
onSearch: (searchTerm: string) => void
}
interface State {
searchTerm: string
}
@ErrorHandling
class SearchBar extends PureComponent<Props, State> {
public static defaultProps: Partial<Props> = {
width: 260,
}
public debouncedHandleSearch: () => void
constructor(props: Props) {
super(props)
this.state = {
searchTerm: '',
}
}
public componentWillMount() {
this.debouncedHandleSearch = _.debounce(this.handleSearch, 50)
}
public render() {
const {placeholder, width} = this.props
return (
<div className="search-widget" style={{width: `${width}px`}}>
<input
type="text"
className="form-control input-sm"
placeholder={placeholder}
onChange={this.handleChange}
/>
<span className="icon search" />
</div>
)
}
private handleSearch = () => {
this.props.onSearch(this.state.searchTerm)
}
private handleChange = (e: ChangeEvent<HTMLInputElement>) => {
this.setState({searchTerm: e.target.value}, this.debouncedHandleSearch)
}
}
export default SearchBar

View File

@ -2,4 +2,14 @@
position: relative;
min-width: 100%;
min-height: 100%;
}
.dashboard-step--filter-controls {
margin-bottom: $ix-marg-c;
padding: 0 2px;
box-sizing: border-box;
min-width: 100%;
display: inline-flex;
justify-content: flex-end;
}

View File

@ -4,16 +4,23 @@ import React, {Component} from 'react'
// APIs
import {getProtoBoards} from 'src/sources/apis'
// Components
// Decorators
import {ErrorHandling} from 'src/shared/decorators/errors'
// Utils
import {isSearchMatch} from 'src/utils/searchMatch'
// Components
import GridSizer from 'src/reusable_ui/components/grid_sizer/GridSizer'
import CardSelectCard from 'src/reusable_ui/components/card_select/CardSelectCard'
import SearchBar from 'src/hosts/components/SearchBar'
// Types
import {Protoboard} from 'src/types'
interface State {
selected: object
searchTerm: string
protoboards: Protoboard[]
}
@ -24,6 +31,7 @@ class DashboardStep extends Component<{}, State> {
this.state = {
selected: {},
protoboards: [],
searchTerm: '',
}
}
@ -37,6 +45,12 @@ class DashboardStep extends Component<{}, State> {
if (protoboards && protoboards.length) {
return (
<div className="dashboard-step">
<div className="dashboard-step--filter-controls">
<SearchBar
placeholder="Filter by name..."
onSearch={this.setSearchTerm}
/>
</div>
<GridSizer>{this.dashboardCards}</GridSizer>
</div>
)
@ -44,10 +58,16 @@ class DashboardStep extends Component<{}, State> {
return <div />
}
private get dashboardCards() {
const {selected, protoboards} = this.state
private setSearchTerm = searchTerm => {
this.setState({searchTerm})
}
return protoboards.map((protoboard, i) => {
private get dashboardCards() {
const {selected, protoboards, searchTerm} = this.state
const filteredProtoboards = protoboards.filter(pb =>
isSearchMatch(pb.meta.name, searchTerm)
)
return filteredProtoboards.map((protoboard, i) => {
const {meta} = protoboard
return (
<CardSelectCard

View File

@ -0,0 +1,2 @@
export const isSearchMatch = (input: string, searchTerm: string): boolean =>
input.toLowerCase().includes(searchTerm.toLowerCase())