diff --git a/.editorconfig b/.editorconfig
index 2b6d1dc3..99557a11 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -5,11 +5,10 @@ root = true
end_of_line = lf
insert_final_newline = true
-
# Matches multiple files with brace expansion notation
# Set default charset
[*.{js,jsx,html,sass}]
charset = utf-8
-indent_style = tab
+indent_style = space
indent_size = 2
trim_trailing_whitespace = true
diff --git a/.travis.yml b/.travis.yml
index b48a6cf6..510eea6e 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -15,6 +15,7 @@ before_install:
install:
- npm install
script:
+ - mkdir public
- npm run build
- npm run lint
- npm run test
diff --git a/package.json b/package.json
index e2d6f739..3cee983e 100644
--- a/package.json
+++ b/package.json
@@ -8,7 +8,7 @@
"build": "webpack --config webpack.production.config.js --progress --profile --colors",
"test": "karma start --single-run",
"test-watch": "karma start",
- "start": "webpack-dev-server --progress --profile --colors",
+ "start": "webpack-dev-server --progress --profile --colors --watch-poll",
"lint": "eslint --ext js --ext jsx {src,test}"
},
"repository": {
@@ -32,7 +32,8 @@
"react-height": "^2.1.1",
"react-icons": "^2.2.1",
"react-motion": "^0.4.4",
- "rebass": "^0.3.1"
+ "rebass": "^0.3.1",
+ "request": "^2.79.0"
},
"babel": {
"presets": [
diff --git a/src/apistore.js b/src/apistore.js
new file mode 100644
index 00000000..6b7c3728
--- /dev/null
+++ b/src/apistore.js
@@ -0,0 +1,41 @@
+import request from 'request'
+import style from './style.js'
+
+export class ApiStyleStore {
+ supported(cb) {
+ request('http://localhost:8000/styles', (error, response, body) => {
+ cb(error === undefined)
+ })
+ }
+
+ latestStyle(cb) {
+ if(this.latestStyleId) {
+ request('http://localhost:8000/styles/' + this.latestStyleId, (error, response, body) => {
+ cb(JSON.parse(body))
+ })
+ } else {
+ request('http://localhost:8000/styles', (error, response, body) => {
+ if (!error && response.statusCode == 200) {
+ const styleIds = JSON.parse(body);
+ this.latestStyleId = styleIds[0];
+ request('http://localhost:8000/styles/' + this.latestStyleId, (error, response, body) => {
+ cb(style.fromJSON(JSON.parse(body)))
+ })
+ }
+ })
+ }
+ }
+
+ // Save current style replacing previous version
+ save(mapStyle) {
+ const id = mapStyle.get('id')
+ request.put({
+ url: 'http://localhost:8000/styles/' + id,
+ json: true,
+ body: style.toJSON(mapStyle)
+ }, (error, response, body) => {
+ console.log('Saved style');
+ })
+ return mapStyle
+ }
+}
diff --git a/src/app.jsx b/src/app.jsx
index 85a9d09d..fe63388d 100644
--- a/src/app.jsx
+++ b/src/app.jsx
@@ -10,111 +10,117 @@ import { Map } from './map.jsx'
import {Toolbar} from './toolbar.jsx'
import style from './style.js'
import { loadDefaultStyle, SettingsStore, StyleStore } from './stylestore.js'
+import { ApiStyleStore } from './apistore.js'
import { WorkspaceDrawer } from './workspace.jsx'
import theme from './theme.js'
import './index.scss'
export default class App extends React.Component {
- static childContextTypes = {
- rebass: React.PropTypes.object,
- reactIconBase: React.PropTypes.object
- }
+ static childContextTypes = {
+ rebass: React.PropTypes.object,
+ reactIconBase: React.PropTypes.object
+ }
- constructor(props) {
- super(props)
- this.styleStore = new StyleStore()
- this.settingsStore = new SettingsStore()
- this.state = {
- accessToken: this.settingsStore.accessToken,
- workContext: "layers",
- currentStyle: this.styleStore.latestStyle(),
- }
- if(this.state.currentStyle.get('layers').size === 0) {
- loadDefaultStyle(mapStyle => this.onStyleUpload(mapStyle))
- }
- }
+ constructor(props) {
+ super(props)
- onReset() {
- this.styleStore.purge()
- loadDefaultStyle(mapStyle => this.onStyleUpload(mapStyle))
- }
+ this.styleStore = new ApiStyleStore()
+ this.styleStore.supported(isSupported => {
+ if(!isSupported) {
+ console.log('Falling back to local storage for storing styles')
+ this.styleStore = new StyleStore()
+ }
+ this.styleStore.latestStyle(mapStyle => this.onStyleUpload(mapStyle))
+ })
- getChildContext() {
- return {
- rebass: theme,
- reactIconBase: { size: 20 }
- }
- }
+ this.settingsStore = new SettingsStore()
+ this.state = {
+ accessToken: this.settingsStore.accessToken,
+ workContext: "layers",
+ currentStyle: style.emptyStyle
+ }
+ }
- onStyleDownload() {
- const mapStyle = style.toJSON(this.state.currentStyle)
- const blob = new Blob([JSON.stringify(mapStyle, null, 4)], {type: "application/json;charset=utf-8"});
- saveAs(blob, mapStyle.id + ".json");
- this.onStyleSave()
- }
+ onReset() {
+ this.styleStore.purge()
+ loadDefaultStyle(mapStyle => this.onStyleUpload(mapStyle))
+ }
- onStyleUpload(newStyle) {
- const savedStyle = this.styleStore.save(newStyle)
- this.setState({ currentStyle: savedStyle })
- }
+ getChildContext() {
+ return {
+ rebass: theme,
+ reactIconBase: { size: 20 }
+ }
+ }
- onStyleSave() {
- const snapshotStyle = this.state.currentStyle.set('modified', new Date().toJSON())
- this.setState({ currentStyle: snapshotStyle })
- this.styleStore.save(snapshotStyle)
- }
+ onStyleDownload() {
+ const mapStyle = style.toJSON(this.state.currentStyle)
+ const blob = new Blob([JSON.stringify(mapStyle, null, 4)], {type: "application/json;charset=utf-8"});
+ saveAs(blob, mapStyle.id + ".json");
+ this.onStyleSave()
+ }
- onStyleChanged(newStyle) {
- this.setState({ currentStyle: newStyle })
- }
+ onStyleUpload(newStyle) {
+ const savedStyle = this.styleStore.save(newStyle)
+ this.setState({ currentStyle: savedStyle })
+ }
- onOpenSettings() {
- this.setState({ workContext: "settings" })
- }
+ onStyleSave() {
+ const snapshotStyle = this.state.currentStyle.set('modified', new Date().toJSON())
+ this.setState({ currentStyle: snapshotStyle })
+ console.log('Save')
+ this.styleStore.save(snapshotStyle)
+ }
- onOpenAbout() {
- this.setState({ workContext: "about" })
- }
+ onStyleChanged(newStyle) {
+ this.setState({ currentStyle: newStyle })
+ }
- onOpenLayers() {
- this.setState({ workContext: "layers", })
- }
+ onOpenSettings() {
+ //TODO: open settings modal
+ //this.setState({ workContext: "settings" })
+ }
- onOpenSources() {
- this.setState({ workContext: "sources", })
- }
+ onOpenAbout() {
+ //TODO: open about modal
+ //this.setState({ workContext: "about" })
+ }
- onAccessTokenChanged(newToken) {
- this.settingsStore.accessToken = newToken
- this.setState({ accessToken: newToken })
- }
+ onOpenSources() {
+ //TODO: open sources modal
+ //this.setState({ workContext: "sources", })
+ }
- render() {
- return
- 0}
- onStyleSave={this.onStyleSave.bind(this)}
- onStyleUpload={this.onStyleUpload.bind(this)}
- onStyleDownload={this.onStyleDownload.bind(this)}
- onOpenSettings={this.onOpenSettings.bind(this)}
- onOpenAbout={this.onOpenAbout.bind(this)}
- onOpenLayers={this.onOpenLayers.bind(this)}
- onOpenSources={this.onOpenSources.bind(this)}
- />
-
-
-
- }
+ onAccessTokenChanged(newToken) {
+ this.settingsStore.accessToken = newToken
+ this.setState({ accessToken: newToken })
+ }
+
+ render() {
+ return
+ 0}
+ onStyleSave={this.onStyleSave.bind(this)}
+ onStyleUpload={this.onStyleUpload.bind(this)}
+ onStyleDownload={this.onStyleDownload.bind(this)}
+ onOpenSettings={this.onOpenSettings.bind(this)}
+ onOpenAbout={this.onOpenAbout.bind(this)}
+ onOpenSources={this.onOpenSources.bind(this)}
+ />
+
+
+
+ }
}
diff --git a/src/layers/list.jsx b/src/layers/list.jsx
index 1adb4582..ccf152d0 100644
--- a/src/layers/list.jsx
+++ b/src/layers/list.jsx
@@ -12,55 +12,48 @@ import PureRenderMixin from 'react-addons-pure-render-mixin';
// List of collapsible layer editors
export class LayerList extends React.Component {
- static propTypes = {
- layers: React.PropTypes.instanceOf(Immutable.OrderedMap),
- onLayersChanged: React.PropTypes.func.isRequired
- }
+ static propTypes = {
+ layers: React.PropTypes.instanceOf(Immutable.OrderedMap),
+ onLayersChanged: React.PropTypes.func.isRequired
+ }
- constructor(props) {
- super(props)
- this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
- }
+ constructor(props) {
+ super(props)
+ this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
+ }
- onLayerDestroyed(deletedLayer) {
- const remainingLayers = this.props.layers.delete(deletedLayer.get('id'))
- this.props.onLayersChanged(remainingLayers)
- }
+ onLayerDestroyed(deletedLayer) {
+ const remainingLayers = this.props.layers.delete(deletedLayer.get('id'))
+ this.props.onLayersChanged(remainingLayers)
+ }
- onLayerChanged(layer) {
- const changedLayers = this.props.layers.set(layer.get('id'), layer)
- this.props.onLayersChanged(changedLayers)
- }
+ onLayerChanged(layer) {
+ const changedLayers = this.props.layers.set(layer.get('id'), layer)
+ this.props.onLayersChanged(changedLayers)
+ }
- render() {
- var layerPanels = []
- layerPanels = this.props.layers.map(layer => {
- return
- }).toIndexedSeq()
+ render() {
+ var layerPanels = []
+ layerPanels = this.props.layers.map(layer => {
+ return
+ }).toIndexedSeq()
- return
-
-
- Layers
-
-
-
-
-
- {layerPanels}
-
-
- }
+ return
+ }
}
diff --git a/src/map.jsx b/src/map.jsx
index df3969e5..e6634c04 100644
--- a/src/map.jsx
+++ b/src/map.jsx
@@ -12,14 +12,15 @@ export class Map extends React.Component {
}
componentWillReceiveProps(nextProps) {
- const tokenChanged = nextProps.accessToken !== MapboxGl.accessToken
+ const hasTokenChanged = nextProps.accessToken !== MapboxGl.accessToken
+ MapboxGl.accessToken = nextProps.accessToken
// If the id has changed a new style has been uplaoded and
// it is safer to do a full new render
// TODO: might already be handled in diff algorithm?
const mapIdChanged = this.props.mapStyle.get('id') !== nextProps.mapStyle.get('id')
- if(mapIdChanged || tokenChanged) {
+ if(mapIdChanged || hasTokenChanged) {
this.state.map.setStyle(style.toJSON(nextProps.mapStyle))
return
}
diff --git a/src/scrollbars.scss b/src/scrollbars.scss
index 5c4ab23a..e7d44eb4 100644
--- a/src/scrollbars.scss
+++ b/src/scrollbars.scss
@@ -1,12 +1,12 @@
.darkScrollbar::-webkit-scrollbar {
- background-color: #313131;
- width: 10px;
+ background-color: #26282e;
+ width: 10px;
}
.darkScrollbar::-webkit-scrollbar-thumb {
- border-radius: 6px;
- -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3);
- background-color: #555;
- padding-left: 2px;
- padding-right: 2px;
+ border-radius: 6px;
+ -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3);
+ background-color: #40444e;
+ padding-left: 2px;
+ padding-right: 2px;
}
diff --git a/src/style.js b/src/style.js
index d5a869e3..ab9e213b 100644
--- a/src/style.js
+++ b/src/style.js
@@ -9,34 +9,41 @@ import randomColor from 'randomcolor'
// It also ensures that every style has an id and
// a created date for future reference
function fromJSON(jsonStyle) {
- if (typeof jsonStyle === 'string' || jsonStyle instanceof String) {
- jsonStyle = JSON.parse(jsonStyle)
- }
+ if (typeof jsonStyle === 'string' || jsonStyle instanceof String) {
+ jsonStyle = JSON.parse(jsonStyle)
+ }
- return Immutable.Map(Object.keys(jsonStyle).map(key => {
- const val = jsonStyle[key]
- if(key === "layers") {
- return [key, Immutable.OrderedMap(val.map(l => [l.id, Immutable.fromJS(l)]))]
- } else if(key === "sources" || key === "metadata" || key === "transition") {
- return [key, Immutable.fromJS(val)]
- } else {
- return [key, val]
- }
- }))
+ return Immutable.Map(Object.keys(jsonStyle).map(key => {
+ const val = jsonStyle[key]
+ if(key === "layers") {
+ return [key, Immutable.OrderedMap(val.map(l => [l.id, Immutable.fromJS(l)]))]
+ } else if(key === "sources" || key === "metadata" || key === "transition") {
+ return [key, Immutable.fromJS(val)]
+ } else {
+ return [key, val]
+ }
+ }))
}
+// Empty style is always used if no style could be restored or fetched
+const emptyStyle = ensureMetadataExists(fromJSON({
+ version: 8,
+ sources: {},
+ layers: [],
+}))
+
function ensureHasId(style) {
- if(style.has('id')) return style
- return style.set('id', Math.random().toString(36).substr(2, 9))
+ if(style.has('id')) return style
+ return style.set('id', Math.random().toString(36).substr(2, 9))
}
function ensureHasTimestamp(style) {
- if(style.has('id')) return style
- return style.set('created', new Date().toJSON())
+ if(style.has('id')) return style
+ return style.set('created', new Date().toJSON())
}
function ensureMetadataExists(style) {
- return ensureHasId(ensureHasTimestamp(style))
+ return ensureHasId(ensureHasTimestamp(style))
}
// Compare style with other style and return changes
@@ -44,41 +51,42 @@ function ensureMetadataExists(style) {
// Should be able to improve performance since we can only compare
// by reference
function diffStyles(before, after) {
- return diffJSONStyles(toJSON(before), toJSON(after))
+ return diffJSONStyles(toJSON(before), toJSON(after))
}
// Turns immutable style back into JSON with the original order of the
// layers preserved
function toJSON(mapStyle) {
- const jsonStyle = {}
- for(let [key, value] of mapStyle.entries()) {
- if(key === "layers") {
- jsonStyle[key] = value.toIndexedSeq().toJS()
- } else if(key === 'sources' || key === "metadata" || key === "transition") {
- jsonStyle[key] = value.toJS()
- } else {
- jsonStyle[key] = value
- }
- }
- return jsonStyle
+ const jsonStyle = {}
+ for(let [key, value] of mapStyle.entries()) {
+ if(key === "layers") {
+ jsonStyle[key] = value.toIndexedSeq().toJS()
+ } else if(key === 'sources' || key === "metadata" || key === "transition") {
+ jsonStyle[key] = value.toJS()
+ } else {
+ jsonStyle[key] = value
+ }
+ }
+ return jsonStyle
}
export function colorizeLayers(layers) {
- return layers.map(layer => {
- if(!layer.metadata) {
- layer.metadata = {}
- }
- if(!"maputnik:color" in layer.metadata) {
- layer.metadata["maputnik:color"] = randomColor()
- }
- return layer
- })
+ return layers.map(layer => {
+ if(!layer.metadata) {
+ layer.metadata = {}
+ }
+ if(!"maputnik:color" in layer.metadata) {
+ layer.metadata["maputnik:color"] = randomColor()
+ }
+ return layer
+ })
}
export default {
- colorizeLayers,
- toJSON,
- fromJSON,
- diffStyles,
- ensureMetadataExists,
+ colorizeLayers,
+ toJSON,
+ fromJSON,
+ diffStyles,
+ ensureMetadataExists,
+ emptyStyle,
}
diff --git a/src/stylestore.js b/src/stylestore.js
index 85db8b45..9927adac 100644
--- a/src/stylestore.js
+++ b/src/stylestore.js
@@ -5,117 +5,114 @@ import style from './style.js'
const storagePrefix = "maputnik"
const stylePrefix = 'style'
const storageKeys = {
- latest: [storagePrefix, 'latest_style'].join(':'),
- accessToken: [storagePrefix, 'access_token'].join(':')
+ latest: [storagePrefix, 'latest_style'].join(':'),
+ accessToken: [storagePrefix, 'access_token'].join(':')
}
-// Empty style is always used if no style could be restored or fetched
-const emptyStyle = style.ensureMetadataExists(style.fromJSON({
- version: 8,
- sources: {},
- layers: [],
-}))
-
const defaultStyleUrl = "https://raw.githubusercontent.com/osm2vectortiles/mapbox-gl-styles/master/styles/basic-v9-cdn.json"
// Fetch a default style via URL and return it or a fallback style via callback
export function loadDefaultStyle(cb) {
- console.log('Load default style')
- var request = new XMLHttpRequest()
- request.open('GET', defaultStyleUrl, true)
+ console.log('Load default style')
+ var request = new XMLHttpRequest()
+ request.open('GET', defaultStyleUrl, true)
- request.onload = () => {
- if (request.status >= 200 && request.status < 400) {
- cb(style.ensureMetadataExists(style.fromJSON(request.responseText)))
- } else {
- cb(emptyStyle)
- }
- }
+ request.onload = () => {
+ if (request.status >= 200 && request.status < 400) {
+ cb(style.ensureMetadataExists(style.fromJSON(request.responseText)))
+ } else {
+ cb(style.emptyStyle)
+ }
+ }
- request.onerror = function() {
- console.log('Could not fetch default style')
- cb(emptyStyle)
- }
+ request.onerror = function() {
+ console.log('Could not fetch default style')
+ cb(style.emptyStyle)
+ }
- request.send()
+ request.send()
}
// Return style ids and dates of all styles stored in local storage
function loadStoredStyles() {
- const styles = []
- for (let i = 0; i < window.localStorage.length; i++) {
- const key = window.localStorage.key(i)
- if(isStyleKey(key)) {
- styles.push(fromKey(key))
- }
- }
- return styles
+ const styles = []
+ for (let i = 0; i < window.localStorage.length; i++) {
+ const key = window.localStorage.key(i)
+ if(isStyleKey(key)) {
+ styles.push(fromKey(key))
+ }
+ }
+ return styles
}
function isStyleKey(key) {
- const parts = key.split(":")
- return parts.length == 3 && parts[0] === storagePrefix && parts[1] === stylePrefix
+ const parts = key.split(":")
+ return parts.length == 3 && parts[0] === storagePrefix && parts[1] === stylePrefix
}
// Load style id from key
function fromKey(key) {
- if(!isStyleKey(key)) {
- throw "Key is not a valid style key"
- }
+ if(!isStyleKey(key)) {
+ throw "Key is not a valid style key"
+ }
- const parts = key.split(":")
- const styleId = parts[2]
- return styleId
+ const parts = key.split(":")
+ const styleId = parts[2]
+ return styleId
}
// Calculate key that identifies the style with a version
function styleKey(styleId) {
- return [storagePrefix, stylePrefix, styleId].join(":")
+ return [storagePrefix, stylePrefix, styleId].join(":")
}
// Store style independent settings
export class SettingsStore {
- get accessToken() {
- const token = window.localStorage.getItem(storageKeys.accessToken)
- return token ? token : ""
- }
- set accessToken(val) {
- window.localStorage.setItem(storageKeys.accessToken, val)
- }
+ get accessToken() {
+ const token = window.localStorage.getItem(storageKeys.accessToken)
+ return token ? token : ""
+ }
+ set accessToken(val) {
+ window.localStorage.setItem(storageKeys.accessToken, val)
+ }
}
// Manages many possible styles that are stored in the local storage
export class StyleStore {
- // Tile store will load all items from local storage and
- // assume they do not change will working on it
- constructor() {
- this.mapStyles = loadStoredStyles()
- }
+ // Tile store will load all items from local storage and
+ // assume they do not change will working on it
+ constructor() {
+ this.mapStyles = loadStoredStyles()
+ }
- // Delete entire style history
- purge() {
- for (let i = 0; i < window.localStorage.length; i++) {
- const key = window.localStorage.key(i)
- if(key.startsWith(storagePrefix)) {
- window.localStorage.removeItem(key)
- }
- }
- }
+ supported(cb) {
+ cb(window.localStorage !== undefined)
+ }
- // Find the last edited style
- latestStyle() {
- if(this.mapStyles.length === 0) return emptyStyle
- const styleId = window.localStorage.getItem(storageKeys.latest)
- const styleItem = window.localStorage.getItem(styleKey(styleId))
+ // Delete entire style history
+ purge() {
+ for (let i = 0; i < window.localStorage.length; i++) {
+ const key = window.localStorage.key(i)
+ if(key.startsWith(storagePrefix)) {
+ window.localStorage.removeItem(key)
+ }
+ }
+ }
- if(styleItem) return style.fromJSON(styleItem)
- return emptyStyle
- }
+ // Find the last edited style
+ latestStyle(cb) {
+ if(this.mapStyles.length === 0) return cb(style.emptyStyle)
+ const styleId = window.localStorage.getItem(storageKeys.latest)
+ const styleItem = window.localStorage.getItem(styleKey(styleId))
- // Save current style replacing previous version
- save(mapStyle) {
- const key = styleKey(mapStyle.get('id'))
- window.localStorage.setItem(key, JSON.stringify(style.toJSON(mapStyle)))
- window.localStorage.setItem(storageKeys.latest, mapStyle.get('id'))
- return mapStyle
- }
+ if(styleItem) return cb(style.fromJSON(styleItem))
+ cb(style.emptyStyle)
+ }
+
+ // Save current style replacing previous version
+ save(mapStyle) {
+ const key = styleKey(mapStyle.get('id'))
+ window.localStorage.setItem(key, JSON.stringify(style.toJSON(mapStyle)))
+ window.localStorage.setItem(storageKeys.latest, mapStyle.get('id'))
+ return mapStyle
+ }
}
diff --git a/src/theme.js b/src/theme.js
index cc8f5fa3..7f5083f1 100644
--- a/src/theme.js
+++ b/src/theme.js
@@ -1,112 +1,112 @@
const caps = {
- textTransform: 'uppercase',
- letterSpacing: '.2em'
+ textTransform: 'uppercase',
+ letterSpacing: '.2em'
}
export const fullHeight = {
- position: "fixed",
- top: 0,
- bottom: 0,
- height: "100%",
+ position: "fixed",
+ top: 0,
+ bottom: 0,
+ height: "100%",
}
const baseColors = {
- black: '#242424',
- gray: '#313131',
- midgray: '#778',
- lowgray: '#dcdcdc',
- white: '#fff',
- blue: '#00d9f7',
- green: '#B4C7AD',
- orange: '#fb3',
- red: '#f04',
+ 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
+ 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
+ ...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,
+ 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 = [28, 24, 20, 16, 14, 12, 10]
const border = {
- borderColor: colors.black,
- borderRadius: 0,
+ borderColor: colors.black,
+ borderRadius: 0,
}
const dark = {
- name: 'Dark',
- color: colors.white,
- fontFamily: 'Roboto, sans-serif',
- scale,
- fontSizes,
- colors,
- inverted: colors.midGray,
- ...border,
+ 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,
- },
- 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],
- },
+ 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,
+ },
+ 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
diff --git a/src/toolbar.jsx b/src/toolbar.jsx
index 918fbd89..7ae776cb 100644
--- a/src/toolbar.jsx
+++ b/src/toolbar.jsx
@@ -12,122 +12,138 @@ import Fixed from 'rebass/dist/Fixed'
import MdFileDownload from 'react-icons/lib/md/file-download'
import MdFileUpload from 'react-icons/lib/md/file-upload'
+import MdOpenInBrowser from 'react-icons/lib/md/open-in-browser'
import MdSettings from 'react-icons/lib/md/settings'
import MdInfo from 'react-icons/lib/md/info'
import MdLayers from 'react-icons/lib/md/layers'
import MdSave from 'react-icons/lib/md/save'
+import MdStyle from 'react-icons/lib/md/style'
import MdMap from 'react-icons/lib/md/map'
+import MdInsertEmoticon from 'react-icons/lib/md/insert-emoticon'
+import MdFontDownload from 'react-icons/lib/md/font-download'
+import MdHelpOutline from 'react-icons/lib/md/help-outline'
+import MdFindInPage from 'react-icons/lib/md/find-in-page'
import style from './style.js'
import { fullHeight } from './theme.js'
import theme from './theme.js';
+const InlineBlock = props =>
+ {props.children}
+
+
export class Toolbar extends React.Component {
- static propTypes = {
- // A new style has been uploaded
- onStyleUpload: React.PropTypes.func.isRequired,
- // Current style is requested for download
- onStyleDownload: React.PropTypes.func.isRequired,
- // Style is explicitely saved to local cache
- onStyleSave: React.PropTypes.func,
- // Open settings drawer
- onOpenSettings: React.PropTypes.func,
- // Open about page
- onOpenAbout: React.PropTypes.func,
- // Open sources drawer
- onOpenSources: React.PropTypes.func,
- // Open layers drawer
- onOpenLayers: React.PropTypes.func,
- // Whether a style is available for download or saving
- // A style with no layers should not be available
- styleAvailable: React.PropTypes.bool,
- }
+ static propTypes = {
+ // A new style has been uploaded
+ onStyleUpload: React.PropTypes.func.isRequired,
+ // Current style is requested for download
+ onStyleDownload: React.PropTypes.func.isRequired,
+ // Style is explicitely saved to local cache
+ onStyleSave: React.PropTypes.func,
+ // Open settings drawer
+ onOpenSettings: React.PropTypes.func,
+ // Open about page
+ onOpenAbout: React.PropTypes.func,
+ // Open sources drawer
+ onOpenSources: React.PropTypes.func,
+ // Whether a style is available for download or saving
+ // A style with no layers should not be available
+ styleAvailable: React.PropTypes.bool,
+ }
- onUpload(_, files) {
- const [e, file] = files[0];
- const reader = new FileReader();
- reader.readAsText(file, "UTF-8");
- reader.onload = e => {
- let mapStyle = style.fromJSON(JSON.parse(e.target.result))
- mapStyle = style.ensureMetadataExists(mapStyle)
- this.props.onStyleUpload(mapStyle);
- }
- reader.onerror = e => console.log(e.target);
- }
+ onUpload(_, files) {
+ const [e, file] = files[0];
+ const reader = new FileReader();
+ reader.readAsText(file, "UTF-8");
+ reader.onload = e => {
+ let mapStyle = style.fromJSON(JSON.parse(e.target.result))
+ mapStyle = style.ensureMetadataExists(mapStyle)
+ this.props.onStyleUpload(mapStyle);
+ }
+ reader.onerror = e => console.log(e.target);
+ }
- saveButton() {
- if(this.props.styleAvailable) {
- return
-
-
- }
- return null
- }
+ saveButton() {
+ if(this.props.styleAvailable) {
+ return
+
+
+ }
+ return null
+ }
- downloadButton() {
- if(this.props.styleAvailable) {
- return
-
-
- }
- return null
- }
+ downloadButton() {
+ if(this.props.styleAvailable) {
+ return
+
+
+ }
+ return null
+ }
- render() {
- return
-
-
-
-
-
- {this.downloadButton()}
- {this.saveButton()}
-
-
-
-
-
-
-
-
-
-
-
-
-
- }
+ render() {
+
+ return
+
+
+
+
+
+
+
+
+ {this.downloadButton()}
+ {this.saveButton()}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ }
}
diff --git a/src/workspace.jsx b/src/workspace.jsx
index 69f1ca73..d2224148 100644
--- a/src/workspace.jsx
+++ b/src/workspace.jsx
@@ -8,65 +8,66 @@ import { colors, fullHeight } from './theme.js'
/** The workspace drawer contains the editor components depending on the edit
* context chosen in the toolbar. It holds the state of the layers.*/
export class WorkspaceDrawer extends React.Component {
- static propTypes = {
- mapStyle: React.PropTypes.object.isRequired,
- onStyleChanged: React.PropTypes.func.isRequired,
- workContext: React.PropTypes.oneOf(['layers', 'settings', 'sources']).isRequired,
- accessToken: React.PropTypes.string,
- onAccessTokenChanged: React.PropTypes.func,
- onReset: React.PropTypes.func,
- }
+ static propTypes = {
+ mapStyle: React.PropTypes.object.isRequired,
+ onStyleChanged: React.PropTypes.func.isRequired,
+ workContext: React.PropTypes.oneOf(['layers', 'settings', 'sources']).isRequired,
+ accessToken: React.PropTypes.string,
+ onAccessTokenChanged: React.PropTypes.func,
+ onReset: React.PropTypes.func,
+ }
- onLayersChanged(changedLayers) {
- const changedStyle = this.props.mapStyle.set('layers', changedLayers)
- this.props.onStyleChanged(changedStyle)
- }
+ onLayersChanged(changedLayers) {
+ const changedStyle = this.props.mapStyle.set('layers', changedLayers)
+ this.props.onStyleChanged(changedStyle)
+ }
- onSourcesChanged(changedSources) {
- const changedStyle = this.props.mapStyle.set('sources', changedSources)
- this.props.onStyleChanged(changedStyle)
- }
+ onSourcesChanged(changedSources) {
+ const changedStyle = this.props.mapStyle.set('sources', changedSources)
+ this.props.onStyleChanged(changedStyle)
+ }
- render() {
- let workspaceContent = null
+ render() {
+ let workspaceContent = null
- if(this.props.workContext === "sources") {
- workspaceContent =
- }
+ if(this.props.workContext === "sources") {
+ workspaceContent =
+ }
- if(this.props.workContext === "layers") {
- workspaceContent =
- }
+ if(this.props.workContext === "layers") {
+ workspaceContent =
+ }
- if(this.props.workContext === "settings") {
- workspaceContent =
- }
+ if(this.props.workContext === "settings") {
+ workspaceContent =
+ }
- if(this.props.workContext === "about") {
- workspaceContent =
- }
+ if(this.props.workContext === "about") {
+ workspaceContent =
+ }
- return
- {workspaceContent}
-
- }
+ return
+ {workspaceContent}
+
+ }
}
diff --git a/webpack.config.js b/webpack.config.js
index 11599662..97d14a4e 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -62,7 +62,9 @@ module.exports = {
}]
},
node: {
- fs: "empty"
+ fs: "empty",
+ net: 'empty',
+ tls: 'empty'
},
devServer: {
contentBase: "./public",