Skip to content

Commit

Permalink
splitted features on map
Browse files Browse the repository at this point in the history
  • Loading branch information
agnlez committed Dec 13, 2023
1 parent 348dbac commit 5eb44f1
Show file tree
Hide file tree
Showing 13 changed files with 241 additions and 182 deletions.
46 changes: 36 additions & 10 deletions app/hooks/features/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@ import { useMemo } from 'react';

import { useQuery, useMutation, useQueryClient, QueryObserverOptions } from 'react-query';

import { useRouter } from 'next/router';

import { AxiosRequestConfig } from 'axios';
import chroma from 'chroma-js';
import Fuse from 'fuse.js';
import flatten from 'lodash/flatten';
import orderBy from 'lodash/orderBy';
import partition from 'lodash/partition';
import { useSession } from 'next-auth/react';

import { COLORS } from 'hooks/map/constants';

import { ItemProps as IntersectItemProps } from 'components/features/intersect-item/component';
import { ItemProps as RawItemProps } from 'components/features/raw-item/component';
import { Feature } from 'types/api/feature';
Expand Down Expand Up @@ -171,13 +176,17 @@ export function useSelectedFeatures(
filters: UseFeaturesFiltersProps = {},
queryOptions = {}
) {
const { query } = useRouter();
const { pid } = query as { pid: string };
const { data: session } = useSession();
const { search, sort, tag } = filters;
const { search } = filters;

const queryClient = useQueryClient();

const featureColorQueryState =
queryClient.getQueryState<{ id: Feature['id']; color: string }[]>('feature-colors');
// const featureColorQueryState =
// queryClient.getQueryState<{ id: Feature['id']; color: string }[]>('feature-colors');

const featureColors = useColorFeatures(pid, sid);

const fetchFeatures = () =>
SCENARIOS.request({
Expand All @@ -193,8 +202,7 @@ export function useSelectedFeatures(

return useQuery(['selected-features', sid], fetchFeatures, {
...queryOptions,
enabled:
!!sid && ((featureColorQueryState && featureColorQueryState.status === 'success') || true),
enabled: (!!sid && featureColors?.length > 0) || true,
select: ({ data }) => {
const { features = [] } = data;

Expand Down Expand Up @@ -271,16 +279,12 @@ export function useSelectedFeatures(
id: featureId,
name: alias || featureClassName,
type: tag,
// type: Math.random() < 0.5 ? 'test' : 'andres',
description,
amountRange: {
min: amountMin,
max: amountMax,
},
color: featureColorQueryState
? featureColorQueryState?.data?.find(({ id }) => featureId === id)?.color
: null,

color: featureColors.find(({ id }) => featureId === id)?.color,
// SPLIT
splitOptions,
splitSelected,
Expand Down Expand Up @@ -749,3 +753,25 @@ export function useProjectFeatures(
}
);
}

export function useColorFeatures(projectId: Project['id'], sid: Scenario['id']) {
const useAllFeaturesQuery = useAllFeatures(projectId, {});
const targetedFeaturesQuery = useTargetedFeatures(sid);

if (targetedFeaturesQuery.isSuccess && useAllFeaturesQuery.isSuccess) {
const data = [...(useAllFeaturesQuery.data?.data || []), ...targetedFeaturesQuery.data];
return data.map(({ id }, index) => {
const color =
data.length > COLORS['features-preview'].ramp.length
? chroma.scale(COLORS['features-preview'].ramp).colors(data.length)[index]
: COLORS['features-preview'].ramp[index];

return {
id,
color,
};
});
}

return [];
}
38 changes: 13 additions & 25 deletions app/hooks/map/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { useMemo } from 'react';

import chroma from 'chroma-js';
import { Layer } from 'mapbox-gl';

import { CostSurface } from 'types/api/cost-surface';
Expand Down Expand Up @@ -484,44 +483,33 @@ export function useTargetedPreviewLayers({
return useMemo(() => {
if (!active || !bbox || !features) return [];

const { selectedFeatures = [] } = options;
const { layerSettings } = options;

const FEATURES = [...features]
.filter((ft) => selectedFeatures.includes(ft.id as string))
.sort((a, b) => {
const aIndex = selectedFeatures.indexOf(a.id as string);
const bIndex = selectedFeatures.indexOf(b.id as string);
return bIndex - aIndex;
});

const { opacity = 1, visibility = true } = options || {};
const FEATURES = features.filter((ft) => Object.keys(layerSettings).includes(ft.id));

const getLayerVisibility = () => {
const getLayerVisibility = (
visibility: UseTargetedPreviewLayers['options']['layerSettings'][string]['visibility']
) => {
if (!visibility) {
return 'none';
}
return 'visible';
};

return FEATURES.map((f, index) => {
const { id, parentId, splitted, value } = f;
return FEATURES.map((f) => {
const { id, parentId, value, splitSelected } = f;

const ID = splitted ? parentId : id;
const { opacity = 1, color } = layerSettings[id] || {};

const COLOR =
selectedFeatures.length > COLORS['features-preview'].ramp.length
? chroma.scale(COLORS['features-preview'].ramp).colors(selectedFeatures.length)[
selectedFeatures.length - 1 - index
]
: COLORS['features-preview'].ramp[selectedFeatures.length - 1 - index];
const _id = splitSelected ? parentId : id;

return {
id: `feature-${id}-targeted-preview-layer-${cache}`,
type: 'vector',
source: {
type: 'vector',
tiles: [
`${process.env.NEXT_PUBLIC_API_URL}/api/v1/geo-features/${ID}/preview/tiles/{z}/{x}/{y}.mvt?bbox=[${bbox}]`,
`${process.env.NEXT_PUBLIC_API_URL}/api/v1/geo-features/${_id}/preview/tiles/{z}/{x}/{y}.mvt?bbox=[${bbox}]`,
],
},
render: {
Expand All @@ -536,10 +524,10 @@ export function useTargetedPreviewLayers({
],
}),
layout: {
visibility: getLayerVisibility(),
visibility: getLayerVisibility(layerSettings[id].visibility),
},
paint: {
'fill-color': COLOR,
'fill-color': color,
'fill-opacity': opacity,
},
},
Expand All @@ -553,7 +541,7 @@ export function useTargetedPreviewLayers({
],
}),
layout: {
visibility: getLayerVisibility(),
visibility: getLayerVisibility(layerSettings[id].visibility),
},
paint: {
'line-color': '#000',
Expand Down
1 change: 1 addition & 0 deletions app/hooks/map/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ export interface UseTargetedPreviewLayers {
selectedFeatures?: Array<string>;
opacity?: number;
visibility?: boolean;
layerSettings?: Record<string, { opacity?: number; visibility?: boolean; color: string }>;
};
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { useCallback, useState, ChangeEvent, useEffect } from 'react';

import { useQueryClient } from 'react-query';

import { useRouter } from 'next/router';

import { useAppDispatch, useAppSelector } from 'store/hooks';
Expand All @@ -11,7 +9,7 @@ import {
setLayerSettings,
} from 'store/slices/projects/[id]';

import { useAllFeatures } from 'hooks/features';
import { useAllFeatures, useColorFeatures } from 'hooks/features';

import ActionsMenu from 'layout/project/sidebar/project/inventory-panel/features/actions-menu';
import FeaturesBulkActionMenu from 'layout/project/sidebar/project/inventory-panel/features/bulk-action-menu';
Expand Down Expand Up @@ -46,12 +44,9 @@ const InventoryPanelFeatures = ({ noData: noDataMessage }: { noData: string }):
});
const [selectedFeaturesIds, setSelectedFeaturesIds] = useState<Feature['id'][]>([]);
const { query } = useRouter();
const { pid } = query as { pid: string };

const queryClient = useQueryClient();
const { pid, sid } = query as { pid: string; sid: string };

const featureColorQueryState =
queryClient.getQueryState<{ id: Feature['id']; color: string }[]>('feature-colors');
const featureColors = useColorFeatures(pid, sid);

const allFeaturesQuery = useAllFeatures(
pid,
Expand All @@ -68,7 +63,7 @@ const InventoryPanelFeatures = ({ noData: noDataMessage }: { noData: string }):
{
select: ({ data }) => {
return data?.map((feature) => {
const { color } = featureColorQueryState?.data?.find(({ id }) => feature.id === id) || {};
const { color } = featureColors?.find(({ id }) => feature.id === id) || {};

return {
id: feature.id,
Expand All @@ -83,7 +78,7 @@ const InventoryPanelFeatures = ({ noData: noDataMessage }: { noData: string }):
},
placeholderData: { data: [] },
keepPreviousData: true,
enabled: featureColorQueryState?.status === 'success',
enabled: featureColors.length > 0,
}
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const DeleteModal = ({
onDismiss,
onDone,
}: {
features: (Feature & { name: string })[];
features: any[];
selectedFeaturesIds: Feature['id'][];
onDismiss?: ModalProps['onDismiss'];
onDone?: () => void;
Expand All @@ -28,23 +28,25 @@ const DeleteModal = ({

const selectedFeaturesQuery = useSelectedFeatures(sid);

const selectedFeatures = useMemo(
const featuresToRemove = useMemo(
() => features.filter(({ id }) => selectedFeaturesIds.includes(id)) ?? [],
[features, selectedFeaturesIds]
);

const featureNames = selectedFeatures.map(({ name }) => name);
const featureNames = featuresToRemove.map(({ name }) => name);

const handleBulkDelete = useCallback(() => {
const deletableFeatureIds = selectedFeatures.map(({ id }) => id);
const deletableFeatureIds = featuresToRemove.map(({ id }) => id);

selectedFeaturesMutation.mutate(
{
id: sid,
data: {
status: 'draft',
features: selectedFeaturesQuery.data
.filter(({ id: featureId }) => !deletableFeatureIds.includes(featureId))
.filter(({ id: featureId }) => {
return !deletableFeatureIds.includes(featureId);
})
.map(
({
metadata,
Expand All @@ -55,30 +57,54 @@ const DeleteModal = ({
color,
splitOptions,
splitFeaturesSelected,
geoprocessingOperations,
splitFeaturesOptions,
intersectFeaturesSelected,
splitSelected,
...sf
}) => ({
...sf,
})
}) => {
if (splitSelected) {
const featureValues = features
.filter(({ id }) => deletableFeatureIds.includes(id))
.map(({ value }) => value);

return {
...sf,
...(geoprocessingOperations && {
geoprocessingOperations: geoprocessingOperations.map((go) => ({
...go,
splits: go.splits.filter((s) => {
return !featureValues.includes(s.value);
}),
})),
}),
};
}

return {
...sf,
geoprocessingOperations,
};
}
),
},
},
{
onSuccess: async () => {
await queryClient.invalidateQueries(['selected-features', sid]);
await queryClient.invalidateQueries(['targeted-features', sid]);
onDone?.();
onDismiss();
},
}
);
}, [
selectedFeatures,
onDismiss,
queryClient,
sid,
selectedFeaturesMutation,
features,
selectedFeaturesQuery.data,
onDone,
featuresToRemove,
]);

return (
Expand Down
Loading

0 comments on commit 5eb44f1

Please sign in to comment.