Merge pull request #81 from maputnik/default-access-token

Default access token
This commit is contained in:
Lukas Martinelli 2017-01-13 17:01:14 +01:00 committed by GitHub
commit 24dc71344e
7 changed files with 80 additions and 42 deletions

View file

@ -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)}
/> />

View file

@ -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')}
/> />

View file

@ -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

View file

@ -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>

View file

@ -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
View file

@ -0,0 +1,4 @@
{
"mapbox": "pk.eyJ1IjoibW9yZ2Vua2FmZmVlIiwiYSI6ImNpeHJmNXNmZTAwNHIycXBid2NqdTJibjMifQ.Dv1-GDpTWi0NP6xW9Fct1w",
"openmaptiles": "Og58UhhtiiTaLVlPtPgs"
}

View file

@ -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,
} }