diff --git a/src/components/map/globe-map.js b/src/components/map/globe-map.js
index 2fcf7c57..af31216f 100644
--- a/src/components/map/globe-map.js
+++ b/src/components/map/globe-map.js
@@ -13,7 +13,11 @@ import { SphereGeometry } from "@luma.gl/engine"
import PropTypes from "prop-types"
import styled from "styled-components"
import { getUniquePlatforms } from "../../utils/get-unique-platforms"
-import { getLineColorAsRGB, getPlatformIcon } from "../../utils/platform-colors"
+import {
+ getLineColorAsRGB,
+ getPlatformIcon,
+ isPlatformVisible,
+} from "../../utils/platform-colors"
const INITIAL_VIEW_STATE = {
longitude: -98,
@@ -22,7 +26,14 @@ const INITIAL_VIEW_STATE = {
}
const MAPBOX_TOKEN = process.env.GATSBY_MAPBOX_TOKEN
-export function GlobeMap({ geojson, deployments, mapStyleID }) {
+export function GlobeMap({
+ geojson,
+ deployments,
+ selectedPlatforms,
+ selectedDeployment,
+ mapStyleID,
+ children,
+}) {
const [initialViewState, setInitialViewState] = useState(INITIAL_VIEW_STATE)
const [iconMapping, setIconMapping] = useState({})
const platforms = getUniquePlatforms(
@@ -112,7 +123,15 @@ export function GlobeMap({ geojson, deployments, mapStyleID }) {
id: "flights",
data: {
...geojson,
- features: geojson.features.filter(f => f.geometry.type !== "Point"),
+ features: geojson.features
+ .filter(f => f.geometry.type !== "Point")
+ .filter(f =>
+ isPlatformVisible({
+ platformProperties: f.properties,
+ selectedDeployment,
+ selectedPlatforms,
+ })
+ ),
},
lineWidthMinPixels: 0.5,
getLineWidth: 1,
@@ -126,9 +145,14 @@ export function GlobeMap({ geojson, deployments, mapStyleID }) {
pickable: true,
iconAtlas: `https://api.mapbox.com/styles/v1/${mapStyleID}/sprite@2x.png?access_token=${MAPBOX_TOKEN}`,
iconMapping: iconMapping,
- getIcon: f => {
- return getPlatformIcon(f.properties.platform_name)
- },
+ getIcon: f =>
+ isPlatformVisible({
+ platformProperties: f.properties,
+ selectedDeployment,
+ selectedPlatforms,
+ })
+ ? getPlatformIcon(f.properties.platform_name)
+ : null,
getPosition: f => f.geometry.coordinates,
getSize: 12,
})
@@ -145,6 +169,7 @@ export function GlobeMap({ geojson, deployments, mapStyleID }) {
initialViewState={initialViewState}
layers={[backgroundLayers, flights, staticLocations]}
>
+ {children}
)
}
@@ -153,7 +178,10 @@ export function GlobeMap({ geojson, deployments, mapStyleID }) {
GlobeMap.propTypes = {
geojson: PropTypes.object,
deployments: PropTypes.array,
+ selectedDeployment: PropTypes.array,
+ selectedPlatforms: PropTypes.array,
mapStyleID: PropTypes.string,
+ children: PropTypes.node,
}
const MapContainer = styled.div`
diff --git a/src/components/timeline/__tests__/map.test.js b/src/components/timeline/__tests__/map-legend.test.js
similarity index 98%
rename from src/components/timeline/__tests__/map.test.js
rename to src/components/timeline/__tests__/map-legend.test.js
index 8e2c4357..cb51c5a3 100644
--- a/src/components/timeline/__tests__/map.test.js
+++ b/src/components/timeline/__tests__/map-legend.test.js
@@ -1,7 +1,7 @@
import React from "react"
import renderer, { act } from "react-test-renderer"
-import { MapLegend, PlatformStatus } from "../map"
+import { MapLegend, PlatformStatus } from "../map-legend"
import { LineIcon } from "../../../icons"
import {
BalloonIcon,
diff --git a/src/components/timeline/map-legend.js b/src/components/timeline/map-legend.js
new file mode 100644
index 00000000..55f65d21
--- /dev/null
+++ b/src/components/timeline/map-legend.js
@@ -0,0 +1,272 @@
+import React from "react"
+import PropTypes from "prop-types"
+import styled from "styled-components"
+import { Tooltip } from "react-tooltip"
+
+import { LineIcon } from "../../icons"
+import { colors } from "../../theme"
+import { usePlatformStatus } from "../../utils/use-platform-status"
+import {
+ FALLBACK_COLOR,
+ MOVING_PLATFORMS_COLORS,
+ STATIC_PLATFORMS,
+} from "../../utils/platform-colors"
+
+export const LegendItem = ({
+ name,
+ type,
+ color,
+ icon,
+ checked,
+ disabled,
+ onClick,
+ activeDeploymentPlatforms,
+ platformsWithData,
+}) => (
+
+
onClick()}
+ />
+
+ {type === "moving" ? (
+
+ ) : (
+ {icon}
+ )}
+ {name}
+
+
+
+)
+
+LegendItem.propTypes = {
+ name: PropTypes.string,
+ type: PropTypes.string,
+ color: PropTypes.string,
+ icon: PropTypes.node,
+ checked: PropTypes.bool,
+ disabled: PropTypes.bool,
+ platformsWithData: PropTypes.array,
+ activeDeploymentPlatforms: PropTypes.array,
+ onClick: PropTypes.func,
+}
+
+export const MapLegend = ({
+ platforms = [],
+ platformsWithData = [],
+ activeDeploymentPlatforms = [],
+ setSelectedPlatforms,
+ selectedPlatforms,
+}) => {
+ const names = platforms.map(i => i.name)
+ const uniquePlatforms = platforms.filter(
+ (i, index) => names.indexOf(i.name) === index
+ )
+ const movingPlatforms = uniquePlatforms.filter(platform =>
+ ["Jet", "Prop", "UAV", "Ships/Boats"].includes(platform.type)
+ )
+ const staticPlatforms = uniquePlatforms.filter(
+ platform => !["Jet", "Prop", "UAV", "Ships/Boats"].includes(platform.type)
+ )
+
+ return (
+
+
+
+ )
+}
+
+MapLegend.propTypes = {
+ platforms: PropTypes.array,
+ platformsWithData: PropTypes.array,
+ activeDeploymentPlatforms: PropTypes.array,
+ setSelectedPlatforms: PropTypes.func,
+ selectedPlatforms: PropTypes.array,
+}
+
+export const PlatformStatus = ({
+ platformName,
+ platformsWithData,
+ activeDeploymentPlatforms,
+}) => {
+ const status = usePlatformStatus(
+ platformName,
+ platformsWithData,
+ activeDeploymentPlatforms
+ )
+
+ if (status !== "operational") {
+ return (
+
+
+ {status === "notShown" ? "(Not Shown)" : "(Not Operating)"}
+
+
+
+ )
+ }
+ return <>>
+}
+
+PlatformStatus.propTypes = {
+ platformName: PropTypes.string,
+ platformsWithData: PropTypes.array,
+ activeDeploymentPlatforms: PropTypes.array,
+}
+
+const LegendText = styled.label`
+ font-weight: ${props => (props.checked ? 600 : 400)};
+ font-family: "Titillium Web", sans-serif;
+ display: inline-flex;
+ gap: 0.25rem;
+ margin-left: 0.5rem;
+ background: transparent;
+ border: none;
+ & svg {
+ vertical-align: middle;
+ }
+`
+
+const IconSpan = styled.span`
+ color: ${props => props.color};
+ background: #294060;
+ border: 0.5px solid;
+ border-color: ${props => props.color};
+ display: inline-flex;
+ height: 1.25rem;
+ width: 1.25rem;
+ justify-content: center;
+ align-items: center;
+ border-radius: 512px;
+ & svg {
+ vertical-align: unset;
+ font-weight: 600;
+ }
+`
+
+const LegendBox = styled.div`
+ display: inline-block;
+ text-align: left;
+ min-width: 14rem;
+ position: absolute;
+ right: 5px;
+ margin-top: 5px;
+ margin-right: 5px;
+ padding: 8px;
+ color: ${colors.lightTheme.text};
+ background-color: rgba(255, 255, 255, 0.75);
+ transition: all 0.24s ease-out;
+ > fieldset {
+ border: 0px;
+ }
+ > fieldset > legend {
+ padding: 0 0 4px;
+ font-family: "Titillium Web", sans-serif;
+ color: ${colors.lightTheme.text};
+ font-size: 1.1rem;
+ font-weight: 600;
+ }
+ & input {
+ cursor: pointer;
+ }
+ & h4 {
+ font-weight: 600;
+ color: ${colors.lightTheme.text};
+ font-size: 0.8rem;
+ margin: 4px 0 2px;
+ }
+ &:hover {
+ background-color: rgba(255, 255, 255, 0.95);
+ }
+`
+
+const Tag = styled.div`
+ display: inline;
+ > u {
+ text-decoration-line: underline;
+ text-decoration-style: dotted;
+ text-decoration-color: #4d4d4d;
+ color: #333;
+ text-decoration-thickness: 2px;
+ padding-left: 7px;
+ &:hover {
+ cursor: pointer;
+ }
+ }
+`
diff --git a/src/components/timeline/map.js b/src/components/timeline/map.js
index 945e340b..99f3c3a0 100644
--- a/src/components/timeline/map.js
+++ b/src/components/timeline/map.js
@@ -1,33 +1,30 @@
import React, { useEffect, useState } from "react"
import PropTypes from "prop-types"
-import styled from "styled-components"
-import { Tooltip } from "react-tooltip"
import Map from "../map"
import Source from "../map/source"
import Layer from "../map/layer"
import { getUniquePlatforms } from "../../utils/get-unique-platforms"
-import { LineIcon } from "../../icons"
import { mapLayerFilter } from "../../utils/filter-utils"
-import { colors } from "../../theme"
import { replaceSlashes } from "../../utils/helpers"
-import { usePlatformStatus } from "../../utils/use-platform-status"
import {
- FALLBACK_COLOR,
- MOVING_PLATFORMS_COLORS,
- STATIC_PLATFORMS,
getLineColors,
getStaticIcons,
getIconColors,
} from "../../utils/platform-colors"
+import Button from "../button"
+import { GlobeMap } from "../map/globe-map"
+import { POSITIVE } from "../../utils/constants"
+import { MapLegend } from "./map-legend"
export function DeploymentMap({
geojson,
deployments,
bounds,
selectedDeployment,
- mapStyleID,
}) {
+ const MAP_STYLE_ID = "devseed/clx25ggbv076o01ql8k8m03k8"
+ const [enable3DView, setEnable3DView] = useState(false)
const platforms = getUniquePlatforms(
deployments.flatMap(d => d.collectionPeriods)
).map(i => ({ name: i.item.shortname, type: i.item.platformType.shortname }))
@@ -53,8 +50,6 @@ export function DeploymentMap({
const lineColorsPaint = getLineColors(
movingPlatforms.filter((i, index) => movingPlatforms.indexOf(i) === index)
)
- const iconImage = getStaticIcons()
- const iconColors = getIconColors()
const [selectedPlatforms, setSelectedPlatforms] = useState(
names
@@ -62,6 +57,74 @@ export function DeploymentMap({
.filter(name => platformsWithData.includes(name))
)
+ return (
+ <>
+ {enable3DView ? (
+
+
+
+ ) : (
+
+
+
+ )}
+
+
+
+ >
+ )
+}
+
+DeploymentMap.propTypes = {
+ geojson: PropTypes.object,
+ deployments: PropTypes.array,
+ bounds: PropTypes.array,
+ selectedDeployment: PropTypes.object,
+}
+
+const MapboxMap = ({
+ geojson,
+ mapStyleID,
+ bounds,
+ lineColorsPaint,
+ selectedDeployment,
+ selectedPlatforms,
+ children,
+}) => {
+ const iconImage = getStaticIcons()
+ const iconColors = getIconColors()
return (
-
+ {children}
)
}
-DeploymentMap.propTypes = {
+MapboxMap.propTypes = {
geojson: PropTypes.object,
- deployments: PropTypes.array,
- bounds: PropTypes.array,
+ children: PropTypes.node,
selectedDeployment: PropTypes.object,
+ selectedPlatforms: PropTypes.array,
+ setSelectedPlatforms: PropTypes.func,
+ lineColorsPaint: PropTypes.array,
+ bounds: PropTypes.array,
mapStyleID: PropTypes.string.isRequired,
}
@@ -237,262 +297,3 @@ DeploymentLayer.propTypes = {
selectedPlatforms: PropTypes.array,
onLoad: PropTypes.func,
}
-
-export const LegendItem = ({
- name,
- type,
- color,
- icon,
- checked,
- disabled,
- onClick,
- activeDeploymentPlatforms,
- platformsWithData,
-}) => (
-
-
onClick()}
- />
-
- {type === "moving" ? (
-
- ) : (
- {icon}
- )}
- {name}
-
-
-
-)
-
-LegendItem.propTypes = {
- name: PropTypes.string,
- type: PropTypes.string,
- color: PropTypes.string,
- icon: PropTypes.node,
- checked: PropTypes.bool,
- disabled: PropTypes.bool,
- platformsWithData: PropTypes.array,
- activeDeploymentPlatforms: PropTypes.array,
- onClick: PropTypes.func,
-}
-
-export const MapLegend = ({
- platforms = [],
- platformsWithData = [],
- activeDeploymentPlatforms = [],
- setSelectedPlatforms,
- selectedPlatforms,
-}) => {
- const names = platforms.map(i => i.name)
- const uniquePlatforms = platforms.filter(
- (i, index) => names.indexOf(i.name) === index
- )
- const movingPlatforms = uniquePlatforms.filter(platform =>
- ["Jet", "Prop", "UAV", "Ships/Boats"].includes(platform.type)
- )
- const staticPlatforms = uniquePlatforms.filter(
- platform => !["Jet", "Prop", "UAV", "Ships/Boats"].includes(platform.type)
- )
-
- return (
-
-
-
- )
-}
-
-MapLegend.propTypes = {
- platforms: PropTypes.array,
- platformsWithData: PropTypes.array,
- activeDeploymentPlatforms: PropTypes.array,
- setSelectedPlatforms: PropTypes.func,
- selectedPlatforms: PropTypes.array,
-}
-
-export const PlatformStatus = ({
- platformName,
- platformsWithData,
- activeDeploymentPlatforms,
-}) => {
- const status = usePlatformStatus(
- platformName,
- platformsWithData,
- activeDeploymentPlatforms
- )
-
- if (status !== "operational") {
- return (
-
-
- {status === "notShown" ? "(Not Shown)" : "(Not Operating)"}
-
-
-
- )
- }
- return <>>
-}
-
-PlatformStatus.propTypes = {
- platformName: PropTypes.string,
- platformsWithData: PropTypes.array,
- activeDeploymentPlatforms: PropTypes.array,
-}
-
-const LegendText = styled.label`
- font-weight: ${props => (props.checked ? 600 : 400)};
- font-family: "Titillium Web", sans-serif;
- display: inline-flex;
- gap: 0.25rem;
- margin-left: 0.5rem;
- background: transparent;
- border: none;
- & svg {
- vertical-align: middle;
- }
-`
-
-const IconSpan = styled.span`
- color: ${props => props.color};
- background: #294060;
- border: 0.5px solid;
- border-color: ${props => props.color};
- display: inline-flex;
- height: 1.25rem;
- width: 1.25rem;
- justify-content: center;
- align-items: center;
- border-radius: 512px;
- & svg {
- vertical-align: unset;
- font-weight: 600;
- }
-`
-
-const LegendBox = styled.div`
- display: inline-block;
- text-align: left;
- min-width: 14rem;
- position: absolute;
- right: 5px;
- margin-top: 5px;
- margin-right: 5px;
- padding: 8px;
- color: ${colors.lightTheme.text};
- background-color: rgba(255, 255, 255, 0.75);
- transition: all 0.24s ease-out;
- > fieldset {
- border: 0px;
- }
- > fieldset > legend {
- padding: 0 0 4px;
- font-family: "Titillium Web", sans-serif;
- color: ${colors.lightTheme.text};
- font-size: 1.1rem;
- font-weight: 600;
- }
- & input {
- cursor: pointer;
- }
- & h4 {
- font-weight: 600;
- color: ${colors.lightTheme.text};
- font-size: 0.8rem;
- margin: 4px 0 2px;
- }
- &:hover {
- background-color: rgba(255, 255, 255, 0.95);
- }
-`
-
-const Tag = styled.div`
- display: inline;
- > u {
- text-decoration-line: underline;
- text-decoration-style: dotted;
- text-decoration-color: #4d4d4d;
- color: #333;
- text-decoration-thickness: 2px;
- padding-left: 7px;
- &:hover {
- cursor: pointer;
- }
- }
-`
diff --git a/src/components/timeline/timeline-chart.js b/src/components/timeline/timeline-chart.js
index bf0e7a49..43709592 100644
--- a/src/components/timeline/timeline-chart.js
+++ b/src/components/timeline/timeline-chart.js
@@ -13,8 +13,6 @@ import { Disclosure } from "@reach/disclosure"
import { DeploymentPanel } from "./deployment-panel"
import { DeploymentMap } from "./map"
import { replaceSlashes } from "../../utils/helpers"
-import { GlobeMap } from "../map/globe-map"
-import Button from "../button"
const chartSettings = {
marginTop: 1,
@@ -42,7 +40,6 @@ export const Swatch = styled.div`
export const TimelineChart = ({ deployments, bounds, campaignName }) => {
const [containerRef, dms] = useChartDimensions(chartSettings)
- const MAP_STYLE_ID = "devseed/clx25ggbv076o01ql8k8m03k8"
const minDateString = d3
.min(
@@ -89,7 +86,6 @@ export const TimelineChart = ({ deployments, bounds, campaignName }) => {
const [count, setCount] = useState(1)
const [priority, setPriority] = useState({})
const [geojson, setGeojson] = useState({})
- const [enable3DView, setEnable3DView] = useState(false)
const [tooltip, setTooltip] = useState({ x: null, y: null })
const [tooltipContent, setTooltipContent] = useState(null)
@@ -150,32 +146,12 @@ export const TimelineChart = ({ deployments, bounds, campaignName }) => {
return (
{geojson?.features?.length && (
- <>
- {enable3DView ? (
-
- ) : (
-
- )}
-
-
-
- >
+
)}
{
@@ -72,3 +73,72 @@ describe("getPlatformIcon", () => {
)
})
})
+
+describe("isPlatformVisible", () => {
+ const platformProperties = {
+ platform_name: "DC-8",
+ deployment: "SPADE_D1_2018",
+ }
+ it("returns true if there is not selected platforms and deployments", () => {
+ expect(
+ isPlatformVisible({
+ platformProperties,
+ selectedPlatforms: null,
+ selectedDeployment: null,
+ })
+ ).toBeTruthy()
+ })
+ it("returns true if it is one of the selected platforms", () => {
+ expect(
+ isPlatformVisible({
+ platformProperties,
+ selectedPlatforms: ["DC-8", "ER-2"],
+ selectedDeployment: null,
+ })
+ ).toBeTruthy()
+ expect(
+ isPlatformVisible({
+ platformProperties,
+ selectedPlatforms: ["DC-8", "ER-2"],
+ selectedDeployment: { longname: "SPADE_D1_2018" },
+ })
+ ).toBeTruthy()
+ expect(
+ isPlatformVisible({
+ platformProperties,
+ selectedPlatforms: null,
+ selectedDeployment: { longname: "SPADE_D1_2018" },
+ })
+ ).toBeTruthy()
+ })
+ it("returns false if the selected platforms and deployment does not match", () => {
+ expect(
+ isPlatformVisible({
+ platformProperties,
+ selectedPlatforms: ["DC-8", "ER-2"],
+ selectedDeployment: { longname: "SPADE_D2_2019" },
+ })
+ ).toBeFalsy()
+ expect(
+ isPlatformVisible({
+ platformProperties,
+ selectedPlatforms: null,
+ selectedDeployment: { longname: "SPADE_D2_2019" },
+ })
+ ).toBeFalsy()
+ expect(
+ isPlatformVisible({
+ platformProperties,
+ selectedPlatforms: ["ER-2"],
+ selectedDeployment: { longname: "SPADE_D1_2018" },
+ })
+ ).toBeFalsy()
+ expect(
+ isPlatformVisible({
+ platformProperties,
+ selectedPlatforms: ["ER-2"],
+ selectedDeployment: null,
+ })
+ ).toBeFalsy()
+ })
+})
diff --git a/src/utils/platform-colors.js b/src/utils/platform-colors.js
index 62bbbc20..9244bcb0 100644
--- a/src/utils/platform-colors.js
+++ b/src/utils/platform-colors.js
@@ -119,3 +119,16 @@ export const getIconColors = () => {
export const getPlatformIcon = platformName =>
STATIC_PLATFORMS.find(i => i.name === platformName).mapIcon
+
+export const isPlatformVisible = ({
+ platformProperties,
+ selectedPlatforms,
+ selectedDeployment,
+}) => {
+ return (
+ (selectedDeployment === null ||
+ selectedDeployment.longname === platformProperties.deployment) &&
+ (selectedPlatforms === null ||
+ selectedPlatforms.includes(platformProperties.platform_name))
+ )
+}