You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
125 lines
3.8 KiB
125 lines
3.8 KiB
import { Layer } from "react-map-gl";
|
|
import {
|
|
matchInitialPointLayer,
|
|
unmatchInitialPointLayer,
|
|
} from "./layers-config";
|
|
import { useLayersVisibility } from "../../stores/useLayersVisibility";
|
|
import { usePointSelection } from "../../stores/usePointSelection";
|
|
import { STATUSES } from "../../config";
|
|
import { useRegionFilterExpression } from "./useRegionFilterExpression";
|
|
import { LAYER_IDS } from "./constants";
|
|
import { RANGE_FILTERS_KEYS, usePendingPointsFilters } from "../../stores/usePendingPointsFilters";
|
|
import { fieldHasChanged } from "../../utils.js";
|
|
import { useSourceLayerName } from "../../api.js";
|
|
|
|
const statusExpression = ["==", ["get", "status"], STATUSES.pending];
|
|
|
|
const useFilterExpression = () => {
|
|
const { filters, ranges } = usePendingPointsFilters();
|
|
const { prediction, categories, region } = filters;
|
|
const { selection } = usePointSelection();
|
|
const includedArr = [...selection.included];
|
|
const excludedArr = [...selection.excluded];
|
|
|
|
const regionExpression = useRegionFilterExpression(region);
|
|
|
|
const includedExpression = ["in", ["get", "id"], ["literal", includedArr]];
|
|
const excludedExpression = ["in", ["get", "id"], ["literal", excludedArr]];
|
|
|
|
const predictionExpression = [
|
|
[">=", ["get", "prediction_current"], prediction[0]],
|
|
["<=", ["get", "prediction_current"], prediction[1]],
|
|
];
|
|
|
|
const staticKeyFiltersExpressions = RANGE_FILTERS_KEYS.map((key) => {
|
|
return [
|
|
[">=", ["get", key], filters[`${key}__gt`]],
|
|
["<=", ["get", key], filters[`${key}__lt`]],
|
|
];
|
|
});
|
|
|
|
const staticKeyExpressions = staticKeyFiltersExpressions.filter((expression) => {
|
|
const filterKey = expression[0][1][1];
|
|
return fieldHasChanged(filters, ranges, filterKey).result;
|
|
}).flat();
|
|
|
|
const categoryExpression =
|
|
categories.length > 0
|
|
? ["in", ["get", "category"], ["literal", categories]]
|
|
: true;
|
|
|
|
const matchFilterExpression = [
|
|
"all",
|
|
statusExpression,
|
|
["!", excludedExpression],
|
|
[
|
|
"any",
|
|
regionExpression
|
|
? ["all", ...predictionExpression, ...staticKeyExpressions, categoryExpression, regionExpression]
|
|
: ["all", ...predictionExpression, ...staticKeyExpressions, categoryExpression],
|
|
includedExpression,
|
|
],
|
|
];
|
|
|
|
const unmatchFilterExpression = [
|
|
"all",
|
|
statusExpression,
|
|
["!", includedExpression],
|
|
[
|
|
"any",
|
|
[
|
|
"!",
|
|
regionExpression
|
|
? [
|
|
"all",
|
|
...predictionExpression,
|
|
categoryExpression,
|
|
regionExpression,
|
|
...staticKeyExpressions,
|
|
categoryExpression,
|
|
]
|
|
: ["all", ...predictionExpression, categoryExpression, ...staticKeyExpressions],
|
|
],
|
|
excludedExpression,
|
|
],
|
|
];
|
|
|
|
return { match: matchFilterExpression, unmatch: unmatchFilterExpression };
|
|
};
|
|
|
|
export const PendingPoints = () => {
|
|
const { isVisible } = useLayersVisibility();
|
|
const layerName = useSourceLayerName();
|
|
const { match: matchFilterExpression, unmatch: unmatchFilterExpression } =
|
|
useFilterExpression();
|
|
|
|
return (
|
|
<>
|
|
<Layer
|
|
{...matchInitialPointLayer}
|
|
id={LAYER_IDS["initial-unmatch"]}
|
|
source={"points"}
|
|
source-layer={useSourceLayerName()}
|
|
layout={{
|
|
...matchInitialPointLayer.layout,
|
|
visibility: isVisible[LAYER_IDS.initial] ? "visible" : "none",
|
|
}}
|
|
filter={unmatchFilterExpression}
|
|
paint={unmatchInitialPointLayer.paint}
|
|
/>
|
|
<Layer
|
|
{...matchInitialPointLayer}
|
|
id={LAYER_IDS["initial-match"]}
|
|
source={"points"}
|
|
source-layer={layerName}
|
|
layout={{
|
|
...matchInitialPointLayer.layout,
|
|
visibility: isVisible[LAYER_IDS.initial] ? "visible" : "none",
|
|
}}
|
|
filter={matchFilterExpression}
|
|
paint={matchInitialPointLayer.paint}
|
|
/>
|
|
</>
|
|
);
|
|
};
|