mirror of
https://github.com/a-nyx/maputnik-with-pmtiles.git
synced 2025-04-24 07:36:24 +02:00
Remove Immutable JS
This commit is contained in:
parent
ed87425f01
commit
36c4032063
22 changed files with 100 additions and 199 deletions
|
@ -21,7 +21,6 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"color": "^1.0.3",
|
"color": "^1.0.3",
|
||||||
"file-saver": "^1.3.2",
|
"file-saver": "^1.3.2",
|
||||||
"immutable": "^3.8.1",
|
|
||||||
"lodash.throttle": "^4.1.1",
|
"lodash.throttle": "^4.1.1",
|
||||||
"lodash.topairs": "^4.3.0",
|
"lodash.topairs": "^4.3.0",
|
||||||
"mapbox-gl": "mapbox/mapbox-gl-js#6c24b9621d2aa770eda67fb5638b4d78087b5624",
|
"mapbox-gl": "mapbox/mapbox-gl-js#6c24b9621d2aa770eda67fb5638b4d78087b5624",
|
||||||
|
|
|
@ -8,18 +8,8 @@ import Toolbar from 'rebass/dist/Toolbar'
|
||||||
import NavItem from 'rebass/dist/NavItem'
|
import NavItem from 'rebass/dist/NavItem'
|
||||||
import Space from 'rebass/dist/Space'
|
import Space from 'rebass/dist/Space'
|
||||||
|
|
||||||
import Immutable from 'immutable'
|
|
||||||
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
|
||||||
|
|
||||||
/** About page with basic infos and links to github repo */
|
/** About page with basic infos and links to github repo */
|
||||||
export class About extends React.Component {
|
export class About extends React.Component {
|
||||||
static propTypes = {}
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return <div>
|
return <div>
|
||||||
<Toolbar style={{marginRight: 20}}>
|
<Toolbar style={{marginRight: 20}}>
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Immutable from 'immutable'
|
|
||||||
import { saveAs } from 'file-saver'
|
import { saveAs } from 'file-saver'
|
||||||
|
|
||||||
import Drawer from 'rebass/dist/Drawer'
|
import Drawer from 'rebass/dist/Drawer'
|
||||||
|
@ -43,7 +42,7 @@ export default class App extends React.Component {
|
||||||
this.state = {
|
this.state = {
|
||||||
accessToken: this.settingsStore.accessToken,
|
accessToken: this.settingsStore.accessToken,
|
||||||
mapStyle: style.emptyStyle,
|
mapStyle: style.emptyStyle,
|
||||||
selectedLayerId: null,
|
selectedLayerIndex: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,19 +59,20 @@ export default class App extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
onStyleDownload() {
|
onStyleDownload() {
|
||||||
const mapStyle = style.toJSON(this.state.mapStyle)
|
const mapStyle = this.state.mapStyle
|
||||||
const blob = new Blob([JSON.stringify(mapStyle, null, 4)], {type: "application/json;charset=utf-8"});
|
const blob = new Blob([JSON.stringify(mapStyle, null, 4)], {type: "application/json;charset=utf-8"});
|
||||||
saveAs(blob, mapStyle.id + ".json");
|
saveAs(blob, mapStyle.id + ".json");
|
||||||
this.onStyleSave()
|
this.onStyleSave()
|
||||||
}
|
}
|
||||||
|
|
||||||
onStyleUpload(newStyle) {
|
onStyleUpload(newStyle) {
|
||||||
|
console.log('upload', newStyle)
|
||||||
const savedStyle = this.styleStore.save(newStyle)
|
const savedStyle = this.styleStore.save(newStyle)
|
||||||
this.setState({ mapStyle: savedStyle })
|
this.setState({ mapStyle: savedStyle })
|
||||||
}
|
}
|
||||||
|
|
||||||
onStyleSave() {
|
onStyleSave() {
|
||||||
const snapshotStyle = this.state.mapStyle.set('modified', new Date().toJSON())
|
const snapshotStyle = this.state.mapStyle.modified = new Date().toJSON()
|
||||||
this.setState({ mapStyle: snapshotStyle })
|
this.setState({ mapStyle: snapshotStyle })
|
||||||
console.log('Save')
|
console.log('Save')
|
||||||
this.styleStore.save(snapshotStyle)
|
this.styleStore.save(snapshotStyle)
|
||||||
|
@ -88,20 +88,22 @@ export default class App extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
onLayersChanged(changedLayers) {
|
onLayersChanged(changedLayers) {
|
||||||
const changedStyle = this.state.mapStyle.set('layers', changedLayers)
|
const changedStyle = {
|
||||||
this.onStyleChanged(changedStyle)
|
...this.state.mapStyle,
|
||||||
|
layers: [changedLayers]
|
||||||
|
}
|
||||||
|
this.setState({ mapStyle: newStyle })
|
||||||
}
|
}
|
||||||
|
|
||||||
onLayerChanged(layer) {
|
onLayerChanged(layer) {
|
||||||
console.log('layer changed', layer)
|
const changedStyle = {
|
||||||
const layers = this.state.mapStyle.get('layers')
|
...this.state.mapStyle,
|
||||||
const changedLayers = layers.set(layer.get('id'), layer)
|
layers: {
|
||||||
this.onLayersChanged(changedLayers)
|
...this.state.mapStyle.layers,
|
||||||
}
|
[layer.id]: layer
|
||||||
|
}
|
||||||
onLayerChanged(layer) {
|
}
|
||||||
const changedStyle = this.state.mapStyle.setIn(['layers', layer.id], Immutable.fromJS(layer))
|
this.setState({ mapStyle: changedStyle })
|
||||||
this.onStyleChanged(changedStyle)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mapRenderer() {
|
mapRenderer() {
|
||||||
|
@ -112,7 +114,9 @@ export default class App extends React.Component {
|
||||||
this.layerWatcher.map = map
|
this.layerWatcher.map = map
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const renderer = this.state.mapStyle.getIn(['metadata', 'maputnik:renderer'], 'mbgljs')
|
|
||||||
|
const metadata = this.state.mapStyle.metadata || {}
|
||||||
|
const renderer = metadata['maputnik:renderer'] || 'mbgljs'
|
||||||
if(renderer === 'ol3') {
|
if(renderer === 'ol3') {
|
||||||
return <OpenLayers3Map {...mapProps} />
|
return <OpenLayers3Map {...mapProps} />
|
||||||
} else {
|
} else {
|
||||||
|
@ -121,11 +125,18 @@ export default class App extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
onLayerSelected(layerId) {
|
onLayerSelected(layerId) {
|
||||||
this.setState({ selectedLayerId: layerId })
|
const layers = this.state.mapStyle.layers
|
||||||
|
for (let i = 0; i < layers.length; i++) {
|
||||||
|
if(layers[i].id === layerId) {
|
||||||
|
this.setState({ selectedLayerIndex: i })
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const selectedLayer = this.state.mapStyle.getIn(['layers', this.state.selectedLayerId], null)
|
const layers = this.state.mapStyle.layers || []
|
||||||
|
const selectedLayer = layers.length > 0 ? layers[this.state.selectedLayerIndex] : null
|
||||||
|
|
||||||
return <div style={{ fontFamily: theme.fontFamily, color: theme.color, fontWeight: 300 }}>
|
return <div style={{ fontFamily: theme.fontFamily, color: theme.color, fontWeight: 300 }}>
|
||||||
<Toolbar
|
<Toolbar
|
||||||
|
@ -149,7 +160,7 @@ export default class App extends React.Component {
|
||||||
<LayerList
|
<LayerList
|
||||||
onLayersChanged={this.onLayersChanged.bind(this)}
|
onLayersChanged={this.onLayersChanged.bind(this)}
|
||||||
onLayerSelected={this.onLayerSelected.bind(this)}
|
onLayerSelected={this.onLayerSelected.bind(this)}
|
||||||
layers={this.state.mapStyle.get('layers')}
|
layers={layers}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div style={{
|
<div style={{
|
||||||
|
@ -162,7 +173,7 @@ export default class App extends React.Component {
|
||||||
width: 300,
|
width: 300,
|
||||||
backgroundColor: colors.gray}
|
backgroundColor: colors.gray}
|
||||||
}>
|
}>
|
||||||
{selectedLayer && <LayerEditor layer={selectedLayer.toJS()} onLayerChanged={this.onLayerChanged.bind(this)} sources={this.layerWatcher.sources} vectorLayers={this.layerWatcher.vectorLayers}/>}
|
{selectedLayer && <LayerEditor layer={selectedLayer} onLayerChanged={this.onLayerChanged.bind(this)} sources={this.layerWatcher.sources} vectorLayers={this.layerWatcher.vectorLayers}/>}
|
||||||
</div>
|
</div>
|
||||||
{this.mapRenderer()}
|
{this.mapRenderer()}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Immutable from 'immutable'
|
|
||||||
import FileReaderInput from 'react-file-reader-input'
|
import FileReaderInput from 'react-file-reader-input'
|
||||||
|
|
||||||
import Button from 'rebass/dist/Button'
|
import Button from 'rebass/dist/Button'
|
||||||
|
@ -37,7 +36,7 @@ const InlineBlock = props => <div style={{display: "inline-block", ...props.styl
|
||||||
|
|
||||||
export default class Toolbar extends React.Component {
|
export default class Toolbar extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
mapStyle: React.PropTypes.instanceOf(Immutable.Map).isRequired,
|
mapStyle: React.PropTypes.object.isRequired,
|
||||||
onStyleChanged: React.PropTypes.func.isRequired,
|
onStyleChanged: React.PropTypes.func.isRequired,
|
||||||
// A new style has been uploaded
|
// A new style has been uploaded
|
||||||
onStyleUpload: React.PropTypes.func.isRequired,
|
onStyleUpload: React.PropTypes.func.isRequired,
|
||||||
|
@ -60,7 +59,7 @@ export default class Toolbar extends React.Component {
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
reader.readAsText(file, "UTF-8");
|
reader.readAsText(file, "UTF-8");
|
||||||
reader.onload = e => {
|
reader.onload = e => {
|
||||||
let mapStyle = style.fromJSON(JSON.parse(e.target.result))
|
let mapStyle = JSON.parse(e.target.result)
|
||||||
mapStyle = style.ensureMetadataExists(mapStyle)
|
mapStyle = style.ensureMetadataExists(mapStyle)
|
||||||
this.props.onStyleUpload(mapStyle);
|
this.props.onStyleUpload(mapStyle);
|
||||||
}
|
}
|
||||||
|
@ -68,7 +67,7 @@ export default class Toolbar extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
saveButton() {
|
saveButton() {
|
||||||
if(this.props.mapStyle.get('layers').size > 0) {
|
if(this.props.mapStyle.layers.length > 0) {
|
||||||
return <InlineBlock>
|
return <InlineBlock>
|
||||||
<Button onClick={this.props.onStyleSave} big={true}>
|
<Button onClick={this.props.onStyleSave} big={true}>
|
||||||
<MdSave />
|
<MdSave />
|
||||||
|
|
|
@ -35,7 +35,6 @@ class ColorField extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
console.log(Color(this.props.value))
|
|
||||||
const picker = <div style={{
|
const picker = <div style={{
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
left: 163,
|
left: 163,
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Immutable from 'immutable'
|
|
||||||
import GlSpec from 'mapbox-gl-style-spec/reference/latest.min.js'
|
import GlSpec from 'mapbox-gl-style-spec/reference/latest.min.js'
|
||||||
|
|
||||||
import ZoomSpecField from './ZoomSpecField'
|
import ZoomSpecField from './ZoomSpecField'
|
||||||
|
@ -26,7 +25,7 @@ function getGroupName(layerType, fieldName) {
|
||||||
export default class PropertyGroup extends React.Component {
|
export default class PropertyGroup extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
layer: React.PropTypes.object.isRequired,
|
layer: React.PropTypes.object.isRequired,
|
||||||
groupFields: React.PropTypes.instanceOf(Immutable.OrderedSet).isRequired,
|
groupFields: React.PropTypes.array.isRequired,
|
||||||
onChange: React.PropTypes.func.isRequired,
|
onChange: React.PropTypes.func.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,7 +49,7 @@ export default class PropertyGroup extends React.Component {
|
||||||
value={fieldValue}
|
value={fieldValue}
|
||||||
fieldSpec={fieldSpec}
|
fieldSpec={fieldSpec}
|
||||||
/>
|
/>
|
||||||
}).toIndexedSeq()
|
})
|
||||||
|
|
||||||
return <div style={{
|
return <div style={{
|
||||||
padding: margins[2],
|
padding: margins[2],
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Immutable from 'immutable'
|
|
||||||
import color from 'color'
|
import color from 'color'
|
||||||
|
|
||||||
import GlSpec from 'mapbox-gl-style-spec/reference/latest.min.js'
|
import GlSpec from 'mapbox-gl-style-spec/reference/latest.min.js'
|
||||||
|
@ -12,10 +11,6 @@ import StringField from './StringField'
|
||||||
import input from '../../config/input.js'
|
import input from '../../config/input.js'
|
||||||
import theme from '../../config/rebass.js'
|
import theme from '../../config/rebass.js'
|
||||||
|
|
||||||
function isZoomField(value) {
|
|
||||||
return Immutable.Map.isMap(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
function labelFromFieldName(fieldName) {
|
function labelFromFieldName(fieldName) {
|
||||||
let label = fieldName.split('-').slice(1).join(' ')
|
let label = fieldName.split('-').slice(1).join(' ')
|
||||||
if(label.length > 0) {
|
if(label.length > 0) {
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Immutable from 'immutable'
|
|
||||||
import Color from 'color'
|
import Color from 'color'
|
||||||
|
|
||||||
import NumberField from './NumberField'
|
import NumberField from './NumberField'
|
||||||
|
@ -14,7 +13,7 @@ import colors from '../../config/colors.js'
|
||||||
import { margins } from '../../config/scales.js'
|
import { margins } from '../../config/scales.js'
|
||||||
|
|
||||||
function isZoomField(value) {
|
function isZoomField(value) {
|
||||||
return Immutable.Map.isMap(value)
|
return typeof value === 'object' && value.stops
|
||||||
}
|
}
|
||||||
|
|
||||||
const specFieldProps = {
|
const specFieldProps = {
|
||||||
|
@ -46,9 +45,9 @@ export default class ZoomSpecField extends React.Component {
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
if(isZoomField(this.props.value)) {
|
if(isZoomField(this.props.value)) {
|
||||||
const zoomFields = this.props.value.get('stops').map(stop => {
|
const zoomFields = this.props.value.stops.map(stop => {
|
||||||
const zoomLevel = stop.get(0)
|
const zoomLevel = stop[0]
|
||||||
const value = stop.get(1)
|
const value = stop[1]
|
||||||
|
|
||||||
return <div style={input.property} key={zoomLevel}>
|
return <div style={input.property} key={zoomLevel}>
|
||||||
{label}
|
{label}
|
||||||
|
@ -71,7 +70,7 @@ export default class ZoomSpecField extends React.Component {
|
||||||
max={22}
|
max={22}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
}).toSeq()
|
})
|
||||||
return <div style={{
|
return <div style={{
|
||||||
border: 1,
|
border: 1,
|
||||||
borderStyle: 'solid',
|
borderStyle: 'solid',
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Immutable from 'immutable'
|
|
||||||
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import GlSpec from 'mapbox-gl-style-spec/reference/latest.min.js'
|
import GlSpec from 'mapbox-gl-style-spec/reference/latest.min.js'
|
||||||
|
|
||||||
|
@ -75,11 +74,11 @@ class SingleFilterEditor extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
filter: React.PropTypes.array.isRequired,
|
filter: React.PropTypes.array.isRequired,
|
||||||
onChange: React.PropTypes.func.isRequired,
|
onChange: React.PropTypes.func.isRequired,
|
||||||
properties: React.PropTypes.instanceOf(Immutable.Map),
|
properties: React.PropTypes.object,
|
||||||
}
|
}
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
properties: Immutable.Map(),
|
properties: {},
|
||||||
}
|
}
|
||||||
|
|
||||||
onFilterPartChanged(filterOp, propertyName, filterArgs) {
|
onFilterPartChanged(filterOp, propertyName, filterArgs) {
|
||||||
|
@ -103,9 +102,9 @@ class SingleFilterEditor extends React.Component {
|
||||||
value={propertyName}
|
value={propertyName}
|
||||||
onChange={newPropertyName => this.onFilterPartChanged(filterOp, newPropertyName, filterArgs)}
|
onChange={newPropertyName => this.onFilterPartChanged(filterOp, newPropertyName, filterArgs)}
|
||||||
>
|
>
|
||||||
{this.props.properties.keySeq().map(propName => {
|
{Object.keys(this.props.properties).map(propName => {
|
||||||
return <option key={propName} value={propName}>{propName}</option>
|
return <option key={propName} value={propName}>{propName}</option>
|
||||||
}).toIndexedSeq()}
|
})}
|
||||||
</select>
|
</select>
|
||||||
<OperatorSelect
|
<OperatorSelect
|
||||||
value={filterOp}
|
value={filterOp}
|
||||||
|
@ -129,7 +128,7 @@ class SingleFilterEditor extends React.Component {
|
||||||
export default class CombiningFilterEditor extends React.Component {
|
export default class CombiningFilterEditor extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
/** Properties of the vector layer and the available fields */
|
/** Properties of the vector layer and the available fields */
|
||||||
properties: React.PropTypes.instanceOf(Immutable.Map).isRequired,
|
properties: React.PropTypes.object.isRequired,
|
||||||
filter: React.PropTypes.array.isRequired,
|
filter: React.PropTypes.array.isRequired,
|
||||||
onChange: React.PropTypes.func.isRequired,
|
onChange: React.PropTypes.func.isRequired,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Immutable from 'immutable'
|
|
||||||
|
|
||||||
import Toolbar from 'rebass/dist/Toolbar'
|
import Toolbar from 'rebass/dist/Toolbar'
|
||||||
import NavItem from 'rebass/dist/NavItem'
|
import NavItem from 'rebass/dist/NavItem'
|
||||||
|
@ -29,8 +28,8 @@ class UnsupportedLayer extends React.Component {
|
||||||
export default class LayerEditor extends React.Component {
|
export default class LayerEditor extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
layer: React.PropTypes.object.isRequired,
|
layer: React.PropTypes.object.isRequired,
|
||||||
sources: React.PropTypes.instanceOf(Immutable.Map),
|
sources: React.PropTypes.object,
|
||||||
vectorLayers: React.PropTypes.instanceOf(Immutable.Map),
|
vectorLayers: React.PropTypes.object,
|
||||||
onLayerChanged: React.PropTypes.func,
|
onLayerChanged: React.PropTypes.func,
|
||||||
onLayerDestroyed: React.PropTypes.func,
|
onLayerDestroyed: React.PropTypes.func,
|
||||||
}
|
}
|
||||||
|
@ -94,7 +93,7 @@ export default class LayerEditor extends React.Component {
|
||||||
return <PropertyGroup
|
return <PropertyGroup
|
||||||
key={this.props.group}
|
key={this.props.group}
|
||||||
layer={this.props.layer}
|
layer={this.props.layer}
|
||||||
groupFields={Immutable.OrderedSet(group.fields)}
|
groupFields={group.fields}
|
||||||
onChange={this.onPropertyChange.bind(this)}
|
onChange={this.onPropertyChange.bind(this)}
|
||||||
/>
|
/>
|
||||||
})
|
})
|
||||||
|
@ -119,19 +118,20 @@ export default class LayerEditor extends React.Component {
|
||||||
</NavItem>
|
</NavItem>
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
{propertyGroups}
|
{propertyGroups}
|
||||||
|
{this.props.layer.type !== 'background' && <div>
|
||||||
<FilterEditor
|
<FilterEditor
|
||||||
filter={this.props.layer.filter}
|
filter={this.props.layer.filter}
|
||||||
properties={this.props.vectorLayers.get(this.props.layer['source-layer'])}
|
properties={this.props.vectorLayers[this.props.layer['source-layer']]}
|
||||||
onChange={f => this.onFilterChange(Immutable.fromJS(f))}
|
onChange={f => this.onFilterChange(f)}
|
||||||
/>
|
/>
|
||||||
{this.props.layer.type !== 'background'
|
<SourceEditor
|
||||||
&& <SourceEditor
|
source={this.props.layer.source}
|
||||||
source={this.props.layer.source}
|
sourceLayer={this.props.layer['source-layer']}
|
||||||
sourceLayer={this.props.layer['source-layer']}
|
sources={this.props.sources}
|
||||||
sources={this.props.sources}
|
onSourceChange={console.log}
|
||||||
onSourceChange={console.log}
|
onSourceLayerChange={console.log}
|
||||||
onSourceLayerChange={console.log}
|
/>
|
||||||
/>}
|
</div>}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import Immutable from 'immutable'
|
|
||||||
|
|
||||||
import Heading from 'rebass/dist/Heading'
|
import Heading from 'rebass/dist/Heading'
|
||||||
import Toolbar from 'rebass/dist/Toolbar'
|
import Toolbar from 'rebass/dist/Toolbar'
|
||||||
|
@ -15,7 +14,7 @@ import { margins } from '../../config/scales.js'
|
||||||
import {SortableContainer, SortableHandle, arrayMove} from 'react-sortable-hoc';
|
import {SortableContainer, SortableHandle, arrayMove} from 'react-sortable-hoc';
|
||||||
|
|
||||||
const layerListPropTypes = {
|
const layerListPropTypes = {
|
||||||
layers: React.PropTypes.instanceOf(Immutable.OrderedMap),
|
layers: React.PropTypes.array.isRequired,
|
||||||
onLayersChanged: React.PropTypes.func.isRequired,
|
onLayersChanged: React.PropTypes.func.isRequired,
|
||||||
onLayerSelected: React.PropTypes.func,
|
onLayerSelected: React.PropTypes.func,
|
||||||
}
|
}
|
||||||
|
@ -34,23 +33,18 @@ class LayerListContainer extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
onLayerDestroyed(deletedLayer) {
|
onLayerDestroyed(deletedLayer) {
|
||||||
const remainingLayers = this.props.layers.delete(deletedLayer.get('id'))
|
const remainingLayers = this.props.layers.delete(deletedLayer.id)
|
||||||
this.props.onLayersChanged(remainingLayers)
|
this.props.onLayersChanged(remainingLayers)
|
||||||
}
|
}
|
||||||
|
|
||||||
onLayerChanged(layer) {
|
|
||||||
const changedLayers = this.props.layers.set(layer.get('id'), layer)
|
|
||||||
this.props.onLayersChanged(changedLayers)
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const layerPanels = this.props.layers.toIndexedSeq().map((layer, index) => {
|
const layerPanels = this.props.layers.map((layer, index) => {
|
||||||
const layerId = layer.get('id')
|
const layerId = layer.id
|
||||||
return <LayerListItem
|
return <LayerListItem
|
||||||
index={index}
|
index={index}
|
||||||
key={layerId}
|
key={layerId}
|
||||||
layerId={layerId}
|
layerId={layerId}
|
||||||
layerType={layer.get('type')}
|
layerType={layer.type}
|
||||||
onLayerSelected={this.props.onLayerSelected}
|
onLayerSelected={this.props.onLayerSelected}
|
||||||
/>
|
/>
|
||||||
})
|
})
|
||||||
|
@ -73,13 +67,8 @@ export default class LayerList extends React.Component {
|
||||||
onSortEnd(move) {
|
onSortEnd(move) {
|
||||||
const { oldIndex, newIndex } = move
|
const { oldIndex, newIndex } = move
|
||||||
if(oldIndex === newIndex) return
|
if(oldIndex === newIndex) return
|
||||||
|
let layers = this.props.layers.slice(0)
|
||||||
//TODO: Implement this more performant for immutable collections
|
|
||||||
// instead of converting back and forth
|
|
||||||
let layers = this.props.layers.toArray()
|
|
||||||
layers = arrayMove(layers, oldIndex, newIndex)
|
layers = arrayMove(layers, oldIndex, newIndex)
|
||||||
layers = Immutable.OrderedMap(layers.map(l => [l.get('id'), l]))
|
|
||||||
|
|
||||||
this.props.onLayersChanged(layers)
|
this.props.onLayersChanged(layers)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PureRenderMixin from 'react-addons-pure-render-mixin'
|
|
||||||
import Radium from 'radium'
|
import Radium from 'radium'
|
||||||
import Immutable from 'immutable'
|
|
||||||
import Color from 'color'
|
import Color from 'color'
|
||||||
|
|
||||||
import Heading from 'rebass/dist/Heading'
|
import Heading from 'rebass/dist/Heading'
|
||||||
|
@ -38,11 +36,6 @@ class LayerListItem extends React.Component {
|
||||||
onLayerSelected: React.PropTypes.func.isRequired,
|
onLayerSelected: React.PropTypes.func.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props)
|
|
||||||
this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return <li
|
return <li
|
||||||
key={this.props.layerId}
|
key={this.props.layerId}
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
|
||||||
import Immutable from 'immutable'
|
|
||||||
|
|
||||||
import PropertyGroup from '../fields/PropertyGroup'
|
import PropertyGroup from '../fields/PropertyGroup'
|
||||||
import input from '../../config/input.js'
|
import input from '../../config/input.js'
|
||||||
|
@ -16,23 +14,18 @@ export default class SourceEditor extends React.Component {
|
||||||
|
|
||||||
/** List of available sources in the style
|
/** List of available sources in the style
|
||||||
* https://www.mapbox.com/mapbox-gl-style-spec/#root-sources */
|
* https://www.mapbox.com/mapbox-gl-style-spec/#root-sources */
|
||||||
sources: React.PropTypes.instanceOf(Immutable.Map).isRequired,
|
sources: React.PropTypes.object.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const options = this.props.sources.map((source, sourceId)=> {
|
const options = Object.keys(this.props.sources).map(sourceId => {
|
||||||
return <option key={sourceId} value={sourceId}>{sourceId}</option>
|
return <option key={sourceId} value={sourceId}>{sourceId}</option>
|
||||||
}).toIndexedSeq()
|
})
|
||||||
|
|
||||||
const layerOptions = this.props.sources.get(this.props.source, Immutable.Set()).map(vectorLayerId => {
|
const layerOptions = this.props.sources[this.props.source].map(vectorLayerId => {
|
||||||
const id = vectorLayerId
|
const id = vectorLayerId
|
||||||
return <option key={id} value={id}>{id}</option>
|
return <option key={id} value={id}>{id}</option>
|
||||||
}).toIndexedSeq()
|
})
|
||||||
|
|
||||||
return <div>
|
return <div>
|
||||||
<div style={input.property}>
|
<div style={input.property}>
|
||||||
|
|
|
@ -1,17 +1,11 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Immutable from 'immutable'
|
|
||||||
|
|
||||||
export default class Map extends React.Component {
|
export default class Map extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
mapStyle: React.PropTypes.instanceOf(Immutable.Map).isRequired,
|
mapStyle: React.PropTypes.object.isRequired,
|
||||||
accessToken: React.PropTypes.string,
|
accessToken: React.PropTypes.string,
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
|
||||||
//TODO: If we enable this React mixin for immutable comparison we can remove this?
|
|
||||||
return nextProps.mapStyle !== this.props.mapStyle
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return <div
|
return <div
|
||||||
ref={x => this.container = x}
|
ref={x => this.container = x}
|
||||||
|
|
|
@ -23,7 +23,7 @@ export default class MapboxGlMap extends Map {
|
||||||
|
|
||||||
//Mapbox GL now does diffing natively so we don't need to calculate
|
//Mapbox GL now does diffing natively so we don't need to calculate
|
||||||
//the necessary operations ourselves!
|
//the necessary operations ourselves!
|
||||||
this.state.map.setStyle(style.toJSON(nextProps.mapStyle), { diff: true})
|
this.state.map.setStyle(nextProps.mapStyle, { diff: true})
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
@ -31,7 +31,7 @@ export default class MapboxGlMap extends Map {
|
||||||
|
|
||||||
const map = new MapboxGl.Map({
|
const map = new MapboxGl.Map({
|
||||||
container: this.container,
|
container: this.container,
|
||||||
style: style.toJSON(this.props.mapStyle),
|
style: this.props.mapStyle,
|
||||||
});
|
});
|
||||||
|
|
||||||
map.on("style.load", (...args) => {
|
map.on("style.load", (...args) => {
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Immutable from 'immutable'
|
|
||||||
|
|
||||||
import Select from 'rebass/dist/Select'
|
import Select from 'rebass/dist/Select'
|
||||||
import Overlay from 'rebass/dist/Overlay'
|
import Overlay from 'rebass/dist/Overlay'
|
||||||
|
@ -15,7 +14,7 @@ import Input from 'rebass/dist/Input'
|
||||||
|
|
||||||
class SettingsModal extends React.Component {
|
class SettingsModal extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
mapStyle: React.PropTypes.instanceOf(Immutable.Map).isRequired,
|
mapStyle: React.PropTypes.object.isRequired,
|
||||||
onStyleChanged: React.PropTypes.func.isRequired,
|
onStyleChanged: React.PropTypes.func.isRequired,
|
||||||
open: React.PropTypes.bool.isRequired,
|
open: React.PropTypes.bool.isRequired,
|
||||||
toggle: React.PropTypes.func.isRequired,
|
toggle: React.PropTypes.func.isRequired,
|
||||||
|
@ -47,31 +46,31 @@ class SettingsModal extends React.Component {
|
||||||
<Input
|
<Input
|
||||||
name="name"
|
name="name"
|
||||||
label="Name"
|
label="Name"
|
||||||
value={this.props.mapStyle.get('name')}
|
value={this.props.mapStyle.name}
|
||||||
onChange={this.onChange.bind(this, "name")}
|
onChange={this.onChange.bind(this, "name")}
|
||||||
/>
|
/>
|
||||||
<Input
|
<Input
|
||||||
name="owner"
|
name="owner"
|
||||||
label="Owner"
|
label="Owner"
|
||||||
value={this.props.mapStyle.get('owner')}
|
value={this.props.mapStyle.owner}
|
||||||
onChange={this.onChange.bind(this, "owner")}
|
onChange={this.onChange.bind(this, "owner")}
|
||||||
/>
|
/>
|
||||||
<Input
|
<Input
|
||||||
name="sprite"
|
name="sprite"
|
||||||
label="Sprite URL"
|
label="Sprite URL"
|
||||||
value={this.props.mapStyle.get('sprite')}
|
value={this.props.mapStyle.sprite}
|
||||||
onChange={this.onChange.bind(this, "sprite")}
|
onChange={this.onChange.bind(this, "sprite")}
|
||||||
/>
|
/>
|
||||||
<Input
|
<Input
|
||||||
name="glyphs"
|
name="glyphs"
|
||||||
label="Glyphs URL"
|
label="Glyphs URL"
|
||||||
value={this.props.mapStyle.get('glyphs')}
|
value={this.props.mapStyle.glyphs}
|
||||||
onChange={this.onChange.bind(this, "glyphs")}
|
onChange={this.onChange.bind(this, "glyphs")}
|
||||||
/>
|
/>
|
||||||
<Input
|
<Input
|
||||||
name="glyphs"
|
name="glyphs"
|
||||||
label="Glyphs URL"
|
label="Glyphs URL"
|
||||||
value={this.props.mapStyle.get('glyphs')}
|
value={this.props.mapStyle.glyphs}
|
||||||
onChange={this.onChange.bind(this, "glyphs")}
|
onChange={this.onChange.bind(this, "glyphs")}
|
||||||
/>
|
/>
|
||||||
<Select
|
<Select
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Immutable from 'immutable'
|
|
||||||
|
|
||||||
import Overlay from 'rebass/dist/Overlay'
|
import Overlay from 'rebass/dist/Overlay'
|
||||||
import Panel from 'rebass/dist/Panel'
|
import Panel from 'rebass/dist/Panel'
|
||||||
|
@ -19,8 +18,7 @@ import theme from '../../config/rebass'
|
||||||
|
|
||||||
class TilesetsModal extends React.Component {
|
class TilesetsModal extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
mapStyle: React.PropTypes.instanceOf(Immutable.Map).isRequired,
|
mapStyle: React.PropTypes.object.isRequired,
|
||||||
onStyleChanged: React.PropTypes.func.isRequired,
|
|
||||||
open: React.PropTypes.bool.isRequired,
|
open: React.PropTypes.bool.isRequired,
|
||||||
toggle: React.PropTypes.func.isRequired,
|
toggle: React.PropTypes.func.isRequired,
|
||||||
}
|
}
|
||||||
|
@ -29,11 +27,6 @@ class TilesetsModal extends React.Component {
|
||||||
super(props);
|
super(props);
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange(property, e) {
|
|
||||||
const changedStyle = this.props.mapStyle.set(property, e.target.value)
|
|
||||||
this.props.onStyleChanged(changedStyle)
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const tilesetOptions = publicTilesets.map(tileset => {
|
const tilesetOptions = publicTilesets.map(tileset => {
|
||||||
return <div key={tileset.id} style={{
|
return <div key={tileset.id} style={{
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Immutable from 'immutable'
|
|
||||||
|
|
||||||
import Input from 'rebass/dist/Input'
|
import Input from 'rebass/dist/Input'
|
||||||
import Toolbar from 'rebass/dist/Toolbar'
|
import Toolbar from 'rebass/dist/Toolbar'
|
||||||
|
@ -20,7 +19,7 @@ class UnsupportedSource extends React.Component {
|
||||||
|
|
||||||
class VectorSource extends React.Component {
|
class VectorSource extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
source: React.PropTypes.instanceOf(Immutable.Map).isRequired,
|
source: React.PropTypes.object.isRequired,
|
||||||
onSourceChanged: React.PropTypes.func.isRequired,
|
onSourceChanged: React.PropTypes.func.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +44,7 @@ class VectorSource extends React.Component {
|
||||||
export class SourceEditor extends React.Component {
|
export class SourceEditor extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
sourceId: React.PropTypes.string.isRequired,
|
sourceId: React.PropTypes.string.isRequired,
|
||||||
source: React.PropTypes.instanceOf(Immutable.Map).isRequired,
|
source: React.PropTypes.object.isRequired,
|
||||||
onSourceChanged: React.PropTypes.func.isRequired,
|
onSourceChanged: React.PropTypes.func.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Immutable from 'immutable'
|
|
||||||
|
|
||||||
import Heading from 'rebass/dist/Heading'
|
import Heading from 'rebass/dist/Heading'
|
||||||
import Toolbar from 'rebass/dist/Toolbar'
|
import Toolbar from 'rebass/dist/Toolbar'
|
||||||
|
@ -13,7 +12,7 @@ import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
// List of collapsible layer editors
|
// List of collapsible layer editors
|
||||||
export class SourceList extends React.Component {
|
export class SourceList extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
sources: React.PropTypes.instanceOf(Immutable.Map).isRequired,
|
sources: React.PropTypes.object.isRequired,
|
||||||
onSourcesChanged: React.PropTypes.func.isRequired,
|
onSourcesChanged: React.PropTypes.func.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
import Immutable from 'immutable'
|
|
||||||
import throttle from 'lodash.throttle'
|
import throttle from 'lodash.throttle'
|
||||||
import entries from 'lodash.topairs'
|
|
||||||
|
|
||||||
/** Listens to map events to build up a store of available vector
|
/** Listens to map events to build up a store of available vector
|
||||||
* layers contained in the tiles */
|
* layers contained in the tiles */
|
||||||
|
@ -47,22 +45,15 @@ export default class LayerWatcher {
|
||||||
this._vectorLayers[vectorLayerId] = knownProperties
|
this._vectorLayers[vectorLayerId] = knownProperties
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
console.log(this.vectorLayers)
|
||||||
console.log(this.vectorLayers.toJSON())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Access all known sources and their vector tile ids */
|
/** Access all known sources and their vector tile ids */
|
||||||
get sources() {
|
get sources() {
|
||||||
return Immutable.Map(Object.keys(this._sources).map(key => {
|
return this._sources
|
||||||
return [key, Immutable.Set(this._sources[key])]
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get vectorLayers() {
|
get vectorLayers() {
|
||||||
return Immutable.Map(entries(this._vectorLayers).map(([key, layer]) => {
|
return this._vectorLayers
|
||||||
return [key, Immutable.Map(entries(layer).map(([propId, values]) => {
|
|
||||||
return [propId, Immutable.Set(Object.keys(values))]
|
|
||||||
}))]
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,68 +1,30 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import Immutable from 'immutable'
|
|
||||||
import spec from 'mapbox-gl-style-spec/reference/latest.min.js'
|
import spec from 'mapbox-gl-style-spec/reference/latest.min.js'
|
||||||
|
|
||||||
// Standard JSON to Immutable conversion except layers
|
|
||||||
// are stored in an OrderedMap to make lookups id fast
|
|
||||||
// It also ensures that every style has an id and
|
|
||||||
// a created date for future reference
|
|
||||||
function fromJSON(jsonStyle) {
|
|
||||||
if (typeof jsonStyle === 'string' || jsonStyle instanceof String) {
|
|
||||||
jsonStyle = JSON.parse(jsonStyle)
|
|
||||||
}
|
|
||||||
|
|
||||||
return Immutable.Map(Object.keys(jsonStyle).map(key => {
|
|
||||||
const val = jsonStyle[key]
|
|
||||||
if(key === "layers") {
|
|
||||||
return [key, Immutable.OrderedMap(val.map(l => [l.id, Immutable.fromJS(l)]))]
|
|
||||||
} else if(key === "sources" || key === "metadata" || key === "transition") {
|
|
||||||
return [key, Immutable.fromJS(val)]
|
|
||||||
} else {
|
|
||||||
return [key, val]
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Empty style is always used if no style could be restored or fetched
|
// Empty style is always used if no style could be restored or fetched
|
||||||
const emptyStyle = ensureMetadataExists(fromJSON({
|
const emptyStyle = ensureMetadataExists({
|
||||||
version: 8,
|
version: 8,
|
||||||
sources: {},
|
sources: {},
|
||||||
layers: [],
|
layers: [],
|
||||||
}))
|
})
|
||||||
|
|
||||||
function ensureHasId(style) {
|
function ensureHasId(style) {
|
||||||
if(style.has('id')) return style
|
if('id' in style) return style
|
||||||
return style.set('id', Math.random().toString(36).substr(2, 9))
|
style.id = Math.random().toString(36).substr(2, 9)
|
||||||
|
return style
|
||||||
}
|
}
|
||||||
|
|
||||||
function ensureHasTimestamp(style) {
|
function ensureHasTimestamp(style) {
|
||||||
if(style.has('id')) return style
|
if('created' in style) return style
|
||||||
return style.set('created', new Date().toJSON())
|
style.created = new Date().toJSON()
|
||||||
|
return style
|
||||||
}
|
}
|
||||||
|
|
||||||
function ensureMetadataExists(style) {
|
function ensureMetadataExists(style) {
|
||||||
return ensureHasId(ensureHasTimestamp(style))
|
return ensureHasId(ensureHasTimestamp(style))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Turns immutable style back into JSON with the original order of the
|
|
||||||
// layers preserved
|
|
||||||
function toJSON(mapStyle) {
|
|
||||||
const jsonStyle = {}
|
|
||||||
for(let [key, value] of mapStyle.entries()) {
|
|
||||||
if(key === "layers") {
|
|
||||||
jsonStyle[key] = value.toIndexedSeq().toJS()
|
|
||||||
} else if(key === 'sources' || key === "metadata" || key === "transition") {
|
|
||||||
jsonStyle[key] = value.toJS()
|
|
||||||
} else {
|
|
||||||
jsonStyle[key] = value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return jsonStyle
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
toJSON,
|
|
||||||
fromJSON,
|
|
||||||
ensureMetadataExists,
|
ensureMetadataExists,
|
||||||
emptyStyle,
|
emptyStyle,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { colorizeLayers } from './style.js'
|
import { colorizeLayers } from './style.js'
|
||||||
import Immutable from 'immutable'
|
|
||||||
import style from './style.js'
|
import style from './style.js'
|
||||||
|
|
||||||
const storagePrefix = "maputnik"
|
const storagePrefix = "maputnik"
|
||||||
|
@ -18,7 +17,7 @@ export function loadDefaultStyle(cb) {
|
||||||
|
|
||||||
request.onload = () => {
|
request.onload = () => {
|
||||||
if (request.status >= 200 && request.status < 400) {
|
if (request.status >= 200 && request.status < 400) {
|
||||||
cb(style.ensureMetadataExists(style.fromJSON(request.responseText)))
|
cb(style.ensureMetadataExists(JSON.parse(request.responseText)))
|
||||||
} else {
|
} else {
|
||||||
cb(style.emptyStyle)
|
cb(style.emptyStyle)
|
||||||
}
|
}
|
||||||
|
@ -104,15 +103,15 @@ export class StyleStore {
|
||||||
const styleId = window.localStorage.getItem(storageKeys.latest)
|
const styleId = window.localStorage.getItem(storageKeys.latest)
|
||||||
const styleItem = window.localStorage.getItem(styleKey(styleId))
|
const styleItem = window.localStorage.getItem(styleKey(styleId))
|
||||||
|
|
||||||
if(styleItem) return cb(style.fromJSON(styleItem))
|
if(styleItem) return cb(JSON.parse(styleItem))
|
||||||
cb(style.emptyStyle)
|
cb(style.emptyStyle)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save current style replacing previous version
|
// Save current style replacing previous version
|
||||||
save(mapStyle) {
|
save(mapStyle) {
|
||||||
const key = styleKey(mapStyle.get('id'))
|
const key = styleKey(mapStyle.id)
|
||||||
window.localStorage.setItem(key, JSON.stringify(style.toJSON(mapStyle)))
|
window.localStorage.setItem(key, JSON.stringify(mapStyle))
|
||||||
window.localStorage.setItem(storageKeys.latest, mapStyle.get('id'))
|
window.localStorage.setItem(storageKeys.latest, mapStyle.id)
|
||||||
return mapStyle
|
return mapStyle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue