Hint about filters not being applied in road info popover

This commit is contained in:
Paul Bienkowski 2022-07-28 18:48:26 +02:00
parent 1a3b971a71
commit c3ed4f24dd
5 changed files with 95 additions and 50 deletions

View file

@ -1,6 +1,14 @@
import React, { useState, useCallback } from "react"; import React, { useState, useCallback } from "react";
import _ from "lodash"; import _ from "lodash";
import { Segment, Menu, Header, Label, Icon, Table } from "semantic-ui-react"; import {
Segment,
Menu,
Header,
Label,
Icon,
Table,
Message,
} from "semantic-ui-react";
import { Layer, Source } from "react-map-gl"; import { Layer, Source } from "react-map-gl";
import { of, from, concat } from "rxjs"; import { of, from, concat } from "rxjs";
import { useObservable } from "rxjs-hooks"; import { useObservable } from "rxjs-hooks";
@ -9,8 +17,9 @@ import { Chart } from "components";
import { pairwise } from "utils"; import { pairwise } from "utils";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import api from 'api' import type { Location } from "types";
import {colorByDistance, borderByZone} from 'mapstyles' import api from "api";
import { colorByDistance, borderByZone } from "mapstyles";
import styles from "./styles.module.less"; import styles from "./styles.module.less";
@ -88,15 +97,20 @@ function RoadStatsTable({ data }) {
} }
function HistogramChart({ bins, counts, zone }) { function HistogramChart({ bins, counts, zone }) {
const diff = bins[1] - bins[0] const diff = bins[1] - bins[0];
const colortype = zone === "rural" ? 3 : 5; const colortype = zone === "rural" ? 3 : 5;
const data = _.zip( const data = _.zip(
bins.slice(0, bins.length - 1).map((v) => v + diff / 2), bins.slice(0, bins.length - 1).map((v) => v + diff / 2),
counts counts
).map((value) => ({ ).map((value) => ({
value, value,
itemStyle: {color: selectFromColorMap(colorByDistance()[3][colortype].slice(2), value[0]),}, itemStyle: {
})) color: selectFromColorMap(
colorByDistance()[3][colortype].slice(2),
value[0]
),
},
}));
return ( return (
<Chart <Chart
@ -123,7 +137,13 @@ function HistogramChart({ bins, counts, zone }) {
); );
} }
export default function RoadInfo({ clickLocation }) { export default function RoadInfo({
clickLocation,
hasFilters,
}: {
clickLocation: Location | null;
hasFilters: boolean;
}) {
const { t } = useTranslation(); const { t } = useTranslation();
const [direction, setDirection] = useState("forwards"); const [direction, setDirection] = useState("forwards");
@ -183,6 +203,15 @@ export default function RoadInfo({ clickLocation }) {
: info?.road.name || t("MapPage.roadInfo.unnamedWay")} : info?.road.name || t("MapPage.roadInfo.unnamedWay")}
</Header> </Header>
{hasFilters && (
<Message info icon>
<Icon name="info circle" small />
<Message.Content>
{t("MapPage.roadInfo.hintFiltersNotApplied")}
</Message.Content>
</Message>
)}
{info?.road.zone && ( {info?.road.zone && (
<Label size="small" color={ZONE_COLORS[info?.road.zone]}> <Label size="small" color={ZONE_COLORS[info?.road.zone]}>
{t(`general.zone.${info.road.zone}`)} {t(`general.zone.${info.road.zone}`)}
@ -220,9 +249,9 @@ export default function RoadInfo({ clickLocation }) {
{info?.[direction]?.distanceOvertaker?.histogram && ( {info?.[direction]?.distanceOvertaker?.histogram && (
<> <>
<Header as="h5"> <Header as="h5">
{t("MapPage.roadInfo.overtakerDistanceDistribution")} {t("MapPage.roadInfo.overtakerDistanceDistribution")}
</Header> </Header>
<HistogramChart <HistogramChart
{...info[direction]?.distanceOvertaker?.histogram} {...info[direction]?.distanceOvertaker?.histogram}
/> />

View file

@ -5,10 +5,17 @@ import { Button } from "semantic-ui-react";
import { Layer, Source } from "react-map-gl"; import { Layer, Source } from "react-map-gl";
import produce from "immer"; import produce from "immer";
import {Page, Map} from 'components' import type { Location } from "types";
import {useConfig} from 'config' import { Page, Map } from "components";
import {colorByDistance, colorByCount, borderByZone, reds, isValidAttribute} from 'mapstyles' import { useConfig } from "config";
import {useMapConfig} from 'reducers/mapConfig' import {
colorByDistance,
colorByCount,
borderByZone,
reds,
isValidAttribute,
} from "mapstyles";
import { useMapConfig } from "reducers/mapConfig";
import RoadInfo from "./RoadInfo"; import RoadInfo from "./RoadInfo";
import LayerSidebar from "./LayerSidebar"; import LayerSidebar from "./LayerSidebar";
@ -43,20 +50,19 @@ const untaggedRoadsLayer = {
const getUntaggedRoadsLayer = (colorAttribute, maxCount) => const getUntaggedRoadsLayer = (colorAttribute, maxCount) =>
produce(untaggedRoadsLayer, (draft) => { produce(untaggedRoadsLayer, (draft) => {
draft.filter = ['!', isValidAttribute(colorAttribute)] draft.filter = ["!", isValidAttribute(colorAttribute)];
}) });
const getRoadsLayer = (colorAttribute, maxCount) => const getRoadsLayer = (colorAttribute, maxCount) =>
produce(untaggedRoadsLayer, (draft) => { produce(untaggedRoadsLayer, (draft) => {
draft.id = "obs_roads_normal"; draft.id = "obs_roads_normal";
draft.filter = isValidAttribute(colorAttribute) draft.filter = isValidAttribute(colorAttribute);
draft.paint["line-width"][6] = 6; // scale bigger on zoom draft.paint["line-width"][6] = 6; // scale bigger on zoom
draft.paint["line-color"] = colorAttribute.startsWith("distance_") draft.paint["line-color"] = colorAttribute.startsWith("distance_")
? colorByDistance(colorAttribute) ? colorByDistance(colorAttribute)
: colorAttribute.endsWith("_count") : colorAttribute.endsWith("_count")
? colorByCount(colorAttribute, maxCount) ? colorByCount(colorAttribute, maxCount)
: colorAttribute.endsWith('zone') : colorAttribute.endsWith("zone")
? borderByZone() ? borderByZone()
: "#DDD"; : "#DDD";
draft.paint["line-opacity"][3] = 12; draft.paint["line-opacity"][3] = 12;
@ -105,10 +111,7 @@ const getEventsTextLayer = () => ({
function MapPage({ login }) { function MapPage({ login }) {
const { obsMapSource } = useConfig() || {}; const { obsMapSource } = useConfig() || {};
const [clickLocation, setClickLocation] = useState<{ const [clickLocation, setClickLocation] = useState<Location | null>(null);
longitude: number;
latitude: number;
} | null>(null);
const mapConfig = useMapConfig(); const mapConfig = useMapConfig();
@ -135,9 +138,12 @@ function MapPage({ login }) {
const layers = []; const layers = [];
const untaggedRoadsLayerCustom = useMemo(() => getUntaggedRoadsLayer(attribute), [attribute]) const untaggedRoadsLayerCustom = useMemo(
() => getUntaggedRoadsLayer(attribute),
[attribute]
);
if (mapConfig.obsRoads.show && mapConfig.obsRoads.showUntagged) { if (mapConfig.obsRoads.show && mapConfig.obsRoads.showUntagged) {
layers.push(untaggedRoadsLayerCustom) layers.push(untaggedRoadsLayerCustom);
} }
const roadsLayer = useMemo( const roadsLayer = useMemo(
@ -159,31 +165,36 @@ function MapPage({ login }) {
return null; return null;
} }
const tiles = obsMapSource?.tiles?.map( const tiles = obsMapSource?.tiles?.map((tileUrl: string) => {
(tileUrl: string) => { const query = new URLSearchParams();
const query = new URLSearchParams() if (login) {
if (login) { if (mapConfig.filters.currentUser) {
if (mapConfig.filters.currentUser) { query.append("user", login.username);
query.append('user', login.username) }
}
if (mapConfig.filters.dateMode === "range") { if (mapConfig.filters.dateMode === "range") {
if (mapConfig.filters.startDate) { if (mapConfig.filters.startDate) {
query.append('start', mapConfig.filters.startDate) query.append("start", mapConfig.filters.startDate);
} }
if (mapConfig.filters.endDate) { if (mapConfig.filters.endDate) {
query.append('end', mapConfig.filters.endDate) query.append("end", mapConfig.filters.endDate);
} }
} else if (mapConfig.filters.dateMode === "threshold") { } else if (mapConfig.filters.dateMode === "threshold") {
if (mapConfig.filters.startDate) { if (mapConfig.filters.startDate) {
query.append(mapConfig.filters.thresholdAfter ? 'start' : 'end', mapConfig.filters.startDate) query.append(
} mapConfig.filters.thresholdAfter ? "start" : "end",
mapConfig.filters.startDate
);
} }
} }
const queryString = String(query)
return tileUrl + (queryString ? '?' : '') + queryString
} }
); const queryString = String(query);
return tileUrl + (queryString ? "?" : "") + queryString;
});
const hasFilters: boolean =
login &&
(mapConfig.filters.currentUser || mapConfig.filters.dateMode !== "none");
return ( return (
<Page fullScreen title="Map"> <Page fullScreen title="Map">
@ -212,7 +223,7 @@ function MapPage({ login }) {
))} ))}
</Source> </Source>
<RoadInfo {...{ clickLocation }} /> <RoadInfo {...{ clickLocation, hasFilters }} />
</Map> </Map>
</div> </div>
</div> </div>
@ -220,6 +231,4 @@ function MapPage({ login }) {
); );
} }
export default connect( export default connect((state) => ({ login: state.login }))(MapPage);
(state) => ({login: state.login}),
)(MapPage);

View file

@ -188,6 +188,7 @@ MapPage:
mean: Durchschnitt mean: Durchschnitt
overtakerDistanceDistribution: Verteilung der Überholabstände overtakerDistanceDistribution: Verteilung der Überholabstände
hintFiltersNotApplied: Filter aus der Seiteleiste werden (noch) nicht auf diese Daten angewandt.
cardinalDirections: cardinalDirections:
unknown: unbekannt unknown: unbekannt

View file

@ -192,6 +192,7 @@ MapPage:
mean: Average mean: Average
overtakerDistanceDistribution: Overtaker distance distribution overtakerDistanceDistribution: Overtaker distance distribution
hintFiltersNotApplied: Filters from the sidebar are not (yet) applied on this data.
cardinalDirections: cardinalDirections:
unknown: unknown unknown: unknown

View file

@ -44,3 +44,8 @@ export type TrackComment = {
createdAt: string createdAt: string
author: UserProfile author: UserProfile
} }
export type Location {
longitude: number;
latitude: number;
}