Skip to content

Commit

Permalink
highlight clicked cell
Browse files Browse the repository at this point in the history
  • Loading branch information
j8seangel committed Apr 24, 2024
1 parent 2e084a2 commit b97f839
Show file tree
Hide file tree
Showing 16 changed files with 90 additions and 106 deletions.
25 changes: 18 additions & 7 deletions apps/fishing-map/features/map/map.hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ import { useSelector } from 'react-redux'
import { useCallback, useEffect, useMemo } from 'react'
import { debounce } from 'lodash'
import { useTranslation } from 'react-i18next'
import { DataviewCategory, DataviewType, Locale } from '@globalfishingwatch/api-types'
import { Locale } from '@globalfishingwatch/api-types'
import { GFWAPI } from '@globalfishingwatch/api-client'
import { ResolverGlobalConfig } from '@globalfishingwatch/deck-layer-composer'
import {
ResolverGlobalConfig,
useMapHoverInteraction,
} from '@globalfishingwatch/deck-layer-composer'
import { DeckLayerPickingObject } from '@globalfishingwatch/deck-layers'
import { useTimerangeConnect } from 'features/timebar/timebar.hooks'
import {
Expand All @@ -25,7 +28,7 @@ import {
} from 'features/app/selectors/app.selectors'
import { selectWorkspaceVisibleEventsArray } from 'features/workspace/workspace.selectors'
import { selectDebugOptions } from 'features/debug/debug.slice'
import { MAX_TOOLTIP_LIST, ExtendedFeatureVessel } from './map.slice'
import { MAX_TOOLTIP_LIST, ExtendedFeatureVessel, selectClickedEvent } from './map.slice'
import { useViewStateAtom } from './map-viewport.hooks'

export const SUBLAYER_INTERACTION_TYPES_WITH_VESSEL_INTERACTION = ['activity', 'detections']
Expand Down Expand Up @@ -53,8 +56,14 @@ export const useGlobalConfigConnect = () => {
const detectionsVisualizationMode = useSelector(selectDetectionsVisualizationMode)
const visibleEvents = useSelector(selectWorkspaceVisibleEventsArray)
const mapResolution = useSelector(selectMapResolution)
const clickedFeatures = useSelector(selectClickedEvent)
const hoverFeatures = useMapHoverInteraction()?.features
const debug = useSelector(selectDebugOptions)?.debug

const highlightedFeatures = useMemo(() => {
return [...(clickedFeatures?.features || []), ...(hoverFeatures || [])]
}, [clickedFeatures?.features, hoverFeatures])

return useMemo(() => {
let globalConfig: ResolverGlobalConfig = {
zoom: viewState.zoom,
Expand All @@ -69,6 +78,7 @@ export const useGlobalConfigConnect = () => {
resolution: mapResolution,
highlightedTime: highlightedTime || {},
visibleEvents,
highlightedFeatures,
}
if (showTimeComparison && timeComparisonValues) {
globalConfig = {
Expand All @@ -87,9 +97,10 @@ export const useGlobalConfigConnect = () => {
activityVisualizationMode,
detectionsVisualizationMode,
mapResolution,
highlightedTime,
visibleEvents,
highlightedFeatures,
showTimeComparison,
highlightedTime,
timeComparisonValues,
])
}
Expand All @@ -111,8 +122,8 @@ export const useDebouncedDispatchHighlightedEvent = () => {

// TODO:deck do this within the deck layer
export const useMapHighlightedEvent = (features?: DeckLayerPickingObject[]) => {
const highlightedEvents = useSelector(selectHighlightedEvents)
const debounceDispatch = useDebouncedDispatchHighlightedEvent()
// const highlightedEvents = useSelector(selectHighlightedEvents)
// const debounceDispatch = useDebouncedDispatchHighlightedEvent()

const setHighlightedEventDebounced = useCallback(() => {
// let highlightEvent: string | undefined
Expand All @@ -134,7 +145,7 @@ export const useMapHighlightedEvent = (features?: DeckLayerPickingObject[]) => {
// } else if (highlightedEvents && highlightedEvents.length) {
// debounceDispatch(undefined)
// }
}, [features, highlightedEvents, debounceDispatch])
}, [])

useEffect(() => {
setHighlightedEventDebounced()
Expand Down
2 changes: 1 addition & 1 deletion apps/fishing-map/features/timebar/timebar-vessel.hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ export const useTimebarVesselEvents = () => {
color: instance.getVesselColor(),
chunks,
// TODO vessel status
status: instance.dataStatus.find((s) => s.type === 'track')?.status,
// status: instance.dataStatus.find((s) => s.type === 'track')?.status,
defaultLabel: instance.getVesselName(),
getHighlighterLabel: getTrackEventHighlighterLabel,
getHighlighterIcon: 'vessel',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { AnyDeckLayer } from '@globalfishingwatch/deck-layers'
import { DataviewInstance } from '@globalfishingwatch/api-types'
import { getDataviewsResolved } from '../resolvers'
import { dataviewToDeckLayer, ResolverGlobalConfig } from '../resolvers'
import { useMapHoverInteraction } from '../interactions'

// Atom used to have all deck instances available
export const deckLayerInstancesAtom = atom<AnyDeckLayer[]>([])
Expand All @@ -17,21 +16,20 @@ export function useDeckLayerComposer({
globalConfig: ResolverGlobalConfig
}) {
const [deckLayers, setDeckLayers] = useAtom(deckLayerInstancesAtom)
const hoverFeatures = useMapHoverInteraction()?.features

const layerInstances = useMemo(() => {
const dataviewsMerged = getDataviewsResolved(dataviews, globalConfig) as DataviewInstance[]
const deckLayers = dataviewsMerged?.flatMap((dataview) => {
// TODO research if we can use atoms here
try {
return dataviewToDeckLayer(dataview, globalConfig, hoverFeatures)
return dataviewToDeckLayer(dataview, globalConfig)
} catch (e) {
console.warn(e)
return []
}
})
return deckLayers
}, [dataviews, hoverFeatures, globalConfig])
}, [dataviews, globalConfig])

useEffect(() => {
setDeckLayers(layerInstances)
Expand Down
11 changes: 5 additions & 6 deletions libs/deck-layer-composer/src/resolvers/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ import {
} from '@globalfishingwatch/datasets-client'
import { DeckResolverFunction } from './types'

export const resolveDeckContextLayerProps: DeckResolverFunction<
ContextLayerProps,
ContextPickingObject
> = (dataview, globalConfig, interactions) => {
export const resolveDeckContextLayerProps: DeckResolverFunction<ContextLayerProps> = (
dataview,
{ highlightedFeatures }
) => {
// TODO make this work for auxiliar layers
// https://github.com/GlobalFishingWatch/frontend/blob/master/libs/dataviews-client/src/resolve-dataviews-generators.ts#L606
const { url } = resolveDataviewDatasetResource(dataview, DatasetTypes.Context)
Expand Down Expand Up @@ -50,7 +50,6 @@ export const resolveDeckContextLayerProps: DeckResolverFunction<
color: dataview.config?.color!,
idProperty,
valueProperties,
hoveredFeatures: interactions,
// clickedFeatures,
highlightedFeatures: highlightedFeatures as ContextPickingObject[],
}
}
10 changes: 5 additions & 5 deletions libs/deck-layer-composer/src/resolvers/fourwings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ import { getDataviewAvailableIntervals } from './dataviews'
import { DeckResolverFunction } from './types'

// TODO: decide if include static here or create a new one
export const resolveDeckFourwingsLayerProps: DeckResolverFunction<
FourwingsLayerProps,
FourwingsPickingObject
> = (dataview, { start, end, resolution, debug }, interactions): FourwingsLayerProps => {
export const resolveDeckFourwingsLayerProps: DeckResolverFunction<FourwingsLayerProps> = (
dataview,
{ start, end, resolution, debug, highlightedFeatures }
): FourwingsLayerProps => {
const startTime = start ? getUTCDateTime(start).toMillis() : 0
const endTime = end ? getUTCDateTime(end).toMillis() : Infinity

Expand Down Expand Up @@ -125,7 +125,7 @@ export const resolveDeckFourwingsLayerProps: DeckResolverFunction<
visualizationMode,
aggregationOperation,
availableIntervals,
hoveredFeatures: interactions,
highlightedFeatures: highlightedFeatures as FourwingsPickingObject[],
minVisibleValue: dataview.config?.minVisibleValue,
maxVisibleValue: dataview.config?.maxVisibleValue,
debug: debug ?? false,
Expand Down
20 changes: 3 additions & 17 deletions libs/deck-layer-composer/src/resolvers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,8 @@ import {
AnyDeckLayer,
BaseMapLayer,
ClusterLayer,
ContextFeature,
ContextLayer,
ContextPickingInfo,
ContextPickingObject,
DeckLayerPickingObject,
FourwingsLayer,
FourwingsPickingObject,
VesselLayer,
} from '@globalfishingwatch/deck-layers'
import { ResolverGlobalConfig } from './types'
Expand All @@ -30,8 +25,7 @@ export * from './vessels'

export const dataviewToDeckLayer = (
dataview: DataviewInstance,
globalConfig: ResolverGlobalConfig,
interactions = [] as DeckLayerPickingObject[]
globalConfig: ResolverGlobalConfig
): AnyDeckLayer => {
if (dataview.config?.type === DataviewType.Basemap) {
const deckLayerProps = resolveDeckBasemapLayerProps(dataview, globalConfig)
Expand All @@ -41,20 +35,12 @@ export const dataviewToDeckLayer = (
dataview.config?.type === DataviewType.HeatmapAnimated ||
dataview.config?.type === DataviewType.HeatmapStatic
) {
const deckLayerProps = resolveDeckFourwingsLayerProps(
dataview,
globalConfig,
interactions as FourwingsPickingObject[]
)
const deckLayerProps = resolveDeckFourwingsLayerProps(dataview, globalConfig)
const layer = new FourwingsLayer(deckLayerProps)
return layer
}
if (dataview.config?.type === DataviewType.Context) {
const deckLayerProps = resolveDeckContextLayerProps(
dataview,
globalConfig,
interactions as ContextPickingObject[]
)
const deckLayerProps = resolveDeckContextLayerProps(dataview, globalConfig)
const layer = new ContextLayer(deckLayerProps)
return layer
}
Expand Down
9 changes: 3 additions & 6 deletions libs/deck-layer-composer/src/resolvers/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,10 @@ export type ResolverGlobalConfig = {
highlightedTime: Partial<TimeRange>
locale?: string
visibleEvents: EventTypes[]
highlightedFeatures?: DeckLayerPickingObject[]
}

export type DeckResolverFunction<
LayerProps = AnyDeckLayer['props'],
InteractionFeature = DeckLayerPickingObject
> = (
export type DeckResolverFunction<LayerProps = AnyDeckLayer['props']> = (
dataview: UrlDataviewInstance,
globalConfig: ResolverGlobalConfig,
interactions?: InteractionFeature[]
globalConfig: ResolverGlobalConfig
) => LayerProps
20 changes: 10 additions & 10 deletions libs/deck-layer-composer/src/resolvers/vessels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ import { DeckResolverFunction } from './types'
export const resolveDeckVesselLayerProps: DeckResolverFunction<VesselLayerProps> = (
dataview,
globalConfig
) => {
): VesselLayerProps => {
const trackUrl = resolveDataviewDatasetResource(dataview, DatasetTypes.Tracks)?.url

const { start, end, highlightedFeatures, visibleEvents, highlightedTime } = globalConfig
return {
id: dataview.id,
visible: dataview.config?.visible ?? true,
category: dataview.category!,
name: dataview.config?.name!,
endTime: getUTCDateTime(globalConfig.end!).toMillis(),
startTime: getUTCDateTime(globalConfig.start!).toMillis(),
endTime: getUTCDateTime(end!).toMillis(),
startTime: getUTCDateTime(start!).toMillis(),
...(trackUrl && {
trackUrl: GFWAPI.generateUrl(trackUrl, { absolute: true }),
}),
Expand All @@ -32,8 +32,8 @@ export const resolveDeckVesselLayerProps: DeckResolverFunction<VesselLayerProps>
url: `${API_GATEWAY}${resource.url}`,
}
}),
visibleEvents: globalConfig.visibleEvents,
// clickedFeatures,
visibleEvents: visibleEvents,
highlightEventIds: highlightedFeatures?.map((feature) => feature.id),
...(dataview.config?.filters?.['speed']?.length && {
minSpeedFilter: parseFloat(dataview.config?.filters?.['speed'][0]),
maxSpeedFilter: parseFloat(dataview.config?.filters?.['speed'][1]),
Expand All @@ -42,11 +42,11 @@ export const resolveDeckVesselLayerProps: DeckResolverFunction<VesselLayerProps>
minElevationFilter: parseFloat(dataview.config?.filters?.['elevation'][0]),
maxElevationFilter: parseFloat(dataview.config?.filters?.['elevation'][1]),
}),
...(globalConfig.highlightedTime?.start && {
highlightStartTime: getUTCDateTime(globalConfig.highlightedTime?.start).toMillis(),
...(highlightedTime?.start && {
highlightStartTime: getUTCDateTime(highlightedTime?.start).toMillis(),
}),
...(globalConfig.highlightedTime?.end && {
highlightEndTime: getUTCDateTime(globalConfig.highlightedTime?.end).toMillis(),
...(highlightedTime?.end && {
highlightEndTime: getUTCDateTime(highlightedTime?.end).toMillis(),
}),
}
}
20 changes: 9 additions & 11 deletions libs/deck-layers/src/layers/context/ContextLayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,16 @@ export class ContextLayer<PropsT = {}> extends CompositeLayer<_ContextLayerProps
static defaultProps = defaultProps

getHighlightLineWidth(d: ContextFeature): number {
const { hoveredFeatures = [], clickedFeatures = [], idProperty } = this.props
return getPickedFeatureToHighlight(d, clickedFeatures, idProperty!) ||
getPickedFeatureToHighlight(d, hoveredFeatures, idProperty!)
const { highlightedFeatures = [], idProperty } = this.props
return getPickedFeatureToHighlight(d, highlightedFeatures, idProperty!) ||
getPickedFeatureToHighlight(d, highlightedFeatures, idProperty!)
? 1
: 0
}

getFillColor(d: ContextFeature): Color {
const { hoveredFeatures = [], idProperty } = this.props
return getPickedFeatureToHighlight(d, hoveredFeatures, idProperty!)
const { highlightedFeatures = [], idProperty } = this.props
return getPickedFeatureToHighlight(d, highlightedFeatures, idProperty!)
? COLOR_HIGHLIGHT_FILL
: COLOR_TRANSPARENT
}
Expand Down Expand Up @@ -120,7 +120,7 @@ export class ContextLayer<PropsT = {}> extends CompositeLayer<_ContextLayerProps
}

renderLayers() {
const { hoveredFeatures, clickedFeatures, color, layers } = this.props
const { highlightedFeatures, color, layers } = this.props
return layers.map((layer) => {
if (layer.id === ContextLayerId.EEZBoundaries) {
return new TileLayer<TileLayerProps>({
Expand Down Expand Up @@ -169,7 +169,7 @@ export class ContextLayer<PropsT = {}> extends CompositeLayer<_ContextLayerProps
getLayerGroupOffset(LayerGroup.OutlinePolygonsBackground, params),
getFillColor: (d) => this.getFillColor(d as ContextFeature),
updateTriggers: {
getFillColor: [clickedFeatures, hoveredFeatures],
getFillColor: [highlightedFeatures],
},
}),
...(layer.id !== ContextLayerId.EEZ && layer.id !== ContextLayerId.EEZBoundaries
Expand All @@ -189,15 +189,13 @@ export class ContextLayer<PropsT = {}> extends CompositeLayer<_ContextLayerProps
lineWidthMinPixels: 0,
lineWidthUnits: 'pixels',
filled: false,
visible:
(hoveredFeatures && hoveredFeatures?.length > 0) ||
(clickedFeatures && clickedFeatures?.length > 0),
visible: highlightedFeatures && highlightedFeatures?.length > 0,
getPolygonOffset: (params) =>
getLayerGroupOffset(LayerGroup.OutlinePolygonsHighlighted, params),
getLineWidth: (d) => this.getHighlightLineWidth(d as ContextFeature),
getLineColor: COLOR_HIGHLIGHT_LINE,
updateTriggers: {
getLineWidth: [clickedFeatures, hoveredFeatures],
getLineWidth: [highlightedFeatures],
},
}),
]
Expand Down
3 changes: 1 addition & 2 deletions libs/deck-layers/src/layers/context/context.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ export type ContextLayerProps = {
color: string
idProperty?: string
valueProperties?: string[]
hoveredFeatures?: ContextPickingObject[]
clickedFeatures?: ContextPickingObject[]
highlightedFeatures?: ContextPickingObject[]
}

export type ContextFeatureProperties = {
Expand Down
Loading

0 comments on commit b97f839

Please sign in to comment.