mirror of
https://github.com/a-nyx/maputnik-with-pmtiles.git
synced 2024-11-10 09:57:45 +01:00
Restructure and rename components
This commit is contained in:
parent
461a001552
commit
fde60ac3e0
46 changed files with 365 additions and 425 deletions
|
@ -35,7 +35,6 @@
|
||||||
"react-color": "^2.10.0",
|
"react-color": "^2.10.0",
|
||||||
"react-dom": "^15.4.0",
|
"react-dom": "^15.4.0",
|
||||||
"react-file-reader-input": "^1.1.0",
|
"react-file-reader-input": "^1.1.0",
|
||||||
"react-height": "^2.1.1",
|
|
||||||
"react-icon-base": "^2.0.4",
|
"react-icon-base": "^2.0.4",
|
||||||
"react-icons": "^2.2.1",
|
"react-icons": "^2.2.1",
|
||||||
"react-simpletabs": "^0.7.0",
|
"react-simpletabs": "^0.7.0",
|
||||||
|
|
|
@ -6,19 +6,19 @@ import Container from 'rebass/dist/Container'
|
||||||
import Block from 'rebass/dist/Block'
|
import Block from 'rebass/dist/Block'
|
||||||
import Fixed from 'rebass/dist/Fixed'
|
import Fixed from 'rebass/dist/Fixed'
|
||||||
|
|
||||||
import { MapboxGlMap } from './gl.jsx'
|
import MapboxGlMap from './map/MapboxGlMap.jsx'
|
||||||
import { OpenLayers3Map } from './ol3.jsx'
|
import OpenLayers3Map from './map/OpenLayers3Map.jsx'
|
||||||
import { LayerList } from './layers/list.jsx'
|
import LayerList from './layers/LayerList.jsx'
|
||||||
import { LayerEditor } from './layers/editor.jsx'
|
import LayerEditor from './layers/LayerEditor.jsx'
|
||||||
import {Toolbar} from './toolbar.jsx'
|
import Toolbar from './Toolbar.jsx'
|
||||||
import style from './style.js'
|
|
||||||
import { loadDefaultStyle, SettingsStore, StyleStore } from './stylestore.js'
|
|
||||||
import { ApiStyleStore } from './apistore.js'
|
|
||||||
|
|
||||||
import LayerWatcher from './layerwatcher.js'
|
import style from '../libs/style.js'
|
||||||
import theme from './theme.js'
|
import { loadDefaultStyle, SettingsStore, StyleStore } from '../libs/stylestore.js'
|
||||||
import { colors, fullHeight } from './theme.js'
|
import { ApiStyleStore } from '../libs/apistore.js'
|
||||||
import './index.css'
|
import LayerWatcher from '../libs/layerwatcher.js'
|
||||||
|
|
||||||
|
import theme from '../config/rebass.js'
|
||||||
|
import colors from '../config/colors.js'
|
||||||
|
|
||||||
export default class App extends React.Component {
|
export default class App extends React.Component {
|
||||||
static childContextTypes = {
|
static childContextTypes = {
|
||||||
|
@ -160,7 +160,7 @@ export default class App extends React.Component {
|
||||||
width: 300,
|
width: 300,
|
||||||
backgroundColor: colors.gray}
|
backgroundColor: colors.gray}
|
||||||
}>
|
}>
|
||||||
{selectedLayer && <LayerEditor layer={selectedLayer} onLayerChanged={this.onLayerChanged.bind(this)} sources={this.layerWatcher.sources}/>}
|
{selectedLayer && <LayerEditor layer={selectedLayer} onLayerChanged={this.onLayerChanged.bind(this)} sources={this.layerWatcher.sources} vectorLayers={this.layerWatcher.vectorLayers}/>}
|
||||||
</div>
|
</div>
|
||||||
{this.mapRenderer()}
|
{this.mapRenderer()}
|
||||||
</div>
|
</div>
|
|
@ -1,5 +1,4 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import theme from './theme.js'
|
|
||||||
import scrollbars from './scrollbars.scss'
|
import scrollbars from './scrollbars.scss'
|
||||||
|
|
||||||
const ScrollContainer = (props) => {
|
const ScrollContainer = (props) => {
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react'
|
||||||
import Immutable from 'immutable'
|
import Immutable from 'immutable'
|
||||||
import FileReaderInput from 'react-file-reader-input';
|
import FileReaderInput from 'react-file-reader-input'
|
||||||
|
|
||||||
import Button from 'rebass/dist/Button'
|
import Button from 'rebass/dist/Button'
|
||||||
import Text from 'rebass/dist/Text'
|
import Text from 'rebass/dist/Text'
|
||||||
|
@ -25,17 +25,17 @@ import MdFontDownload from 'react-icons/lib/md/font-download'
|
||||||
import MdHelpOutline from 'react-icons/lib/md/help-outline'
|
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/settings.jsx'
|
import SettingsModal from './modals/SettingsModal'
|
||||||
import TilesetsModal from './modals/tilesets.jsx'
|
import TilesetsModal from './modals/TilesetsModal'
|
||||||
import style from './style.js'
|
|
||||||
import { fullHeight } from './theme.js'
|
import style from '../libs/style'
|
||||||
import theme from './theme.js';
|
import colors from '../config/colors';
|
||||||
|
|
||||||
const InlineBlock = props => <div style={{display: "inline-block", ...props.style}}>
|
const InlineBlock = props => <div style={{display: "inline-block", ...props.style}}>
|
||||||
{props.children}
|
{props.children}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
export class Toolbar extends React.Component {
|
export default class Toolbar extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
mapStyle: React.PropTypes.instanceOf(Immutable.Map).isRequired,
|
mapStyle: React.PropTypes.instanceOf(Immutable.Map).isRequired,
|
||||||
onStyleChanged: React.PropTypes.func.isRequired,
|
onStyleChanged: React.PropTypes.func.isRequired,
|
||||||
|
@ -107,7 +107,7 @@ export class Toolbar extends React.Component {
|
||||||
zIndex: 100,
|
zIndex: 100,
|
||||||
left: 0,
|
left: 0,
|
||||||
top: 0,
|
top: 0,
|
||||||
backgroundColor: theme.colors.black
|
backgroundColor: colors.black
|
||||||
}}>
|
}}>
|
||||||
<SettingsModal
|
<SettingsModal
|
||||||
mapStyle={this.props.mapStyle}
|
mapStyle={this.props.mapStyle}
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import inputStyle from './input.js'
|
import input from '../../config/input.js'
|
||||||
|
|
||||||
class BooleanField extends React.Component {
|
class BooleanField extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
@ -14,7 +14,7 @@ class BooleanField extends React.Component {
|
||||||
return <input
|
return <input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
style={{
|
style={{
|
||||||
...inputStyle.checkbox,
|
...input.checkbox,
|
||||||
...this.props.style
|
...this.props.style
|
||||||
}}
|
}}
|
||||||
value={this.props.value}
|
value={this.props.value}
|
|
@ -1,8 +1,9 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Color from 'color'
|
import Color from 'color'
|
||||||
import inputStyle from './input.js'
|
|
||||||
import ChromePicker from 'react-color/lib/components/chrome/Chrome'
|
import ChromePicker from 'react-color/lib/components/chrome/Chrome'
|
||||||
|
|
||||||
|
import input from '../../config/input.js'
|
||||||
|
|
||||||
function formatColor(color) {
|
function formatColor(color) {
|
||||||
const rgb = color.rgb
|
const rgb = color.rgb
|
||||||
return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${rgb.a})`
|
return `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${rgb.a})`
|
||||||
|
@ -53,7 +54,7 @@ class ColorField extends React.Component {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
return <div style={{
|
return <div style={{
|
||||||
...inputStyle.property,
|
...input.property,
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
display: 'inline',
|
display: 'inline',
|
||||||
}}>
|
}}>
|
||||||
|
@ -61,7 +62,7 @@ class ColorField extends React.Component {
|
||||||
<input
|
<input
|
||||||
onClick={this.togglePicker.bind(this)}
|
onClick={this.togglePicker.bind(this)}
|
||||||
style={{
|
style={{
|
||||||
...inputStyle.select,
|
...input.select,
|
||||||
...this.props.style
|
...this.props.style
|
||||||
}}
|
}}
|
||||||
name={this.props.name}
|
name={this.props.name}
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import inputStyle from './input.js'
|
import input from '../../config/input.js'
|
||||||
|
|
||||||
class EnumField extends React.Component {
|
class EnumField extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
@ -22,7 +22,7 @@ class EnumField extends React.Component {
|
||||||
|
|
||||||
return <select
|
return <select
|
||||||
style={{
|
style={{
|
||||||
...inputStyle.select,
|
...input.select,
|
||||||
...this.props.style
|
...this.props.style
|
||||||
}}
|
}}
|
||||||
value={this.props.value}
|
value={this.props.value}
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import inputStyle from './input.js'
|
import input from '../../config/input.js'
|
||||||
|
|
||||||
/*** Number fields with support for min, max and units and documentation*/
|
/*** Number fields with support for min, max and units and documentation*/
|
||||||
class NumberField extends React.Component {
|
class NumberField extends React.Component {
|
||||||
|
@ -27,7 +27,7 @@ class NumberField extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return <input
|
return <input
|
||||||
style={{
|
style={{
|
||||||
...inputStyle.input,
|
...input.input,
|
||||||
...this.props.style
|
...this.props.style
|
||||||
}}
|
}}
|
||||||
type="number"
|
type="number"
|
|
@ -1,11 +1,13 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { ZoomSpecField } from './spec.jsx'
|
|
||||||
import Immutable from 'immutable'
|
import Immutable from 'immutable'
|
||||||
import GlSpec from 'mapbox-gl-style-spec/reference/latest.min.js'
|
import GlSpec from 'mapbox-gl-style-spec/reference/latest.min.js'
|
||||||
import theme from '../theme.js'
|
|
||||||
|
|
||||||
console.log(ZoomSpecField)
|
import ZoomSpecField from './ZoomSpecField'
|
||||||
|
import colors from '../../config/colors'
|
||||||
|
import { margins } from '../../config/scales'
|
||||||
|
|
||||||
|
/** Extract field spec by {@fieldName} from the {@layerType} in the
|
||||||
|
* style specification from either the paint or layout group */
|
||||||
function getFieldSpec(layerType, fieldName) {
|
function getFieldSpec(layerType, fieldName) {
|
||||||
const paint = GlSpec['paint_' + layerType] || {}
|
const paint = GlSpec['paint_' + layerType] || {}
|
||||||
const layout = GlSpec['layout_' + layerType] || {}
|
const layout = GlSpec['layout_' + layerType] || {}
|
||||||
|
@ -25,10 +27,8 @@ export default class PropertyGroup extends React.Component {
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const fields = this.props.groupFields.map(fieldName => {
|
const fields = this.props.groupFields.map(fieldName => {
|
||||||
console.log(fieldName)
|
|
||||||
const fieldSpec = getFieldSpec(this.props.layer.get('type'), fieldName)
|
const fieldSpec = getFieldSpec(this.props.layer.get('type'), fieldName)
|
||||||
const fieldValue = this.props.layer.getIn(['paint', fieldName], this.props.layer.getIn(['layout', fieldName]))
|
const fieldValue = this.props.layer.getIn(['paint', fieldName], this.props.layer.getIn(['layout', fieldName]))
|
||||||
|
|
||||||
return <ZoomSpecField
|
return <ZoomSpecField
|
||||||
onChange={this.props.onChange}
|
onChange={this.props.onChange}
|
||||||
key={fieldName}
|
key={fieldName}
|
||||||
|
@ -39,10 +39,10 @@ export default class PropertyGroup extends React.Component {
|
||||||
}).toIndexedSeq()
|
}).toIndexedSeq()
|
||||||
|
|
||||||
return <div style={{
|
return <div style={{
|
||||||
padding: theme.scale[2],
|
padding: margins[2],
|
||||||
paddingRight: 0,
|
paddingRight: 0,
|
||||||
backgroundColor: theme.colors.black,
|
backgroundColor: colors.black,
|
||||||
marginBottom: theme.scale[2],
|
marginBottom: margins[2],
|
||||||
}}>
|
}}>
|
||||||
{fields}
|
{fields}
|
||||||
</div>
|
</div>
|
|
@ -3,87 +3,19 @@ import Immutable from 'immutable'
|
||||||
import color from 'color'
|
import color from 'color'
|
||||||
|
|
||||||
import GlSpec from 'mapbox-gl-style-spec/reference/latest.min.js'
|
import GlSpec from 'mapbox-gl-style-spec/reference/latest.min.js'
|
||||||
import NumberField from './number'
|
import NumberField from './NumberField'
|
||||||
import EnumField from './enum'
|
import EnumField from './EnumField'
|
||||||
import BooleanField from './boolean'
|
import BooleanField from './BooleanField'
|
||||||
import ColorField from './color'
|
import ColorField from './ColorField'
|
||||||
import StringField from './string'
|
import StringField from './StringField'
|
||||||
import inputStyle from './input.js'
|
|
||||||
import theme from '../theme.js'
|
import input from '../../config/input.js'
|
||||||
|
import theme from '../../config/rebass.js'
|
||||||
|
|
||||||
function isZoomField(value) {
|
function isZoomField(value) {
|
||||||
return Immutable.Map.isMap(value)
|
return Immutable.Map.isMap(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
const specFieldProps = {
|
|
||||||
onChange: React.PropTypes.func.isRequired,
|
|
||||||
fieldName: React.PropTypes.string.isRequired,
|
|
||||||
fieldSpec: React.PropTypes.object.isRequired,
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Supports displaying spec field for zoom function objects
|
|
||||||
* https://www.mapbox.com/mapbox-gl-style-spec/#types-function-zoom-property
|
|
||||||
*/
|
|
||||||
export class ZoomSpecField extends React.Component {
|
|
||||||
static propTypes = {
|
|
||||||
...specFieldProps,
|
|
||||||
value: React.PropTypes.oneOfType([
|
|
||||||
React.PropTypes.object,
|
|
||||||
React.PropTypes.string,
|
|
||||||
React.PropTypes.number,
|
|
||||||
React.PropTypes.bool,
|
|
||||||
]),
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const label = <label style={inputStyle.label}>
|
|
||||||
{labelFromFieldName(this.props.fieldName)}
|
|
||||||
</label>
|
|
||||||
|
|
||||||
if(isZoomField(this.props.value)) {
|
|
||||||
const zoomFields = this.props.value.get('stops').map(stop => {
|
|
||||||
const zoomLevel = stop.get(0)
|
|
||||||
const value = stop.get(1)
|
|
||||||
|
|
||||||
return <div style={inputStyle.property} key={zoomLevel}>
|
|
||||||
{label}
|
|
||||||
<SpecField {...this.props}
|
|
||||||
value={value}
|
|
||||||
style={{
|
|
||||||
width: '33%'
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<input
|
|
||||||
style={{
|
|
||||||
...inputStyle.input,
|
|
||||||
width: '10%',
|
|
||||||
marginLeft: theme.scale[0],
|
|
||||||
}}
|
|
||||||
type="number"
|
|
||||||
value={zoomLevel}
|
|
||||||
min={0}
|
|
||||||
max={22}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
}).toSeq()
|
|
||||||
return <div style={{
|
|
||||||
border: 1,
|
|
||||||
borderStyle: 'solid',
|
|
||||||
borderColor: color(theme.colors.gray).lighten(0.1).string(),
|
|
||||||
padding: theme.scale[1],
|
|
||||||
}}>
|
|
||||||
{zoomFields}
|
|
||||||
</div>
|
|
||||||
} else {
|
|
||||||
return <div style={inputStyle.property}>
|
|
||||||
{label}
|
|
||||||
<SpecField {...this.props} />
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function labelFromFieldName(fieldName) {
|
function labelFromFieldName(fieldName) {
|
||||||
let label = fieldName.split('-').slice(1).join(' ')
|
let label = fieldName.split('-').slice(1).join(' ')
|
||||||
if(label.length > 0) {
|
if(label.length > 0) {
|
||||||
|
@ -92,13 +24,15 @@ function labelFromFieldName(fieldName) {
|
||||||
return label
|
return label
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Display any field from the Mapbox GL style spec and
|
/** Display any field from the Mapbox GL style spec and
|
||||||
* choose the correct field component based on the @{fieldSpec}
|
* choose the correct field component based on the @{fieldSpec}
|
||||||
* to display @{value}. */
|
* to display @{value}. */
|
||||||
class SpecField extends React.Component {
|
export default class SpecField extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
...specFieldProps,
|
onChange: React.PropTypes.func.isRequired,
|
||||||
|
fieldName: React.PropTypes.string.isRequired,
|
||||||
|
fieldSpec: React.PropTypes.object.isRequired,
|
||||||
|
|
||||||
value: React.PropTypes.oneOfType([
|
value: React.PropTypes.oneOfType([
|
||||||
React.PropTypes.string,
|
React.PropTypes.string,
|
||||||
React.PropTypes.number,
|
React.PropTypes.number,
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import inputStyle from './input.js'
|
import input from '../../config/input.js'
|
||||||
|
|
||||||
/*** Number fields with support for min, max and units and documentation*/
|
/*** Number fields with support for min, max and units and documentation*/
|
||||||
class StringField extends React.Component {
|
class StringField extends React.Component {
|
||||||
|
@ -20,7 +20,7 @@ class StringField extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return <input
|
return <input
|
||||||
style={{
|
style={{
|
||||||
...inputStyle.input,
|
...input.input,
|
||||||
...this.props.style
|
...this.props.style
|
||||||
}}
|
}}
|
||||||
name={this.props.name}
|
name={this.props.name}
|
98
src/components/fields/ZoomSpecField.jsx
Normal file
98
src/components/fields/ZoomSpecField.jsx
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
import React from 'react'
|
||||||
|
import Immutable from 'immutable'
|
||||||
|
import Color from 'color'
|
||||||
|
|
||||||
|
import NumberField from './NumberField'
|
||||||
|
import EnumField from './EnumField'
|
||||||
|
import BooleanField from './BooleanField'
|
||||||
|
import ColorField from './ColorField'
|
||||||
|
import StringField from './StringField'
|
||||||
|
import SpecField from './SpecField'
|
||||||
|
|
||||||
|
import input from '../../config/input.js'
|
||||||
|
import colors from '../../config/colors.js'
|
||||||
|
import { margins } from '../../config/scales.js'
|
||||||
|
|
||||||
|
function isZoomField(value) {
|
||||||
|
return Immutable.Map.isMap(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
const specFieldProps = {
|
||||||
|
onChange: React.PropTypes.func.isRequired,
|
||||||
|
fieldName: React.PropTypes.string.isRequired,
|
||||||
|
fieldSpec: React.PropTypes.object.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Supports displaying spec field for zoom function objects
|
||||||
|
* https://www.mapbox.com/mapbox-gl-style-spec/#types-function-zoom-property
|
||||||
|
*/
|
||||||
|
export default class ZoomSpecField extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
onChange: React.PropTypes.func.isRequired,
|
||||||
|
fieldName: React.PropTypes.string.isRequired,
|
||||||
|
fieldSpec: React.PropTypes.object.isRequired,
|
||||||
|
|
||||||
|
value: React.PropTypes.oneOfType([
|
||||||
|
React.PropTypes.object,
|
||||||
|
React.PropTypes.string,
|
||||||
|
React.PropTypes.number,
|
||||||
|
React.PropTypes.bool,
|
||||||
|
]),
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const label = <label style={input.label}>
|
||||||
|
{labelFromFieldName(this.props.fieldName)}
|
||||||
|
</label>
|
||||||
|
|
||||||
|
if(isZoomField(this.props.value)) {
|
||||||
|
const zoomFields = this.props.value.get('stops').map(stop => {
|
||||||
|
const zoomLevel = stop.get(0)
|
||||||
|
const value = stop.get(1)
|
||||||
|
|
||||||
|
return <div style={input.property} key={zoomLevel}>
|
||||||
|
{label}
|
||||||
|
<SpecField {...this.props}
|
||||||
|
value={value}
|
||||||
|
style={{
|
||||||
|
width: '33%'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<input
|
||||||
|
style={{
|
||||||
|
...input.input,
|
||||||
|
width: '10%',
|
||||||
|
marginLeft: margins[0],
|
||||||
|
}}
|
||||||
|
type="number"
|
||||||
|
value={zoomLevel}
|
||||||
|
min={0}
|
||||||
|
max={22}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
}).toSeq()
|
||||||
|
return <div style={{
|
||||||
|
border: 1,
|
||||||
|
borderStyle: 'solid',
|
||||||
|
borderColor: Color(colors.gray).lighten(0.1).string(),
|
||||||
|
padding: margins[1],
|
||||||
|
}}>
|
||||||
|
{zoomFields}
|
||||||
|
</div>
|
||||||
|
} else {
|
||||||
|
return <div style={input.property}>
|
||||||
|
{label}
|
||||||
|
<SpecField {...this.props} />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function labelFromFieldName(fieldName) {
|
||||||
|
let label = fieldName.split('-').slice(1).join(' ')
|
||||||
|
if(label.length > 0) {
|
||||||
|
label = label.charAt(0).toUpperCase() + label.slice(1);
|
||||||
|
}
|
||||||
|
return label
|
||||||
|
}
|
|
@ -1,10 +1,11 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Immutable from 'immutable'
|
import Immutable from 'immutable'
|
||||||
import { PropertyGroup } from '../fields/spec'
|
|
||||||
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import GlSpec from 'mapbox-gl-style-spec/reference/latest.min.js'
|
import GlSpec from 'mapbox-gl-style-spec/reference/latest.min.js'
|
||||||
import inputStyle from '../fields/input.js'
|
|
||||||
import theme from '../theme.js'
|
import input from '../../config/input.js'
|
||||||
|
import colors from '../../config/colors.js'
|
||||||
|
import { margins } from '../../config/scales.js'
|
||||||
|
|
||||||
const combiningFilterOps = ['all', 'any', 'none']
|
const combiningFilterOps = ['all', 'any', 'none']
|
||||||
const setFilterOps = ['in', '!in']
|
const setFilterOps = ['in', '!in']
|
||||||
|
@ -26,9 +27,9 @@ class CombiningOperatorSelect extends React.Component {
|
||||||
return <div>
|
return <div>
|
||||||
<select
|
<select
|
||||||
style={{
|
style={{
|
||||||
...inputStyle.select,
|
...input.select,
|
||||||
width: '20.5%',
|
width: '20.5%',
|
||||||
margin: theme.scale[0],
|
margin: margins[0],
|
||||||
}}
|
}}
|
||||||
value={this.props.value}
|
value={this.props.value}
|
||||||
onChange={e => this.props.onChange(e.target.value)}
|
onChange={e => this.props.onChange(e.target.value)}
|
||||||
|
@ -36,9 +37,9 @@ class CombiningOperatorSelect extends React.Component {
|
||||||
{options}
|
{options}
|
||||||
</select>
|
</select>
|
||||||
<label style={{
|
<label style={{
|
||||||
...inputStyle.label,
|
...input.label,
|
||||||
width: '60%',
|
width: '60%',
|
||||||
marginLeft: theme.scale[0],
|
marginLeft: margins[0],
|
||||||
}}>
|
}}>
|
||||||
of the filters matches
|
of the filters matches
|
||||||
</label>
|
</label>
|
||||||
|
@ -58,9 +59,9 @@ class OperatorSelect extends React.Component {
|
||||||
})
|
})
|
||||||
return <select
|
return <select
|
||||||
style={{
|
style={{
|
||||||
...inputStyle.select,
|
...input.select,
|
||||||
width: '15%',
|
width: '15%',
|
||||||
margin: theme.scale[0]
|
margin: margins[0]
|
||||||
}}
|
}}
|
||||||
value={this.props.value}
|
value={this.props.value}
|
||||||
onChange={e => this.props.onChange(e.target.value)}
|
onChange={e => this.props.onChange(e.target.value)}
|
||||||
|
@ -74,6 +75,7 @@ class SingleFilterEditor extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
filter: React.PropTypes.array.isRequired,
|
filter: React.PropTypes.array.isRequired,
|
||||||
onChange: React.PropTypes.func.isRequired,
|
onChange: React.PropTypes.func.isRequired,
|
||||||
|
properties: React.PropTypes.instanceOf(Immutable.Map).isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
onFilterPartChanged(filterOp, propertyName, filterArgs) {
|
onFilterPartChanged(filterOp, propertyName, filterArgs) {
|
||||||
|
@ -88,24 +90,28 @@ class SingleFilterEditor extends React.Component {
|
||||||
const filterArgs = f.slice(2)
|
const filterArgs = f.slice(2)
|
||||||
|
|
||||||
return <div>
|
return <div>
|
||||||
<input
|
<select
|
||||||
style={{
|
style={{
|
||||||
...inputStyle.input,
|
...input.select,
|
||||||
width: '17%',
|
width: '17%',
|
||||||
margin: theme.scale[0]
|
margin: margins[0]
|
||||||
}}
|
}}
|
||||||
value={propertyName}
|
value={propertyName}
|
||||||
onChange={newPropertyName => this.onFilterPartChanged(filterOp, newPropertyName, filterArgs)}
|
onChange={newPropertyName => this.onFilterPartChanged(filterOp, newPropertyName, filterArgs)}
|
||||||
/>
|
>
|
||||||
|
{this.props.properties.keySeq().map(propName => {
|
||||||
|
return <option key={propName} value={propName}>{propName}</option>
|
||||||
|
}).toIndexedSeq()}
|
||||||
|
</select>
|
||||||
<OperatorSelect
|
<OperatorSelect
|
||||||
value={filterOp}
|
value={filterOp}
|
||||||
onChange={newFilterOp => this.onFilterPartChanged(newFilterOp, propertyName, filterArgs)}
|
onChange={newFilterOp => this.onFilterPartChanged(newFilterOp, propertyName, filterArgs)}
|
||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
style={{
|
style={{
|
||||||
...inputStyle.input,
|
...input.input,
|
||||||
width: '53%',
|
width: '53%',
|
||||||
margin: theme.scale[0]
|
margin: margins[0]
|
||||||
}}
|
}}
|
||||||
value={filterArgs.join(',')}
|
value={filterArgs.join(',')}
|
||||||
onChange={e => {
|
onChange={e => {
|
||||||
|
@ -118,6 +124,8 @@ class SingleFilterEditor extends React.Component {
|
||||||
|
|
||||||
export default class CombiningFilterEditor extends React.Component {
|
export default class CombiningFilterEditor extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
/** Properties of the vector layer and the available fields */
|
||||||
|
properties: React.PropTypes.instanceOf(Immutable.Map).isRequired,
|
||||||
filter: React.PropTypes.array.isRequired,
|
filter: React.PropTypes.array.isRequired,
|
||||||
onChange: React.PropTypes.func.isRequired,
|
onChange: React.PropTypes.func.isRequired,
|
||||||
}
|
}
|
||||||
|
@ -154,15 +162,16 @@ export default class CombiningFilterEditor extends React.Component {
|
||||||
const filterEditors = filters.map((f, idx) => {
|
const filterEditors = filters.map((f, idx) => {
|
||||||
return <SingleFilterEditor
|
return <SingleFilterEditor
|
||||||
key={idx}
|
key={idx}
|
||||||
|
properties={this.props.properties}
|
||||||
filter={f}
|
filter={f}
|
||||||
onChange={this.onFilterPartChanged.bind(this, idx + 1)}
|
onChange={this.onFilterPartChanged.bind(this, idx + 1)}
|
||||||
/>
|
/>
|
||||||
})
|
})
|
||||||
|
|
||||||
return <div style={{
|
return <div style={{
|
||||||
padding: theme.scale[2],
|
padding: margins[2],
|
||||||
paddingRight: 0,
|
paddingRight: 0,
|
||||||
backgroundColor: theme.colors.black
|
backgroundColor: colors.black
|
||||||
}}>
|
}}>
|
||||||
<CombiningOperatorSelect
|
<CombiningOperatorSelect
|
||||||
value={combiningOp}
|
value={combiningOp}
|
26
src/components/icons/LayerIcon.jsx
Normal file
26
src/components/icons/LayerIcon.jsx
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
import LineIcon from './LineIcon.jsx'
|
||||||
|
import FillIcon from './FillIcon.jsx'
|
||||||
|
import SymbolIcon from './SymbolIcon.jsx'
|
||||||
|
import BackgroundIcon from './BackgroundIcon.jsx'
|
||||||
|
|
||||||
|
class LayerIcon extends React.Component {
|
||||||
|
static propTypes = {
|
||||||
|
type: React.PropTypes.string.isRequired,
|
||||||
|
style: React.PropTypes.object,
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const iconProps = { style: this.props.style }
|
||||||
|
switch(this.props.type) {
|
||||||
|
case 'fill': return <FillIcon {...iconProps} />
|
||||||
|
case 'background': return <BackgroundIcon {...iconProps} />
|
||||||
|
case 'line': return <LineIcon {...iconProps} />
|
||||||
|
case 'symbol': return <SymbolIcon {...iconProps} />
|
||||||
|
default: return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LayerIcon
|
|
@ -6,18 +6,19 @@ import NavItem from 'rebass/dist/NavItem'
|
||||||
import Space from 'rebass/dist/Space'
|
import Space from 'rebass/dist/Space'
|
||||||
import Tabs from 'react-simpletabs'
|
import Tabs from 'react-simpletabs'
|
||||||
|
|
||||||
import theme from '../theme.js'
|
import SourceEditor from './SourceEditor'
|
||||||
import SourceEditor from './source.jsx'
|
import FilterEditor from '../filter/FilterEditor'
|
||||||
import FilterEditor from '../filter/editor.jsx'
|
import PropertyGroup from '../fields/PropertyGroup'
|
||||||
import PropertyGroup from '../fields/propertygroup.jsx'
|
|
||||||
|
|
||||||
import MdVisibility from 'react-icons/lib/md/visibility'
|
import MdVisibility from 'react-icons/lib/md/visibility'
|
||||||
import MdVisibilityOff from 'react-icons/lib/md/visibility-off'
|
import MdVisibilityOff from 'react-icons/lib/md/visibility-off'
|
||||||
import MdDelete from 'react-icons/lib/md/delete'
|
import MdDelete from 'react-icons/lib/md/delete'
|
||||||
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
|
|
||||||
import ScrollContainer from '../scrollcontainer.jsx'
|
import ScrollContainer from '../ScrollContainer'
|
||||||
import layout from '../layout.json'
|
|
||||||
|
import layout from '../../config/layout.json'
|
||||||
|
import theme from '../../config/rebass.js'
|
||||||
|
|
||||||
class UnsupportedLayer extends React.Component {
|
class UnsupportedLayer extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
|
@ -26,10 +27,11 @@ class UnsupportedLayer extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Layer editor supporting multiple types of layers. */
|
/** Layer editor supporting multiple types of layers. */
|
||||||
export class LayerEditor extends React.Component {
|
export default class LayerEditor extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
layer: React.PropTypes.object.isRequired,
|
layer: React.PropTypes.object.isRequired,
|
||||||
sources: React.PropTypes.instanceOf(Immutable.Map),
|
sources: React.PropTypes.instanceOf(Immutable.Map),
|
||||||
|
vectorLayers: React.PropTypes.instanceOf(Immutable.Map),
|
||||||
onLayerChanged: React.PropTypes.func,
|
onLayerChanged: React.PropTypes.func,
|
||||||
onLayerDestroyed: React.PropTypes.func,
|
onLayerDestroyed: React.PropTypes.func,
|
||||||
}
|
}
|
||||||
|
@ -82,12 +84,14 @@ export class LayerEditor extends React.Component {
|
||||||
const groups = layout[layerType].groups
|
const groups = layout[layerType].groups
|
||||||
const propertyGroups = groups.map(group => {
|
const propertyGroups = groups.map(group => {
|
||||||
return <PropertyGroup
|
return <PropertyGroup
|
||||||
|
key={this.props.group}
|
||||||
layer={this.props.layer}
|
layer={this.props.layer}
|
||||||
groupFields={Immutable.OrderedSet(group.fields)}
|
groupFields={Immutable.OrderedSet(group.fields)}
|
||||||
onChange={this.onPropertyChange.bind(this)}
|
onChange={this.onPropertyChange.bind(this)}
|
||||||
/>
|
/>
|
||||||
})
|
})
|
||||||
|
|
||||||
|
console.log(this.props.layer.toJSON())
|
||||||
let visibleIcon = <MdVisibilityOff />
|
let visibleIcon = <MdVisibilityOff />
|
||||||
if(this.props.layer.has('layout') && this.props.layer.getIn(['layout', 'visibility']) === 'none') {
|
if(this.props.layer.has('layout') && this.props.layer.getIn(['layout', 'visibility']) === 'none') {
|
||||||
visibleIcon = <MdVisibility />
|
visibleIcon = <MdVisibility />
|
||||||
|
@ -110,6 +114,7 @@ export class LayerEditor extends React.Component {
|
||||||
{propertyGroups}
|
{propertyGroups}
|
||||||
<FilterEditor
|
<FilterEditor
|
||||||
filter={this.props.layer.get('filter', Immutable.List()).toJSON()}
|
filter={this.props.layer.get('filter', Immutable.List()).toJSON()}
|
||||||
|
properties={this.props.vectorLayers.get(this.props.layer.get('source-layer'))}
|
||||||
onChange={f => this.onFilterChange(Immutable.fromJS(f))}
|
onChange={f => this.onFilterChange(Immutable.fromJS(f))}
|
||||||
/>
|
/>
|
||||||
{this.props.layer.get('type') !== 'background'
|
{this.props.layer.get('type') !== 'background'
|
|
@ -1,4 +1,5 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import Immutable from 'immutable'
|
import Immutable from 'immutable'
|
||||||
|
|
||||||
import Heading from 'rebass/dist/Heading'
|
import Heading from 'rebass/dist/Heading'
|
||||||
|
@ -6,11 +7,10 @@ import Toolbar from 'rebass/dist/Toolbar'
|
||||||
import NavItem from 'rebass/dist/NavItem'
|
import NavItem from 'rebass/dist/NavItem'
|
||||||
import Space from 'rebass/dist/Space'
|
import Space from 'rebass/dist/Space'
|
||||||
|
|
||||||
import { LayerEditor } from './editor.jsx'
|
import LayerListItem from './LayerListItem'
|
||||||
import LayerListItem from './listitem.jsx'
|
import ScrollContainer from '../ScrollContainer'
|
||||||
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
|
||||||
import theme from '../theme.js'
|
import { margins } from '../../config/scales.js'
|
||||||
import ScrollContainer from '../scrollcontainer.jsx'
|
|
||||||
|
|
||||||
import {SortableContainer, SortableHandle, arrayMove} from 'react-sortable-hoc';
|
import {SortableContainer, SortableHandle, arrayMove} from 'react-sortable-hoc';
|
||||||
|
|
||||||
|
@ -55,14 +55,14 @@ class LayerListContainer extends React.Component {
|
||||||
/>
|
/>
|
||||||
})
|
})
|
||||||
return <ScrollContainer>
|
return <ScrollContainer>
|
||||||
<ul style={{ padding: theme.scale[1], margin: 0 }}>
|
<ul style={{ padding: margins[1], margin: 0 }}>
|
||||||
{layerPanels}
|
{layerPanels}
|
||||||
</ul>
|
</ul>
|
||||||
</ScrollContainer>
|
</ScrollContainer>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class LayerList extends React.Component {
|
export default class LayerList extends React.Component {
|
||||||
static propTypes = {...layerListPropTypes}
|
static propTypes = {...layerListPropTypes}
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
|
@ -1,4 +1,5 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import PureRenderMixin from 'react-addons-pure-render-mixin'
|
||||||
import Radium from 'radium'
|
import Radium from 'radium'
|
||||||
import Immutable from 'immutable'
|
import Immutable from 'immutable'
|
||||||
import Color from 'color'
|
import Color from 'color'
|
||||||
|
@ -8,12 +9,12 @@ import Toolbar from 'rebass/dist/Toolbar'
|
||||||
import NavItem from 'rebass/dist/NavItem'
|
import NavItem from 'rebass/dist/NavItem'
|
||||||
import Space from 'rebass/dist/Space'
|
import Space from 'rebass/dist/Space'
|
||||||
|
|
||||||
import LayerIcon from '../icons/layer.jsx'
|
import LayerIcon from '../icons/LayerIcon'
|
||||||
import { LayerEditor } from './editor.jsx'
|
import LayerEditor from './LayerEditor'
|
||||||
import scrollbars from '../scrollbars.scss'
|
import {SortableElement, SortableHandle} from 'react-sortable-hoc'
|
||||||
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
|
||||||
import theme from '../theme.js'
|
import colors from '../../config/colors.js'
|
||||||
import {SortableElement, SortableHandle} from 'react-sortable-hoc';
|
import { fontSizes, margins } from '../../config/scales.js'
|
||||||
|
|
||||||
|
|
||||||
@SortableHandle
|
@SortableHandle
|
||||||
|
@ -48,8 +49,8 @@ class LayerListItem extends React.Component {
|
||||||
onClick={() => this.props.onLayerSelected(this.props.layerId)}
|
onClick={() => this.props.onLayerSelected(this.props.layerId)}
|
||||||
style={{
|
style={{
|
||||||
fontWeight: 400,
|
fontWeight: 400,
|
||||||
color: theme.colors.lowgray,
|
color: colors.lowgray,
|
||||||
fontSize: theme.fontSizes[5],
|
fontSize: fontSizes[5],
|
||||||
borderBottom: 1,
|
borderBottom: 1,
|
||||||
borderLeft: 2,
|
borderLeft: 2,
|
||||||
borderRight: 0,
|
borderRight: 0,
|
||||||
|
@ -59,11 +60,11 @@ class LayerListItem extends React.Component {
|
||||||
zIndex: 2000,
|
zIndex: 2000,
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
padding: theme.scale[1],
|
padding: margins[1],
|
||||||
borderColor: Color(theme.colors.gray).lighten(0.1).string(),
|
borderColor: Color(colors.gray).lighten(0.1).string(),
|
||||||
backgroundColor: theme.colors.gray,
|
backgroundColor: colors.gray,
|
||||||
":hover": {
|
":hover": {
|
||||||
backgroundColor: Color(theme.colors.gray).lighten(0.15).string(),
|
backgroundColor: Color(colors.gray).lighten(0.15).string(),
|
||||||
}
|
}
|
||||||
}}>
|
}}>
|
||||||
<LayerTypeDragHandle type={this.props.layerType} />
|
<LayerTypeDragHandle type={this.props.layerType} />
|
|
@ -1,8 +1,9 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Immutable from 'immutable'
|
|
||||||
import { PropertyGroup } from '../fields/spec'
|
|
||||||
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
||||||
import inputStyle from '../fields/input.js'
|
import Immutable from 'immutable'
|
||||||
|
|
||||||
|
import PropertyGroup from '../fields/PropertyGroup'
|
||||||
|
import input from '../../config/input.js'
|
||||||
|
|
||||||
/** Choose tileset (source) and the source layer */
|
/** Choose tileset (source) and the source layer */
|
||||||
export default class SourceEditor extends React.Component {
|
export default class SourceEditor extends React.Component {
|
||||||
|
@ -33,22 +34,21 @@ export default class SourceEditor extends React.Component {
|
||||||
return <option key={id} value={id}>{id}</option>
|
return <option key={id} value={id}>{id}</option>
|
||||||
}).toIndexedSeq()
|
}).toIndexedSeq()
|
||||||
|
|
||||||
console.log(this.props.sources)
|
|
||||||
return <div>
|
return <div>
|
||||||
<div style={inputStyle.property}>
|
<div style={input.property}>
|
||||||
<label style={inputStyle.label}>Source</label>
|
<label style={input.label}>Source</label>
|
||||||
<select
|
<select
|
||||||
style={inputStyle.select}
|
style={input.select}
|
||||||
value={this.props.source}
|
value={this.props.source}
|
||||||
onChange={(e) => this.onSourceChange(e.target.value)}
|
onChange={(e) => this.onSourceChange(e.target.value)}
|
||||||
>
|
>
|
||||||
{options}
|
{options}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div style={inputStyle.property}>
|
<div style={input.property}>
|
||||||
<label style={inputStyle.label}>Source Layer</label>
|
<label style={input.label}>Source Layer</label>
|
||||||
<select
|
<select
|
||||||
style={inputStyle.select}
|
style={input.select}
|
||||||
value={this.props.sourceLayer}
|
value={this.props.sourceLayer}
|
||||||
onChange={(e) => this.onSourceLayerChange(e.target.value)}
|
onChange={(e) => this.onSourceLayerChange(e.target.value)}
|
||||||
>
|
>
|
|
@ -1,8 +1,7 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { fullHeight } from './theme.js'
|
|
||||||
import Immutable from 'immutable'
|
import Immutable from 'immutable'
|
||||||
|
|
||||||
export class Map extends React.Component {
|
export default class Map extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
mapStyle: React.PropTypes.instanceOf(Immutable.Map).isRequired,
|
mapStyle: React.PropTypes.instanceOf(Immutable.Map).isRequired,
|
||||||
accessToken: React.PropTypes.string,
|
accessToken: React.PropTypes.string,
|
||||||
|
@ -17,7 +16,10 @@ export class Map extends React.Component {
|
||||||
return <div
|
return <div
|
||||||
ref={x => this.container = x}
|
ref={x => this.container = x}
|
||||||
style={{
|
style={{
|
||||||
...fullHeight,
|
position: "fixed",
|
||||||
|
top: 0,
|
||||||
|
bottom: 0,
|
||||||
|
height: "100%",
|
||||||
width: "100%",
|
width: "100%",
|
||||||
}}></div>
|
}}></div>
|
||||||
}
|
}
|
|
@ -1,12 +1,11 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import MapboxGl from 'mapbox-gl'
|
import MapboxGl from 'mapbox-gl'
|
||||||
import { fullHeight } from './theme.js'
|
|
||||||
import style from './style.js'
|
|
||||||
import { Map } from './map.jsx'
|
|
||||||
import Immutable from 'immutable'
|
|
||||||
import validateColor from 'mapbox-gl-style-spec/lib/validate/validate_color'
|
import validateColor from 'mapbox-gl-style-spec/lib/validate/validate_color'
|
||||||
|
|
||||||
export class MapboxGlMap extends Map {
|
import Map from './Map.jsx'
|
||||||
|
import style from '../../libs/style.js'
|
||||||
|
|
||||||
|
export default class MapboxGlMap extends Map {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
onMapLoaded: React.PropTypes.func,
|
onMapLoaded: React.PropTypes.func,
|
||||||
}
|
}
|
|
@ -1,10 +1,11 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import style from './style.js'
|
|
||||||
import { Map } from './map.jsx'
|
|
||||||
import ol from 'openlayers'
|
import ol from 'openlayers'
|
||||||
import olms from 'ol-mapbox-style'
|
import olms from 'ol-mapbox-style'
|
||||||
|
|
||||||
export class OpenLayers3Map extends Map {
|
import Map from './Map'
|
||||||
|
import style from '../../libs/style.js'
|
||||||
|
|
||||||
|
export default class OpenLayers3Map extends Map {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
|
|
|
@ -14,8 +14,8 @@ import Input from 'rebass/dist/Input'
|
||||||
import Toolbar from 'rebass/dist/Toolbar'
|
import Toolbar from 'rebass/dist/Toolbar'
|
||||||
import NavItem from 'rebass/dist/NavItem'
|
import NavItem from 'rebass/dist/NavItem'
|
||||||
|
|
||||||
import publicTilesets from '../tilesets.json'
|
import publicTilesets from '../../config/tilesets.json'
|
||||||
import theme from '../theme.js'
|
import theme from '../../config/rebass'
|
||||||
|
|
||||||
class TilesetsModal extends React.Component {
|
class TilesetsModal extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
29
src/config/colors.js
Normal file
29
src/config/colors.js
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
const baseColors = {
|
||||||
|
black: '#1c1f24',
|
||||||
|
gray: '#26282e',
|
||||||
|
midgray: '#36383e',
|
||||||
|
lowgray: '#8e8e8e',
|
||||||
|
|
||||||
|
white: '#fff',
|
||||||
|
blue: '#00d9f7',
|
||||||
|
green: '#B4C7AD',
|
||||||
|
orange: '#fb3',
|
||||||
|
red: '#f04',
|
||||||
|
}
|
||||||
|
|
||||||
|
const themeColors = {
|
||||||
|
primary: baseColors.gray,
|
||||||
|
secondary: baseColors.midgray,
|
||||||
|
default: baseColors.gray,
|
||||||
|
info: baseColors.blue,
|
||||||
|
success: baseColors.green,
|
||||||
|
warning: baseColors.orange,
|
||||||
|
error: baseColors.red
|
||||||
|
}
|
||||||
|
|
||||||
|
const colors = {
|
||||||
|
...baseColors,
|
||||||
|
...themeColors
|
||||||
|
}
|
||||||
|
|
||||||
|
export default colors
|
|
@ -1,6 +1,4 @@
|
||||||
/** Common input styling */
|
import theme from './rebass.js'
|
||||||
|
|
||||||
import theme from '../theme.js'
|
|
||||||
|
|
||||||
const base = {
|
const base = {
|
||||||
display: 'inline-block',
|
display: 'inline-block',
|
66
src/config/rebass.js
Normal file
66
src/config/rebass.js
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
import colors from './colors'
|
||||||
|
import { margins, fontSizes } from './scales'
|
||||||
|
|
||||||
|
const border = {
|
||||||
|
borderColor: colors.black,
|
||||||
|
borderRadius: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
const dark = {
|
||||||
|
name: 'Dark',
|
||||||
|
color: colors.white,
|
||||||
|
fontFamily: 'Roboto, sans-serif',
|
||||||
|
scale: margins,
|
||||||
|
fontSizes: fontSizes,
|
||||||
|
colors,
|
||||||
|
inverted: colors.midGray,
|
||||||
|
...border,
|
||||||
|
|
||||||
|
Block: {
|
||||||
|
backgroundColor: colors.gray,
|
||||||
|
...border,
|
||||||
|
borderLeft: 0,
|
||||||
|
borderRight: 0,
|
||||||
|
marginBottom: 0,
|
||||||
|
paddingBottom: 0,
|
||||||
|
},
|
||||||
|
PanelHeader: {
|
||||||
|
marginRight: -10,
|
||||||
|
marginBottom: 0,
|
||||||
|
fontSize: fontSizes[5],
|
||||||
|
fontWeight: 400,
|
||||||
|
color: colors.white,
|
||||||
|
},
|
||||||
|
Panel: {
|
||||||
|
backgroundColor: colors.gray,
|
||||||
|
},
|
||||||
|
Button: {
|
||||||
|
color: '#00d9f7',
|
||||||
|
},
|
||||||
|
Menu: {
|
||||||
|
color: '#00d9f7',
|
||||||
|
backgroundColor: '#000'
|
||||||
|
},
|
||||||
|
Message: {
|
||||||
|
color: '#111',
|
||||||
|
opacity: 15/16
|
||||||
|
},
|
||||||
|
Header: {
|
||||||
|
fontWeight: 400,
|
||||||
|
},
|
||||||
|
ButtonCircle : {
|
||||||
|
},
|
||||||
|
Toolbar: {
|
||||||
|
fontWeight: 400,
|
||||||
|
minHeight: margins[3]
|
||||||
|
},
|
||||||
|
Label: {
|
||||||
|
fontWeight: 300,
|
||||||
|
},
|
||||||
|
Input: {
|
||||||
|
fontWeight: 300,
|
||||||
|
fontSize: fontSizes[5],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default dark
|
2
src/config/scales.js
Normal file
2
src/config/scales.js
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export const margins = [3, 5, 10, 30, 40]
|
||||||
|
export const fontSizes = [26, 20, 16, 14, 12, 10]
|
|
@ -1,35 +0,0 @@
|
||||||
import React from 'react'
|
|
||||||
|
|
||||||
import LineIcon from './line.jsx'
|
|
||||||
import FillIcon from './fill.jsx'
|
|
||||||
import SymbolIcon from './symbol.jsx'
|
|
||||||
import BackgroundIcon from './background.jsx'
|
|
||||||
|
|
||||||
class LayerIcon extends React.Component {
|
|
||||||
static propTypes = {
|
|
||||||
type: React.PropTypes.string.isRequired,
|
|
||||||
style: React.PropTypes.object,
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
if (this.props.type === "fill") {
|
|
||||||
return <FillIcon style={this.props.style} />
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.props.type === "background") {
|
|
||||||
return <BackgroundIcon style={this.props.style} />
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.props.type === "line") {
|
|
||||||
return <LineIcon style={this.props.style} />
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.props.type === "symbol") {
|
|
||||||
return <SymbolIcon style={this.props.style} />
|
|
||||||
}
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default LayerIcon
|
|
|
@ -1,6 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
|
|
||||||
import App from './app.jsx';
|
import './index.css'
|
||||||
|
import App from './components/App';
|
||||||
|
|
||||||
ReactDOM.render(<App/>, document.querySelector("#app"));
|
ReactDOM.render(<App/>, document.querySelector("#app"));
|
||||||
|
|
|
@ -1,79 +0,0 @@
|
||||||
import React from 'react'
|
|
||||||
import theme from './theme.js'
|
|
||||||
|
|
||||||
import Heading from 'rebass/dist/Heading'
|
|
||||||
import Container from 'rebass/dist/Container'
|
|
||||||
import Input from 'rebass/dist/Input'
|
|
||||||
import Toolbar from 'rebass/dist/Toolbar'
|
|
||||||
import NavItem from 'rebass/dist/NavItem'
|
|
||||||
import Space from 'rebass/dist/Space'
|
|
||||||
import Button from 'rebass/dist/Button'
|
|
||||||
|
|
||||||
import Immutable from 'immutable'
|
|
||||||
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
|
||||||
|
|
||||||
/** Edit global settings within a style such as the name */
|
|
||||||
export class SettingsEditor extends React.Component {
|
|
||||||
static propTypes = {
|
|
||||||
mapStyle: React.PropTypes.instanceOf(Immutable.Map).isRequired,
|
|
||||||
onStyleChanged: React.PropTypes.func.isRequired,
|
|
||||||
accessToken: React.PropTypes.string,
|
|
||||||
onAccessTokenChanged: React.PropTypes.func,
|
|
||||||
onReset: React.PropTypes.func
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
onChange(property, e) {
|
|
||||||
const changedStyle = this.props.mapStyle.set(property, e.target.value)
|
|
||||||
this.props.onStyleChanged(changedStyle)
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return <div>
|
|
||||||
<Toolbar style={{marginRight: 20}}>
|
|
||||||
<NavItem>
|
|
||||||
<Heading>Settings</Heading>
|
|
||||||
</NavItem>
|
|
||||||
</Toolbar>
|
|
||||||
<Container>
|
|
||||||
<Input
|
|
||||||
name="access-token"
|
|
||||||
label="Mapbox GL access token"
|
|
||||||
value={this.props.accessToken}
|
|
||||||
onChange={e => this.props.onAccessTokenChanged(e.target.value)}
|
|
||||||
/>
|
|
||||||
<Input
|
|
||||||
name="name"
|
|
||||||
label="Name"
|
|
||||||
value={this.props.mapStyle.get('name')}
|
|
||||||
onChange={this.onChange.bind(this, "name")}
|
|
||||||
/>
|
|
||||||
<Input
|
|
||||||
name="owner"
|
|
||||||
label="Owner"
|
|
||||||
value={this.props.mapStyle.get('owner')}
|
|
||||||
onChange={this.onChange.bind(this, "owner")}
|
|
||||||
/>
|
|
||||||
<Input
|
|
||||||
name="sprite"
|
|
||||||
label="Sprite URL"
|
|
||||||
value={this.props.mapStyle.get('sprite')}
|
|
||||||
onChange={this.onChange.bind(this, "sprite")}
|
|
||||||
/>
|
|
||||||
<Input
|
|
||||||
name="glyphs"
|
|
||||||
label="Glyphs URL"
|
|
||||||
value={this.props.mapStyle.get('glyphs')}
|
|
||||||
onChange={this.onChange.bind(this, "glyphs")}
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
onClick={this.props.onReset}
|
|
||||||
>Reset style</Button>
|
|
||||||
</Container>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
115
src/theme.js
115
src/theme.js
|
@ -1,115 +0,0 @@
|
||||||
const caps = {
|
|
||||||
textTransform: 'uppercase',
|
|
||||||
letterSpacing: '.2em'
|
|
||||||
}
|
|
||||||
|
|
||||||
export const fullHeight = {
|
|
||||||
position: "fixed",
|
|
||||||
top: 0,
|
|
||||||
bottom: 0,
|
|
||||||
height: "100%",
|
|
||||||
}
|
|
||||||
|
|
||||||
const baseColors = {
|
|
||||||
black: '#1c1f24',
|
|
||||||
gray: '#26282e',
|
|
||||||
midgray: '#36383e',
|
|
||||||
lowgray: '#8e8e8e',
|
|
||||||
white: '#fff',
|
|
||||||
blue: '#00d9f7',
|
|
||||||
green: '#B4C7AD',
|
|
||||||
orange: '#fb3',
|
|
||||||
red: '#f04',
|
|
||||||
}
|
|
||||||
|
|
||||||
const themeColors = {
|
|
||||||
primary: baseColors.gray,
|
|
||||||
secondary: baseColors.midgray,
|
|
||||||
default: baseColors.gray,
|
|
||||||
info: baseColors.blue,
|
|
||||||
success: baseColors.green,
|
|
||||||
warning: baseColors.orange,
|
|
||||||
error: baseColors.red
|
|
||||||
}
|
|
||||||
|
|
||||||
export const colors = {
|
|
||||||
...baseColors,
|
|
||||||
...themeColors
|
|
||||||
}
|
|
||||||
|
|
||||||
export const inputBase = {
|
|
||||||
display: 'block',
|
|
||||||
border: '1px solid rgb(36, 36, 36)',
|
|
||||||
height: 30,
|
|
||||||
width: '100%',
|
|
||||||
paddingLeft: 5,
|
|
||||||
paddingRight: 5,
|
|
||||||
backgroundColor: colors.gray,
|
|
||||||
}
|
|
||||||
|
|
||||||
const scale = [3, 5, 10, 30, 40]
|
|
||||||
const fontSizes = [26, 20, 16, 14, 12, 10]
|
|
||||||
|
|
||||||
const border = {
|
|
||||||
borderColor: colors.black,
|
|
||||||
borderRadius: 0,
|
|
||||||
}
|
|
||||||
|
|
||||||
const dark = {
|
|
||||||
name: 'Dark',
|
|
||||||
color: colors.white,
|
|
||||||
fontFamily: 'Roboto, sans-serif',
|
|
||||||
scale,
|
|
||||||
fontSizes,
|
|
||||||
colors,
|
|
||||||
inverted: colors.midGray,
|
|
||||||
...border,
|
|
||||||
|
|
||||||
Block: {
|
|
||||||
backgroundColor: colors.gray,
|
|
||||||
...border,
|
|
||||||
borderLeft: 0,
|
|
||||||
borderRight: 0,
|
|
||||||
marginBottom: 0,
|
|
||||||
paddingBottom: 0,
|
|
||||||
},
|
|
||||||
PanelHeader: {
|
|
||||||
marginRight: -10,
|
|
||||||
marginBottom: 0,
|
|
||||||
fontSize: fontSizes[5],
|
|
||||||
fontWeight: 400,
|
|
||||||
color: colors.white,
|
|
||||||
},
|
|
||||||
Panel: {
|
|
||||||
backgroundColor: colors.gray,
|
|
||||||
},
|
|
||||||
Button: {
|
|
||||||
color: '#00d9f7',
|
|
||||||
},
|
|
||||||
Menu: {
|
|
||||||
color: '#00d9f7',
|
|
||||||
backgroundColor: '#000'
|
|
||||||
},
|
|
||||||
Message: {
|
|
||||||
color: '#111',
|
|
||||||
opacity: 15/16
|
|
||||||
},
|
|
||||||
Header: {
|
|
||||||
fontWeight: 400,
|
|
||||||
},
|
|
||||||
ButtonCircle : {
|
|
||||||
},
|
|
||||||
Toolbar: {
|
|
||||||
fontWeight: 400,
|
|
||||||
minHeight: scale[3]
|
|
||||||
},
|
|
||||||
Label: {
|
|
||||||
fontWeight: 300,
|
|
||||||
},
|
|
||||||
Input: {
|
|
||||||
fontWeight: 300,
|
|
||||||
fontSize: fontSizes[5],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
export default dark
|
|
|
@ -32,15 +32,14 @@ module.exports = {
|
||||||
'mapbox-gl',
|
'mapbox-gl',
|
||||||
//TODO: Cannot resolve migrations file?
|
//TODO: Cannot resolve migrations file?
|
||||||
//"mapbox-gl-style-spec",
|
//"mapbox-gl-style-spec",
|
||||||
|
"radium",
|
||||||
"randomcolor",
|
"randomcolor",
|
||||||
'react',
|
'react',
|
||||||
"react-collapse",
|
|
||||||
"react-dom",
|
"react-dom",
|
||||||
|
"react-color",
|
||||||
"react-file-reader-input",
|
"react-file-reader-input",
|
||||||
"react-height",
|
|
||||||
//TODO: Icons raise multi vendor errors?
|
//TODO: Icons raise multi vendor errors?
|
||||||
//"react-icons",
|
//"react-icons",
|
||||||
"react-motion",
|
|
||||||
"rebass",
|
"rebass",
|
||||||
// Open Layers
|
// Open Layers
|
||||||
'openlayers',
|
'openlayers',
|
||||||
|
|
Loading…
Reference in a new issue