diff --git a/apps/fishing-map/features/datasets/datasets.mock.ts b/apps/fishing-map/features/datasets/datasets.mock.ts index 6f0a954748..a2dcea44dc 100644 --- a/apps/fishing-map/features/datasets/datasets.mock.ts +++ b/apps/fishing-map/features/datasets/datasets.mock.ts @@ -1,5 +1,211 @@ import { Dataset } from '@globalfishingwatch/api-types' -export const datasets: Dataset[] = [] +export const datasets: Dataset[] = [ + { + alias: ['public-global-all-tracks:latest'], + id: 'public-global-all-tracks:v20231026', + name: 'Tracks', + type: 'tracks:v1', + description: 'The dataset contains the tracks from all vessels (AIS) - Version 20231026', + startDate: '2012-01-01T00:00:00.000Z', + endDate: '2024-01-14T00:00:00.000Z', + unit: 'NA', + status: 'done', + importLogs: null, + category: 'vessel', + subcategory: 'track', + source: 'Global Fishing Watch - AIS', + ownerId: 0, + ownerType: 'super-user', + configuration: { + id: '', + max: 0, + min: 0, + ttl: 0, + band: '', + srid: null, + scale: 0, + bucket: 'api-tracks-us-central1', + fields: null, + folder: 'public-global-all-tracks:v20231026', + format: null, + images: null, + offset: 0, + source: 'gcs', + maxZoom: 12, + filePath: null, + function: null, + latitude: null, + numBytes: null, + gcsFolder: '', + intervals: [], + longitude: null, + numLayers: null, + timestamp: null, + translate: true, + idProperty: '', + indexBoost: null, + emailGroups: [], + geometryType: null, + insightSources: [], + configurationUI: null, + valueProperties: null, + propertyToInclude: null, + disableInteraction: false, + apiSupportedVersions: ['v2', 'v3'], + propertyToIncludeRange: null, + }, + relatedDatasets: [], + schema: { + lat: { + type: 'number', + }, + lon: { + type: 'number', + }, + flag: { + type: 'string', + }, + night: { + type: 'boolean', + }, + speed: { + enum: [0, 20], + type: 'range', + }, + course: { + type: 'number', + }, + seg_id: { + type: 'string', + }, + elevation: { + min: 0, + type: 'number', + }, + timestamp: { + type: 'string', + format: 'date-time', + }, + distance_from_port: { + min: 0, + type: 'number', + }, + distance_from_shore: { + min: 0, + type: 'number', + }, + }, + fieldsAllowed: ['lat', 'lon', 'timestamp', 'latlon', 'seg_id', 'speed'], + createdAt: '2023-10-17T12:34:21.417Z', + endpoints: [ + { + id: 'tracks', + description: 'Endpoint to retrieve vessel track', + downloadable: true, + method: 'GET', + pathTemplate: '/v3/vessels/{{vesselId}}/tracks', + params: [ + { + label: 'vessel id', + id: 'vesselId', + type: 'string', + }, + ], + query: [ + { + label: 'dataset', + id: 'dataset', + type: 'string', + required: true, + array: false, + }, + { + label: 'start-date', + id: 'start-date', + type: 'Date ISO', + required: false, + }, + { + label: 'end-date', + id: 'end-date', + type: 'Date ISO', + required: false, + }, + { + label: 'binary', + id: 'binary', + type: 'boolean', + default: true, + }, + { + id: 'fields', + type: 'enum', + label: 'fields', + array: true, + enum: ['LAT', 'LON', 'TIMESTAMP', 'SPEED', 'COURSE'], + }, + { + label: 'format', + id: 'format', + type: 'enum', + enum: ['POINT', 'LINES', 'VALUEARRAY'], + default: 'LINES', + description: + 'Specific encoding format to use for the track. Possible values lines, points or valueArray. valueArray: is a custom compact format, an array with all the fields serialized. The format is further explained in this issue: valueArray format. lines: Geojson with a single LineString feature containing all the points in the track points: Geojson with a FeatureCollection containing a Point feature for every point in the track', + }, + { + id: 'distance-fishing', + type: 'number', + label: 'Distance fishing', + required: false, + }, + { + id: 'bearing-val-fishing', + type: 'number', + label: 'Bearing value fishing', + required: false, + }, + { + id: 'change-speed-fishing', + type: 'number', + label: 'Change speed fishing', + required: false, + }, + { + id: 'min-accuracy-fishing', + type: 'number', + label: 'Minimun accuracy fishing', + required: false, + }, + { + id: 'distance-transit', + type: 'number', + label: 'Distance transit', + required: false, + }, + { + id: 'bearing-val-transit', + type: 'number', + label: 'Bearing value transit', + required: false, + }, + { + id: 'change-speed-transit', + type: 'number', + label: 'Change speed transit', + required: false, + }, + { + id: 'min-accuracy-transit', + type: 'number', + label: 'Minimun accuracy transit', + required: false, + }, + ], + }, + ], + }, +] export default datasets diff --git a/apps/fishing-map/features/datasets/datasets.utils.ts b/apps/fishing-map/features/datasets/datasets.utils.ts index 6e1866f67d..73993eb55b 100644 --- a/apps/fishing-map/features/datasets/datasets.utils.ts +++ b/apps/fishing-map/features/datasets/datasets.utils.ts @@ -785,7 +785,9 @@ export const getFiltersBySchema = ( ? activeDatasets.some((d) => datasetsWithSchema.includes(d)) : activeDatasets.every((d) => datasetsWithSchema.includes(d)) const incompatibleFilterSelection = getIncompatibleFilterSelection(dataview, schema)!?.length > 0 - const disabled = !hasDatasetsWithSchema || incompatibleFilterSelection + // const disabled = !hasDatasetsWithSchema || incompatibleFilterSelection + // TODO remove this once we know why speed is disabled + const disabled = false const datasetId = removeDatasetVersion(getActiveDatasetsInDataview(dataview)!?.[0]?.id) let label: string = CONTEXT_DATASETS_SCHEMAS.includes(schema as SupportedContextDatasetSchema) ? t(`datasets:${datasetId}.schema.${schema}.keyword`, schema.toString()) @@ -826,10 +828,16 @@ export const getSchemaFiltersInDataview = ( }) : fieldsAllowed const filtersAllowed = fielsAllowedOrdered.map((id) => { - return getFiltersBySchema(dataview, id, { vesselGroups }) + return getFiltersBySchema(dataview, id, { + vesselGroups, + compatibilityOperation: id === 'speed' ? 'some' : 'every', + }) }) const filtersDisabled = fieldsDisabled.map((id) => { - return getFiltersBySchema(dataview, id, { vesselGroups }) + return getFiltersBySchema(dataview, id, { + vesselGroups, + compatibilityOperation: id === 'speed' ? 'some' : 'every', + }) }) return { filtersAllowed, diff --git a/apps/fishing-map/features/dataviews/dataviews.mock.ts b/apps/fishing-map/features/dataviews/dataviews.mock.ts index 96a7bbf16d..f18fceaa4e 100644 --- a/apps/fishing-map/features/dataviews/dataviews.mock.ts +++ b/apps/fishing-map/features/dataviews/dataviews.mock.ts @@ -2,62 +2,219 @@ import { Dataview, DataviewCategory } from '@globalfishingwatch/api-types' export const dataviews: Dataview[] = [ { - id: 330, - name: 'User track', - slug: 'user-track', - description: 'User track', + id: 341, + name: 'Fishing map vessel with identity dataset', + slug: 'fishing-map-vessel-track', app: 'fishing-map', config: { type: 'TRACK', color: '#F95E5E', }, - category: DataviewCategory.User, - createdAt: '2023-02-21T20:32:02.152Z', - updatedAt: '2023-02-21T20:32:02.152Z', - }, - { - id: 353, - name: 'Default context layer', - slug: 'default-context-layer', - description: 'Default context layer', - app: 'fishing-map', - config: { - type: 'USER_CONTEXT', - color: '#F95E5E', - }, - category: DataviewCategory.User, - createdAt: '2023-02-21T20:32:32.709Z', - updatedAt: '2023-02-21T20:32:32.709Z', - }, - { - id: 339, - name: 'Default points layer', - slug: 'default-points-layer', - description: 'Default points layer', - app: 'fishing-map', - config: { - type: 'USER_POINTS', - color: '#00FFBC', - colorRamp: 'teal', - }, - category: DataviewCategory.User, - createdAt: '2023-02-21T20:32:04.646Z', - updatedAt: '2023-02-21T20:32:04.646Z', - }, - { - id: 347, - name: 'Default environmental layer', - slug: 'default-environmental-layer', - description: 'Default environmental layer', - app: 'fishing-map', - config: { - type: 'USER_CONTEXT', - color: '#00FFBC', - colorRamp: 'teal', - }, - category: DataviewCategory.User, - createdAt: '2023-02-21T20:32:23.719Z', - updatedAt: '2023-02-21T20:32:23.719Z', + infoConfig: {}, + filtersConfig: null, + eventsConfig: {}, + datasetsConfig: [ + { + query: [ + { + id: 'binary', + value: true, + }, + { + id: 'wrap-longitudes', + value: false, + }, + { + id: 'fields', + value: ['LONLAT', 'TIMESTAMP', 'SPEED'], + }, + { + id: 'format', + value: 'VALUE_ARRAY', + }, + ], + params: [ + { + id: 'vesselId', + value: '', + }, + ], + endpoint: 'tracks', + datasetId: 'public-global-all-tracks:v20201001', + }, + { + params: [ + { + id: 'vesselId', + value: '', + }, + ], + endpoint: 'vessel', + datasetId: 'public-global-vessel-identity:v20231026', + }, + { + query: [ + { + id: 'vessels', + value: '', + }, + { + id: 'vessel-types', + value: ['FISHING'], + }, + { + id: 'includes', + value: [ + 'id', + 'type', + 'start', + 'end', + 'position', + 'regions.mpa', + 'regions.eez', + 'regions.fao', + 'regions.rfmo', + 'fishing.averageSpeedKnots', + ], + }, + { + id: 'limit', + value: 9999999, + }, + { + id: 'offset', + value: 0, + }, + ], + params: [], + endpoint: 'events', + datasetId: 'public-global-fishing-events:v20231026', + }, + { + query: [ + { + id: 'vessels', + value: '', + }, + { + id: 'includes', + value: [ + 'id', + 'type', + 'start', + 'end', + 'position', + 'regions.mpa', + 'regions.eez', + 'regions.fao', + 'regions.rfmo', + 'loitering.totalDistanceKm', + 'loitering.averageSpeedKnots', + ], + }, + { + id: 'limit', + value: 9999999, + }, + { + id: 'offset', + value: 0, + }, + ], + params: [], + endpoint: 'events', + datasetId: 'public-global-loitering-events:v20231026', + }, + { + query: [ + { + id: 'vessels', + value: '', + }, + { + id: 'includes', + value: [ + 'id', + 'type', + 'start', + 'end', + 'position', + 'regions.mpa', + 'regions.eez', + 'regions.fao', + 'regions.rfmo', + 'vessel.name', + 'encounter.mainVesselAuthorizationStatus', + 'encounter.encounteredVesselAuthorizationStatus', + 'encounter.medianSpeedKnots', + 'encounter.vessel.id', + 'encounter.vessel.ssvid', + 'encounter.vessel.type', + 'encounter.vessel.name', + 'encounter.vessel.flag', + ], + }, + { + id: 'encounter-types', + value: ['CARRIER-FISHING', 'FISHING-CARRIER', 'FISHING-SUPPORT', 'SUPPORT-FISHING'], + }, + { + id: 'limit', + value: 9999999, + }, + { + id: 'offset', + value: 0, + }, + ], + params: [], + endpoint: 'events', + datasetId: 'public-global-encounters-events:v20231026', + }, + { + query: [ + { + id: 'vessels', + value: '', + }, + { + id: 'confidences', + value: [4], + }, + { + id: 'includes', + value: [ + 'id', + 'type', + 'start', + 'end', + 'position', + 'regions.mpa', + 'regions.eez', + 'regions.fao', + 'regions.rfmo', + 'port_visit.intermediateAnchorage.name', + 'port_visit.intermediateAnchorage.flag', + ], + }, + { + id: 'limit', + value: 9999999, + }, + { + id: 'offset', + value: 0, + }, + ], + params: [], + endpoint: 'events', + datasetId: 'public-global-port-visits-c2-events:v20231026', + }, + ], + description: 'Fishing map vessel with track, info and events', + createdAt: '2023-01-16T15:35:34.588Z', + updatedAt: '2023-11-16T14:04:08.289Z', + category: 'vessels', }, ] diff --git a/apps/fishing-map/features/workspace/vessels/VesselLayerPanel.tsx b/apps/fishing-map/features/workspace/vessels/VesselLayerPanel.tsx index 8487584ac4..2e3cf524b8 100644 --- a/apps/fishing-map/features/workspace/vessels/VesselLayerPanel.tsx +++ b/apps/fishing-map/features/workspace/vessels/VesselLayerPanel.tsx @@ -33,6 +33,8 @@ import { getOtherVesselNames } from 'features/vessel/vessel.utils' import { formatI18nDate } from 'features/i18n/i18nDate' import { t } from 'features/i18n/i18n' import { selectIsGFWUser } from 'features/user/selectors/user.selectors' +import ExpandedContainer from 'features/workspace/shared/ExpandedContainer' +import Filters from '../common/LayerFilters' import Color from '../common/Color' import LayerSwitch from '../common/LayerSwitch' import Remove from '../common/Remove' @@ -93,6 +95,7 @@ export const getVesselIdentityTooltipSummary = ( function VesselLayerPanel({ dataview }: VesselLayerPanelProps): React.ReactElement { const { t } = useTranslation() + const [filterOpen, setFiltersOpen] = useState(false) const { upsertDataviewInstance } = useDataviewInstancesConnect() const { url: infoUrl, dataset } = resolveDataviewDatasetResource(dataview, DatasetTypes.Vessels) const resources = useSelector(selectResources) @@ -123,6 +126,10 @@ function VesselLayerPanel({ dataview }: VesselLayerPanelProps): React.ReactEleme setColorOpen(!colorOpen) } + const onToggleFilterOpen = () => { + setFiltersOpen(!filterOpen) + } + // const onToggleInfoOpen = () => { // setInfoOpen(!infoOpen) // } @@ -288,6 +295,27 @@ function VesselLayerPanel({ dataview }: VesselLayerPanelProps): React.ReactEleme onClickOutside={closeExpandedContainer} /> {layerActive && !infoLoading && TrackIconComponent} + {layerActive && ( + } + > +
+ +
+
+ )} {infoResource && InfoIconComponent} diff --git a/libs/data-transforms/src/segments/segments-to-geojson.ts b/libs/data-transforms/src/segments/segments-to-geojson.ts index f8153038a1..55e51e7df4 100644 --- a/libs/data-transforms/src/segments/segments-to-geojson.ts +++ b/libs/data-transforms/src/segments/segments-to-geojson.ts @@ -12,6 +12,7 @@ const segmentsToFeatures = (segment: Segment | Segment[]): Feature[] return [] } const times = segment.map((point) => point.timestamp) + const speed = segment.map((point) => point.speed) const coordinateProperties = segment?.reduce( (acc, point) => { const properties = point.properties || {} @@ -25,7 +26,6 @@ const segmentsToFeatures = (segment: Segment | Segment[]): Feature[] }, {} as Record ) - console.log('🚀 ~ coordinateProperties ~ coordinateProperties:', coordinateProperties) const feature: Feature = { type: 'Feature', geometry: { @@ -39,6 +39,7 @@ const segmentsToFeatures = (segment: Segment | Segment[]): Feature[] coordinateProperties: { ...coordinateProperties, times: times.some((time) => !!time) ? times : undefined, + speed: speed.some((time) => !!time) ? speed : undefined, }, }, }