Merge remote-tracking branch 'upstream/master' into feature/ol-experimental-support

This commit is contained in:
orangemug
2018-10-06 14:06:10 +01:00
13 changed files with 139 additions and 26 deletions
+3 -1
View File
@@ -9,12 +9,14 @@ class Button extends React.Component {
onClick: PropTypes.func, onClick: PropTypes.func,
style: PropTypes.object, style: PropTypes.object,
className: PropTypes.string, className: PropTypes.string,
children: PropTypes.node children: PropTypes.node,
disabled: PropTypes.bool,
} }
render() { render() {
return <button return <button
onClick={this.props.onClick} onClick={this.props.onClick}
disabled={this.props.disabled}
aria-label={this.props["aria-label"]} aria-label={this.props["aria-label"]}
className={classnames("maputnik-button", this.props.className)} className={classnames("maputnik-button", this.props.className)}
data-wd-key={this.props["data-wd-key"]} data-wd-key={this.props["data-wd-key"]}
+2 -1
View File
@@ -124,7 +124,8 @@ export default class Toolbar extends React.Component {
className="maputnik-toolbar-logo" className="maputnik-toolbar-logo"
> >
<img src={logoImage} alt="Maputnik" /> <img src={logoImage} alt="Maputnik" />
<h1>Maputnik <h1>
<span className="maputnik-toolbar-name">{pkgJson.name}</span>
<span className="maputnik-toolbar-version">v{pkgJson.version}</span> <span className="maputnik-toolbar-version">v{pkgJson.version}</span>
</h1> </h1>
</a> </a>
+15 -3
View File
@@ -32,6 +32,16 @@ export default class FunctionSpecProperty extends React.Component {
]), ]),
} }
getFieldFunctionType(fieldSpec) {
if (fieldSpec.expression.interpolated) {
return "exponential"
}
if (fieldSpec.type === "number") {
return "interval"
}
return "categorical"
}
addStop = () => { addStop = () => {
const stops = this.props.value.stops.slice(0) const stops = this.props.value.stops.slice(0)
const lastStop = stops[stops.length - 1] const lastStop = stops[stops.length - 1]
@@ -80,12 +90,14 @@ export default class FunctionSpecProperty extends React.Component {
} }
makeDataFunction = () => { makeDataFunction = () => {
const functionType = this.getFieldFunctionType(this.props.fieldSpec);
const stopValue = functionType === 'categorical' ? '' : 0;
const dataFunc = { const dataFunc = {
property: "", property: "",
type: "categorical", type: functionType,
stops: [ stops: [
[{zoom: 6, value: 0}, this.props.value], [{zoom: 6, value: stopValue}, this.props.value || stopValue],
[{zoom: 10, value: 0}, this.props.value] [{zoom: 10, value: stopValue}, this.props.value || stopValue]
] ]
} }
this.props.onChange(this.props.fieldName, dataFunc) this.props.onChange(this.props.fieldName, dataFunc)
+4 -4
View File
@@ -30,7 +30,7 @@ export default class DataProperty extends React.Component {
} }
getFieldFunctionType(fieldSpec) { getFieldFunctionType(fieldSpec) {
if (fieldSpec.function === "interpolated") { if (fieldSpec.expression.interpolated) {
return "exponential" return "exponential"
} }
if (fieldSpec.type === "number") { if (fieldSpec.type === "number") {
@@ -39,8 +39,8 @@ export default class DataProperty extends React.Component {
return "categorical" return "categorical"
} }
getDataFunctionTypes(functionType) { getDataFunctionTypes(fieldSpec) {
if (functionType === "interpolated") { if (fieldSpec.expression.interpolated) {
return ["categorical", "interval", "exponential"] return ["categorical", "interval", "exponential"]
} }
else { else {
@@ -150,7 +150,7 @@ export default class DataProperty extends React.Component {
<SelectInput <SelectInput
value={this.props.value.type} value={this.props.value.type}
onChange={propVal => this.changeDataProperty("type", propVal)} onChange={propVal => this.changeDataProperty("type", propVal)}
options={this.getDataFunctionTypes(this.props.fieldSpec.function)} options={this.getDataFunctionTypes(this.props.fieldSpec)}
/> />
</div> </div>
</div> </div>
+1 -1
View File
@@ -28,7 +28,7 @@ export default class FunctionButtons extends React.Component {
/> />
</Button> </Button>
if (this.props.fieldSpec['property-function'] && ['piecewise-constant', 'interpolated'].indexOf(this.props.fieldSpec['function']) !== -1) { if (this.props.fieldSpec['property-type'] === 'data-driven') {
makeDataButton = <Button makeDataButton = <Button
className="maputnik-make-data-function" className="maputnik-make-data-function"
onClick={this.props.onDataClick} onClick={this.props.onDataClick}
+4
View File
@@ -10,6 +10,10 @@ export default class CollapseAlt extends React.Component {
children: PropTypes.element.isRequired children: PropTypes.element.isRequired
} }
static defaultProps = {
isActive: true
}
render() { render() {
if (accessibility.reducedMotionEnabled()) { if (accessibility.reducedMotionEnabled()) {
return ( return (
+22 -3
View File
@@ -31,7 +31,9 @@ class IconAction extends React.Component {
static propTypes = { static propTypes = {
action: PropTypes.string.isRequired, action: PropTypes.string.isRequired,
onClick: PropTypes.func.isRequired, onClick: PropTypes.func.isRequired,
wdKey: PropTypes.string wdKey: PropTypes.string,
classBlockName: PropTypes.string,
classBlockModifier: PropTypes.string,
} }
renderIcon() { renderIcon() {
@@ -44,10 +46,21 @@ class IconAction extends React.Component {
} }
render() { render() {
const {classBlockName, classBlockModifier} = this.props;
let classAdditions = '';
if (classBlockName) {
classAdditions = `maputnik-layer-list-icon-action__${classBlockName}`;
if (classBlockModifier) {
classAdditions += ` maputnik-layer-list-icon-action__${classBlockName}--${classBlockModifier}`;
}
}
return <button return <button
tabIndex="-1" tabIndex="-1"
title={this.props.action} title={this.props.action}
className="maputnik-layer-list-icon-action" className={`maputnik-layer-list-icon-action ${classAdditions}`}
data-wd-key={this.props.wdKey} data-wd-key={this.props.wdKey}
onClick={this.props.onClick} onClick={this.props.onClick}
> >
@@ -90,6 +103,8 @@ class LayerListItem extends React.Component {
} }
render() { render() {
const visibilityAction = this.props.visibility === 'visible' ? 'show' : 'hide';
return <li return <li
key={this.props.layerId} key={this.props.layerId}
onClick={e => this.props.onLayerSelect(this.props.layerId)} onClick={e => this.props.onLayerSelect(this.props.layerId)}
@@ -105,16 +120,20 @@ class LayerListItem extends React.Component {
<IconAction <IconAction
wdKey={"layer-list-item:"+this.props.layerId+":delete"} wdKey={"layer-list-item:"+this.props.layerId+":delete"}
action={'delete'} action={'delete'}
classBlockName="delete"
onClick={e => this.props.onLayerDestroy(this.props.layerId)} onClick={e => this.props.onLayerDestroy(this.props.layerId)}
/> />
<IconAction <IconAction
wdKey={"layer-list-item:"+this.props.layerId+":copy"} wdKey={"layer-list-item:"+this.props.layerId+":copy"}
action={'duplicate'} action={'duplicate'}
classBlockName="duplicate"
onClick={e => this.props.onLayerCopy(this.props.layerId)} onClick={e => this.props.onLayerCopy(this.props.layerId)}
/> />
<IconAction <IconAction
wdKey={"layer-list-item:"+this.props.layerId+":toggle-visibility"} wdKey={"layer-list-item:"+this.props.layerId+":toggle-visibility"}
action={this.props.visibility === 'visible' ? 'show' : 'hide'} action={visibilityAction}
classBlockName="visibility"
classBlockModifier={visibilityAction}
onClick={e => this.props.onLayerVisibilityToggle(this.props.layerId)} onClick={e => this.props.onLayerVisibilityToggle(this.props.layerId)}
/> />
</li> </li>
+28 -3
View File
@@ -51,7 +51,9 @@ class OpenModal extends React.Component {
constructor(props) { constructor(props) {
super(props); super(props);
this.state = {}; this.state = {
styleUrl: ""
};
} }
clearError() { clearError() {
@@ -102,6 +104,7 @@ class OpenModal extends React.Component {
}) })
.catch((err) => { .catch((err) => {
this.setState({ this.setState({
error: `Failed to load: '${styleUrl}'`,
activeRequest: null, activeRequest: null,
activeRequestUrl: null activeRequestUrl: null
}); });
@@ -150,10 +153,19 @@ class OpenModal extends React.Component {
} }
onOpenToggle() { onOpenToggle() {
this.setState({
styleUrl: ""
});
this.clearError(); this.clearError();
this.props.onOpenToggle(); this.props.onOpenToggle();
} }
onChangeUrl = () => {
this.setState({
styleUrl: this.styleUrlElement.value
});
}
render() { render() {
const styleOptions = publicStyles.map(style => { const styleOptions = publicStyles.map(style => {
return <PublicStyle return <PublicStyle
@@ -197,9 +209,22 @@ class OpenModal extends React.Component {
<p> <p>
Load from a URL. Note that the URL must have <a href="https://enable-cors.org" target="_blank" rel="noopener noreferrer">CORS enabled</a>. Load from a URL. Note that the URL must have <a href="https://enable-cors.org" target="_blank" rel="noopener noreferrer">CORS enabled</a>.
</p> </p>
<input data-wd-key="open-modal.url.input" type="text" ref={(input) => this.styleUrlElement = input} className="maputnik-input" placeholder="Enter URL..."/> <input
data-wd-key="open-modal.url.input"
type="text"
ref={(input) => this.styleUrlElement = input}
className="maputnik-input"
placeholder="Enter URL..."
value={this.state.styleUrl}
onChange={this.onChangeUrl}
/>
<div> <div>
<Button data-wd-key="open-modal.url.button" className="maputnik-big-button" onClick={this.onOpenUrl}>Open URL</Button> <Button
data-wd-key="open-modal.url.button"
className="maputnik-big-button"
onClick={this.onOpenUrl}
disabled={this.state.styleUrl.length < 1}
>Open URL</Button>
</div> </div>
</section> </section>
+24
View File
@@ -34,5 +34,29 @@
"title": "Empty Style", "title": "Empty Style",
"url": "https://rawgit.com/maputnik/editor/master/src/config/empty-style.json", "url": "https://rawgit.com/maputnik/editor/master/src/config/empty-style.json",
"thumbnail": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAECAQAAAAHDYbIAAAAEUlEQVR42mP8/58BDhiJ4wAA974H/U5Xe1oAAAAASUVORK5CYII=" "thumbnail": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAECAQAAAAHDYbIAAAAEUlEQVR42mP8/58BDhiJ4wAA974H/U5Xe1oAAAAASUVORK5CYII="
},
{
"id": "os-zoomstack-outdoor",
"title": "Zoomstack Outdoor",
"url": "https://s3-eu-west-1.amazonaws.com/tiles.os.uk/styles/open-zoomstack-outdoor/style.json",
"thumbnail": "https://maputnik.github.io/thumbnails/os-zoomstack-outdoor.png"
},
{
"id": "os-zoomstack-road",
"title": "Zoomstack Road",
"url": "https://s3-eu-west-1.amazonaws.com/tiles.os.uk/styles/open-zoomstack-road/style.json",
"thumbnail": "https://maputnik.github.io/thumbnails/os-zoomstack-road.png"
},
{
"id": "os-zoomstack-light",
"title": "Zoomstack Light",
"url": "https://s3-eu-west-1.amazonaws.com/tiles.os.uk/styles/open-zoomstack-light/style.json",
"thumbnail": "https://maputnik.github.io/thumbnails/os-zoomstack-light.png"
},
{
"id": "os-zoomstack-night",
"title": "Zoomstack Night",
"url": "https://s3-eu-west-1.amazonaws.com/tiles.os.uk/styles/open-zoomstack-night/style.json",
"thumbnail": "https://maputnik.github.io/thumbnails/os-zoomstack-night.png"
} }
] ]
+6 -1
View File
@@ -1,7 +1,7 @@
{ {
"openmaptiles": { "openmaptiles": {
"type": "vector", "type": "vector",
"url": "https://free.tilehosting.com/data/v3.json?key={key}", "url": "https://maps.tilehosting.com/data/v3.json?key={key}",
"title": "OpenMapTiles" "title": "OpenMapTiles"
}, },
"thunderforest_transport": { "thunderforest_transport": {
@@ -13,5 +13,10 @@
"type": "vector", "type": "vector",
"url": "https://tile.thunderforest.com/thunderforest.outdoors-v1.json?apikey={key}", "url": "https://tile.thunderforest.com/thunderforest.outdoors-v1.json?apikey={key}",
"title": "Thunderforest Outdoors (heavy)" "title": "Thunderforest Outdoors (heavy)"
},
"open_zoomstack": {
"type": "vector",
"url": "https://s3-eu-west-1.amazonaws.com/tiles.os.uk/data/vector/open-zoomstack/config.json",
"title": "OS Open Zoomstack"
} }
} }
+6
View File
@@ -77,6 +77,12 @@
background-color: lighten($color-midgray, 12); background-color: lighten($color-midgray, 12);
color: $color-white; color: $color-white;
} }
&:disabled {
background-color: darken($color-midgray, 5);
color: $color-midgray;
cursor: not-allowed;
}
} }
.maputnik-big-button { .maputnik-big-button {
+20 -9
View File
@@ -58,22 +58,33 @@
} }
} }
.maputnik-layer-list-icon-action {
background: initial;
border: none;
padding: 0 2px;
svg {
fill: darken($color-lowgray, 20);
&:hover {
fill: $color-white;
}
}
}
.maputnik-layer-list-icon-action__visibility--hide {
display: block;
}
.maputnik-layer-list-item:hover, .maputnik-layer-list-item:hover,
.maputnik-layer-list-item-selected { .maputnik-layer-list-item-selected {
background-color: lighten($color-black, 2); background-color: lighten($color-black, 2);
.maputnik-layer-list-icon-action { .maputnik-layer-list-icon-action {
display: block; display: block;
background: initial;
border: none;
padding: 0 2px;
}
.maputnik-layer-list-icon-action svg { svg {
fill: darken($color-lowgray, 0.5); fill: darken($color-lowgray, 0.5);
&:hover {
fill: $color-white;
} }
} }
} }
+4
View File
@@ -80,6 +80,10 @@
} }
} }
.maputnik-toolbar-name {
text-transform: capitalize;
}
.maputnik-toolbar-version { .maputnik-toolbar-version {
font-size: 10px; font-size: 10px;
margin-left: 4px; margin-left: 4px;