mirror of
https://github.com/a-nyx/maputnik-with-pmtiles.git
synced 2025-01-14 14:23:27 +01:00
Switch over to tabs
This commit is contained in:
parent
e27b88c6bc
commit
0e65ac8937
10 changed files with 80 additions and 75 deletions
20
src/app.jsx
20
src/app.jsx
|
@ -12,10 +12,10 @@ import theme from './theme.js'
|
||||||
import layout from './layout.scss'
|
import layout from './layout.scss'
|
||||||
|
|
||||||
export default class App extends React.Component {
|
export default class App extends React.Component {
|
||||||
static childContextTypes = {
|
static childContextTypes = {
|
||||||
rebass: React.PropTypes.object,
|
rebass: React.PropTypes.object,
|
||||||
reactIconBase: React.PropTypes.object
|
reactIconBase: React.PropTypes.object
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
|
@ -26,8 +26,8 @@ export default class App extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getChildContext() {
|
getChildContext() {
|
||||||
return {
|
return {
|
||||||
rebass: theme,
|
rebass: theme,
|
||||||
reactIconBase: { size: 20 }
|
reactIconBase: { size: 20 }
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ export default class App extends React.Component {
|
||||||
|
|
||||||
onStyleDownload() {
|
onStyleDownload() {
|
||||||
this.styleStore.save(newStyle)
|
this.styleStore.save(newStyle)
|
||||||
const mapStyle = JSON.stringify(this.state.currentStyle.toJS(), null, 4)
|
const mapStyle = JSON.stringify(this.state.currentStyle.toJS(), null, 4)
|
||||||
const blob = new Blob([mapStyle], {type: "application/json;charset=utf-8"});
|
const blob = new Blob([mapStyle], {type: "application/json;charset=utf-8"});
|
||||||
saveAs(blob, mapStyle.id + ".json");
|
saveAs(blob, mapStyle.id + ".json");
|
||||||
}
|
}
|
||||||
|
@ -56,15 +56,15 @@ export default class App extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
onOpenSettings() {
|
onOpenSettings() {
|
||||||
this.setState({ workContext: "settings", })
|
this.setState({ workContext: "settings" })
|
||||||
}
|
}
|
||||||
|
|
||||||
onOpenLayers() {
|
onOpenLayers() {
|
||||||
this.setState({ workContext: "layers", })
|
this.setState({ workContext: "layers", })
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return <div style={{ fontFamily: theme.fontFamily, color: theme.color, fontWeight: 300 }}>
|
return <div style={{ fontFamily: theme.fontFamily, color: theme.color, fontWeight: 300 }}>
|
||||||
<Toolbar
|
<Toolbar
|
||||||
styleAvailable={this.state.currentStyle.get('layers').size > 0}
|
styleAvailable={this.state.currentStyle.get('layers').size > 0}
|
||||||
onStyleSave={this.onStyleSave.bind(this)}
|
onStyleSave={this.onStyleSave.bind(this)}
|
||||||
|
@ -82,5 +82,5 @@ export default class App extends React.Component {
|
||||||
<Map mapStyle={this.state.currentStyle} />
|
<Map mapStyle={this.state.currentStyle} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,9 @@ import { Input } from 'rebass'
|
||||||
|
|
||||||
export default class BackgroundLayer extends React.Component {
|
export default class BackgroundLayer extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
layer: React.PropTypes.object.isRequired,
|
layer: React.PropTypes.object.isRequired,
|
||||||
onPaintChanged: React.PropTypes.func.isRequired
|
onPaintChanged: React.PropTypes.func.isRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
onPaintChanged(property, e) {
|
onPaintChanged(property, e) {
|
||||||
let value = e.target.value
|
let value = e.target.value
|
||||||
|
|
|
@ -20,14 +20,14 @@ 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 class LayerEditor extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
layer: React.PropTypes.object.isRequired,
|
layer: React.PropTypes.object.isRequired,
|
||||||
onLayerChanged: React.PropTypes.func.isRequired,
|
onLayerChanged: React.PropTypes.func.isRequired,
|
||||||
onLayerDestroyed: React.PropTypes.func.isRequired,
|
onLayerDestroyed: React.PropTypes.func.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
static childContextTypes = {
|
static childContextTypes = {
|
||||||
reactIconBase: React.PropTypes.object
|
reactIconBase: React.PropTypes.object
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
@ -36,12 +36,12 @@ export class LayerEditor extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getChildContext () {
|
getChildContext () {
|
||||||
return {
|
return {
|
||||||
reactIconBase: {
|
reactIconBase: {
|
||||||
size: theme.fontSizes[4],
|
size: theme.fontSizes[4],
|
||||||
color: theme.colors.lowgray,
|
color: theme.colors.lowgray,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ export class LayerEditor extends React.Component {
|
||||||
</NavItem>
|
</NavItem>
|
||||||
<Space auto x={1} />
|
<Space auto x={1} />
|
||||||
<NavItem onClick={this.toggleVisibility.bind(this)}>
|
<NavItem onClick={this.toggleVisibility.bind(this)}>
|
||||||
{visibleIcon}
|
{visibleIcon}
|
||||||
</NavItem>
|
</NavItem>
|
||||||
<NavItem onClick={(e) => this.props.onLayerDestroyed(this.props.layer)}>
|
<NavItem onClick={(e) => this.props.onLayerDestroyed(this.props.layer)}>
|
||||||
<MdDelete />
|
<MdDelete />
|
||||||
|
|
|
@ -8,8 +8,8 @@ import scrollbars from '../scrollbars.scss'
|
||||||
export class LayerList extends React.Component {
|
export class LayerList extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
layers: React.PropTypes.instanceOf(Immutable.List),
|
layers: React.PropTypes.instanceOf(Immutable.List),
|
||||||
onLayersChanged: React.PropTypes.func.isRequired
|
onLayersChanged: React.PropTypes.func.isRequired
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props)
|
super(props)
|
||||||
|
|
16
src/map.jsx
16
src/map.jsx
|
@ -6,8 +6,8 @@ import Immutable from 'immutable'
|
||||||
|
|
||||||
export class Map extends React.Component {
|
export class Map extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
mapStyle: React.PropTypes.instanceOf(Immutable.Map).isRequired,
|
mapStyle: React.PropTypes.instanceOf(Immutable.Map).isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(nextProps) {
|
componentWillReceiveProps(nextProps) {
|
||||||
// If the id has changed a new style has been uplaoded and
|
// If the id has changed a new style has been uplaoded and
|
||||||
|
@ -31,9 +31,9 @@ export class Map extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps, nextState) {
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
return nextProps.mapStyle !== this.props.mapStyle
|
return nextProps.mapStyle !== this.props.mapStyle
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
//TODO: Read MapboxGL token from settings
|
//TODO: Read MapboxGL token from settings
|
||||||
|
@ -44,9 +44,9 @@ export class Map extends React.Component {
|
||||||
style: this.props.mapStyle.toJS(),
|
style: this.props.mapStyle.toJS(),
|
||||||
});
|
});
|
||||||
|
|
||||||
map.on("style.load", (...args) => {
|
map.on("style.load", (...args) => {
|
||||||
this.setState({ map });
|
this.setState({ map });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
|
|
@ -6,9 +6,9 @@ import Immutable from 'immutable'
|
||||||
/** Edit global settings within a style such as the name */
|
/** Edit global settings within a style such as the name */
|
||||||
export class SettingsEditor extends React.Component {
|
export class SettingsEditor 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
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange(property, e) {
|
onChange(property, e) {
|
||||||
const changedStyle = this.props.mapStyle.set(property, e.target.value)
|
const changedStyle = this.props.mapStyle.set(property, e.target.value)
|
||||||
|
|
42
src/theme.js
42
src/theme.js
|
@ -1,6 +1,6 @@
|
||||||
const caps = {
|
const caps = {
|
||||||
textTransform: 'uppercase',
|
textTransform: 'uppercase',
|
||||||
letterSpacing: '.2em'
|
letterSpacing: '.2em'
|
||||||
}
|
}
|
||||||
|
|
||||||
const baseColors = {
|
const baseColors = {
|
||||||
|
@ -34,22 +34,22 @@ const scale = [3, 5, 10, 30, 40]
|
||||||
const fontSizes = [28, 24, 20, 16, 14, 12, 10]
|
const fontSizes = [28, 24, 20, 16, 14, 12, 10]
|
||||||
|
|
||||||
const border = {
|
const border = {
|
||||||
borderColor: colors.black,
|
borderColor: colors.black,
|
||||||
borderRadius: 0,
|
borderRadius: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
const dark = {
|
const dark = {
|
||||||
name: 'Dark',
|
name: 'Dark',
|
||||||
color: colors.white,
|
color: colors.white,
|
||||||
fontFamily: 'Roboto, sans-serif',
|
fontFamily: 'Roboto, sans-serif',
|
||||||
scale,
|
scale,
|
||||||
fontSizes,
|
fontSizes,
|
||||||
colors,
|
colors,
|
||||||
inverted: colors.midGray,
|
inverted: colors.midGray,
|
||||||
...border,
|
...border,
|
||||||
|
|
||||||
Block: {
|
Block: {
|
||||||
backgroundColor: colors.gray,
|
backgroundColor: colors.gray,
|
||||||
...border,
|
...border,
|
||||||
borderLeft: 0,
|
borderLeft: 0,
|
||||||
borderRight: 0,
|
borderRight: 0,
|
||||||
|
@ -63,17 +63,17 @@ const dark = {
|
||||||
fontWeight: 400,
|
fontWeight: 400,
|
||||||
color: colors.white,
|
color: colors.white,
|
||||||
},
|
},
|
||||||
Button: {
|
Button: {
|
||||||
color: '#00d9f7',
|
color: '#00d9f7',
|
||||||
},
|
},
|
||||||
Menu: {
|
Menu: {
|
||||||
color: '#00d9f7',
|
color: '#00d9f7',
|
||||||
backgroundColor: '#000'
|
backgroundColor: '#000'
|
||||||
},
|
},
|
||||||
Message: {
|
Message: {
|
||||||
color: '#111',
|
color: '#111',
|
||||||
opacity: 15/16
|
opacity: 15/16
|
||||||
},
|
},
|
||||||
Header: {
|
Header: {
|
||||||
fontWeight: 400,
|
fontWeight: 400,
|
||||||
},
|
},
|
||||||
|
|
|
@ -14,25 +14,30 @@ import theme from './theme.js';
|
||||||
|
|
||||||
export class Toolbar extends React.Component {
|
export class Toolbar extends React.Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
onStyleUpload: React.PropTypes.func.isRequired,
|
// A new style has been uploaded
|
||||||
onStyleDownload: React.PropTypes.func.isRequired,
|
onStyleUpload: React.PropTypes.func.isRequired,
|
||||||
onStyleSave: React.PropTypes.func,
|
// Current style is requested for download
|
||||||
onOpenSettings: React.PropTypes.func,
|
onStyleDownload: React.PropTypes.func.isRequired,
|
||||||
onOpenLayers: React.PropTypes.func,
|
// Style is explicitely saved to local cache
|
||||||
|
onStyleSave: React.PropTypes.func,
|
||||||
|
// Open settings drawer
|
||||||
|
onOpenSettings: React.PropTypes.func,
|
||||||
|
// Open layers drawer
|
||||||
|
onOpenLayers: React.PropTypes.func,
|
||||||
// Whether a style is available for download or saving
|
// Whether a style is available for download or saving
|
||||||
// A style with no layers should not be available
|
// A style with no layers should not be available
|
||||||
styleAvailable: React.PropTypes.bool,
|
styleAvailable: React.PropTypes.bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
onUpload(_, files) {
|
onUpload(_, files) {
|
||||||
const [e, file] = files[0];
|
const [e, file] = files[0];
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
reader.readAsText(file, "UTF-8");
|
reader.readAsText(file, "UTF-8");
|
||||||
reader.onload = e => {
|
reader.onload = e => {
|
||||||
const style = JSON.parse(e.target.result);
|
const style = JSON.parse(e.target.result);
|
||||||
this.props.onStyleUpload(style);
|
this.props.onStyleUpload(style);
|
||||||
}
|
}
|
||||||
reader.onerror = e => console.log(e.target);
|
reader.onerror = e => console.log(e.target);
|
||||||
}
|
}
|
||||||
|
|
||||||
saveButton() {
|
saveButton() {
|
||||||
|
@ -72,13 +77,13 @@ export class Toolbar extends React.Component {
|
||||||
backgroundColor: theme.colors.black }
|
backgroundColor: theme.colors.black }
|
||||||
}>
|
}>
|
||||||
<Block>
|
<Block>
|
||||||
<FileReaderInput onChange={this.onUpload.bind(this)}>
|
<FileReaderInput onChange={this.onUpload.bind(this)}>
|
||||||
<Button big={true} theme={this.props.styleAvailable ? "default" : "success"}>
|
<Button big={true} theme={this.props.styleAvailable ? "default" : "success"}>
|
||||||
<Tooltip inverted rounded title="Upload style">
|
<Tooltip inverted rounded title="Upload style">
|
||||||
<MdFileUpload />
|
<MdFileUpload />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Button>
|
</Button>
|
||||||
</FileReaderInput>
|
</FileReaderInput>
|
||||||
</Block>
|
</Block>
|
||||||
{this.downloadButton()}
|
{this.downloadButton()}
|
||||||
{this.saveButton()}
|
{this.saveButton()}
|
||||||
|
@ -86,14 +91,14 @@ export class Toolbar extends React.Component {
|
||||||
<Button big={true} onClick={this.props.onOpenLayers}>
|
<Button big={true} onClick={this.props.onOpenLayers}>
|
||||||
<Tooltip inverted rounded title="Layers">
|
<Tooltip inverted rounded title="Layers">
|
||||||
<MdLayers />
|
<MdLayers />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Button>
|
</Button>
|
||||||
</Block>
|
</Block>
|
||||||
<Block>
|
<Block>
|
||||||
<Button big={true} onClick={this.props.onOpenSettings}>
|
<Button big={true} onClick={this.props.onOpenSettings}>
|
||||||
<Tooltip inverted rounded title="Settings">
|
<Tooltip inverted rounded title="Settings">
|
||||||
<MdSettings />
|
<MdSettings />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Button>
|
</Button>
|
||||||
</Block>
|
</Block>
|
||||||
</Container>
|
</Container>
|
||||||
|
|
|
@ -9,8 +9,8 @@ export class WorkspaceDrawer 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,
|
||||||
workContext: React.PropTypes.oneOf(['layers', 'settings']).isRequired,
|
workContext: React.PropTypes.oneOf(['layers', 'settings']).isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
onLayersChanged(changedLayers) {
|
onLayersChanged(changedLayers) {
|
||||||
const changedStyle = this.props.mapStyle.set('layers', changedLayers)
|
const changedStyle = this.props.mapStyle.set('layers', changedLayers)
|
||||||
|
|
Loading…
Reference in a new issue