mirror of
https://github.com/a-nyx/maputnik-with-pmtiles.git
synced 2025-04-01 18:50:10 +02:00
Restructure layer settings for add modal
This commit is contained in:
parent
ccc39b87db
commit
bf5131cadd
10 changed files with 205 additions and 120 deletions
|
@ -164,6 +164,7 @@ export default class App extends React.Component {
|
||||||
|
|
||||||
const toolbar = <Toolbar
|
const toolbar = <Toolbar
|
||||||
mapStyle={this.state.mapStyle}
|
mapStyle={this.state.mapStyle}
|
||||||
|
sources={this.layerWatcher.sources}
|
||||||
onStyleChanged={this.onStyleChanged.bind(this)}
|
onStyleChanged={this.onStyleChanged.bind(this)}
|
||||||
onStyleOpen={this.onStyleChanged.bind(this)}
|
onStyleOpen={this.onStyleChanged.bind(this)}
|
||||||
onStyleDownload={this.onStyleDownload.bind(this)}
|
onStyleDownload={this.onStyleDownload.bind(this)}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import HelpIcon from 'react-icons/lib/md/help-outline'
|
||||||
import InspectionIcon from 'react-icons/lib/md/find-in-page'
|
import InspectionIcon from 'react-icons/lib/md/find-in-page'
|
||||||
import AddIcon from 'react-icons/lib/md/add-circle-outline'
|
import AddIcon from 'react-icons/lib/md/add-circle-outline'
|
||||||
|
|
||||||
|
import AddModal from './modals/AddModal'
|
||||||
import SettingsModal from './modals/SettingsModal'
|
import SettingsModal from './modals/SettingsModal'
|
||||||
import SourcesModal from './modals/SourcesModal'
|
import SourcesModal from './modals/SourcesModal'
|
||||||
import OpenModal from './modals/OpenModal'
|
import OpenModal from './modals/OpenModal'
|
||||||
|
@ -80,6 +81,8 @@ export default class Toolbar extends React.Component {
|
||||||
onStyleOpen: React.PropTypes.func.isRequired,
|
onStyleOpen: React.PropTypes.func.isRequired,
|
||||||
// Current style is requested for download
|
// Current style is requested for download
|
||||||
onStyleDownload: React.PropTypes.func.isRequired,
|
onStyleDownload: React.PropTypes.func.isRequired,
|
||||||
|
// A dict of source id's and the available source layers
|
||||||
|
sources: React.PropTypes.object.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -89,6 +92,7 @@ export default class Toolbar extends React.Component {
|
||||||
settings: false,
|
settings: false,
|
||||||
sources: false,
|
sources: false,
|
||||||
open: false,
|
open: false,
|
||||||
|
add: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,6 +156,13 @@ export default class Toolbar extends React.Component {
|
||||||
isOpen={this.state.isOpen.sources}
|
isOpen={this.state.isOpen.sources}
|
||||||
onOpenToggle={this.toggleModal.bind(this, 'sources')}
|
onOpenToggle={this.toggleModal.bind(this, 'sources')}
|
||||||
/>
|
/>
|
||||||
|
<AddModal
|
||||||
|
mapStyle={this.props.mapStyle}
|
||||||
|
sources={this.props.sources}
|
||||||
|
onStyleChanged={this.props.onStyleChanged}
|
||||||
|
isOpen={this.state.isOpen.add}
|
||||||
|
onOpenToggle={this.toggleModal.bind(this, 'add')}
|
||||||
|
/>
|
||||||
<ToolbarLink
|
<ToolbarLink
|
||||||
href={"https://github.com/maputnik/editor"}
|
href={"https://github.com/maputnik/editor"}
|
||||||
style={{
|
style={{
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
import JSONEditor from './JSONEditor'
|
import JSONEditor from './JSONEditor'
|
||||||
import SourceEditor from './SourceEditor'
|
|
||||||
import FilterEditor from '../filter/FilterEditor'
|
import FilterEditor from '../filter/FilterEditor'
|
||||||
import PropertyGroup from '../fields/PropertyGroup'
|
import PropertyGroup from '../fields/PropertyGroup'
|
||||||
import LayerEditorGroup from './LayerEditorGroup'
|
import LayerEditorGroup from './LayerEditorGroup'
|
||||||
import LayerSettings from './LayerSettings'
|
import LayerTypeBlock from './LayerTypeBlock'
|
||||||
|
import LayerIdBlock from './LayerIdBlock'
|
||||||
|
import LayerSourceBlock from './LayerSourceBlock'
|
||||||
|
import LayerSourceLayerBlock from './LayerSourceLayerBlock'
|
||||||
|
|
||||||
import InputBlock from '../inputs/InputBlock'
|
import InputBlock from '../inputs/InputBlock'
|
||||||
import MultiButtonInput from '../inputs/MultiButtonInput'
|
import MultiButtonInput from '../inputs/MultiButtonInput'
|
||||||
|
@ -80,7 +82,7 @@ export default class LayerEditor extends React.Component {
|
||||||
/** A {@property} in either the paint our layout {@group} has changed
|
/** A {@property} in either the paint our layout {@group} has changed
|
||||||
* to a {@newValue}.
|
* to a {@newValue}.
|
||||||
*/
|
*/
|
||||||
onPropertyChange(group, property, newValue) {
|
changeProperty(group, property, newValue) {
|
||||||
if(group) {
|
if(group) {
|
||||||
this.props.onLayerChanged({
|
this.props.onLayerChanged({
|
||||||
...this.props.layer,
|
...this.props.layer,
|
||||||
|
@ -117,12 +119,16 @@ export default class LayerEditor extends React.Component {
|
||||||
|
|
||||||
renderGroupType(type, fields) {
|
renderGroupType(type, fields) {
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case 'settings': return <LayerSettings
|
case 'settings': return <div>
|
||||||
id={this.props.layer.id}
|
<LayerIdBlock
|
||||||
type={this.props.layer.type}
|
value={this.props.layer.id}
|
||||||
onTypeChange={v => this.onPropertyChange(null, 'type', v)}
|
onChange={newId => this.props.onLayerIdChange(this.props.layer.id, newId)}
|
||||||
onIdChange={newId => this.props.onLayerIdChange(this.props.layer.id, newId)}
|
/>
|
||||||
/>
|
<LayerTypeBlock
|
||||||
|
value={this.props.layer.type}
|
||||||
|
onChange={v => this.changeProperty(null, 'type', v)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
case 'source': return <div>
|
case 'source': return <div>
|
||||||
{this.props.layer.filter &&
|
{this.props.layer.filter &&
|
||||||
<FilterEditor
|
<FilterEditor
|
||||||
|
@ -131,12 +137,15 @@ export default class LayerEditor extends React.Component {
|
||||||
onChange={f => this.onFilterChange(f)}
|
onChange={f => this.onFilterChange(f)}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
<SourceEditor
|
<LayerSourceBlock
|
||||||
source={this.props.layer.source}
|
sourceIds={Object.keys(this.props.sources)}
|
||||||
sourceLayer={this.props.layer['source-layer']}
|
value={this.props.layer.source}
|
||||||
sources={this.props.sources}
|
onChange={v => this.changeProperty(null, 'source', v)}
|
||||||
onSourceChange={console.log}
|
/>
|
||||||
onSourceLayerChange={console.log}
|
<LayerSourceLayerBlock
|
||||||
|
sourceLayerIds={this.props.sources[this.props.layer.source]}
|
||||||
|
value={this.props.layer['source-layer']}
|
||||||
|
onChange={v => this.changeProperty(null, 'source-layer', v)}
|
||||||
/>
|
/>
|
||||||
<InputBlock label={"Inspection Mode"}>
|
<InputBlock label={"Inspection Mode"}>
|
||||||
<MultiButtonInput
|
<MultiButtonInput
|
||||||
|
@ -149,7 +158,7 @@ export default class LayerEditor extends React.Component {
|
||||||
case 'properties': return <PropertyGroup
|
case 'properties': return <PropertyGroup
|
||||||
layer={this.props.layer}
|
layer={this.props.layer}
|
||||||
groupFields={fields}
|
groupFields={fields}
|
||||||
onChange={this.onPropertyChange.bind(this)}
|
onChange={this.changeProperty.bind(this)}
|
||||||
/>
|
/>
|
||||||
case 'jsoneditor': return <JSONEditor
|
case 'jsoneditor': return <JSONEditor
|
||||||
layer={this.props.layer}
|
layer={this.props.layer}
|
||||||
|
|
22
src/components/layers/LayerIdBlock.jsx
Normal file
22
src/components/layers/LayerIdBlock.jsx
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
import InputBlock from '../inputs/InputBlock'
|
||||||
|
import StringInput from '../inputs/StringInput'
|
||||||
|
|
||||||
|
class LayerIdBlock extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
value: React.PropTypes.string.isRequired,
|
||||||
|
onChange: React.PropTypes.func.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return <InputBlock label={"Layer ID"}>
|
||||||
|
<StringInput
|
||||||
|
value={this.props.value}
|
||||||
|
onChange={this.props.onChange}
|
||||||
|
/>
|
||||||
|
</InputBlock>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LayerIdBlock
|
|
@ -1,50 +0,0 @@
|
||||||
import React from 'react'
|
|
||||||
import GlSpec from 'mapbox-gl-style-spec/reference/latest.min.js'
|
|
||||||
import InputBlock from '../inputs/InputBlock'
|
|
||||||
import StringInput from '../inputs/StringInput'
|
|
||||||
import SelectInput from '../inputs/SelectInput'
|
|
||||||
|
|
||||||
import colors from '../../config/colors'
|
|
||||||
import { margins } from '../../config/scales'
|
|
||||||
|
|
||||||
|
|
||||||
class LayerSettings extends React.Component {
|
|
||||||
static propTypes = {
|
|
||||||
id: React.PropTypes.string.isRequired,
|
|
||||||
type: React.PropTypes.oneOf(Object.keys(GlSpec.layer.type.values)).isRequired,
|
|
||||||
onIdChange: React.PropTypes.func.isRequired,
|
|
||||||
onTypeChange: React.PropTypes.func.isRequired,
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return <div style={{
|
|
||||||
padding: margins[2],
|
|
||||||
paddingRight: 0,
|
|
||||||
backgroundColor: colors.black,
|
|
||||||
}}>
|
|
||||||
<InputBlock label={"Layer ID"}>
|
|
||||||
<StringInput
|
|
||||||
value={this.props.id}
|
|
||||||
onChange={this.props.onIdChange}
|
|
||||||
/>
|
|
||||||
</InputBlock>
|
|
||||||
<InputBlock label={"Layer Type"}>
|
|
||||||
<SelectInput
|
|
||||||
options={[
|
|
||||||
['background', 'Background'],
|
|
||||||
['fill', 'Fill'],
|
|
||||||
['line', 'Line'],
|
|
||||||
['symbol', 'Symbol'],
|
|
||||||
['raster', 'Raster'],
|
|
||||||
['circle', 'Circle'],
|
|
||||||
['fill-extrusion', 'Fill Extrusion'],
|
|
||||||
]}
|
|
||||||
onChange={this.props.onTypeChange}
|
|
||||||
value={this.props.type}
|
|
||||||
/>
|
|
||||||
</InputBlock>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default LayerSettings
|
|
25
src/components/layers/LayerSourceBlock.jsx
Normal file
25
src/components/layers/LayerSourceBlock.jsx
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
import InputBlock from '../inputs/InputBlock'
|
||||||
|
import StringInput from '../inputs/StringInput'
|
||||||
|
import SelectInput from '../inputs/SelectInput'
|
||||||
|
|
||||||
|
class LayerSourceBlock extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
value: React.PropTypes.string.isRequired,
|
||||||
|
onChange: React.PropTypes.func.isRequired,
|
||||||
|
sourceIds: React.PropTypes.array.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return <InputBlock label={"Source"}>
|
||||||
|
<SelectInput
|
||||||
|
value={this.props.value}
|
||||||
|
onChange={this.props.onChange}
|
||||||
|
options={this.props.sourceIds.map(s => [s, s])}
|
||||||
|
/>
|
||||||
|
</InputBlock>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LayerSourceBlock
|
25
src/components/layers/LayerSourceLayerBlock.jsx
Normal file
25
src/components/layers/LayerSourceLayerBlock.jsx
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
import InputBlock from '../inputs/InputBlock'
|
||||||
|
import StringInput from '../inputs/StringInput'
|
||||||
|
import SelectInput from '../inputs/SelectInput'
|
||||||
|
|
||||||
|
class LayerSourceLayer extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
value: React.PropTypes.string.isRequired,
|
||||||
|
onChange: React.PropTypes.func.isRequired,
|
||||||
|
sourceLayerIds: React.PropTypes.array.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return <InputBlock label={"Source Layer"}>
|
||||||
|
<SelectInput
|
||||||
|
value={this.props.value}
|
||||||
|
onChange={this.props.onChange}
|
||||||
|
options={this.props.sourceLayerIds.map(l => [l, l])}
|
||||||
|
/>
|
||||||
|
</InputBlock>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LayerSourceLayer
|
31
src/components/layers/LayerTypeBlock.jsx
Normal file
31
src/components/layers/LayerTypeBlock.jsx
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
import InputBlock from '../inputs/InputBlock'
|
||||||
|
import SelectInput from '../inputs/SelectInput'
|
||||||
|
|
||||||
|
class LayerTypeBlock extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
value: React.PropTypes.string.isRequired,
|
||||||
|
onChange: React.PropTypes.func.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return <InputBlock label={"Layer Type"}>
|
||||||
|
<SelectInput
|
||||||
|
options={[
|
||||||
|
['background', 'Background'],
|
||||||
|
['fill', 'Fill'],
|
||||||
|
['line', 'Line'],
|
||||||
|
['symbol', 'Symbol'],
|
||||||
|
['raster', 'Raster'],
|
||||||
|
['circle', 'Circle'],
|
||||||
|
['fill-extrusion', 'Fill Extrusion'],
|
||||||
|
]}
|
||||||
|
onChange={this.props.onChange}
|
||||||
|
value={this.props.value}
|
||||||
|
/>
|
||||||
|
</InputBlock>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LayerTypeBlock
|
|
@ -1,54 +0,0 @@
|
||||||
import React from 'react'
|
|
||||||
|
|
||||||
import PropertyGroup from '../fields/PropertyGroup'
|
|
||||||
import input from '../../config/input.js'
|
|
||||||
|
|
||||||
/** Choose tileset (source) and the source layer */
|
|
||||||
export default class SourceEditor extends React.Component {
|
|
||||||
static propTypes = {
|
|
||||||
source: React.PropTypes.string.isRequired,
|
|
||||||
sourceLayer: React.PropTypes.string.isRequired,
|
|
||||||
|
|
||||||
onSourceChange: React.PropTypes.func.isRequired,
|
|
||||||
onSourceLayerChange: React.PropTypes.func.isRequired,
|
|
||||||
|
|
||||||
/** List of available sources in the style
|
|
||||||
* https://www.mapbox.com/mapbox-gl-style-spec/#root-sources */
|
|
||||||
sources: React.PropTypes.object.isRequired,
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const options = Object.keys(this.props.sources).map(sourceId => {
|
|
||||||
return <option key={sourceId} value={sourceId}>{sourceId}</option>
|
|
||||||
})
|
|
||||||
|
|
||||||
const layerOptions = this.props.sources[this.props.source].map(vectorLayerId => {
|
|
||||||
const id = vectorLayerId
|
|
||||||
return <option key={id} value={id}>{id}</option>
|
|
||||||
})
|
|
||||||
|
|
||||||
return <div>
|
|
||||||
<div style={input.property}>
|
|
||||||
<label style={input.label}>Source</label>
|
|
||||||
<select
|
|
||||||
style={input.select}
|
|
||||||
value={this.props.source}
|
|
||||||
onChange={(e) => this.onSourceChange(e.target.value)}
|
|
||||||
>
|
|
||||||
{options}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div style={input.property}>
|
|
||||||
<label style={input.label}>Source Layer</label>
|
|
||||||
<select
|
|
||||||
style={input.select}
|
|
||||||
value={this.props.sourceLayer}
|
|
||||||
onChange={(e) => this.onSourceLayerChange(e.target.value)}
|
|
||||||
>
|
|
||||||
{layerOptions}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
65
src/components/modals/AddModal.jsx
Normal file
65
src/components/modals/AddModal.jsx
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
import InputBlock from '../inputs/InputBlock'
|
||||||
|
import StringInput from '../inputs/StringInput'
|
||||||
|
import SelectInput from '../inputs/SelectInput'
|
||||||
|
import Modal from './Modal'
|
||||||
|
import colors from '../../config/colors'
|
||||||
|
|
||||||
|
import LayerTypeBlock from '../layers/LayerTypeBlock'
|
||||||
|
import LayerIdBlock from '../layers/LayerIdBlock'
|
||||||
|
import LayerSourceBlock from '../layers/LayerSourceBlock'
|
||||||
|
import LayerSourceLayerBlock from '../layers/LayerSourceLayerBlock'
|
||||||
|
|
||||||
|
class AddModal extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
mapStyle: React.PropTypes.object.isRequired,
|
||||||
|
onStyleChanged: React.PropTypes.func.isRequired,
|
||||||
|
isOpen: React.PropTypes.bool.isRequired,
|
||||||
|
onOpenToggle: React.PropTypes.func.isRequired,
|
||||||
|
|
||||||
|
// A dict of source id's and the available source layers
|
||||||
|
sources: React.PropTypes.object.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props)
|
||||||
|
|
||||||
|
console.log('sources', this.props.sources)
|
||||||
|
this.state = {
|
||||||
|
type: 'fill',
|
||||||
|
id: '',
|
||||||
|
//source: Object.keys(this.props.sources)[0],
|
||||||
|
//'source-layer': this.props.sources[0][0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return <Modal
|
||||||
|
isOpen={this.props.isOpen}
|
||||||
|
onOpenToggle={this.props.onOpenToggle}
|
||||||
|
title={'Add Layer'}
|
||||||
|
>
|
||||||
|
<LayerIdBlock
|
||||||
|
value={this.state.id}
|
||||||
|
onChange={v => this.setState({ id: v })}
|
||||||
|
/>
|
||||||
|
<LayerTypeBlock
|
||||||
|
value={this.state.type}
|
||||||
|
onChange={v => this.setState({ type: v })}
|
||||||
|
/>
|
||||||
|
<LayerSourceBlock
|
||||||
|
sourceIds={Object.keys(this.props.sources)}
|
||||||
|
value={this.state.source}
|
||||||
|
onChange={v => this.setState({ source: v })}
|
||||||
|
/>
|
||||||
|
<LayerSourceLayerBlock
|
||||||
|
sourceLayerIds={this.props.sources[this.state.source] || []}
|
||||||
|
value={this.state['source-layer']}
|
||||||
|
onChange={v => this.setState({ 'source-layer': v })}
|
||||||
|
/>
|
||||||
|
</Modal>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AddModal
|
Loading…
Add table
Reference in a new issue