diff --git a/apps/api-portal/features/user-applications/user-applications.ts b/apps/api-portal/features/user-applications/user-applications.ts
index e4ca2cc5fe..929f506032 100644
--- a/apps/api-portal/features/user-applications/user-applications.ts
+++ b/apps/api-portal/features/user-applications/user-applications.ts
@@ -1,9 +1,9 @@
import { stringify } from 'qs'
import { useMutation, useQuery, useQueryClient } from 'react-query'
import { useMemo, useState } from 'react'
+import type { FieldValidationError } from 'lib/types'
import { GFWAPI } from '@globalfishingwatch/api-client'
import type { APIPagination, UserApplication } from '@globalfishingwatch/api-types'
-import type { FieldValidationError } from 'lib/types'
import useUser, { checkUserApplicationPermission } from 'features/user/user'
export type UserApplicationCreateArguments = Omit<
diff --git a/apps/fishing-map/data/layer-library/layers-events.ts b/apps/fishing-map/data/layer-library/layers-events.ts
index 85a1829480..9a0a06b2e9 100644
--- a/apps/fishing-map/data/layer-library/layers-events.ts
+++ b/apps/fishing-map/data/layer-library/layers-events.ts
@@ -20,24 +20,24 @@ export const LAYERS_LIBRARY_EVENTS: LibraryLayerConfig[] = [
color: '#FAE9A0',
},
},
- // {
- // id: LOITERING_EVENTS_SOURCE_ID,
- // dataviewId: CLUSTER_LOITERING_EVENTS_DATAVIEW_SLUG,
- // previewImageUrl: `${PATH_BASENAME}/images/layer-library/loitering.jpg`,
- // config: {
- // color: '#CEA9F9',
- // },
- // onlyGFWUser: true,
- // },
- // {
- // id: PORT_VISITS_EVENTS_SOURCE_ID,
- // dataviewId: CLUSTER_PORT_VISIT_EVENTS_DATAVIEW_SLUG,
- // previewImageUrl: `${PATH_BASENAME}/images/layer-library/port-visits.jpg`,
- // config: {
- // color: '#9AEEFF',
- // },
- // onlyGFWUser: true,
- // },
+ {
+ id: LOITERING_EVENTS_SOURCE_ID,
+ dataviewId: CLUSTER_LOITERING_EVENTS_DATAVIEW_SLUG,
+ previewImageUrl: `${PATH_BASENAME}/images/layer-library/loitering.jpg`,
+ config: {
+ color: '#CEA9F9',
+ },
+ onlyGFWUser: true,
+ },
+ {
+ id: PORT_VISITS_EVENTS_SOURCE_ID,
+ dataviewId: CLUSTER_PORT_VISIT_EVENTS_DATAVIEW_SLUG,
+ previewImageUrl: `${PATH_BASENAME}/images/layer-library/port-visits.jpg`,
+ config: {
+ color: '#9AEEFF',
+ },
+ onlyGFWUser: true,
+ },
]
export const LAYER_LIBRARY_EVENTS_IDS = LAYERS_LIBRARY_EVENTS.map((layer) => layer.id)
diff --git a/apps/fishing-map/features/download/downloadActivity.slice.ts b/apps/fishing-map/features/download/downloadActivity.slice.ts
index b520ef2cd3..063d7a6e7e 100644
--- a/apps/fishing-map/features/download/downloadActivity.slice.ts
+++ b/apps/fishing-map/features/download/downloadActivity.slice.ts
@@ -2,6 +2,7 @@ import type { PayloadAction } from '@reduxjs/toolkit'
import { createAsyncThunk, createSelector, createSlice } from '@reduxjs/toolkit'
import { stringify } from 'qs'
import { saveAs } from 'file-saver'
+import type { RootState } from 'reducers'
import type { Dataview, DownloadActivity } from '@globalfishingwatch/api-types'
import {
getIsConcurrentError,
@@ -10,7 +11,6 @@ import {
parseAPIError,
} from '@globalfishingwatch/api-client'
import type { UrlDataviewInstance } from '@globalfishingwatch/dataviews-client'
-import type { RootState } from 'reducers'
import type { AsyncError } from 'utils/async-slice'
import { AsyncReducerStatus } from 'utils/async-slice'
import type { AreaKeyId, AreaKeys } from 'features/areas/areas.slice'
diff --git a/apps/fishing-map/features/download/downloadTrack.slice.ts b/apps/fishing-map/features/download/downloadTrack.slice.ts
index 7dfe608dba..9ebaafca88 100644
--- a/apps/fishing-map/features/download/downloadTrack.slice.ts
+++ b/apps/fishing-map/features/download/downloadTrack.slice.ts
@@ -2,9 +2,9 @@ import type { PayloadAction } from '@reduxjs/toolkit'
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'
import { stringify } from 'qs'
import { saveAs } from 'file-saver'
+import type { RootState } from 'reducers'
import type { DownloadRateLimit, ThinningConfig } from '@globalfishingwatch/api-types'
import { GFWAPI, parseAPIError } from '@globalfishingwatch/api-client'
-import type { RootState } from 'reducers'
import type { AsyncError } from 'utils/async-slice'
import { AsyncReducerStatus } from 'utils/async-slice'
import type { DateRange } from 'features/download/downloadActivity.slice'
diff --git a/apps/fishing-map/features/editor/editor.slice.ts b/apps/fishing-map/features/editor/editor.slice.ts
index ff0434b1af..54eb6af431 100644
--- a/apps/fishing-map/features/editor/editor.slice.ts
+++ b/apps/fishing-map/features/editor/editor.slice.ts
@@ -1,8 +1,8 @@
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
import { stringify } from 'qs'
+import type { RootState } from 'reducers'
import { GFWAPI, parseAPIError } from '@globalfishingwatch/api-client'
import type { APIPagination, Dataview } from '@globalfishingwatch/api-types'
-import type { RootState } from 'reducers'
import type { AsyncError } from 'utils/async-slice'
import { AsyncReducerStatus } from 'utils/async-slice'
import { APP_NAME, DEFAULT_PAGINATION_PARAMS } from 'data/config'
diff --git a/apps/fishing-map/features/map/controls/map-controls.slice.ts b/apps/fishing-map/features/map/controls/map-controls.slice.ts
index fafd660000..deaf4f4a31 100644
--- a/apps/fishing-map/features/map/controls/map-controls.slice.ts
+++ b/apps/fishing-map/features/map/controls/map-controls.slice.ts
@@ -1,7 +1,7 @@
import type { PayloadAction } from '@reduxjs/toolkit'
import { createSelector, createSlice } from '@reduxjs/toolkit'
-import type { RulerData } from '@globalfishingwatch/deck-layers'
import type { RootState } from 'reducers'
+import type { RulerData } from '@globalfishingwatch/deck-layers'
import type { MapAnnotation } from '../overlays/annotations/annotations.types'
export type MapControl = 'annotations' | 'rulers' | 'errorNotification'
diff --git a/apps/fishing-map/features/map/popups/Popup.module.css b/apps/fishing-map/features/map/popups/Popup.module.css
index 88c27f80a0..e89412c2c2 100644
--- a/apps/fishing-map/features/map/popups/Popup.module.css
+++ b/apps/fishing-map/features/map/popups/Popup.module.css
@@ -24,7 +24,9 @@
font: var(--font-L);
line-height: 1;
margin: var(--space-XS);
- transition: opacity 0.15s linear, color 0.15s linear;
+ transition:
+ opacity 0.15s linear,
+ color 0.15s linear;
z-index: 1;
top: -2rem;
right: -2rem;
@@ -283,3 +285,9 @@
overflow: hidden;
text-overflow: ellipsis;
}
+
+.portCTA {
+ margin-top: var(--space-S);
+ display: block;
+ width: 100%;
+}
diff --git a/apps/fishing-map/features/map/popups/categories/TileClusterTooltipRow.tsx b/apps/fishing-map/features/map/popups/categories/TileClusterTooltipRow.tsx
index c6e6f69f2d..e3c9bb89a9 100644
--- a/apps/fishing-map/features/map/popups/categories/TileClusterTooltipRow.tsx
+++ b/apps/fishing-map/features/map/popups/categories/TileClusterTooltipRow.tsx
@@ -2,7 +2,7 @@ import { Fragment, useEffect } from 'react'
import { useTranslation } from 'react-i18next'
import { stringify } from 'qs'
import { useSelector } from 'react-redux'
-import { Button, Icon, IconButton } from '@globalfishingwatch/ui-components'
+import { Button, Icon } from '@globalfishingwatch/ui-components'
import { DatasetTypes, DataviewCategory } from '@globalfishingwatch/api-types'
import { AsyncReducerStatus } from 'utils/async-slice'
import I18nDate from 'features/i18n/i18nDate'
@@ -22,6 +22,7 @@ import { VESSEL_GROUP_EVENTS_DATAVIEW_IDS } from 'features/reports/vessel-groups
import { getEventDescriptionComponent } from 'utils/events'
import PortsReportLink from 'features/reports/ports/PortsReportLink'
import { selectIsGFWUser } from 'features/user/selectors/user.selectors'
+import { selectIsPortReportLocation } from 'routes/routes.selectors'
import { useMapViewState } from '../../map-viewport.hooks'
import type {
ExtendedEventVessel,
@@ -193,6 +194,8 @@ type PortVisitLayerProps = {
error?: string
}
function PortVisitEventTooltipRow({ feature, showFeaturesDetails, error }: PortVisitLayerProps) {
+ const { t } = useTranslation()
+ const isPortReportLocation = useSelector(selectIsPortReportLocation)
const { datasetId, event, color } = feature
const title = getDatasetLabel({ id: datasetId! })
const isGFWUser = useSelector(selectIsGFWUser)
@@ -201,15 +204,6 @@ function PortVisitEventTooltipRow({ feature, showFeaturesDetails, error }: PortV
{
{title}
}
- {isGFWUser && event?.port && (
-
-
- {event?.port?.name || event?.port?.id}
- {event?.port?.country && ` (${formatInfoField(event.port.country, 'flag')})`}
-
-
-
- )}
{error &&
{error}
}
{showFeaturesDetails && (
)}
+ {isGFWUser && event?.port && !isPortReportLocation && (
+
+
+
+ )}
)
diff --git a/apps/fishing-map/features/modals/modals.slice.ts b/apps/fishing-map/features/modals/modals.slice.ts
index ea1fcecc1c..94d3a2a08e 100644
--- a/apps/fishing-map/features/modals/modals.slice.ts
+++ b/apps/fishing-map/features/modals/modals.slice.ts
@@ -1,7 +1,7 @@
import type { PayloadAction } from '@reduxjs/toolkit'
import { createSlice } from '@reduxjs/toolkit'
-import type { DatasetGeometryType, DataviewCategory } from '@globalfishingwatch/api-types'
import type { RootState } from 'reducers'
+import type { DatasetGeometryType, DataviewCategory } from '@globalfishingwatch/api-types'
type ModalId =
| 'feedback'
diff --git a/apps/fishing-map/features/reports/areas/area-reports.hooks.ts b/apps/fishing-map/features/reports/areas/area-reports.hooks.ts
index b3ced38dd2..c757581906 100644
--- a/apps/fishing-map/features/reports/areas/area-reports.hooks.ts
+++ b/apps/fishing-map/features/reports/areas/area-reports.hooks.ts
@@ -1,11 +1,11 @@
import { useCallback, useEffect, useMemo } from 'react'
import { useSelector } from 'react-redux'
+import { useGetStatsByDataviewQuery } from 'queries/stats-api'
import type { UrlDataviewInstance } from '@globalfishingwatch/dataviews-client'
import type { Dataset, Dataview } from '@globalfishingwatch/api-types'
import { useLocalStorage } from '@globalfishingwatch/react-hooks'
import { useGetDeckLayers } from '@globalfishingwatch/deck-layer-composer'
import type { ContextFeature, ContextLayer } from '@globalfishingwatch/deck-layers'
-import { useGetStatsByDataviewQuery } from 'queries/stats-api'
import { useAppDispatch } from 'features/app/app.hooks'
import { selectTimeRange } from 'features/app/selectors/app.timebar.selectors'
import {
diff --git a/apps/fishing-map/features/reports/ports/PortsReportLink.tsx b/apps/fishing-map/features/reports/ports/PortsReportLink.tsx
index 0527dea631..583320b3bd 100644
--- a/apps/fishing-map/features/reports/ports/PortsReportLink.tsx
+++ b/apps/fishing-map/features/reports/ports/PortsReportLink.tsx
@@ -1,7 +1,7 @@
import { useSelector } from 'react-redux'
+import cx from 'classnames'
import React from 'react'
import Link from 'redux-first-router-link'
-import { useTranslation } from 'react-i18next'
import { Tooltip } from '@globalfishingwatch/ui-components'
import type { UrlDataviewInstance } from '@globalfishingwatch/dataviews-client'
import { DataviewType } from '@globalfishingwatch/api-types'
@@ -21,12 +21,12 @@ import { getPortClusterDataviewForReport } from './ports-report.utils'
type PortsReportLinkProps = {
port: ExtendedFeatureByVesselEventPort
children: React.ReactNode
+ tooltip?: string
}
-function PortsReportLink({ children, port }: PortsReportLinkProps) {
+function PortsReportLink({ children, port, tooltip }: PortsReportLinkProps) {
const workspace = useSelector(selectWorkspace)
const query = useSelector(selectLocationQuery)
- const { t } = useTranslation()
if (!workspace || !port) {
return children
@@ -55,7 +55,7 @@ function PortsReportLink({ children, port }: PortsReportLinkProps) {
return (
-
- {children}
-
+ {children}
)
}
diff --git a/apps/fishing-map/features/reports/ports/ports-report.utils.ts b/apps/fishing-map/features/reports/ports/ports-report.utils.ts
index a0b6f948c4..0c5905b124 100644
--- a/apps/fishing-map/features/reports/ports/ports-report.utils.ts
+++ b/apps/fishing-map/features/reports/ports/ports-report.utils.ts
@@ -8,21 +8,23 @@ export function isPortClusterDataviewForReport(dataview: UrlDataviewInstance) {
export function getPortClusterDataviewForReport(
dataview: UrlDataviewInstance,
- { portId, clusterMaxZoomLevels } = {} as {
+ { portId, clusterMaxZoomLevels: newClusterMaxZoomLevels } = {} as {
portId?: string
clusterMaxZoomLevels?: ClusterMaxZoomLevelConfig
}
) {
if (isPortClusterDataviewForReport(dataview)) {
+ const { clusterMaxZoomLevels, ...restConfig } = dataview.config || {}
+ const { port_id, ...restFilters } = restConfig.filters || {}
return {
...dataview,
config: {
- ...dataview.config,
+ ...restConfig,
visible: true,
- clusterMaxZoomLevels,
+ ...(newClusterMaxZoomLevels && { clusterMaxZoomLevels: newClusterMaxZoomLevels }),
filters: {
- ...(dataview.config?.filters || {}),
- port_id: portId,
+ ...(restFilters || {}),
+ ...(portId && { port_id: portId }),
},
},
}
diff --git a/apps/fishing-map/features/reports/vessel-groups/insights/VGRInsightFishing.tsx b/apps/fishing-map/features/reports/vessel-groups/insights/VGRInsightFishing.tsx
index 42ad940bd5..4b864fd30b 100644
--- a/apps/fishing-map/features/reports/vessel-groups/insights/VGRInsightFishing.tsx
+++ b/apps/fishing-map/features/reports/vessel-groups/insights/VGRInsightFishing.tsx
@@ -2,10 +2,10 @@ import { useTranslation } from 'react-i18next'
import { useState } from 'react'
import cx from 'classnames'
import { useSelector } from 'react-redux'
+import { useGetVesselGroupInsightQuery } from 'queries/vessel-insight-api'
import type { ParsedAPIError } from '@globalfishingwatch/api-client'
import { Collapsable } from '@globalfishingwatch/ui-components'
import { RegionType, VesselIdentitySourceEnum } from '@globalfishingwatch/api-types'
-import { useGetVesselGroupInsightQuery } from 'queries/vessel-insight-api'
import InsightError from 'features/vessel/insights/InsightErrorMessage'
import DataTerminology from 'features/vessel/identity/DataTerminology'
import { formatInfoField } from 'utils/info'
diff --git a/apps/fishing-map/features/reports/vessel-groups/insights/VGRInsightMOU.tsx b/apps/fishing-map/features/reports/vessel-groups/insights/VGRInsightMOU.tsx
index 6e46f253ef..35e0137058 100644
--- a/apps/fishing-map/features/reports/vessel-groups/insights/VGRInsightMOU.tsx
+++ b/apps/fishing-map/features/reports/vessel-groups/insights/VGRInsightMOU.tsx
@@ -3,10 +3,10 @@ import { useState } from 'react'
import cx from 'classnames'
import { useSelector } from 'react-redux'
import { groupBy } from 'es-toolkit'
+import { useGetVesselGroupInsightQuery } from 'queries/vessel-insight-api'
import type { ParsedAPIError } from '@globalfishingwatch/api-client'
import { Collapsable } from '@globalfishingwatch/ui-components'
import { VesselIdentitySourceEnum } from '@globalfishingwatch/api-types'
-import { useGetVesselGroupInsightQuery } from 'queries/vessel-insight-api'
import InsightError from 'features/vessel/insights/InsightErrorMessage'
import DataTerminology from 'features/vessel/identity/DataTerminology'
import { selectIsGuestUser } from 'features/user/selectors/user.selectors'
diff --git a/apps/fishing-map/features/reports/vessel-groups/vessel-group-report.selectors.ts b/apps/fishing-map/features/reports/vessel-groups/vessel-group-report.selectors.ts
index 5bb33d04c0..9dd5f87ea8 100644
--- a/apps/fishing-map/features/reports/vessel-groups/vessel-group-report.selectors.ts
+++ b/apps/fishing-map/features/reports/vessel-groups/vessel-group-report.selectors.ts
@@ -1,11 +1,11 @@
import { createSelector } from '@reduxjs/toolkit'
-import type { InsightType } from '@globalfishingwatch/api-types'
import type { VesselGroupInsightParams } from 'queries/vessel-insight-api'
import {
selectVesselGroupInsight,
selectVesselGroupInsightApiSlice,
} from 'queries/vessel-insight-api'
import type { RootState } from 'reducers'
+import type { InsightType } from '@globalfishingwatch/api-types'
import { selectReportVesselGroupId } from 'routes/routes.selectors'
import { selectTimeRange } from 'features/app/selectors/app.timebar.selectors'
import { dataviewHasVesselGroupId } from 'features/dataviews/dataviews.utils'
diff --git a/apps/fishing-map/features/vessel/insights/InsightGapsDetails.tsx b/apps/fishing-map/features/vessel/insights/InsightGapsDetails.tsx
index 5cad17adf3..9e57b5b15e 100644
--- a/apps/fishing-map/features/vessel/insights/InsightGapsDetails.tsx
+++ b/apps/fishing-map/features/vessel/insights/InsightGapsDetails.tsx
@@ -1,10 +1,10 @@
import { useSelector } from 'react-redux'
import { Fragment } from 'react'
import { useTranslation } from 'react-i18next'
+import { useGetVesselEventsQuery } from 'queries/vessel-events-api'
import type { InsightResponse } from '@globalfishingwatch/api-types'
import { VesselIdentitySourceEnum } from '@globalfishingwatch/api-types'
import { IconButton } from '@globalfishingwatch/ui-components'
-import { useGetVesselEventsQuery } from 'queries/vessel-events-api'
import { getVesselIdentities } from 'features/vessel/vessel.utils'
import { selectTimeRange } from 'features/app/selectors/app.timebar.selectors'
import { removeNonTunaRFMO } from 'features/vessel/insights/insights.utils'
diff --git a/apps/fishing-map/features/vessel/insights/InsightWrapper.tsx b/apps/fishing-map/features/vessel/insights/InsightWrapper.tsx
index c6f4df362b..7ab709667a 100644
--- a/apps/fishing-map/features/vessel/insights/InsightWrapper.tsx
+++ b/apps/fishing-map/features/vessel/insights/InsightWrapper.tsx
@@ -1,8 +1,8 @@
import { useSelector } from 'react-redux'
+import { useGetVesselInsightQuery } from 'queries/vessel-insight-api'
import type { InsightType } from '@globalfishingwatch/api-types'
import { VesselIdentitySourceEnum } from '@globalfishingwatch/api-types'
import type { ParsedAPIError } from '@globalfishingwatch/api-client'
-import { useGetVesselInsightQuery } from 'queries/vessel-insight-api'
import { getVesselIdentities } from 'features/vessel/vessel.utils'
import { selectTimeRange } from 'features/app/selectors/app.timebar.selectors'
import InsightMOUList from 'features/vessel/insights/InsightMOUList'
diff --git a/apps/fishing-map/features/vessel/vessel.slice.ts b/apps/fishing-map/features/vessel/vessel.slice.ts
index 0cfe07d333..c69b076958 100644
--- a/apps/fishing-map/features/vessel/vessel.slice.ts
+++ b/apps/fishing-map/features/vessel/vessel.slice.ts
@@ -1,6 +1,7 @@
import type { PayloadAction } from '@reduxjs/toolkit'
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
import { HYDRATE } from 'next-redux-wrapper'
+import type { RootState } from 'reducers'
import type { ParsedAPIError } from '@globalfishingwatch/api-client'
import { GFWAPI, parseAPIError } from '@globalfishingwatch/api-client'
import type {
@@ -19,7 +20,6 @@ import { DatasetTypes, ResourceStatus } from '@globalfishingwatch/api-types'
import { setResource } from '@globalfishingwatch/dataviews-client'
import { resolveEndpoint } from '@globalfishingwatch/datasets-client'
import { VesselIdentitySourceEnum } from '@globalfishingwatch/api-types'
-import type { RootState } from 'reducers'
import { AsyncReducerStatus } from 'utils/async-slice'
import { selectResources } from 'features/resources/resources.slice'
import {
diff --git a/apps/fishing-map/middlewares.ts b/apps/fishing-map/middlewares.ts
index b78c930411..02ca639987 100644
--- a/apps/fishing-map/middlewares.ts
+++ b/apps/fishing-map/middlewares.ts
@@ -1,8 +1,8 @@
import type { Middleware } from 'redux'
import type { ThunkDispatch } from '@reduxjs/toolkit'
import { isRejectedWithValue } from '@reduxjs/toolkit'
-import { isUnauthorized } from '@globalfishingwatch/api-client'
import type { RootState } from 'reducers'
+import { isUnauthorized } from '@globalfishingwatch/api-client'
import type { AsyncError } from 'utils/async-slice'
import { setLoginExpired } from 'features/user/user.slice'
import { selectIsGuestUser } from 'features/user/selectors/user.selectors'
diff --git a/apps/fishing-map/routes/routes.middlewares.ts b/apps/fishing-map/routes/routes.middlewares.ts
index a2d64c2df9..0f84bd93e5 100644
--- a/apps/fishing-map/routes/routes.middlewares.ts
+++ b/apps/fishing-map/routes/routes.middlewares.ts
@@ -1,6 +1,6 @@
import type { Middleware, Dispatch } from 'redux'
-import { ACCESS_TOKEN_STRING } from '@globalfishingwatch/api-client'
import type { RootState } from 'reducers'
+import { ACCESS_TOKEN_STRING } from '@globalfishingwatch/api-client'
import { REPLACE_URL_PARAMS } from 'routes/routes.config'
import { setLastWorkspaceVisited } from 'features/workspace/workspace.slice'
import type { QueryParam, QueryParams } from 'types'
diff --git a/apps/fishing-map/server/vessel/vessel.tsx b/apps/fishing-map/server/vessel/vessel.tsx
index c8c400712d..ae372159a7 100644
--- a/apps/fishing-map/server/vessel/vessel.tsx
+++ b/apps/fishing-map/server/vessel/vessel.tsx
@@ -1,7 +1,7 @@
import cx from 'classnames'
import { useSelector } from 'react-redux'
-import { Logo } from '@globalfishingwatch/ui-components'
import { serverT } from 'server/i18n'
+import { Logo } from '@globalfishingwatch/ui-components'
import { AsyncReducerStatus } from 'utils/async-slice'
import { IDENTITY_FIELD_GROUPS } from 'features/vessel/vessel.config'
import { formatInfoField } from 'utils/info'
diff --git a/apps/real-time-prototype/features/map/Map.tsx b/apps/real-time-prototype/features/map/Map.tsx
index d24f481842..1d6d1dab15 100644
--- a/apps/real-time-prototype/features/map/Map.tsx
+++ b/apps/real-time-prototype/features/map/Map.tsx
@@ -8,14 +8,14 @@ import { useAtom } from 'jotai'
import { BitmapLayer } from '@deck.gl/layers'
import { TileLayer } from '@deck.gl/geo-layers'
import uniqBy from 'lodash/uniqBy'
-import { GFWAPI } from '@globalfishingwatch/api-client'
-import type { MiniglobeBounds} from '@globalfishingwatch/ui-components';
-import { MiniGlobe, Tooltip } from '@globalfishingwatch/ui-components'
-import { BasemapType } from '@globalfishingwatch/layer-composer'
import { useTracksLayer, useTracksSublayers } from 'layers/tracks/tracks.hooks'
import { useLatestPositionsLayer } from 'layers/latest-positions/latest-positions.hooks'
import { useContextsLayer } from 'layers/context/context.hooks'
import { useBasemapLayer } from 'layers/basemap/basemap.hooks'
+import { GFWAPI } from '@globalfishingwatch/api-client'
+import type { MiniglobeBounds} from '@globalfishingwatch/ui-components';
+import { MiniGlobe, Tooltip } from '@globalfishingwatch/ui-components'
+import { BasemapType } from '@globalfishingwatch/layer-composer'
import { useURLViewport, useViewport } from 'features/map/map-viewport.hooks'
import { hoveredFeaturesAtom } from 'features/map/map-picking.hooks'
import { getDateLabel } from 'utils/dates'