Skip to content

Commit

Permalink
Merge pull request #2764 from GlobalFishingWatch/fishing-map/release-…
Browse files Browse the repository at this point in the history
…hotfixes

Release fixes
  • Loading branch information
j8seangel authored Aug 5, 2024
2 parents 93d37a4 + 74a62be commit 893f9fb
Show file tree
Hide file tree
Showing 18 changed files with 169 additions and 95 deletions.
10 changes: 7 additions & 3 deletions apps/fishing-map/features/map/Map.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCallback, useEffect, useRef } from 'react'
import { Fragment, useCallback, useEffect, useRef } from 'react'
import { useSelector } from 'react-redux'
import { DeckGL, DeckGLRef } from '@deck.gl/react'
import dynamic from 'next/dynamic'
Expand Down Expand Up @@ -135,11 +135,15 @@ const MapWrapper = () => {
>
<MapAnnotations />
</DeckGL>
{isMapDrawing && <DrawDialog />}
{isMapDrawing && (
<Fragment>
<CoordinateEditOverlay />
<DrawDialog />
</Fragment>
)}
<MapPopups />
<ErrorNotificationDialog />
<MapAnnotationsDialog />
<CoordinateEditOverlay />
<MapControls mapLoading={mapLoading || isReportAreaLoading} />
{isWorkspaceLocation && !isReportLocation && (
<Hint id="fishingEffortHeatmap" className={styles.helpHintLeft} />
Expand Down
19 changes: 18 additions & 1 deletion apps/fishing-map/features/map/map-layers.hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
} from '@globalfishingwatch/deck-layer-composer'
import { GFWAPI } from '@globalfishingwatch/api-client'
import { FourwingsLayer, HEATMAP_ID } from '@globalfishingwatch/deck-layers'
import { UrlDataviewInstance } from '@globalfishingwatch/dataviews-client'
import { AsyncReducerStatus } from 'utils/async-slice'
import {
selectWorkspaceStatus,
Expand All @@ -22,7 +23,11 @@ import {
selectIsUserLocation,
selectIsWorkspaceLocation,
} from 'routes/routes.selectors'
import { selectDataviewInstancesResolvedVisible } from 'features/dataviews/selectors/dataviews.selectors'
import {
selectActivityMergedDataviewId,
selectDataviewInstancesResolvedVisible,
selectDetectionsMergedDataviewId,
} from 'features/dataviews/selectors/dataviews.selectors'
import {
selectBivariateDataviews,
selectActivityVisualizationMode,
Expand All @@ -48,6 +53,18 @@ import { useDrawLayerInstance } from './overlays/draw/draw.hooks'
import { useMapViewState } from './map-viewport.hooks'
import { selectClickedEvent } from './map.slice'

export const useActivityDataviewId = (dataview: UrlDataviewInstance) => {
const activityMergedDataviewId = useSelector(selectActivityMergedDataviewId)
const detectionsMergedDataviewId = useSelector(selectDetectionsMergedDataviewId)
const dataviewId =
dataview.category === DataviewCategory.Environment
? dataview.id
: dataview.category === DataviewCategory.Detections
? detectionsMergedDataviewId
: activityMergedDataviewId
return dataviewId
}

export const useGlobalConfigConnect = () => {
const { start, end } = useTimerangeConnect()
const timebarHighlightedTime = useSelector(selectHighlightedTime)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useTranslation } from 'react-i18next'
import { useCallback, useState } from 'react'
import { useCallback, useEffect, useState } from 'react'
import { useSelector } from 'react-redux'
import { Feature, Polygon } from 'geojson'
import { Button, IconButton, InputText } from '@globalfishingwatch/ui-components'
Expand All @@ -25,6 +25,13 @@ export const CoordinateEditOverlay = () => {
const editingPointLongitude =
newPointLongitude !== null ? Number(newPointLongitude) : Number(currentPointCoordinates?.[0])

useEffect(() => {
if (!currentPointCoordinates?.length) {
setNewPointLatitude(null)
setNewPointLongitude(null)
}
}, [currentPointCoordinates])

const allowDeletePoint =
drawingMode === 'polygons'
? drawData &&
Expand Down Expand Up @@ -65,12 +72,6 @@ export const CoordinateEditOverlay = () => {
[drawLayer, editingPointLatitude]
)

const onDeletePoint = useCallback(() => {
if (allowDeletePoint) {
drawLayer?.deleteSelectedPosition()
}
}, [allowDeletePoint, drawLayer])

const resetEditingPoint = useCallback(() => {
// As this is triggered with clickOutside we need to wait to reset
// in case before the deleteSelectedPosition is called
Expand All @@ -81,6 +82,13 @@ export const CoordinateEditOverlay = () => {
}, 1)
}, [drawLayer])

const onDeletePoint = useCallback(() => {
if (allowDeletePoint) {
drawLayer?.deleteSelectedPosition()
resetEditingPoint()
}
}, [allowDeletePoint, drawLayer, resetEditingPoint])

const onConfirm = useCallback(() => {
drawLayer?.setCurrentPointCoordinates([editingPointLongitude, editingPointLatitude])
resetEditingPoint()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ export const getAreaIdFromFeature = (
): AreaKeyId => {
return (
feature.properties?.gfw_id ||
// TODO:deck check if promoteId is covered for every case in the getPickingInfo function
feature.properties?.[(feature as any).promoteId as string] ||
(feature.id as string)
)
Expand Down Expand Up @@ -63,20 +62,6 @@ export const useContextInteractions = () => {
const setReportArea = useCallback(
(feature: ContextPickingObject | UserLayerPickingObject) => {
const { title, value } = feature
// TODO:deck review this
// const areaId = getAreaIdFromFeature(feature) as string
// Report already does it on page reload but to avoid waiting
// this moves the map to the same position
// const bounds = getFeatureBounds(feature)
// if (bounds) {
// const boundsParams = {
// padding: FIT_BOUNDS_REPORT_PADDING,
// mapWidth: window.innerWidth / 2,
// mapHeight: window.innerHeight - TIMEBAR_HEIGHT - FOOTER_HEIGHT,
// }
// fitMapBounds(bounds, boundsParams)
// }

dispatchClickedEvent(null)

trackEvent({
Expand Down
3 changes: 1 addition & 2 deletions apps/fishing-map/features/timebar/TimebarSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,7 @@ const TimebarSettings = ({ loading = false }: { loading: boolean }) => {
const isStandaloneVesselLocation = useSelector(selectIsVesselLocation)
const vesselIds = activeTrackDataviews.map((v) => v.id)
const vesselLayers = useGetDeckLayers<VesselLayer>(vesselIds)
// TODO:deck better validation of the layer contains data
const hasTracksData = vesselLayers?.length > 0
const hasTracksData = vesselLayers?.some((layer) => layer?.instance.getVesselTracksLayersLoaded())
const activeVesselsDataviews = useSelector(selectActiveVesselsDataviews)
const { timebarVisualisation, dispatchTimebarVisualisation } = useTimebarVisualisationConnect()
const { timebarSelectedEnvId, dispatchTimebarSelectedEnvId } = useTimebarEnvironmentConnect()
Expand Down
10 changes: 6 additions & 4 deletions apps/fishing-map/features/vessel/activity/VesselActivity.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { useTranslation } from 'react-i18next'
import { Fragment, useMemo } from 'react'
import { useSelector } from 'react-redux'
import { Choice, ChoiceOption, Spinner } from '@globalfishingwatch/ui-components'
import { useDebounce } from '@globalfishingwatch/react-hooks'
import ActivityByType from 'features/vessel/activity/activity-by-type/ActivityByType'
import ActivityByVoyage from 'features/vessel/activity/activity-by-voyage/ActivityByVoyage'
import { VesselActivitySummary } from 'features/vessel/activity/VesselActivitySummary'
Expand All @@ -21,6 +22,7 @@ const VesselActivity = () => {
const activityMode = useSelector(selectVesselActivityMode)
const hasEventsDataset = useSelector(selectVesselHasEventsDatasets)
const eventsLoading = useVesselProfileEventsLoading()
const eventsLoadingDebounce = useDebounce(eventsLoading, 400)
const eventsError = useVesselProfileEventsError()
const vesselProfileDataview = useSelector(selectVesselProfileDataview)
const vesselLayer = useVesselProfileLayer()
Expand Down Expand Up @@ -49,7 +51,7 @@ const VesselActivity = () => {
[t]
)

if (hasVesselEvents && (!vesselLayer?.instance || eventsLoading)) {
if (hasVesselEvents && (!vesselLayer?.instance || eventsLoadingDebounce)) {
return (
<div className={styles.placeholder}>
<Spinner />
Expand Down Expand Up @@ -87,13 +89,13 @@ const VesselActivity = () => {
onSelect={setActivityMode}
/>
</div>
{eventsLoading && (
{eventsLoadingDebounce && (
<div className={styles.placeholder}>
<Spinner />
</div>
)}
{!eventsLoading && activityMode === 'type' && <ActivityByType />}
{!eventsLoading && activityMode === 'voyage' && <ActivityByVoyage />}
{!eventsLoadingDebounce && activityMode === 'type' && <ActivityByType />}
{!eventsLoadingDebounce && activityMode === 'voyage' && <ActivityByVoyage />}
</Fragment>
)
}
Expand Down
1 change: 0 additions & 1 deletion apps/fishing-map/features/vessel/vessel-events.hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ const useVesselProfileEvents = () => {

export const useVesselProfileEventsLoading = () => {
const vesselInstance = useVesselProfileLayer()
// TODO:deck review this and try to avoid intermediate loading states while toggled on events load
return vesselInstance?.instance && !vesselInstance?.instance?.getVesselEventsLayersLoaded()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import {
UrlDataviewInstance,
} from '@globalfishingwatch/dataviews-client'
import { DatasetTypes } from '@globalfishingwatch/api-types'
import { useDeckLayerLoadedState } from '@globalfishingwatch/deck-layer-composer'
import { useGetDeckLayer } from '@globalfishingwatch/deck-layer-composer'
import { FourwingsLayer } from '@globalfishingwatch/deck-layers'
import { useDataviewInstancesConnect } from 'features/workspace/workspace.hook'
import { selectBivariateDataviews, selectReadOnly } from 'features/app/selectors/app.selectors'
import { useLocationConnect } from 'routes/routes.hook'
Expand All @@ -23,8 +24,10 @@ import { SAR_DATAVIEW_SLUG } from 'data/workspaces'
import DatasetNotFound from 'features/workspace/shared/DatasetNotFound'
import styles from 'features/workspace/shared/LayerPanel.module.css'
import Color from 'features/workspace/common/Color'
import { selectIsGFWUser } from 'features/user/selectors/user.selectors'
import { TrackCategory, trackEvent } from 'features/app/analytics.hooks'
import MapLegend from 'features/workspace/common/MapLegend'
import { useActivityDataviewId } from 'features/map/map-layers.hooks'
import DatasetFilterSource from '../shared/DatasetSourceField'
import DatasetFlagField from '../shared/DatasetFlagsField'
import DatasetSchemaField from '../shared/DatasetSchemaField'
Expand Down Expand Up @@ -57,14 +60,15 @@ function ActivityLayerPanel({

const { deleteDataviewInstance, upsertDataviewInstance } = useDataviewInstancesConnect()
const { dispatchQueryParams } = useLocationConnect()
const isGFWUser = useSelector(selectIsGFWUser)
const bivariateDataviews = useSelector(selectBivariateDataviews)
const hintsDismissed = useSelector(selectHintsDismissed)
const readOnly = useSelector(selectReadOnly)
const layerActive = dataview?.config?.visible ?? true
const layerLoadedState = useDeckLayerLoadedState()
const layerLoaded = Object.entries(layerLoadedState).some(
([id, state]) => id.split(',').includes(dataview.id) && state.loaded
)
const dataviewId = useActivityDataviewId(dataview)
const activityLayer = useGetDeckLayer<FourwingsLayer>(dataviewId)
const layerLoaded = activityLayer?.loaded
const layerError = activityLayer?.instance?.getError?.()

// TODO remove when final decission on stats display is taken
// const urlTimeRange = useSelector(selectUrlTimeRange)
Expand Down Expand Up @@ -256,10 +260,25 @@ function ActivityLayerPanel({
{!readOnly && (
<Remove onClick={onRemoveLayerClick} loading={layerActive && !layerLoaded} />
)}
{!readOnly && layerError && (
<IconButton
icon={'warning'}
type={'warning'}
tooltip={
isGFWUser
? `${t(
'errors.layerLoading',
'There was an error loading the layer'
)} (${layerError})`
: t('errors.layerLoading', 'There was an error loading the layer')
}
size="small"
/>
)}
</div>
<IconButton
icon={layerActive ? 'more' : undefined}
type="default"
icon={layerError ? 'warning' : layerActive ? 'more' : undefined}
type={layerError ? 'warning' : 'default'}
loading={layerActive && !layerLoaded}
className={cx('print-hidden', styles.shownUntilHovered)}
size="small"
Expand Down
16 changes: 2 additions & 14 deletions apps/fishing-map/features/workspace/common/MapLegend.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
import cx from 'classnames'
import { useTranslation } from 'react-i18next'
import { useSelector } from 'react-redux'
import { LegendType, MapLegend, Tooltip, UILegend } from '@globalfishingwatch/ui-components'
import { DataviewCategory } from '@globalfishingwatch/api-types'
import { UrlDataviewInstance } from '@globalfishingwatch/dataviews-client'
import { DeckLegendAtom, useGetDeckLayerLegend } from '@globalfishingwatch/deck-layer-composer'
import {
selectActivityMergedDataviewId,
selectDetectionsMergedDataviewId,
} from 'features/dataviews/selectors/dataviews.selectors'
import { formatI18nNumber } from 'features/i18n/i18nNumber'
import { t } from 'features/i18n/i18n'
import MapLegendPlaceholder from 'features/workspace/common/MapLegendPlaceholder'
import { useActivityDataviewId } from 'features/map/map-layers.hooks'
import styles from './MapLegend.module.css'

const getLegendLabelTranslated = (legend?: DeckLegendAtom, tFn = t) => {
Expand Down Expand Up @@ -48,15 +44,7 @@ const MapLegendWrapper = ({
showPlaceholder?: boolean
}) => {
const { t } = useTranslation()
// TODO: restore useTimeCompareTimeDescription and delete the component in the map folder
const activityMergedDataviewId = useSelector(selectActivityMergedDataviewId)
const detectionsMergedDataviewId = useSelector(selectDetectionsMergedDataviewId)
const dataviewId =
dataview.category === DataviewCategory.Environment
? dataview.id
: dataview.category === DataviewCategory.Detections
? detectionsMergedDataviewId
: activityMergedDataviewId
const dataviewId = useActivityDataviewId(dataview)
const deckLegend = getLegendLabelTranslated(useGetDeckLayerLegend(dataviewId))
const isBivariate = deckLegend?.type === LegendType.Bivariate
const legendSublayerIndex = deckLegend?.sublayers?.findIndex(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { useState, useMemo, useTransition } from 'react'
import cx from 'classnames'
import { useTranslation } from 'react-i18next'
import { useSelector } from 'react-redux'
import { DatasetStatus, DatasetTypes } from '@globalfishingwatch/api-types'
import { Tooltip, ColorBarOption, IconButton } from '@globalfishingwatch/ui-components'
import { UrlDataviewInstance } from '@globalfishingwatch/dataviews-client'
import { getEnvironmentalDatasetRange } from '@globalfishingwatch/datasets-client'
import { useDeckLayerLoadedState } from '@globalfishingwatch/deck-layer-composer'
import { useDeckLayerLoadedState, useGetDeckLayer } from '@globalfishingwatch/deck-layer-composer'
import { FourwingsLayer } from '@globalfishingwatch/deck-layers'
import styles from 'features/workspace/shared/LayerPanel.module.css'
import { useDataviewInstancesConnect } from 'features/workspace/workspace.hook'
import ExpandedContainer from 'features/workspace/shared/ExpandedContainer'
Expand All @@ -22,6 +24,9 @@ import { getDatasetNameTranslated } from 'features/i18n/utils.datasets'
import { isBathymetryDataview } from 'features/dataviews/dataviews.utils'
import { showSchemaFilter } from 'features/workspace/common/LayerSchemaFilter'
import MapLegend from 'features/workspace/common/MapLegend'
import { useActivityDataviewId } from 'features/map/map-layers.hooks'
import { selectReadOnly } from 'features/app/selectors/app.selectors'
import { selectIsGFWUser } from 'features/user/selectors/user.selectors'
import DatasetNotFound from '../shared/DatasetNotFound'
import Color from '../common/Color'
import LayerSwitch from '../common/LayerSwitch'
Expand All @@ -41,6 +46,8 @@ function EnvironmentalLayerPanel({ dataview, onToggle }: LayerPanelProps): React
const { t } = useTranslation()
const { upsertDataviewInstance } = useDataviewInstancesConnect()
const [colorOpen, setColorOpen] = useState(false)
const isGFWUser = useSelector(selectIsGFWUser)
const readOnly = useSelector(selectReadOnly)
const {
items,
attributes,
Expand All @@ -51,6 +58,9 @@ function EnvironmentalLayerPanel({ dataview, onToggle }: LayerPanelProps): React
isSorting,
activeIndex,
} = useLayerPanelDataviewSort(dataview.id)
const dataviewId = useActivityDataviewId(dataview)
const activityLayer = useGetDeckLayer<FourwingsLayer>(dataviewId)
const layerError = activityLayer?.instance?.getError?.()

const datasetFields: { field: SupportedEnvDatasetSchema; label: string }[] = useMemo(
() => [
Expand Down Expand Up @@ -139,7 +149,7 @@ function EnvironmentalLayerPanel({ dataview, onToggle }: LayerPanelProps): React
: false
const hasFilters = dataview.config?.filters && Object.keys(dataview.config?.filters).length > 0
const showVisibleFilterValues = showMinVisibleFilter || showMaxVisibleFilter || hasFilters
const showSortHandler = items.length > 1
const showSortHandler = items.length > 1 && !readOnly

return (
<div
Expand Down Expand Up @@ -207,7 +217,9 @@ function EnvironmentalLayerPanel({ dataview, onToggle }: LayerPanelProps): React
/>
)}
<InfoModal dataview={dataview} />
<Remove dataview={dataview} loading={!showSortHandler && layerActive && !layerLoaded} />
{!readOnly && (
<Remove dataview={dataview} loading={!showSortHandler && layerActive && !layerLoaded} />
)}
{showSortHandler && (
<IconButton
size="small"
Expand All @@ -218,10 +230,25 @@ function EnvironmentalLayerPanel({ dataview, onToggle }: LayerPanelProps): React
className={styles.dragger}
/>
)}
{!readOnly && layerError && (
<IconButton
icon={'warning'}
type={'warning'}
tooltip={
isGFWUser
? `${t(
'errors.layerLoading',
'There was an error loading the layer'
)} (${layerError})`
: t('errors.layerLoading', 'There was an error loading the layer')
}
size="small"
/>
)}
</div>
<IconButton
icon={layerActive ? 'more' : undefined}
type="default"
icon={layerError ? 'warning' : layerActive ? 'more' : undefined}
type={layerError ? 'warning' : 'default'}
loading={layerActive && !layerLoaded}
className={cx('print-hidden', styles.shownUntilHovered)}
size="small"
Expand Down
Loading

0 comments on commit 893f9fb

Please sign in to comment.