mirror of
https://github.com/a-nyx/maputnik-with-pmtiles.git
synced 2024-12-28 16:01:15 +01:00
Change to always attempt rendering of map state, even if broken, allowing the user to fix style issues step-by-step.
This commit is contained in:
parent
26907f7014
commit
29a0ef0d1c
1 changed files with 59 additions and 58 deletions
|
@ -3,6 +3,7 @@ import React from 'react'
|
||||||
import cloneDeep from 'lodash.clonedeep'
|
import cloneDeep from 'lodash.clonedeep'
|
||||||
import clamp from 'lodash.clamp'
|
import clamp from 'lodash.clamp'
|
||||||
import get from 'lodash.get'
|
import get from 'lodash.get'
|
||||||
|
import {unset} from 'lodash'
|
||||||
import {arrayMove} from 'react-sortable-hoc'
|
import {arrayMove} from 'react-sortable-hoc'
|
||||||
import url from 'url'
|
import url from 'url'
|
||||||
|
|
||||||
|
@ -97,7 +98,7 @@ export default class App extends React.Component {
|
||||||
port = window.location.port
|
port = window.location.port
|
||||||
}
|
}
|
||||||
this.styleStore = new ApiStyleStore({
|
this.styleStore = new ApiStyleStore({
|
||||||
onLocalStyleChange: mapStyle => this.onStyleChanged(mapStyle, false),
|
onLocalStyleChange: mapStyle => this.onStyleChanged(mapStyle, {save: false}),
|
||||||
port: port,
|
port: port,
|
||||||
host: params.get("localhost")
|
host: params.get("localhost")
|
||||||
})
|
})
|
||||||
|
@ -207,7 +208,6 @@ export default class App extends React.Component {
|
||||||
errors: [],
|
errors: [],
|
||||||
infos: [],
|
infos: [],
|
||||||
mapStyle: style.emptyStyle,
|
mapStyle: style.emptyStyle,
|
||||||
dirtyMapStyle: style.emptyStyle,
|
|
||||||
selectedLayerIndex: 0,
|
selectedLayerIndex: 0,
|
||||||
sources: {},
|
sources: {},
|
||||||
vectorLayers: {},
|
vectorLayers: {},
|
||||||
|
@ -280,7 +280,7 @@ export default class App extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
updateFonts(urlTemplate) {
|
updateFonts(urlTemplate) {
|
||||||
const metadata = this.state.dirtyMapStyle.metadata || {}
|
const metadata = this.state.mapStyle.metadata || {}
|
||||||
const accessToken = metadata['maputnik:openmaptiles_access_token'] || tokens.openmaptiles
|
const accessToken = metadata['maputnik:openmaptiles_access_token'] || tokens.openmaptiles
|
||||||
|
|
||||||
let glyphUrl = (typeof urlTemplate === 'string')? urlTemplate.replace('{key}', accessToken): urlTemplate;
|
let glyphUrl = (typeof urlTemplate === 'string')? urlTemplate.replace('{key}', accessToken): urlTemplate;
|
||||||
|
@ -316,7 +316,12 @@ export default class App extends React.Component {
|
||||||
this.onStyleChanged(changedStyle)
|
this.onStyleChanged(changedStyle)
|
||||||
}
|
}
|
||||||
|
|
||||||
onStyleChanged = (newStyle, save=true) => {
|
onStyleChanged = (newStyle, opts={}) => {
|
||||||
|
opts = {
|
||||||
|
save: true,
|
||||||
|
addRevision: true,
|
||||||
|
...opts,
|
||||||
|
};
|
||||||
|
|
||||||
const errors = validate(newStyle, latest) || [];
|
const errors = validate(newStyle, latest) || [];
|
||||||
const mappedErrors = errors.map(error => {
|
const mappedErrors = errors.map(error => {
|
||||||
|
@ -343,68 +348,63 @@ export default class App extends React.Component {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if(errors.length === 0) {
|
let dirtyMapStyle = undefined;
|
||||||
|
if (errors.length > 0) {
|
||||||
|
dirtyMapStyle = cloneDeep(newStyle);
|
||||||
|
|
||||||
if(newStyle.glyphs !== this.state.dirtyMapStyle.glyphs) {
|
errors.forEach(error => {
|
||||||
|
const {message} = error;
|
||||||
|
const objPath = message.split(":")[0];
|
||||||
|
unset(dirtyMapStyle, objPath);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if(newStyle.glyphs !== this.state.mapStyle.glyphs) {
|
||||||
this.updateFonts(newStyle.glyphs)
|
this.updateFonts(newStyle.glyphs)
|
||||||
}
|
}
|
||||||
if(newStyle.sprite !== this.state.dirtyMapStyle.sprite) {
|
if(newStyle.sprite !== this.state.mapStyle.sprite) {
|
||||||
this.updateIcons(newStyle.sprite)
|
this.updateIcons(newStyle.sprite)
|
||||||
}
|
}
|
||||||
|
|
||||||
this.revisionStore.addRevision(newStyle)
|
if (opts.addRevision) {
|
||||||
if(save) this.saveStyle(newStyle)
|
this.revisionStore.addRevision(newStyle);
|
||||||
|
}
|
||||||
|
if (opts.save) {
|
||||||
|
this.saveStyle(newStyle);
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
dirtyMapStyle: newStyle,
|
|
||||||
mapStyle: newStyle,
|
mapStyle: newStyle,
|
||||||
errors: [],
|
dirtyMapStyle: dirtyMapStyle,
|
||||||
})
|
|
||||||
} else {
|
|
||||||
this.setState({
|
|
||||||
dirtyMapStyle: newStyle,
|
|
||||||
errors: mappedErrors,
|
errors: mappedErrors,
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
|
||||||
this.fetchSources();
|
this.fetchSources();
|
||||||
}
|
}
|
||||||
|
|
||||||
onUndo = () => {
|
onUndo = () => {
|
||||||
let activeStyle;
|
let activeStyle;
|
||||||
|
|
||||||
// Check our dirty style state first, otherwise just undo to that state.
|
|
||||||
if (isEqual(this.state.mapStyle, this.state.dirtyMapStyle)) {
|
|
||||||
activeStyle = this.revisionStore.undo()
|
activeStyle = this.revisionStore.undo()
|
||||||
}
|
|
||||||
else {
|
|
||||||
activeStyle = this.state.mapStyle;
|
|
||||||
}
|
|
||||||
|
|
||||||
const messages = undoMessages(this.state.dirtyMapStyle, activeStyle)
|
const messages = undoMessages(this.state.mapStyle, activeStyle)
|
||||||
this.saveStyle(activeStyle)
|
this.onStyleChanged(activeStyle, {addRevision: false});
|
||||||
this.setState({
|
this.setState({
|
||||||
infos: messages,
|
infos: messages,
|
||||||
mapStyle: activeStyle,
|
|
||||||
dirtyMapStyle: activeStyle,
|
|
||||||
errors: [],
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
onRedo = () => {
|
onRedo = () => {
|
||||||
const activeStyle = this.revisionStore.redo()
|
const activeStyle = this.revisionStore.redo()
|
||||||
const messages = redoMessages(this.state.dirtyMapStyle, activeStyle)
|
const messages = redoMessages(this.state.mapStyle, activeStyle)
|
||||||
this.saveStyle(activeStyle)
|
this.onStyleChanged(activeStyle, {addRevision: false});
|
||||||
this.setState({
|
this.setState({
|
||||||
infos: messages,
|
infos: messages,
|
||||||
mapStyle: activeStyle,
|
|
||||||
dirtyMapStyle: activeStyle,
|
|
||||||
errors: [],
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
onMoveLayer = (move) => {
|
onMoveLayer = (move) => {
|
||||||
let { oldIndex, newIndex } = move;
|
let { oldIndex, newIndex } = move;
|
||||||
let layers = this.state.dirtyMapStyle.layers;
|
let layers = this.state.mapStyle.layers;
|
||||||
oldIndex = clamp(oldIndex, 0, layers.length-1);
|
oldIndex = clamp(oldIndex, 0, layers.length-1);
|
||||||
newIndex = clamp(newIndex, 0, layers.length-1);
|
newIndex = clamp(newIndex, 0, layers.length-1);
|
||||||
if(oldIndex === newIndex) return;
|
if(oldIndex === newIndex) return;
|
||||||
|
@ -422,14 +422,14 @@ export default class App extends React.Component {
|
||||||
|
|
||||||
onLayersChange = (changedLayers) => {
|
onLayersChange = (changedLayers) => {
|
||||||
const changedStyle = {
|
const changedStyle = {
|
||||||
...this.state.dirtyMapStyle,
|
...this.state.mapStyle,
|
||||||
layers: changedLayers
|
layers: changedLayers
|
||||||
}
|
}
|
||||||
this.onStyleChanged(changedStyle)
|
this.onStyleChanged(changedStyle)
|
||||||
}
|
}
|
||||||
|
|
||||||
onLayerDestroy = (layerId) => {
|
onLayerDestroy = (layerId) => {
|
||||||
let layers = this.state.dirtyMapStyle.layers;
|
let layers = this.state.mapStyle.layers;
|
||||||
const remainingLayers = layers.slice(0);
|
const remainingLayers = layers.slice(0);
|
||||||
const idx = style.indexOfLayer(remainingLayers, layerId)
|
const idx = style.indexOfLayer(remainingLayers, layerId)
|
||||||
remainingLayers.splice(idx, 1);
|
remainingLayers.splice(idx, 1);
|
||||||
|
@ -448,7 +448,7 @@ export default class App extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
onLayerVisibilityToggle = (layerId) => {
|
onLayerVisibilityToggle = (layerId) => {
|
||||||
let layers = this.state.dirtyMapStyle.layers;
|
let layers = this.state.mapStyle.layers;
|
||||||
const changedLayers = layers.slice(0)
|
const changedLayers = layers.slice(0)
|
||||||
const idx = style.indexOfLayer(changedLayers, layerId)
|
const idx = style.indexOfLayer(changedLayers, layerId)
|
||||||
|
|
||||||
|
@ -463,7 +463,7 @@ export default class App extends React.Component {
|
||||||
|
|
||||||
|
|
||||||
onLayerIdChange = (oldId, newId) => {
|
onLayerIdChange = (oldId, newId) => {
|
||||||
const changedLayers = this.state.dirtyMapStyle.layers.slice(0)
|
const changedLayers = this.state.mapStyle.layers.slice(0)
|
||||||
const idx = style.indexOfLayer(changedLayers, oldId)
|
const idx = style.indexOfLayer(changedLayers, oldId)
|
||||||
|
|
||||||
changedLayers[idx] = {
|
changedLayers[idx] = {
|
||||||
|
@ -476,7 +476,7 @@ export default class App extends React.Component {
|
||||||
|
|
||||||
onLayerChanged = (layer) => {
|
onLayerChanged = (layer) => {
|
||||||
console.log("test: onLayerChanged", layer);
|
console.log("test: onLayerChanged", layer);
|
||||||
const changedLayers = this.state.dirtyMapStyle.layers.slice(0)
|
const changedLayers = this.state.mapStyle.layers.slice(0)
|
||||||
const idx = style.indexOfLayer(changedLayers, layer.id)
|
const idx = style.indexOfLayer(changedLayers, layer.id)
|
||||||
changedLayers[idx] = layer
|
changedLayers[idx] = layer
|
||||||
|
|
||||||
|
@ -513,7 +513,7 @@ export default class App extends React.Component {
|
||||||
fetchSources() {
|
fetchSources() {
|
||||||
const sourceList = {...this.state.sources};
|
const sourceList = {...this.state.sources};
|
||||||
|
|
||||||
for(let [key, val] of Object.entries(this.state.dirtyMapStyle.sources)) {
|
for(let [key, val] of Object.entries(this.state.mapStyle.sources)) {
|
||||||
if(sourceList.hasOwnProperty(key)) {
|
if(sourceList.hasOwnProperty(key)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -586,10 +586,11 @@ export default class App extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
mapRenderer() {
|
mapRenderer() {
|
||||||
|
const {mapStyle, dirtyMapStyle} = this.state;
|
||||||
const metadata = this.state.mapStyle.metadata || {};
|
const metadata = this.state.mapStyle.metadata || {};
|
||||||
|
|
||||||
const mapProps = {
|
const mapProps = {
|
||||||
mapStyle: this.state.mapStyle,
|
mapStyle: (dirtyMapStyle || mapStyle),
|
||||||
replaceAccessTokens: (mapStyle) => {
|
replaceAccessTokens: (mapStyle) => {
|
||||||
return style.replaceAccessTokens(mapStyle, {
|
return style.replaceAccessTokens(mapStyle, {
|
||||||
allowFallback: true
|
allowFallback: true
|
||||||
|
@ -637,7 +638,7 @@ export default class App extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
onLayerSelect = (layerId) => {
|
onLayerSelect = (layerId) => {
|
||||||
const idx = style.indexOfLayer(this.state.dirtyMapStyle.layers, layerId)
|
const idx = style.indexOfLayer(this.state.mapStyle.layers, layerId)
|
||||||
this.setState({ selectedLayerIndex: idx })
|
this.setState({ selectedLayerIndex: idx })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -677,14 +678,14 @@ export default class App extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const layers = this.state.dirtyMapStyle.layers || []
|
const layers = this.state.mapStyle.layers || []
|
||||||
const selectedLayer = layers.length > 0 ? layers[this.state.selectedLayerIndex] : null
|
const selectedLayer = layers.length > 0 ? layers[this.state.selectedLayerIndex] : null
|
||||||
const metadata = this.state.dirtyMapStyle.metadata || {}
|
const metadata = this.state.mapStyle.metadata || {}
|
||||||
|
|
||||||
const toolbar = <Toolbar
|
const toolbar = <Toolbar
|
||||||
renderer={this._getRenderer()}
|
renderer={this._getRenderer()}
|
||||||
mapState={this.state.mapState}
|
mapState={this.state.mapState}
|
||||||
mapStyle={this.state.dirtyMapStyle}
|
mapStyle={this.state.mapStyle}
|
||||||
inspectModeEnabled={this.state.mapState === "inspect"}
|
inspectModeEnabled={this.state.mapState === "inspect"}
|
||||||
sources={this.state.sources}
|
sources={this.state.sources}
|
||||||
onStyleChanged={this.onStyleChanged}
|
onStyleChanged={this.onStyleChanged}
|
||||||
|
@ -711,7 +712,7 @@ export default class App extends React.Component {
|
||||||
layer={selectedLayer}
|
layer={selectedLayer}
|
||||||
layerIndex={this.state.selectedLayerIndex}
|
layerIndex={this.state.selectedLayerIndex}
|
||||||
isFirstLayer={this.state.selectedLayerIndex < 1}
|
isFirstLayer={this.state.selectedLayerIndex < 1}
|
||||||
isLastLayer={this.state.selectedLayerIndex === this.state.dirtyMapStyle.layers.length-1}
|
isLastLayer={this.state.selectedLayerIndex === this.state.mapStyle.layers.length-1}
|
||||||
sources={this.state.sources}
|
sources={this.state.sources}
|
||||||
vectorLayers={this.state.vectorLayers}
|
vectorLayers={this.state.vectorLayers}
|
||||||
spec={this.state.spec}
|
spec={this.state.spec}
|
||||||
|
@ -748,7 +749,7 @@ export default class App extends React.Component {
|
||||||
onOpenToggle={this.toggleModal.bind(this, 'shortcuts')}
|
onOpenToggle={this.toggleModal.bind(this, 'shortcuts')}
|
||||||
/>
|
/>
|
||||||
<SettingsModal
|
<SettingsModal
|
||||||
mapStyle={this.state.dirtyMapStyle}
|
mapStyle={this.state.mapStyle}
|
||||||
onStyleChanged={this.onStyleChanged}
|
onStyleChanged={this.onStyleChanged}
|
||||||
onChangeMetadataProperty={this.onChangeMetadataProperty}
|
onChangeMetadataProperty={this.onChangeMetadataProperty}
|
||||||
isOpen={this.state.isOpen.settings}
|
isOpen={this.state.isOpen.settings}
|
||||||
|
@ -756,7 +757,7 @@ export default class App extends React.Component {
|
||||||
openlayersDebugOptions={this.state.openlayersDebugOptions}
|
openlayersDebugOptions={this.state.openlayersDebugOptions}
|
||||||
/>
|
/>
|
||||||
<ExportModal
|
<ExportModal
|
||||||
mapStyle={this.state.dirtyMapStyle}
|
mapStyle={this.state.mapStyle}
|
||||||
onStyleChanged={this.onStyleChanged}
|
onStyleChanged={this.onStyleChanged}
|
||||||
isOpen={this.state.isOpen.export}
|
isOpen={this.state.isOpen.export}
|
||||||
onOpenToggle={this.toggleModal.bind(this, 'export')}
|
onOpenToggle={this.toggleModal.bind(this, 'export')}
|
||||||
|
@ -767,7 +768,7 @@ export default class App extends React.Component {
|
||||||
onOpenToggle={this.toggleModal.bind(this, 'open')}
|
onOpenToggle={this.toggleModal.bind(this, 'open')}
|
||||||
/>
|
/>
|
||||||
<SourcesModal
|
<SourcesModal
|
||||||
mapStyle={this.state.dirtyMapStyle}
|
mapStyle={this.state.mapStyle}
|
||||||
onStyleChanged={this.onStyleChanged}
|
onStyleChanged={this.onStyleChanged}
|
||||||
isOpen={this.state.isOpen.sources}
|
isOpen={this.state.isOpen.sources}
|
||||||
onOpenToggle={this.toggleModal.bind(this, 'sources')}
|
onOpenToggle={this.toggleModal.bind(this, 'sources')}
|
||||||
|
|
Loading…
Reference in a new issue