Skip to content
Snippets Groups Projects
Commit 9d49adaf authored by Tom Robinson's avatar Tom Robinson Committed by GitHub
Browse files

Merge pull request #4637 from metabase/map-filter-rect

Filter pin map by drawing rectangle
parents d2535e3e a930539a
No related branches found
No related tags found
No related merge requests found
......@@ -5,9 +5,14 @@ import MetabaseSettings from "metabase/lib/settings";
import "leaflet/dist/leaflet.css";
import L from "leaflet";
import "leaflet-draw";
import _ from "underscore";
import { updateIn } from "icepick";
import * as Query from "metabase/lib/query/query";
import { mbqlEq } from "metabase/lib/query/util";
export default class LeafletMap extends Component {
componentDidMount() {
try {
......@@ -15,8 +20,28 @@ export default class LeafletMap extends Component {
const map = this.map = L.map(element, {
scrollWheelZoom: false,
minZoom: 2
})
minZoom: 2,
drawControlTooltips: false
});
const drawnItems = new L.FeatureGroup();
map.addLayer(drawnItems);
const drawControl = this.drawControl = new L.Control.Draw({
draw: {
rectangle: false,
polyline: false,
polygon: false,
circle: false,
marker: false
},
edit: {
featureGroup: drawnItems,
edit: false,
remove: false
}
});
map.addControl(drawControl);
map.on("draw:created", this.onFilter);
map.setView([0,0], 8);
......@@ -49,10 +74,48 @@ export default class LeafletMap extends Component {
], settings["map.zoom"]);
} else {
this.map.fitBounds(bounds);
this.map.setZoom(this.map.getBoundsZoom(bounds, true));
}
}
}
startFilter() {
this._filter = new L.Draw.Rectangle(this.map, this.drawControl.options.rectangle);
this._filter.enable();
this.props.onFiltering(true);
}
stopFilter() {
this._filter && this._filter.disable();
this.props.onFiltering(false);
}
onFilter = (e) => {
const bounds = e.layer.getBounds();
const { series: [{ card, data: { cols } }], settings, setCardAndRun } = this.props;
const latitudeColumn = _.findWhere(cols, { name: settings["map.latitude_column"] });
const longitudeColumn = _.findWhere(cols, { name: settings["map.longitude_column"] });
const filter = [
"inside",
latitudeColumn.id, longitudeColumn.id,
bounds.getNorth(), bounds.getWest(), bounds.getSouth(), bounds.getEast()
]
setCardAndRun(updateIn(card, ["dataset_query", "query"], (query) => {
const index = _.findIndex(Query.getFilters(query), (filter) =>
mbqlEq(filter[0], "inside") && filter[1] === latitudeColumn.id && filter[2] === longitudeColumn.id
);
if (index >= 0) {
return Query.updateFilter(query, index, filter);
} else {
return Query.addFilter(query, filter);
}
}));
this.props.onFiltering(false);
}
render() {
const { className } = this.props;
return (
......
......@@ -23,6 +23,7 @@ type State = {
zoom: ?number,
points: L.Point[],
bounds: L.Bounds,
filtering: boolean,
};
const MAP_COMPONENTS_BY_TYPE = {
......@@ -44,6 +45,7 @@ export default class PinMap extends Component<*, Props, State> {
}
state: State;
_map: ?(LeafletMarkerPinMap|LeafletTilePinMap) = null;
constructor(props: Props) {
super(props);
......@@ -51,6 +53,7 @@ export default class PinMap extends Component<*, Props, State> {
lat: null,
lng: null,
zoom: null,
filtering: false,
...this._getPoints(props)
};
}
......@@ -106,10 +109,11 @@ export default class PinMap extends Component<*, Props, State> {
const { points, bounds } = this.state;//this._getPoints(this.props);
return (
<div className={cx(className, "PinMap relative")} onMouseDownCapture={(e) =>e.stopPropagation() /* prevent dragging */}>
<div className={cx(className, "PinMap relative hover-parent hover--visibility")} onMouseDownCapture={(e) =>e.stopPropagation() /* prevent dragging */}>
{ Map ?
<Map
{...this.props}
ref={map => this._map = map}
className="absolute top left bottom right z1"
onMapCenterChange={this.onMapCenterChange}
onMapZoomChange={this.onMapZoomChange}
......@@ -118,13 +122,30 @@ export default class PinMap extends Component<*, Props, State> {
zoom={zoom}
points={points}
bounds={bounds}
onFiltering={(filtering) => this.setState({ filtering })}
/>
: null }
{ isEditing || !isDashboard ?
<div className={cx("PinMapUpdateButton Button Button--small absolute top right m1 z2", { "PinMapUpdateButton--disabled": disableUpdateButton })} onClick={this.updateSettings}>
Save as default view
</div>
: null }
<div className="absolute top right m1 z2 flex flex-column hover-child">
{ isEditing || !isDashboard ?
<div className={cx("PinMapUpdateButton Button Button--small mb1", { "PinMapUpdateButton--disabled": disableUpdateButton })} onClick={this.updateSettings}>
Save as default view
</div>
: null }
{ !isDashboard &&
<div
className={cx("PinMapUpdateButton Button Button--small mb1")}
onClick={() => {
if (!this.state.filtering && this._map && this._map.startFilter) {
this._map.startFilter();
} else if (this.state.filtering && this._map && this._map.stopFilter) {
this._map.stopFilter();
}
}}
>
{ !this.state.filtering ? "Draw box to filter" : "Cancel filter" }
</div>
}
</div>
</div>
);
}
......
......@@ -29,6 +29,7 @@
"js-cookie": "^2.1.2",
"jsrsasign": "^7.1.0",
"leaflet": "^1.0.1",
"leaflet-draw": "^0.4.9",
"moment": "2.14.1",
"node-libs-browser": "^2.0.0",
"normalizr": "^3.0.2",
......
......@@ -4450,6 +4450,10 @@ lcid@^1.0.0:
dependencies:
invert-kv "^1.0.0"
leaflet-draw@^0.4.9:
version "0.4.9"
resolved "https://registry.yarnpkg.com/leaflet-draw/-/leaflet-draw-0.4.9.tgz#44105088310f47e4856d5ede37d47ecfad0cf2d5"
leaflet@^1.0.1:
version "1.0.3"
resolved "https://registry.yarnpkg.com/leaflet/-/leaflet-1.0.3.tgz#1f401b98b45c8192134c6c8d69686253805007c8"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment