Add source layer support

This commit is contained in:
lukasmartinelli 2016-09-10 22:08:26 +02:00
parent 95ae8892f4
commit 890169751b
6 changed files with 150 additions and 3 deletions

View file

@ -2,7 +2,7 @@ import React from 'react'
import {saveAs} from 'file-saver' import {saveAs} from 'file-saver'
import { Drawer, Container, Block, Fixed } from 'rebass' import { Drawer, Container, Block, Fixed } from 'rebass'
import {Map} from './map.jsx' import { Map } from './map.jsx'
import {Toolbar} from './toolbar.jsx' import {Toolbar} from './toolbar.jsx'
import { StyleManager } from './style.js' import { StyleManager } from './style.js'
import { loadDefaultStyle, SettingsStore, StyleStore } from './stylestore.js' import { loadDefaultStyle, SettingsStore, StyleStore } from './stylestore.js'
@ -67,6 +67,10 @@ export default class App extends React.Component {
this.setState({ workContext: "layers", }) this.setState({ workContext: "layers", })
} }
onOpenSources() {
this.setState({ workContext: "sources", })
}
onAccessTokenChanged(newToken) { onAccessTokenChanged(newToken) {
this.settingsStore.accessToken = newToken this.settingsStore.accessToken = newToken
this.setState({ accessToken: newToken }) this.setState({ accessToken: newToken })
@ -81,6 +85,7 @@ export default class App extends React.Component {
onStyleDownload={this.onStyleDownload.bind(this)} onStyleDownload={this.onStyleDownload.bind(this)}
onOpenSettings={this.onOpenSettings.bind(this)} onOpenSettings={this.onOpenSettings.bind(this)}
onOpenLayers={this.onOpenLayers.bind(this)} onOpenLayers={this.onOpenLayers.bind(this)}
onOpenSources={this.onOpenSources.bind(this)}
/> />
<WorkspaceDrawer <WorkspaceDrawer
onStyleChanged={this.onStyleChanged.bind(this)} onStyleChanged={this.onStyleChanged.bind(this)}

86
src/sources/editor.jsx Normal file
View file

@ -0,0 +1,86 @@
import React from 'react'
import Immutable from 'immutable'
import { Input, Toolbar, NavItem, Space} from 'rebass'
import Collapse from 'react-collapse'
import PureRenderMixin from 'react-addons-pure-render-mixin';
import theme from '../theme.js'
class UnsupportedSource extends React.Component {
render() {
return <div></div>
}
}
class VectorSource extends React.Component {
static propTypes = {
source: React.PropTypes.instanceOf(Immutable.Map).isRequired,
}
constructor(props) {
super(props);
this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
}
render() {
return <div>
<Input name="url" label="TileJSON url" value={this.props.source.get("url")} />
<Input name="minzoom" label="Minimum zoom level" value={this.props.source.get("minzoom")} />
<Input name="maxzoom" label="Maximum zoom level" value={this.props.source.get("maxzoom")} />
</div>
}
}
export class SourceEditor extends React.Component {
static propTypes = {
sourceId: React.PropTypes.string.isRequired,
source: React.PropTypes.instanceOf(Immutable.Map).isRequired,
}
constructor(props) {
super(props);
this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
this.state = {
isOpened: false,
}
}
toggleLayer() {
this.setState({isOpened: !this.state.isOpened})
}
sourceFromType(type) {
if (type === "vector") {
return <VectorSource
source={this.props.source}
/>
}
return <UnsupportedSource />
}
render() {
return <div style={{
padding: theme.scale[0],
borderBottom: 1,
borderTop: 1,
borderLeft: 2,
borderRight: 0,
borderStyle: "solid",
borderColor: theme.borderColor,
}}>
<Toolbar onClick={this.toggleLayer.bind(this)}>
<NavItem style={{fontWeight: 400}}>
#{this.props.sourceId}
</NavItem>
<Space auto x={1} />
</Toolbar>
<Collapse isOpened={this.state.isOpened}>
<div style={{padding: theme.scale[2], paddingRight: 0, backgroundColor: theme.colors.black}}>
{this.sourceFromType(this.props.source.get('type'))}
</div>
</Collapse>
</div>
}
}

38
src/sources/list.jsx Normal file
View file

@ -0,0 +1,38 @@
import React from 'react'
import Immutable from 'immutable'
import { Heading, Toolbar, NavItem, Space} from 'rebass'
import { SourceEditor } from './editor.jsx'
import scrollbars from '../scrollbars.scss'
import PureRenderMixin from 'react-addons-pure-render-mixin';
// List of collapsible layer editors
export class SourceList extends React.Component {
static propTypes = {
sources: React.PropTypes.instanceOf(Immutable.Map).isRequired,
}
constructor(props) {
super(props)
this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
}
render() {
const sourceEditors = this.props.sources.map((source, sourceId) => {
return <SourceEditor
key={sourceId}
sourceId={sourceId}
source={source}
/>
}).toIndexedSeq()
return <div>
<Toolbar style={{marginRight: 20}}>
<NavItem>
<Heading>Layers</Heading>
</NavItem>
<Space auto x={1} />
</Toolbar>
{sourceEditors}
</div>
}
}

View file

@ -26,7 +26,7 @@ function fromJSON(jsonStyle) {
if(key === "layers") { if(key === "layers") {
return [key, Immutable.OrderedMap(val.map(l => [l.id, Immutable.fromJS(l)]))] return [key, Immutable.OrderedMap(val.map(l => [l.id, Immutable.fromJS(l)]))]
} else if(key === "sources" || key === "metadata" || key === "transition") { } else if(key === "sources" || key === "metadata" || key === "transition") {
return [key, Immutable.Map(val)] return [key, Immutable.fromJS(val)]
} else { } else {
return [key, val] return [key, val]
} }

View file

@ -9,6 +9,8 @@ import MdFileUpload from 'react-icons/lib/md/file-upload'
import MdSettings from 'react-icons/lib/md/settings' import MdSettings from 'react-icons/lib/md/settings'
import MdLayers from 'react-icons/lib/md/layers' import MdLayers from 'react-icons/lib/md/layers'
import MdSave from 'react-icons/lib/md/save' import MdSave from 'react-icons/lib/md/save'
import MdMap from 'react-icons/lib/md/map'
import { GlStyle } from './style.js' import { GlStyle } from './style.js'
import { fullHeight } from './theme.js' import { fullHeight } from './theme.js'
@ -24,6 +26,8 @@ export class Toolbar extends React.Component {
onStyleSave: React.PropTypes.func, onStyleSave: React.PropTypes.func,
// Open settings drawer // Open settings drawer
onOpenSettings: React.PropTypes.func, onOpenSettings: React.PropTypes.func,
// Open sources drawer
onOpenSources: React.PropTypes.func,
// Open layers drawer // Open layers drawer
onOpenLayers: React.PropTypes.func, onOpenLayers: React.PropTypes.func,
// Whether a style is available for download or saving // Whether a style is available for download or saving
@ -94,6 +98,13 @@ export class Toolbar extends React.Component {
</Tooltip> </Tooltip>
</Button> </Button>
</Block> </Block>
<Block>
<Button big={true} onClick={this.props.onOpenSources}>
<Tooltip inverted rounded title="Sources">
<MdMap />
</Tooltip>
</Button>
</Block>
<Block> <Block>
<Button big={true} onClick={this.props.onOpenSettings}> <Button big={true} onClick={this.props.onOpenSettings}>
<Tooltip inverted rounded title="Settings"> <Tooltip inverted rounded title="Settings">

View file

@ -1,5 +1,6 @@
import React from 'react' import React from 'react'
import { LayerList } from './layers/list.jsx' import { LayerList } from './layers/list.jsx'
import { SourceList } from './sources/list.jsx'
import { SettingsEditor } from './settings.jsx' import { SettingsEditor } from './settings.jsx'
import { colors, fullHeight } from './theme.js' import { colors, fullHeight } from './theme.js'
@ -9,7 +10,7 @@ export class WorkspaceDrawer extends React.Component {
static propTypes = { static propTypes = {
mapStyle: React.PropTypes.object.isRequired, mapStyle: React.PropTypes.object.isRequired,
onStyleChanged: React.PropTypes.func.isRequired, onStyleChanged: React.PropTypes.func.isRequired,
workContext: React.PropTypes.oneOf(['layers', 'settings']).isRequired, workContext: React.PropTypes.oneOf(['layers', 'settings', 'sources']).isRequired,
accessToken: React.PropTypes.string, accessToken: React.PropTypes.string,
onAccessTokenChanged: React.PropTypes.func, onAccessTokenChanged: React.PropTypes.func,
} }
@ -22,6 +23,12 @@ export class WorkspaceDrawer extends React.Component {
render() { render() {
let workspaceContent = null let workspaceContent = null
if(this.props.workContext === "sources") {
workspaceContent = <SourceList
sources={this.props.mapStyle.get('sources')}
/>
}
if(this.props.workContext === "layers") { if(this.props.workContext === "layers") {
workspaceContent = <LayerList workspaceContent = <LayerList
onLayersChanged={this.onLayersChanged.bind(this)} onLayersChanged={this.onLayersChanged.bind(this)}