Introduce component for individual filters
parent
f2fff2385b
commit
6bbed0cadd
|
@ -0,0 +1,94 @@
|
|||
import React, {PureComponent} from 'react'
|
||||
import classnames from 'classnames'
|
||||
import {Filter} from 'src/logs/containers/LogsPage'
|
||||
|
||||
interface Props {
|
||||
filter: Filter
|
||||
onDelete: (id: string) => () => void
|
||||
onToggleStatus: (id: string) => () => void
|
||||
onToggleOperator: (id: string) => () => void
|
||||
}
|
||||
|
||||
interface State {
|
||||
expanded: boolean
|
||||
}
|
||||
|
||||
class LogsFilter extends PureComponent<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props)
|
||||
|
||||
this.state = {
|
||||
expanded: false,
|
||||
}
|
||||
}
|
||||
|
||||
public render() {
|
||||
const {
|
||||
filter: {id},
|
||||
onDelete,
|
||||
} = this.props
|
||||
const {expanded} = this.state
|
||||
|
||||
return (
|
||||
<li className={this.className} onMouseLeave={this.handleMouseLeave}>
|
||||
{this.label}
|
||||
<div className="logs-viewer--filter-remove" onClick={onDelete(id)} />
|
||||
{expanded && this.renderTooltip}
|
||||
</li>
|
||||
)
|
||||
}
|
||||
|
||||
private get label(): JSX.Element {
|
||||
const {
|
||||
filter: {key, operator, value},
|
||||
} = this.props
|
||||
|
||||
return (
|
||||
<span
|
||||
onMouseEnter={this.handleMouseEnter}
|
||||
>{`${key} ${operator} ${value}`}</span>
|
||||
)
|
||||
}
|
||||
|
||||
private get className(): string {
|
||||
const {expanded} = this.state
|
||||
const {
|
||||
filter: {enabled},
|
||||
} = this.props
|
||||
|
||||
return classnames('logs-viewer--filter', {
|
||||
active: expanded,
|
||||
disabled: !enabled,
|
||||
})
|
||||
}
|
||||
|
||||
private handleMouseEnter = (): void => {
|
||||
this.setState({expanded: true})
|
||||
}
|
||||
|
||||
private handleMouseLeave = (): void => {
|
||||
this.setState({expanded: false})
|
||||
}
|
||||
|
||||
private get renderTooltip(): JSX.Element {
|
||||
const {
|
||||
filter: {id, enabled, operator},
|
||||
onDelete,
|
||||
onToggleStatus,
|
||||
onToggleOperator,
|
||||
} = this.props
|
||||
|
||||
const toggleStatusText = enabled ? 'Disable' : 'Enable'
|
||||
const toggleOperatorText = operator === '==' ? '!=' : '=='
|
||||
|
||||
return (
|
||||
<ul className="logs-viewer--filter-tooltip">
|
||||
<li onClick={onToggleStatus(id)}>{toggleStatusText}</li>
|
||||
<li onClick={onToggleOperator(id)}>{toggleOperatorText}</li>
|
||||
<li onClick={onDelete(id)}>Delete</li>
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default LogsFilter
|
|
@ -1,5 +1,6 @@
|
|||
import React, {PureComponent} from 'react'
|
||||
import {Filter} from 'src/logs/containers/LogsPage'
|
||||
import FilterBlock from 'src/logs/components/LogsFilter'
|
||||
|
||||
interface Props {
|
||||
numResults: number
|
||||
|
@ -25,31 +26,25 @@ class LogsFilters extends PureComponent<Props> {
|
|||
const {filters} = this.props
|
||||
|
||||
return filters.map(filter => (
|
||||
<li className="logs-viewer--filter">
|
||||
<span>
|
||||
{filter.key}
|
||||
{filter.operator}
|
||||
{filter.value}
|
||||
</span>
|
||||
<button
|
||||
className="logs-viewer--filter-remove"
|
||||
onClick={this.handleDeleteFilter(filter.id)}
|
||||
<FilterBlock
|
||||
key={filter.id}
|
||||
filter={filter}
|
||||
onDelete={this.handleDeleteFilter}
|
||||
onToggleStatus={this.handleToggleFilterStatus}
|
||||
onToggleOperator={this.handleToggleFilterOperator}
|
||||
/>
|
||||
</li>
|
||||
))
|
||||
}
|
||||
|
||||
private handleDeleteFilter = (id: string) => (): void => {
|
||||
const {filters, onUpdateFilters} = this.props
|
||||
|
||||
const filteredFilters = filters.map(
|
||||
filter => (filter.id === id ? null : filter)
|
||||
)
|
||||
const filteredFilters = filters.filter(filter => filter.id !== id)
|
||||
|
||||
onUpdateFilters(filteredFilters)
|
||||
}
|
||||
|
||||
private handleToggleFilter = (id: string) => (): void => {
|
||||
private handleToggleFilterStatus = (id: string) => (): void => {
|
||||
const {filters, onUpdateFilters} = this.props
|
||||
|
||||
const filteredFilters = filters.map(filter => {
|
||||
|
@ -62,6 +57,28 @@ class LogsFilters extends PureComponent<Props> {
|
|||
|
||||
onUpdateFilters(filteredFilters)
|
||||
}
|
||||
|
||||
private handleToggleFilterOperator = (id: string) => (): void => {
|
||||
const {filters, onUpdateFilters} = this.props
|
||||
|
||||
const filteredFilters = filters.map(filter => {
|
||||
if (filter.id === id) {
|
||||
return {...filter, operator: this.toggleOperator(filter.operator)}
|
||||
}
|
||||
|
||||
return filter
|
||||
})
|
||||
|
||||
onUpdateFilters(filteredFilters)
|
||||
}
|
||||
|
||||
private toggleOperator = (op: string): string => {
|
||||
if (op === '==') {
|
||||
return '!='
|
||||
}
|
||||
|
||||
return '=='
|
||||
}
|
||||
}
|
||||
|
||||
export default LogsFilters
|
||||
|
|
|
@ -34,13 +34,23 @@ interface State {
|
|||
filters: Filter[]
|
||||
}
|
||||
|
||||
const DUMMY_FILTERS = [
|
||||
{
|
||||
id: '0',
|
||||
key: 'host',
|
||||
value: 'prod1-rsavage.local',
|
||||
operator: '==',
|
||||
enabled: true,
|
||||
},
|
||||
]
|
||||
|
||||
class LogsPage extends PureComponent<Props, State> {
|
||||
constructor(props: Props) {
|
||||
super(props)
|
||||
|
||||
this.state = {
|
||||
searchString: '',
|
||||
filters: [],
|
||||
filters: DUMMY_FILTERS,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -94,6 +94,7 @@ $logs-viewer-gutter: 60px;
|
|||
}
|
||||
|
||||
.logs-viewer--filter {
|
||||
position: relative;
|
||||
font-size: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -103,8 +104,20 @@ $logs-viewer-gutter: 60px;
|
|||
border-radius: 4px;
|
||||
background-color: $g5-pepper;
|
||||
color: $g13-mist;
|
||||
font-weight: 500;
|
||||
font-weight: 600;
|
||||
margin: 2px;
|
||||
|
||||
&.disabled {
|
||||
background-color: $g4-onyx;
|
||||
color: $g9-mountain;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background-color: $g6-smoke;
|
||||
color: $g15-platinum;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.logs-viewer--filter-remove {
|
||||
|
@ -145,3 +158,37 @@ $logs-viewer-gutter: 60px;
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.logs-viewer--filter-tooltip {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
border-radius: $radius;
|
||||
z-index: 9999;
|
||||
@extend %drop-shadow;
|
||||
background-color: $g4-onyx;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
overflow: hidden;
|
||||
|
||||
> li {
|
||||
height: 26px;
|
||||
line-height: 26px;
|
||||
padding: 0 8px;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: $g11-sidewalk;
|
||||
transition: background-color 0.25s ease, color 0.25s ease;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
background-color: $g5-pepper;
|
||||
color: $g18-cloud;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue