Merge pull request #352 from orangemug/feature/add-thunderforest-source-v2

Added thunderforest source
This commit is contained in:
Orange Mug
2018-08-01 20:48:12 +01:00
committed by GitHub
8 changed files with 77 additions and 18 deletions
+2 -2
View File
@@ -22,7 +22,7 @@ import SurveyModal from './modals/SurveyModal'
import { downloadGlyphsMetadata, downloadSpriteMetadata } from '../libs/metadata' import { downloadGlyphsMetadata, downloadSpriteMetadata } from '../libs/metadata'
import * as styleSpec from '@mapbox/mapbox-gl-style-spec/style-spec' import * as styleSpec from '@mapbox/mapbox-gl-style-spec/style-spec'
import style from '../libs/style.js' import style from '../libs/style'
import { initialStyleUrl, loadStyleUrl } from '../libs/urlopen' import { initialStyleUrl, loadStyleUrl } from '../libs/urlopen'
import { undoMessages, redoMessages } from '../libs/diffmessage' import { undoMessages, redoMessages } from '../libs/diffmessage'
import { loadDefaultStyle, StyleStore } from '../libs/stylestore' import { loadDefaultStyle, StyleStore } from '../libs/stylestore'
@@ -407,7 +407,7 @@ export default class App extends React.Component {
mapRenderer() { mapRenderer() {
const mapProps = { const mapProps = {
mapStyle: style.replaceAccessToken(this.state.mapStyle, {allowFallback: true}), mapStyle: style.replaceAccessTokens(this.state.mapStyle, {allowFallback: true}),
options: this.state.mapOptions, options: this.state.mapOptions,
onDataChange: (e) => { onDataChange: (e) => {
this.layerWatcher.analyzeMap(e.map) this.layerWatcher.analyzeMap(e.map)
+9 -3
View File
@@ -10,7 +10,7 @@ import Button from '../Button'
import Modal from './Modal' import Modal from './Modal'
import MdFileDownload from 'react-icons/lib/md/file-download' import MdFileDownload from 'react-icons/lib/md/file-download'
import TiClipboard from 'react-icons/lib/ti/clipboard' import TiClipboard from 'react-icons/lib/ti/clipboard'
import style from '../../libs/style.js' import style from '../../libs/style'
import GitHub from 'github-api' import GitHub from 'github-api'
import { CopyToClipboard } from 'react-copy-to-clipboard' import { CopyToClipboard } from 'react-copy-to-clipboard'
@@ -49,7 +49,7 @@ class Gist extends React.Component {
const mapboxToken = (this.props.mapStyle.metadata || {})['maputnik:mapbox_access_token']; const mapboxToken = (this.props.mapStyle.metadata || {})['maputnik:mapbox_access_token'];
const mapStyleStr = preview ? const mapStyleStr = preview ?
styleSpec.format(stripAccessTokens(style.replaceAccessToken(this.props.mapStyle))) : styleSpec.format(stripAccessTokens(style.replaceAccessTokens(this.props.mapStyle))) :
styleSpec.format(stripAccessTokens(this.props.mapStyle)); styleSpec.format(stripAccessTokens(this.props.mapStyle));
const styleTitle = this.props.mapStyle.name || 'Style'; const styleTitle = this.props.mapStyle.name || 'Style';
const htmlStr = ` const htmlStr = `
@@ -235,7 +235,7 @@ class ExportModal extends React.Component {
} }
downloadStyle() { downloadStyle() {
const tokenStyle = styleSpec.format(stripAccessTokens(style.replaceAccessToken(this.props.mapStyle))); const tokenStyle = styleSpec.format(stripAccessTokens(style.replaceAccessTokens(this.props.mapStyle)));
const blob = new Blob([tokenStyle], {type: "application/json;charset=utf-8"}); const blob = new Blob([tokenStyle], {type: "application/json;charset=utf-8"});
saveAs(blob, this.props.mapStyle.id + ".json"); saveAs(blob, this.props.mapStyle.id + ".json");
@@ -280,6 +280,12 @@ class ExportModal extends React.Component {
onChange={this.changeMetadataProperty.bind(this, "maputnik:mapbox_access_token")} onChange={this.changeMetadataProperty.bind(this, "maputnik:mapbox_access_token")}
/> />
</InputBlock> </InputBlock>
<InputBlock label={"Thunderforest Access Token: "}>
<StringInput
value={(this.props.mapStyle.metadata || {})['maputnik:thunderforest_access_token']}
onChange={this.changeMetadataProperty.bind(this, "maputnik:thunderforest_access_token")}
/>
</InputBlock>
</p> </p>
<Button onClick={this.downloadStyle.bind(this)}> <Button onClick={this.downloadStyle.bind(this)}>
+8
View File
@@ -94,6 +94,14 @@ class SettingsModal extends React.Component {
/> />
</InputBlock> </InputBlock>
<InputBlock label={"Thunderforest Access Token"} doc={"Public access token for Thunderforest services."}>
<StringInput {...inputProps}
data-wd-key="modal-settings.maputnik:thunderforest_access_token"
value={metadata['maputnik:thunderforest_access_token']}
onChange={this.changeMetadataProperty.bind(this, "maputnik:thunderforest_access_token")}
/>
</InputBlock>
<InputBlock label={"Style Renderer"} doc={"Choose the default Maputnik renderer for this style."}> <InputBlock label={"Style Renderer"} doc={"Choose the default Maputnik renderer for this style."}>
<SelectInput {...inputProps} <SelectInput {...inputProps}
data-wd-key="modal-settings.maputnik:renderer" data-wd-key="modal-settings.maputnik:renderer"
+4 -1
View File
@@ -236,9 +236,12 @@ class SourcesModal extends React.Component {
<p> <p>
Add one of the publicly available sources to your style. Add one of the publicly available sources to your style.
</p> </p>
<div style={{maxwidth: 500}}> <div className="maputnik-public-sources" style={{maxwidth: 500}}>
{tilesetOptions} {tilesetOptions}
</div> </div>
<p>
<strong>Note:</strong> Some of the tilesets are not optimised for online use, and as a result the file sizes of the tiles can be quite large (heavy) for online vector rendering. Please review any tilesets before use.
</p>
</div> </div>
<div className="maputnik-modal-section"> <div className="maputnik-modal-section">
+10
View File
@@ -8,5 +8,15 @@
"type": "vector", "type": "vector",
"url": "https://free.tilehosting.com/data/v3.json?key={key}", "url": "https://free.tilehosting.com/data/v3.json?key={key}",
"title": "OpenMapTiles" "title": "OpenMapTiles"
},
"thunderforest_transport": {
"type": "vector",
"url": "https://tile.thunderforest.com/thunderforest.transport-v1.json?apikey={key}",
"title": "Thunderforest Transport (heavy)"
},
"thunderforest_outdoors": {
"type": "vector",
"url": "https://tile.thunderforest.com/thunderforest.outdoors-v1.json?apikey={key}",
"title": "Thunderforest Outdoors (heavy)"
} }
} }
+2 -1
View File
@@ -1,4 +1,5 @@
{ {
"mapbox": "pk.eyJ1IjoibW9yZ2Vua2FmZmVlIiwiYSI6ImNpeHJmNXNmZTAwNHIycXBid2NqdTJibjMifQ.Dv1-GDpTWi0NP6xW9Fct1w", "mapbox": "pk.eyJ1IjoibW9yZ2Vua2FmZmVlIiwiYSI6ImNpeHJmNXNmZTAwNHIycXBid2NqdTJibjMifQ.Dv1-GDpTWi0NP6xW9Fct1w",
"openmaptiles": "Og58UhhtiiTaLVlPtPgs" "openmaptiles": "Og58UhhtiiTaLVlPtPgs",
"thunderforest": "b71f7f0ba4064f5eb9e903859a9cf5c6"
} }
+37 -11
View File
@@ -54,18 +54,28 @@ function indexOfLayer(layers, layerId) {
return null return null
} }
function replaceAccessToken(mapStyle, opts={}) { function getAccessToken(key, mapStyle, opts) {
const omtSource = mapStyle.sources.openmaptiles if(key === "thunderforest_transport" || key === "thunderforest_outdoors") {
if(!omtSource) return mapStyle key = "thunderforest";
if(!omtSource.hasOwnProperty("url")) return mapStyle }
const metadata = mapStyle.metadata || {} const metadata = mapStyle.metadata || {}
let accessToken = metadata['maputnik:openmaptiles_access_token']; let accessToken = metadata['maputnik:'+key+'_access_token'];
if(opts.allowFallback && !accessToken) { if(opts.allowFallback && !accessToken) {
accessToken = tokens.openmaptiles; accessToken = tokens[key];
} }
return accessToken;
}
function replaceSourceAccessToken(mapStyle, key, opts={}) {
const source = mapStyle.sources[key]
if(!source) return mapStyle
if(!source.hasOwnProperty("url")) return mapStyle
const accessToken = getAccessToken(key, mapStyle, opts)
if(!accessToken) { if(!accessToken) {
// Early exit. // Early exit.
return mapStyle; return mapStyle;
@@ -73,24 +83,40 @@ function replaceAccessToken(mapStyle, opts={}) {
const changedSources = { const changedSources = {
...mapStyle.sources, ...mapStyle.sources,
openmaptiles: { [key]: {
...omtSource, ...source,
url: omtSource.url.replace('{key}', accessToken) url: source.url.replace('{key}', accessToken)
} }
} }
const changedStyle = { const changedStyle = {
...mapStyle, ...mapStyle,
glyphs: mapStyle.glyphs ? mapStyle.glyphs.replace('{key}', accessToken) : mapStyle.glyphs,
sources: changedSources sources: changedSources
} }
return changedStyle return changedStyle
} }
function replaceAccessTokens(mapStyle, opts={}) {
let changedStyle = mapStyle;
Object.keys(mapStyle.sources).forEach((tokenKey) => {
changedStyle = replaceSourceAccessToken(changedStyle, tokenKey, opts);
})
if(mapStyle.glyphs && mapStyle.glyphs.match(/\.tileserver\.org/)) {
changedStyle = {
...changedStyle,
glyphs: mapStyle.glyphs ? mapStyle.glyphs.replace('{key}', getAccessToken("openmaptiles", mapStyle, opts)) : mapStyle.glyphs
}
}
return changedStyle
}
export default { export default {
ensureStyleValidity, ensureStyleValidity,
emptyStyle, emptyStyle,
indexOfLayer, indexOfLayer,
generateId, generateId,
replaceAccessToken, replaceAccessTokens,
} }
+5
View File
@@ -125,6 +125,10 @@
} }
//SOURCE MODAL //SOURCE MODAL
.maputnik-public-sources {
margin-bottom: 1.5%;
}
.maputnik-public-source { .maputnik-public-source {
vertical-align: top; vertical-align: top;
margin-top: 1.5%; margin-top: 1.5%;
@@ -150,6 +154,7 @@
.maputnik-public-source-id { .maputnik-public-source-id {
font-weight: 400; font-weight: 400;
text-align: left;
} }
.maputnik-active-source-type-editor { .maputnik-active-source-type-editor {