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 = {
...base,
border: '1px solid rgb(36, 36, 36)',
border: 'none',
width: '47%',
backgroundColor: theme.colors.gray,
color: theme.colors.lowgray,

View file

@ -2,13 +2,122 @@ import React from 'react'
import Immutable from 'immutable'
import { PropertyGroup } from '../fields/spec'
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 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 = {
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) {
@ -16,47 +125,48 @@ export default class FilterEditor extends React.Component {
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() {
const op = this.props.filter[0]
const filters = this.props.filter.slice(1)
const filterElems = filters.map(f => {
const filterOp = f[0]
const prop = f[1]
const args = f.slice(2)
const filter = this.combiningFilter()
let combiningOp = filter[0]
let filters = filter.slice(1)
const availableFilterOperators = Object.keys(GlSpec.filter_operator.values)
const filterOpOptions = availableFilterOperators.map(value => {
return <option value={value}>{value}</option>
})
return <div>
<select
style={{...inputStyle.select, width: '15%'}}
value={filterOp}
>
{filterOpOptions}
</select>
<input
style={{...inputStyle.input, width: '17%'}}
value={prop}
/>
<input
style={{...inputStyle.input, width: '55%'}}
value={args}
/>
</div>
const filterEditors = filters.map((f, idx) => {
return <SingleFilterEditor
key={idx}
filter={f}
onChange={this.onFilterPartChanged.bind(this, idx + 1)}
/>
})
return <div>
<select
style={{...inputStyle.select, width: '15%'}}
value={op}
>
<option value={"all"}>all</option>
<option value={"any"}>any</option>
</select>
<br/>
{filterElems}
return <div style={{
padding: theme.scale[2],
paddingRight: 0,
backgroundColor: theme.colors.black
}}>
<CombiningOperatorSelect
value={combiningOp}
onChange={this.onFilterPartChanged.bind(this, 0)}
/>
{filterEditors}
</div>
}
}

View file

@ -149,7 +149,7 @@ export class LayerEditor extends React.Component {
</Toolbar>
<FilterEditor
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
source={this.props.layer.get('source')}