Split filter editor into more components

This commit is contained in:
Lukas Martinelli 2016-12-19 14:52:28 +01:00
parent 7da97ddd6e
commit a981a39691
3 changed files with 152 additions and 42 deletions

View file

@ -24,7 +24,7 @@ const property = {
const input = { const input = {
...base, ...base,
border: '1px solid rgb(36, 36, 36)', border: 'none',
width: '47%', width: '47%',
backgroundColor: theme.colors.gray, backgroundColor: theme.colors.gray,
color: theme.colors.lowgray, color: theme.colors.lowgray,

View file

@ -2,13 +2,122 @@ import React from 'react'
import Immutable from 'immutable' import Immutable from 'immutable'
import { PropertyGroup } from '../fields/spec' import { PropertyGroup } from '../fields/spec'
import PureRenderMixin from 'react-addons-pure-render-mixin'; import PureRenderMixin from 'react-addons-pure-render-mixin';
import inputStyle from '../fields/input.js'
import GlSpec from 'mapbox-gl-style-spec/reference/latest.min.js' import GlSpec from 'mapbox-gl-style-spec/reference/latest.min.js'
import inputStyle from '../fields/input.js'
import theme from '../theme.js'
export default class FilterEditor extends React.Component { const combiningFilterOps = ['all', 'any', 'none']
const otherFilterOps = Object
.keys(GlSpec.filter_operator.values)
.filter(op => combiningFilterOps.indexOf(op) < 0)
class CombiningOperatorSelect extends React.Component {
static propTypes = {
value: React.PropTypes.string.isRequired,
onChange: React.PropTypes.func.isRequired,
}
render() {
const options = combiningFilterOps.map(op => {
return <option key={op} value={op}>{op}</option>
})
return <div>
<select
style={{
...inputStyle.select,
width: '20.5%',
margin: theme.scale[0],
}}
value={this.props.value}
onChange={e => this.props.onChange(e.target.value)}
>
{options}
</select>
<label style={{
...inputStyle.label,
width: '60%',
marginLeft: theme.scale[0],
}}>
of the filters matches
</label>
</div>
}
}
class OperatorSelect extends React.Component {
static propTypes = {
value: React.PropTypes.string.isRequired,
onChange: React.PropTypes.func.isRequired,
}
render() {
const options = otherFilterOps.map(op => {
return <option key={op} value={op}>{op}</option>
})
return <select
style={{
...inputStyle.select,
width: '15%',
margin: theme.scale[0]
}}
value={this.props.value}
onChange={e => this.props.onChange(e.target.value)}
>
{options}
</select>
}
}
class SingleFilterEditor extends React.Component {
static propTypes = { static propTypes = {
filter: React.PropTypes.array.isRequired, filter: React.PropTypes.array.isRequired,
onFilterChanged: React.PropTypes.func.isRequired, onChange: React.PropTypes.func.isRequired,
}
onFilterPartChanged(filterOp, propertyName, filterArgs) {
const newFilter = [filterOp, propertyName, ...filterArgs]
this.props.onChange(newFilter)
}
render() {
const f = this.props.filter
const filterOp = f[0]
const propertyName = f[1]
const filterArgs = f.slice(2)
return <div>
<input
style={{
...inputStyle.input,
width: '17%',
margin: theme.scale[0]
}}
value={propertyName}
onChange={newPropertyName => this.onFilterPartChanged(filterOp, newPropertyName, filterArgs)}
/>
<OperatorSelect
value={filterOp}
onChange={newFilterOp => this.onFilterPartChanged(newFilterOp, propertyName, filterArgs)}
/>
<input
style={{
...inputStyle.input,
width: '53%',
margin: theme.scale[0]
}}
value={filterArgs}
onChange={newFilterArgs => this.onFilterPartChanged(filterOp, propertyName, newFilterArgs)}
/>
</div>
}
}
export default class CombiningFilterEditor extends React.Component {
static propTypes = {
filter: React.PropTypes.array.isRequired,
onChange: React.PropTypes.func.isRequired,
} }
constructor(props) { constructor(props) {
@ -16,47 +125,48 @@ export default class FilterEditor extends React.Component {
this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this); this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
} }
// Convert filter to combining filter
combiningFilter() {
let combiningOp = this.props.filter[0]
let filters = this.props.filter.slice(1)
if(combiningFilterOps.indexOf(combiningOp) < 0) {
combiningOp = 'all'
filters = [this.props.filter.slice(0)]
}
return [combiningOp, ...filters]
}
onFilterPartChanged(filterIdx, newPart) {
const newFilter = this.combiningFilter().slice(0)
newFilter[filterIdx] = newPart
this.props.onChange(newFilter)
}
render() { render() {
const op = this.props.filter[0] const filter = this.combiningFilter()
const filters = this.props.filter.slice(1) let combiningOp = filter[0]
const filterElems = filters.map(f => { let filters = filter.slice(1)
const filterOp = f[0]
const prop = f[1]
const args = f.slice(2)
const availableFilterOperators = Object.keys(GlSpec.filter_operator.values) const filterEditors = filters.map((f, idx) => {
const filterOpOptions = availableFilterOperators.map(value => { return <SingleFilterEditor
return <option value={value}>{value}</option> key={idx}
filter={f}
onChange={this.onFilterPartChanged.bind(this, idx + 1)}
/>
}) })
return <div> return <div style={{
<select padding: theme.scale[2],
style={{...inputStyle.select, width: '15%'}} paddingRight: 0,
value={filterOp} backgroundColor: theme.colors.black
> }}>
{filterOpOptions} <CombiningOperatorSelect
</select> value={combiningOp}
<input onChange={this.onFilterPartChanged.bind(this, 0)}
style={{...inputStyle.input, width: '17%'}}
value={prop}
/> />
<input {filterEditors}
style={{...inputStyle.input, width: '55%'}}
value={args}
/>
</div>
})
return <div>
<select
style={{...inputStyle.select, width: '15%'}}
value={op}
>
<option value={"all"}>all</option>
<option value={"any"}>any</option>
</select>
<br/>
{filterElems}
</div> </div>
} }
} }

View file

@ -149,7 +149,7 @@ export class LayerEditor extends React.Component {
</Toolbar> </Toolbar>
<FilterEditor <FilterEditor
filter={this.props.layer.get('filter', Immutable.List()).toJSON()} filter={this.props.layer.get('filter', Immutable.List()).toJSON()}
onFilterChanged={console.log} onChange={f => console.log('filter changed', f)}
/> />
{this.props.layer.get('type') !== 'background' && <SourceEditor {this.props.layer.get('type') !== 'background' && <SourceEditor
source={this.props.layer.get('source')} source={this.props.layer.get('source')}