mirror of
https://github.com/a-nyx/maputnik-with-pmtiles.git
synced 2024-12-28 15:31:15 +01:00
Hack on source modal
This commit is contained in:
parent
b55099ea38
commit
ee4bcc4c0b
9 changed files with 213 additions and 62 deletions
30
src/components/Heading.jsx
Normal file
30
src/components/Heading.jsx
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import React from 'react'
|
||||||
|
import { fontSizes } from '../config/scales'
|
||||||
|
|
||||||
|
class Heading extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
level: React.PropTypes.number.isRequired,
|
||||||
|
style: React.PropTypes.object,
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const headingProps = {
|
||||||
|
style: {
|
||||||
|
fontSize: fontSizes[this.props.level - 1],
|
||||||
|
...this.props.style
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(this.props.level) {
|
||||||
|
case 1: return <h1 {...headingProps}>{this.props.children}</h1>
|
||||||
|
case 2: return <h2 {...headingProps}>{this.props.children}</h2>
|
||||||
|
case 3: return <h3 {...headingProps}>{this.props.children}</h3>
|
||||||
|
case 4: return <h4 {...headingProps}>{this.props.children}</h4>
|
||||||
|
case 5: return <h5 {...headingProps}>{this.props.children}</h5>
|
||||||
|
default: return <h6 {...headingProps}>{this.props.children}</h6>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export default Heading
|
|
@ -16,7 +16,7 @@ import MdHelpOutline from 'react-icons/lib/md/help-outline'
|
||||||
import MdFindInPage from 'react-icons/lib/md/find-in-page'
|
import MdFindInPage from 'react-icons/lib/md/find-in-page'
|
||||||
|
|
||||||
import SettingsModal from './modals/SettingsModal'
|
import SettingsModal from './modals/SettingsModal'
|
||||||
import TilesetsModal from './modals/TilesetsModal'
|
import SourcesModal from './modals/SourcesModal'
|
||||||
|
|
||||||
import style from '../libs/style'
|
import style from '../libs/style'
|
||||||
import colors from '../config/colors'
|
import colors from '../config/colors'
|
||||||
|
@ -53,7 +53,7 @@ export default class Toolbar extends React.Component {
|
||||||
super(props)
|
super(props)
|
||||||
this.state = {
|
this.state = {
|
||||||
openSettingsModal: false,
|
openSettingsModal: false,
|
||||||
openTilesetsModal: false,
|
openSourcesModal: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,8 +90,8 @@ export default class Toolbar extends React.Component {
|
||||||
this.setState({openSettingsModal: !this.state.openSettingsModal})
|
this.setState({openSettingsModal: !this.state.openSettingsModal})
|
||||||
}
|
}
|
||||||
|
|
||||||
toggleTilesets() {
|
toggleSources() {
|
||||||
this.setState({openTilesetsModal: !this.state.openTilesetsModal})
|
this.setState({openSourcesModal: !this.state.openSourcesModal})
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -107,14 +107,14 @@ export default class Toolbar extends React.Component {
|
||||||
<SettingsModal
|
<SettingsModal
|
||||||
mapStyle={this.props.mapStyle}
|
mapStyle={this.props.mapStyle}
|
||||||
onStyleChanged={this.props.onStyleChanged}
|
onStyleChanged={this.props.onStyleChanged}
|
||||||
open={this.state.openSettingsModal}
|
isOpen={this.state.openSettingsModal}
|
||||||
toggle={() => this.toggleSettings.bind(this)}
|
toggle={() => this.toggleSettings.bind(this)}
|
||||||
/>
|
/>
|
||||||
<TilesetsModal
|
<SourcesModal
|
||||||
mapStyle={this.props.mapStyle}
|
mapStyle={this.props.mapStyle}
|
||||||
onStyleChanged={this.props.onStyleChanged}
|
onStyleChanged={this.props.onStyleChanged}
|
||||||
open={this.state.openTilesetsModal}
|
isOpen={this.state.openSourcesModal}
|
||||||
toggle={() => this.toggleSettings.bind(this)}
|
toggle={() => this.toggleSources.bind(this)}
|
||||||
/>
|
/>
|
||||||
<ToolbarAction style={{
|
<ToolbarAction style={{
|
||||||
width: 180,
|
width: 180,
|
||||||
|
@ -132,9 +132,9 @@ export default class Toolbar extends React.Component {
|
||||||
</ToolbarAction>
|
</ToolbarAction>
|
||||||
{this.downloadButton()}
|
{this.downloadButton()}
|
||||||
{this.saveButton()}
|
{this.saveButton()}
|
||||||
<ToolbarAction onClick={this.toggleTilesets.bind(this)}>
|
<ToolbarAction onClick={this.toggleSources.bind(this)}>
|
||||||
<MdLayers />
|
<MdLayers />
|
||||||
<IconText>Tilesets</IconText>
|
<IconText>Sources</IconText>
|
||||||
</ToolbarAction>
|
</ToolbarAction>
|
||||||
<ToolbarAction onClick={this.toggleSettings.bind(this)}>
|
<ToolbarAction onClick={this.toggleSettings.bind(this)}>
|
||||||
<MdSettings />
|
<MdSettings />
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import input from '../../config/input'
|
import input from '../../config/input'
|
||||||
|
import { margins } from '../../config/scales'
|
||||||
|
|
||||||
/** Wrap a component with a label */
|
/** Wrap a component with a label */
|
||||||
class InputBlock extends React.Component {
|
class InputBlock extends React.Component {
|
||||||
|
@ -15,7 +16,9 @@ class InputBlock extends React.Component {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return <div style={{
|
return <div style={{
|
||||||
display: 'block'
|
display: 'block',
|
||||||
|
marginTop: margins[2],
|
||||||
|
marginBottom: margins[2],
|
||||||
}}>
|
}}>
|
||||||
<label style={input.label}>{this.props.label}</label>
|
<label style={input.label}>{this.props.label}</label>
|
||||||
{this.props.children}
|
{this.props.children}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import CloseIcon from 'react-icons/lib/md/close'
|
||||||
|
|
||||||
import Overlay from './Overlay'
|
import Overlay from './Overlay'
|
||||||
import colors from '../../config/colors'
|
import colors from '../../config/colors'
|
||||||
import { margins } from '../../config/scales'
|
import { margins, fontSizes } from '../../config/scales'
|
||||||
|
|
||||||
class Modal extends React.Component {
|
class Modal extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
@ -17,17 +17,21 @@ class Modal extends React.Component {
|
||||||
return <Overlay isOpen={this.props.isOpen}>
|
return <Overlay isOpen={this.props.isOpen}>
|
||||||
<div style={{
|
<div style={{
|
||||||
minWidth: 350,
|
minWidth: 350,
|
||||||
|
maxWidth: 600,
|
||||||
backgroundColor: colors.gray,
|
backgroundColor: colors.gray,
|
||||||
}}>
|
}}>
|
||||||
<div style={{
|
<div style={{
|
||||||
backgroundColor: colors.midgray,
|
backgroundColor: colors.midgray,
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'row',
|
flexDirection: 'row',
|
||||||
padding: margins[1]
|
padding: margins[1],
|
||||||
|
fontSize: fontSizes[4],
|
||||||
}}>
|
}}>
|
||||||
{this.props.title}
|
{this.props.title}
|
||||||
<span style={{flexGrow: 1}} />
|
<span style={{flexGrow: 1}} />
|
||||||
<a onClick={this.props.toggleOpen(false)}>
|
<a
|
||||||
|
onClick={this.props.toggleOpen(false)}
|
||||||
|
style={{ cursor: 'pointer' }} >
|
||||||
<CloseIcon />
|
<CloseIcon />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -10,7 +10,7 @@ class SettingsModal extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
mapStyle: React.PropTypes.object.isRequired,
|
mapStyle: React.PropTypes.object.isRequired,
|
||||||
onStyleChanged: React.PropTypes.func.isRequired,
|
onStyleChanged: React.PropTypes.func.isRequired,
|
||||||
open: React.PropTypes.bool.isRequired,
|
isOpen: React.PropTypes.bool.isRequired,
|
||||||
toggle: React.PropTypes.func.isRequired,
|
toggle: React.PropTypes.func.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,11 +31,11 @@ class SettingsModal extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
const inputProps = {
|
const inputProps = {
|
||||||
style: {
|
style: {
|
||||||
backgroundColor: colors.gray
|
backgroundColor: colors.midgray
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return <Modal
|
return <Modal
|
||||||
isOpen={this.props.open}
|
isOpen={this.props.isOpen}
|
||||||
toggleOpen={this.props.toggle}
|
toggleOpen={this.props.toggle}
|
||||||
title={'StyleSettings'}
|
title={'StyleSettings'}
|
||||||
>
|
>
|
||||||
|
|
132
src/components/modals/SourcesModal.jsx
Normal file
132
src/components/modals/SourcesModal.jsx
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
import React from 'react'
|
||||||
|
import Modal from './Modal'
|
||||||
|
import Heading from '../Heading'
|
||||||
|
import InputBlock from '../inputs/InputBlock'
|
||||||
|
import StringInput from '../inputs/StringInput'
|
||||||
|
import publicSources from '../../config/tilesets.json'
|
||||||
|
import colors from '../../config/colors'
|
||||||
|
import { margins } from '../../config/scales'
|
||||||
|
|
||||||
|
class PublicSource extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
id: React.PropTypes.string.isRequired,
|
||||||
|
type: React.PropTypes.string.isRequired,
|
||||||
|
title: React.PropTypes.string.isRequired,
|
||||||
|
description: React.PropTypes.string.isRequired,
|
||||||
|
onSelect: React.PropTypes.func.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return <div style={{
|
||||||
|
verticalAlign: 'top',
|
||||||
|
marginTop: margins[2],
|
||||||
|
marginRight: margins[2],
|
||||||
|
borderColor: colors.midgray,
|
||||||
|
borderStyle: 'solid',
|
||||||
|
borderWidth: 2,
|
||||||
|
display: 'inline-block',
|
||||||
|
width: 240,
|
||||||
|
height: 120,
|
||||||
|
}}>
|
||||||
|
<div style={{
|
||||||
|
backgroundColor: colors.midgray,
|
||||||
|
padding: margins[1],
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
}}>
|
||||||
|
<span>{this.props.title}</span>
|
||||||
|
<span style={{flexGrow: 1}} />
|
||||||
|
<span>#{this.props.id}</span>
|
||||||
|
</div>
|
||||||
|
<div style={{
|
||||||
|
padding: margins[1],
|
||||||
|
}}>
|
||||||
|
<p>{this.props.description}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SourceEditor extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
sourceId: React.PropTypes.string.isRequired,
|
||||||
|
source: React.PropTypes.object.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const inputProps = {
|
||||||
|
style: {
|
||||||
|
backgroundColor: colors.midgray
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return <div style={{
|
||||||
|
}}>
|
||||||
|
<InputBlock label={"Source ID"}>
|
||||||
|
<StringInput {...inputProps}
|
||||||
|
value={this.props.sourceId}
|
||||||
|
/>
|
||||||
|
</InputBlock>
|
||||||
|
<InputBlock label={"Source URL"}>
|
||||||
|
<StringInput {...inputProps}
|
||||||
|
value={this.props.source.url}
|
||||||
|
/>
|
||||||
|
</InputBlock>
|
||||||
|
<InputBlock label={"Source Type"}>
|
||||||
|
<StringInput {...inputProps}
|
||||||
|
value={this.props.source.type}
|
||||||
|
/>
|
||||||
|
</InputBlock>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class SourcesModal extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
mapStyle: React.PropTypes.object.isRequired,
|
||||||
|
isOpen: React.PropTypes.bool.isRequired,
|
||||||
|
toggle: React.PropTypes.func.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const activeSources = Object.keys(this.props.mapStyle.sources).map(sourceId => {
|
||||||
|
const source = this.props.mapStyle.sources[sourceId]
|
||||||
|
return <SourceEditor sourceId={sourceId} source={source} />
|
||||||
|
})
|
||||||
|
|
||||||
|
const tilesetOptions = publicSources.map(tileset => {
|
||||||
|
return <PublicSource
|
||||||
|
id={tileset.id}
|
||||||
|
type={tileset.type}
|
||||||
|
title={tileset.title}
|
||||||
|
description={tileset.description}
|
||||||
|
/>
|
||||||
|
})
|
||||||
|
|
||||||
|
const inputProps = {
|
||||||
|
style: {
|
||||||
|
backgroundColor: colors.midgray
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return <Modal
|
||||||
|
isOpen={this.props.isOpen}
|
||||||
|
toggleOpen={this.props.toggle}
|
||||||
|
title={'Sources'}
|
||||||
|
>
|
||||||
|
<Heading level={4}>Active Sources</Heading>
|
||||||
|
{activeSources}
|
||||||
|
|
||||||
|
<Heading level={4}>Add New Source</Heading>
|
||||||
|
<InputBlock label={"TileJSON URL"}>
|
||||||
|
<StringInput {...inputProps} />
|
||||||
|
</InputBlock>
|
||||||
|
<Heading level={4}>Choose Public Source</Heading>
|
||||||
|
<div style={{maxwidth: 500}}>
|
||||||
|
{tilesetOptions}
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SourcesModal
|
|
@ -1,44 +0,0 @@
|
||||||
import React from 'react'
|
|
||||||
|
|
||||||
import Modal from './Modal'
|
|
||||||
|
|
||||||
import publicTilesets from '../../config/tilesets.json'
|
|
||||||
import colors from '../../config/colors'
|
|
||||||
import { margins } from '../../config/scales'
|
|
||||||
|
|
||||||
class TilesetsModal extends React.Component {
|
|
||||||
static propTypes = {
|
|
||||||
mapStyle: React.PropTypes.object.isRequired,
|
|
||||||
open: React.PropTypes.bool.isRequired,
|
|
||||||
toggle: React.PropTypes.func.isRequired,
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props)
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const tilesetOptions = publicTilesets.map(tileset => {
|
|
||||||
return <div key={tileset.id} style={{
|
|
||||||
padding: margins[0],
|
|
||||||
borderBottom: 1,
|
|
||||||
}}>
|
|
||||||
#{tileset.id}
|
|
||||||
<br />
|
|
||||||
{tileset.url}
|
|
||||||
</div>
|
|
||||||
})
|
|
||||||
|
|
||||||
return <Modal
|
|
||||||
isOpen={this.props.open}
|
|
||||||
toggleOpen={this.props.toggle}
|
|
||||||
title={'Tilesets'}
|
|
||||||
>
|
|
||||||
<h2>Add New Tileset</h2>
|
|
||||||
<h2>Choose Public Tileset</h2>
|
|
||||||
{tilesetOptions}
|
|
||||||
</Modal>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default TilesetsModal
|
|
|
@ -5,5 +5,30 @@
|
||||||
"url": "mapbox://mapbox.mapbox-streets-v7",
|
"url": "mapbox://mapbox.mapbox-streets-v7",
|
||||||
"title": "Mapbox Streets",
|
"title": "Mapbox Streets",
|
||||||
"description": "Mapbox Streets provides a vector tileset for complex general-purpose maps."
|
"description": "Mapbox Streets provides a vector tileset for complex general-purpose maps."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "tilezen",
|
||||||
|
"type": "vector",
|
||||||
|
"tiles": [
|
||||||
|
"http://tile.mapzen.com/mapzen/vector/v1/{layers}/{z}/{x}/{y}.pbf?api_key=mapzen-RVcyVL7"
|
||||||
|
],
|
||||||
|
"minZoom": 0,
|
||||||
|
"maxZoom": 15,
|
||||||
|
"title": "Mapzen",
|
||||||
|
"description": "Mapzen vector tile services"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "openmaptiles",
|
||||||
|
"type": "vector",
|
||||||
|
"url": "https://free.tilehosting.com/data/v3.json?key=25ItXg7aI5wurYDtttD",
|
||||||
|
"title": "OpenMapTiles",
|
||||||
|
"description": "A free vector tile schema for general-purpose maps."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "swissnames-landscape",
|
||||||
|
"type": "geojson",
|
||||||
|
"data": "http://swissnames.lukasmartinelli.ch/data/landscape.geojson",
|
||||||
|
"title": "Geographic Names of Switzerland",
|
||||||
|
"description": "GeoJSON example from https://github.com/lukasmartinelli/swissnames"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -4,8 +4,9 @@
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
.app {
|
|
||||||
|
|
||||||
|
html {
|
||||||
|
font-size: 10px
|
||||||
}
|
}
|
||||||
|
|
||||||
.chrome-picker {
|
.chrome-picker {
|
||||||
|
|
Loading…
Reference in a new issue