import React from 'react' import PropTypes from 'prop-types' import { Wrapper, Button, Menu, MenuItem } from 'react-aria-menubutton' import JSONEditor from './JSONEditor' import FilterEditor from '../filter/FilterEditor' import PropertyGroup from '../fields/PropertyGroup' import LayerEditorGroup from './LayerEditorGroup' import LayerTypeBlock from './LayerTypeBlock' import LayerIdBlock from './LayerIdBlock' import MinZoomBlock from './MinZoomBlock' import MaxZoomBlock from './MaxZoomBlock' import CommentBlock from './CommentBlock' import LayerSourceBlock from './LayerSourceBlock' import LayerSourceLayerBlock from './LayerSourceLayerBlock' import MoreVertIcon from 'react-icons/lib/md/more-vert' import InputBlock from '../inputs/InputBlock' import MultiButtonInput from '../inputs/MultiButtonInput' import { changeType, changeProperty } from '../../libs/layer' import layout from '../../config/layout.json' function layoutGroups(layerType) { const layerGroup = { title: 'Layer', type: 'layer' } const filterGroup = { title: 'Filter', type: 'filter' } const editorGroup = { title: 'JSON Editor', type: 'jsoneditor' } return [layerGroup, filterGroup].concat(layout[layerType].groups).concat([editorGroup]) } /** Layer editor supporting multiple types of layers. */ export default class LayerEditor extends React.Component { static propTypes = { layer: PropTypes.object.isRequired, sources: PropTypes.object, vectorLayers: PropTypes.object, spec: PropTypes.object.isRequired, onLayerChanged: PropTypes.func, onLayerIdChange: PropTypes.func, onMoveLayer: PropTypes.func, onLayerDestroy: PropTypes.func, onLayerCopy: PropTypes.func, onLayerVisibilityToggle: PropTypes.func, isFirstLayer: PropTypes.bool, isLastLayer: PropTypes.bool, layerIndex: PropTypes.number, } static defaultProps = { onLayerChanged: () => {}, onLayerIdChange: () => {}, onLayerDestroyed: () => {}, } static childContextTypes = { reactIconBase: PropTypes.object } constructor(props) { super(props) //TODO: Clean this up and refactor into function const editorGroups = {} layoutGroups(this.props.layer.type).forEach(group => { editorGroups[group.title] = true }) this.state = { editorGroups } } UNSAFE_componentWillReceiveProps(nextProps) { const additionalGroups = { ...this.state.editorGroups } layout[nextProps.layer.type].groups.forEach(group => { if(!(group.title in additionalGroups)) { additionalGroups[group.title] = true } }) this.setState({ editorGroups: additionalGroups }) } getChildContext () { return { reactIconBase: { size: 14, color: '#8e8e8e', } } } changeProperty(group, property, newValue) { this.props.onLayerChanged(changeProperty(this.props.layer, group, property, newValue)) } onGroupToggle(groupTitle, active) { const changedActiveGroups = { ...this.state.editorGroups, [groupTitle]: active, } this.setState({ editorGroups: changedActiveGroups }) } renderGroupType(type, fields) { let comment = "" if(this.props.layer.metadata) { comment = this.props.layer.metadata['maputnik:comment'] } let sourceLayerIds; if(this.props.sources.hasOwnProperty(this.props.layer.source)) { sourceLayerIds = this.props.sources[this.props.layer.source].layers; } switch(type) { case 'layer': return
this.props.onLayerIdChange(this.props.layer.id, newId)} /> this.props.onLayerChanged(changeType(this.props.layer, newType))} /> {this.props.layer.type !== 'background' && this.changeProperty(null, 'source', v)} /> } {['background', 'raster', 'hillshade', 'heatmap'].indexOf(this.state.type) < 0 && this.changeProperty(null, 'source-layer', v)} /> } this.changeProperty(null, 'minzoom', v)} /> this.changeProperty(null, 'maxzoom', v)} /> this.changeProperty('metadata', 'maputnik:comment', v == "" ? undefined : v)} />
case 'filter': return
this.changeProperty(null, 'filter', f)} />
case 'properties': return case 'jsoneditor': return } } moveLayer(offset) { this.props.onMoveLayer({ oldIndex: this.props.layerIndex, newIndex: this.props.layerIndex+offset }) } render() { const layerType = this.props.layer.type const groups = layoutGroups(layerType).filter(group => { return !(layerType === 'background' && group.type === 'source') }).map(group => { return {this.renderGroupType(group.type, group.fields)} }) const layout = this.props.layer.layout || {} const items = { delete: { text: "Delete", handler: () => this.props.onLayerDestroy(this.props.layer.id) }, duplicate: { text: "Duplicate", handler: () => this.props.onLayerCopy(this.props.layer.id) }, hide: { text: (layout.visibility === "none") ? "Show" : "Hide", handler: () => this.props.onLayerVisibilityToggle(this.props.layer.id) }, moveLayerUp: { text: "Move layer up", // Not actually used... disabled: this.props.isFirstLayer, handler: () => this.moveLayer(-1) }, moveLayerDown: { text: "Move layer down", // Not actually used... disabled: this.props.isLastLayer, handler: () => this.moveLayer(+1) } } function handleSelection(id, event) { event.stopPropagation; items[id].handler(); } return

Layer: {this.props.layer.id}

    {Object.keys(items).map((id, idx) => { const item = items[id]; return
  • {item.text}
  • })}
{groups}
} }