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

View file

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

View file

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

View file

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

View file

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