mirror of
https://github.com/a-nyx/maputnik-with-pmtiles.git
synced 2025-01-01 07:38:18 +01:00
Merge pull request #81 from maputnik/default-access-token
Default access token
This commit is contained in:
commit
24dc71344e
7 changed files with 80 additions and 42 deletions
|
@ -1,5 +1,4 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { saveAs } from 'file-saver'
|
|
||||||
import Mousetrap from 'mousetrap'
|
import Mousetrap from 'mousetrap'
|
||||||
|
|
||||||
import MapboxGlMap from './map/MapboxGlMap'
|
import MapboxGlMap from './map/MapboxGlMap'
|
||||||
|
@ -21,6 +20,7 @@ import { loadDefaultStyle, StyleStore } from '../libs/stylestore'
|
||||||
import { ApiStyleStore } from '../libs/apistore'
|
import { ApiStyleStore } from '../libs/apistore'
|
||||||
import { RevisionStore } from '../libs/revisions'
|
import { RevisionStore } from '../libs/revisions'
|
||||||
import LayerWatcher from '../libs/layerwatcher'
|
import LayerWatcher from '../libs/layerwatcher'
|
||||||
|
import tokens from '../config/tokens.json'
|
||||||
|
|
||||||
function updateRootSpec(spec, fieldName, newValues) {
|
function updateRootSpec(spec, fieldName, newValues) {
|
||||||
return {
|
return {
|
||||||
|
@ -89,18 +89,14 @@ export default class App extends React.Component {
|
||||||
loadDefaultStyle(mapStyle => this.onStyleOpen(mapStyle))
|
loadDefaultStyle(mapStyle => this.onStyleOpen(mapStyle))
|
||||||
}
|
}
|
||||||
|
|
||||||
onStyleDownload() {
|
|
||||||
const mapStyle = this.state.mapStyle
|
|
||||||
const blob = new Blob([formatStyle(mapStyle)], {type: "application/json;charset=utf-8"});
|
|
||||||
saveAs(blob, mapStyle.id + ".json");
|
|
||||||
}
|
|
||||||
|
|
||||||
saveStyle(snapshotStyle) {
|
saveStyle(snapshotStyle) {
|
||||||
this.styleStore.save(snapshotStyle)
|
this.styleStore.save(snapshotStyle)
|
||||||
}
|
}
|
||||||
|
|
||||||
updateFonts(urlTemplate) {
|
updateFonts(urlTemplate) {
|
||||||
downloadGlyphsMetadata(urlTemplate, fonts => {
|
const metadata = this.state.mapStyle.metadata || {}
|
||||||
|
const accessToken = metadata['maputnik:openmaptiles_access_token'] || tokens.openmaptiles
|
||||||
|
downloadGlyphsMetadata(urlTemplate.replace('{key}', accessToken), fonts => {
|
||||||
this.setState({ spec: updateRootSpec(this.state.spec, 'glyphs', fonts)})
|
this.setState({ spec: updateRootSpec(this.state.spec, 'glyphs', fonts)})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -189,20 +185,14 @@ export default class App extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
mapRenderer() {
|
mapRenderer() {
|
||||||
const metadata = this.state.mapStyle.metadata || {}
|
|
||||||
const mapProps = {
|
const mapProps = {
|
||||||
mapStyle: this.state.mapStyle,
|
mapStyle: style.replaceAccessToken(this.state.mapStyle),
|
||||||
accessToken: metadata['maputnik:access_token'],
|
|
||||||
onDataChange: (e) => {
|
onDataChange: (e) => {
|
||||||
this.layerWatcher.analyzeMap(e.map)
|
this.layerWatcher.analyzeMap(e.map)
|
||||||
},
|
},
|
||||||
//TODO: This would actually belong to the layout component
|
|
||||||
style:{
|
|
||||||
top: 40,
|
|
||||||
//left: 500,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const metadata = this.state.mapStyle.metadata || {}
|
||||||
const renderer = metadata['maputnik:renderer'] || 'mbgljs'
|
const renderer = metadata['maputnik:renderer'] || 'mbgljs'
|
||||||
|
|
||||||
// Check if OL3 code has been loaded?
|
// Check if OL3 code has been loaded?
|
||||||
|
@ -231,7 +221,6 @@ export default class App extends React.Component {
|
||||||
sources={this.state.sources}
|
sources={this.state.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)}
|
|
||||||
onInspectModeToggle={this.changeInspectMode.bind(this)}
|
onInspectModeToggle={this.changeInspectMode.bind(this)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
|
@ -54,8 +54,6 @@ export default class Toolbar extends React.Component {
|
||||||
onStyleChanged: React.PropTypes.func.isRequired,
|
onStyleChanged: React.PropTypes.func.isRequired,
|
||||||
// A new style has been uploaded
|
// A new style has been uploaded
|
||||||
onStyleOpen: React.PropTypes.func.isRequired,
|
onStyleOpen: React.PropTypes.func.isRequired,
|
||||||
// Current style is requested for download
|
|
||||||
onStyleDownload: React.PropTypes.func.isRequired,
|
|
||||||
// A dict of source id's and the available source layers
|
// A dict of source id's and the available source layers
|
||||||
sources: React.PropTypes.object.isRequired,
|
sources: React.PropTypes.object.isRequired,
|
||||||
onInspectModeToggle: React.PropTypes.func.isRequired
|
onInspectModeToggle: React.PropTypes.func.isRequired
|
||||||
|
@ -74,13 +72,6 @@ export default class Toolbar extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
downloadButton() {
|
|
||||||
return <ToolbarAction onClick={this.props.onStyleDownload}>
|
|
||||||
<MdFileDownload />
|
|
||||||
<IconText>Download</IconText>
|
|
||||||
</ToolbarAction>
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleModal(modalName) {
|
toggleModal(modalName) {
|
||||||
this.setState({
|
this.setState({
|
||||||
isOpen: {
|
isOpen: {
|
||||||
|
@ -100,7 +91,6 @@ export default class Toolbar extends React.Component {
|
||||||
/>
|
/>
|
||||||
<ExportModal
|
<ExportModal
|
||||||
mapStyle={this.props.mapStyle}
|
mapStyle={this.props.mapStyle}
|
||||||
onStyleDownload={this.props.onStyleDownload}
|
|
||||||
isOpen={this.state.isOpen.export}
|
isOpen={this.state.isOpen.export}
|
||||||
onOpenToggle={this.toggleModal.bind(this, 'export')}
|
onOpenToggle={this.toggleModal.bind(this, 'export')}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -6,6 +6,7 @@ import FeatureLayerPopup from './FeatureLayerPopup'
|
||||||
import FeaturePropertyPopup from './FeaturePropertyPopup'
|
import FeaturePropertyPopup from './FeaturePropertyPopup'
|
||||||
import validateColor from 'mapbox-gl-style-spec/lib/validate/validate_color'
|
import validateColor from 'mapbox-gl-style-spec/lib/validate/validate_color'
|
||||||
import style from '../../libs/style.js'
|
import style from '../../libs/style.js'
|
||||||
|
import tokens from '../../config/tokens.json'
|
||||||
import { colorHighlightedLayer } from '../../libs/highlight'
|
import { colorHighlightedLayer } from '../../libs/highlight'
|
||||||
import 'mapbox-gl/dist/mapbox-gl.css'
|
import 'mapbox-gl/dist/mapbox-gl.css'
|
||||||
import '../../mapboxgl.css'
|
import '../../mapboxgl.css'
|
||||||
|
@ -56,8 +57,6 @@ export default class MapboxGlMap extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
onDataChange: React.PropTypes.func,
|
onDataChange: React.PropTypes.func,
|
||||||
mapStyle: React.PropTypes.object.isRequired,
|
mapStyle: React.PropTypes.object.isRequired,
|
||||||
accessToken: React.PropTypes.string,
|
|
||||||
style: React.PropTypes.object,
|
|
||||||
inspectModeEnabled: React.PropTypes.bool.isRequired,
|
inspectModeEnabled: React.PropTypes.bool.isRequired,
|
||||||
highlightedLayer: React.PropTypes.object,
|
highlightedLayer: React.PropTypes.object,
|
||||||
}
|
}
|
||||||
|
@ -65,11 +64,12 @@ export default class MapboxGlMap extends React.Component {
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
onMapLoaded: () => {},
|
onMapLoaded: () => {},
|
||||||
onDataChange: () => {},
|
onDataChange: () => {},
|
||||||
|
mapboxAccessToken: tokens.mapbox,
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
MapboxGl.accessToken = props.accessToken
|
MapboxGl.accessToken = tokens.mapbox
|
||||||
this.state = {
|
this.state = {
|
||||||
map: null,
|
map: null,
|
||||||
inspect: null,
|
inspect: null,
|
||||||
|
@ -80,8 +80,9 @@ export default class MapboxGlMap extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
MapboxGl.accessToken = nextProps.accessToken
|
|
||||||
if(!this.state.map) return
|
if(!this.state.map) return
|
||||||
|
const metadata = nextProps.mapStyle.metadata || {}
|
||||||
|
MapboxGl.accessToken = metadata['maputnik:mapbox_access_token'] || tokens.mapbox
|
||||||
|
|
||||||
if(!nextProps.inspectModeEnabled) {
|
if(!nextProps.inspectModeEnabled) {
|
||||||
//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
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { saveAs } from 'file-saver'
|
||||||
|
|
||||||
import GlSpec from 'mapbox-gl-style-spec/reference/latest.js'
|
import GlSpec from 'mapbox-gl-style-spec/reference/latest.js'
|
||||||
import InputBlock from '../inputs/InputBlock'
|
import InputBlock from '../inputs/InputBlock'
|
||||||
|
@ -103,24 +104,30 @@ class Gist extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function stripAccessTokens(mapStyle) {
|
||||||
|
const changedMetadata = { ...mapStyle.metadata }
|
||||||
|
delete changedMetadata['maputnik:mapbox_access_token']
|
||||||
|
delete changedMetadata['maputnik:openmaptiles_access_token']
|
||||||
|
return {
|
||||||
|
...mapStyle,
|
||||||
|
metadata: changedMetadata
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ExportModal extends React.Component {
|
class ExportModal extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
mapStyle: React.PropTypes.object.isRequired,
|
mapStyle: React.PropTypes.object.isRequired,
|
||||||
isOpen: React.PropTypes.bool.isRequired,
|
isOpen: React.PropTypes.bool.isRequired,
|
||||||
onOpenToggle: React.PropTypes.func.isRequired,
|
onOpenToggle: React.PropTypes.func.isRequired,
|
||||||
// Current style is requested for download
|
|
||||||
onStyleDownload: React.PropTypes.func.isRequired,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
}
|
}
|
||||||
|
|
||||||
onStyleDownload() {
|
downloadStyle() {
|
||||||
const blob = new Blob([formatStyle(mapStyle)], {type: "application/json;charset=utf-8"});
|
const blob = new Blob([formatStyle(stripAccessTokens(this.props.mapStyle))], {type: "application/json;charset=utf-8"});
|
||||||
saveAs(blob, mapStyle.id + ".json");
|
saveAs(blob, this.props.mapStyle.id + ".json");
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -135,7 +142,7 @@ class ExportModal extends React.Component {
|
||||||
<p>
|
<p>
|
||||||
Download a JSON style to your computer.
|
Download a JSON style to your computer.
|
||||||
</p>
|
</p>
|
||||||
<Button onClick={this.props.onStyleDownload}>
|
<Button onClick={this.downloadStyle.bind(this)}>
|
||||||
<MdFileDownload />
|
<MdFileDownload />
|
||||||
Download
|
Download
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
@ -45,6 +45,7 @@ class SettingsModal extends React.Component {
|
||||||
onOpenToggle={this.props.onOpenToggle}
|
onOpenToggle={this.props.onOpenToggle}
|
||||||
title={'Style Settings'}
|
title={'Style Settings'}
|
||||||
>
|
>
|
||||||
|
<div style={{minWidth: 350}}>
|
||||||
<InputBlock label={"Name"} doc={GlSpec.$root.name.doc}>
|
<InputBlock label={"Name"} doc={GlSpec.$root.name.doc}>
|
||||||
<StringInput {...inputProps}
|
<StringInput {...inputProps}
|
||||||
value={this.props.mapStyle.name}
|
value={this.props.mapStyle.name}
|
||||||
|
@ -71,10 +72,17 @@ class SettingsModal extends React.Component {
|
||||||
/>
|
/>
|
||||||
</InputBlock>
|
</InputBlock>
|
||||||
|
|
||||||
<InputBlock label={"Access Token"} doc={"Public access token for Mapbox GL."}>
|
<InputBlock label={"Mapbox Access Token"} doc={"Public access token for Mapbox services."}>
|
||||||
<StringInput {...inputProps}
|
<StringInput {...inputProps}
|
||||||
value={metadata['maputnik:access_token']}
|
value={metadata['maputnik:mapbox_access_token']}
|
||||||
onChange={this.changeMetadataProperty.bind(this, "maputnik:access_token")}
|
onChange={this.changeMetadataProperty.bind(this, "maputnik:mapbox_access_token")}
|
||||||
|
/>
|
||||||
|
</InputBlock>
|
||||||
|
|
||||||
|
<InputBlock label={"OpenMapTiles Access Token"} doc={"Public access token for the OpenMapTiles CDN."}>
|
||||||
|
<StringInput {...inputProps}
|
||||||
|
value={metadata['maputnik:openmaptiles_access_token']}
|
||||||
|
onChange={this.changeMetadataProperty.bind(this, "maputnik:openmaptiles_access_token")}
|
||||||
/>
|
/>
|
||||||
</InputBlock>
|
</InputBlock>
|
||||||
|
|
||||||
|
@ -88,6 +96,7 @@ class SettingsModal extends React.Component {
|
||||||
onChange={this.changeMetadataProperty.bind(this, 'maputnik:renderer')}
|
onChange={this.changeMetadataProperty.bind(this, 'maputnik:renderer')}
|
||||||
/>
|
/>
|
||||||
</InputBlock>
|
</InputBlock>
|
||||||
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
4
src/config/tokens.json
Normal file
4
src/config/tokens.json
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"mapbox": "pk.eyJ1IjoibW9yZ2Vua2FmZmVlIiwiYSI6ImNpeHJmNXNmZTAwNHIycXBid2NqdTJibjMifQ.Dv1-GDpTWi0NP6xW9Fct1w",
|
||||||
|
"openmaptiles": "Og58UhhtiiTaLVlPtPgs"
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import spec from 'mapbox-gl-style-spec/reference/latest.min.js'
|
import spec from 'mapbox-gl-style-spec/reference/latest.min.js'
|
||||||
import derefLayers from 'mapbox-gl-style-spec/lib/deref'
|
import derefLayers from 'mapbox-gl-style-spec/lib/deref'
|
||||||
|
import tokens from '../config/tokens.json'
|
||||||
|
|
||||||
// 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 = ensureStyleValidity({
|
const emptyStyle = ensureStyleValidity({
|
||||||
|
@ -19,6 +20,20 @@ function ensureHasId(style) {
|
||||||
return style
|
return style
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ensureHasNoInteractive(style) {
|
||||||
|
const changedLayers = style.layers.map(layer => {
|
||||||
|
const changedLayer = { ...layer }
|
||||||
|
delete changedLayer.interactive
|
||||||
|
return changedLayer
|
||||||
|
})
|
||||||
|
|
||||||
|
const nonInteractiveStyle = {
|
||||||
|
...style,
|
||||||
|
layers: changedLayers
|
||||||
|
}
|
||||||
|
return nonInteractiveStyle
|
||||||
|
}
|
||||||
|
|
||||||
function ensureHasNoRefs(style) {
|
function ensureHasNoRefs(style) {
|
||||||
const derefedStyle = {
|
const derefedStyle = {
|
||||||
...style,
|
...style,
|
||||||
|
@ -28,7 +43,7 @@ function ensureHasNoRefs(style) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function ensureStyleValidity(style) {
|
function ensureStyleValidity(style) {
|
||||||
return ensureHasNoRefs(ensureHasId(style))
|
return ensureHasNoInteractive(ensureHasNoRefs(ensureHasId(style)))
|
||||||
}
|
}
|
||||||
|
|
||||||
function indexOfLayer(layers, layerId) {
|
function indexOfLayer(layers, layerId) {
|
||||||
|
@ -40,9 +55,32 @@ function indexOfLayer(layers, layerId) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function replaceAccessToken(mapStyle) {
|
||||||
|
const omtSource = mapStyle.sources.openmaptiles
|
||||||
|
if(!omtSource) return mapStyle
|
||||||
|
|
||||||
|
const metadata = mapStyle.metadata || {}
|
||||||
|
const accessToken = metadata['maputnik:openmaptiles_access_token'] || tokens.openmaptiles
|
||||||
|
const changedSources = {
|
||||||
|
...mapStyle.sources,
|
||||||
|
openmaptiles: {
|
||||||
|
...omtSource,
|
||||||
|
url: omtSource.url.replace('{key}', accessToken)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const changedStyle = {
|
||||||
|
...mapStyle,
|
||||||
|
glyphs: mapStyle.glyphs.replace('{key}', accessToken),
|
||||||
|
sources: changedSources
|
||||||
|
}
|
||||||
|
|
||||||
|
return changedStyle
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
ensureStyleValidity,
|
ensureStyleValidity,
|
||||||
emptyStyle,
|
emptyStyle,
|
||||||
indexOfLayer,
|
indexOfLayer,
|
||||||
generateId,
|
generateId,
|
||||||
|
replaceAccessToken,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue