mirror of
https://github.com/DOI-DO/j40-cejst-2.git
synced 2025-02-23 10:04:18 -08:00
Add tribal info to side panel and feature selection
- create a state variable to keep track of weather or not the layer was toggled - allow mapInfoPanel to reset on layer switch - allow AreaDetail to show census and tribal info - allow LayerSelector to set layer toggled - Add selectedFeature to both MapTribal and MapTract components - create various tribal constants for styling - i18n constants
This commit is contained in:
parent
d4aed789cc
commit
1d3af3023b
11 changed files with 228 additions and 112 deletions
|
@ -22,6 +22,7 @@ import mailIcon from '/node_modules/uswds/dist/img/usa-icons/mail_outline.svg';
|
||||||
interface IAreaDetailProps {
|
interface IAreaDetailProps {
|
||||||
properties: constants.J40Properties,
|
properties: constants.J40Properties,
|
||||||
hash: string[],
|
hash: string[],
|
||||||
|
isCensusLayerSelected: boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -60,7 +61,8 @@ export interface ICategory {
|
||||||
isExceed1MoreBurden: boolean | null,
|
isExceed1MoreBurden: boolean | null,
|
||||||
isExceedBothSocioBurdens: boolean | null,
|
isExceedBothSocioBurdens: boolean | null,
|
||||||
}
|
}
|
||||||
const AreaDetail = ({properties, hash}: IAreaDetailProps) => {
|
|
||||||
|
const AreaDetail = ({properties, hash, isCensusLayerSelected}: IAreaDetailProps) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
// console.log the properties of the census that is selected:
|
// console.log the properties of the census that is selected:
|
||||||
|
@ -72,6 +74,7 @@ const AreaDetail = ({properties, hash}: IAreaDetailProps) => {
|
||||||
const countyName = properties[constants.COUNTY_NAME] ? properties[constants.COUNTY_NAME] : "N/A";
|
const countyName = properties[constants.COUNTY_NAME] ? properties[constants.COUNTY_NAME] : "N/A";
|
||||||
const stateName = properties[constants.STATE_NAME] ? properties[constants.STATE_NAME] : "N/A";
|
const stateName = properties[constants.STATE_NAME] ? properties[constants.STATE_NAME] : "N/A";
|
||||||
const sidePanelState = properties[constants.SIDE_PANEL_STATE];
|
const sidePanelState = properties[constants.SIDE_PANEL_STATE];
|
||||||
|
const landAreaName = properties[constants.LAND_AREA_NAME];
|
||||||
|
|
||||||
const isCommunityFocus = score >= constants.SCORE_BOUNDARY_THRESHOLD;
|
const isCommunityFocus = score >= constants.SCORE_BOUNDARY_THRESHOLD;
|
||||||
|
|
||||||
|
@ -572,96 +575,110 @@ const AreaDetail = ({properties, hash}: IAreaDetailProps) => {
|
||||||
{EXPLORE_COPY.SIDE_PANEL_VERION.TITLE}
|
{EXPLORE_COPY.SIDE_PANEL_VERION.TITLE}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Census Info */}
|
{
|
||||||
<ul className={styles.censusRow}>
|
isCensusLayerSelected ? (
|
||||||
<li>
|
<>
|
||||||
<span className={styles.censusLabel}>
|
{/* Census Info */}
|
||||||
{intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_CBG_INFO.CENSUS_BLOCK_GROUP)}
|
<ul className={styles.censusRow}>
|
||||||
</span>
|
<li>
|
||||||
<span className={styles.censusText}>{` ${blockGroup}`}</span>
|
<span className={styles.censusLabel}>
|
||||||
</li>
|
{intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_CBG_INFO.CENSUS_BLOCK_GROUP)}
|
||||||
<li>
|
</span>
|
||||||
<span className={styles.censusLabel}>
|
<span className={styles.censusText}>{` ${blockGroup}`}</span>
|
||||||
{intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_CBG_INFO.COUNTY)}
|
</li>
|
||||||
</span>
|
<li>
|
||||||
<span className={styles.censusText}>{` ${countyName}`}</span>
|
<span className={styles.censusLabel}>
|
||||||
</li>
|
{intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_CBG_INFO.COUNTY)}
|
||||||
<li>
|
</span>
|
||||||
<span className={styles.censusLabel}>
|
<span className={styles.censusText}>{` ${countyName}`}</span>
|
||||||
{properties[constants.SIDE_PANEL_STATE] !== constants.SIDE_PANEL_STATE_VALUES.NATION ?
|
</li>
|
||||||
intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_CBG_INFO.TERRITORY) :
|
<li>
|
||||||
intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_CBG_INFO.STATE)
|
<span className={styles.censusLabel}>
|
||||||
}
|
{properties[constants.SIDE_PANEL_STATE] !== constants.SIDE_PANEL_STATE_VALUES.NATION ?
|
||||||
</span>
|
intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_CBG_INFO.TERRITORY) :
|
||||||
<span className={styles.censusText}>{` ${stateName}`}</span>
|
intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_CBG_INFO.STATE)
|
||||||
</li>
|
}
|
||||||
<li>
|
</span>
|
||||||
<span className={styles.censusLabel}>
|
<span className={styles.censusText}>{` ${stateName}`}</span>
|
||||||
{intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_CBG_INFO.POPULATION)}
|
</li>
|
||||||
</span>
|
<li>
|
||||||
<span className={styles.censusText}>{` ${population.toLocaleString()}`}</span>
|
<span className={styles.censusLabel}>
|
||||||
</li>
|
{intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_CBG_INFO.POPULATION)}
|
||||||
</ul>
|
</span>
|
||||||
|
<span className={styles.censusText}>{` ${population.toLocaleString()}`}</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
{/* Disadvantaged? */}
|
{/* Disadvantaged? */}
|
||||||
<div className={styles.categorization}>
|
<div className={styles.categorization}>
|
||||||
|
|
||||||
{/* Questions asking if disadvantaged? */}
|
{/* Questions asking if disadvantaged? */}
|
||||||
<div className={styles.isInFocus}>
|
<div className={styles.isInFocus}>
|
||||||
{EXPLORE_COPY.COMMUNITY.IS_FOCUS}
|
{EXPLORE_COPY.COMMUNITY.IS_FOCUS}
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* YES with Dot or NO with no Dot */}
|
|
||||||
<div className={styles.communityOfFocus}>
|
|
||||||
{isCommunityFocus ?
|
|
||||||
<>
|
|
||||||
<h3>{EXPLORE_COPY.COMMUNITY.OF_FOCUS}</h3>
|
|
||||||
<DisadvantageDot isDisadvantaged={isCommunityFocus} />
|
|
||||||
</> :
|
|
||||||
<h3>{EXPLORE_COPY.COMMUNITY.NOT_OF_FOCUS}</h3>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Number of categories exceeded */}
|
|
||||||
<div className={styles.showCategoriesExceed}>
|
|
||||||
{EXPLORE_COPY.numberOfCategoriesExceeded(properties[constants.COUNT_OF_CATEGORIES_DISADV])}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Number of thresholds exceeded */}
|
|
||||||
{/* <div className={styles.showThresholdExceed}>
|
|
||||||
{EXPLORE_COPY.numberOfThresholdsExceeded(properties[constants.TOTAL_NUMBER_OF_DISADVANTAGE_INDICATORS])}
|
|
||||||
</div> */}
|
|
||||||
{/* Send Feedback button */}
|
|
||||||
<a
|
|
||||||
className={styles.sendFeedbackLink}
|
|
||||||
// The mailto string must be on a single line otherwise the email does not display subject and body
|
|
||||||
href={`
|
|
||||||
mailto:${COMMON_COPY.FEEDBACK_EMAIL}?subject=${feedbackEmailSubject}&body=${feedbackEmailBody}
|
|
||||||
`}
|
|
||||||
target={"_blank"}
|
|
||||||
rel="noreferrer"
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
type="button"
|
|
||||||
className={styles.sendFeedbackBtn}
|
|
||||||
>
|
|
||||||
<div className={styles.buttonContainer}>
|
|
||||||
<div className={styles.buttonText}>
|
|
||||||
{EXPLORE_COPY.COMMUNITY.SEND_FEEDBACK.TITLE}
|
|
||||||
</div>
|
|
||||||
<img
|
|
||||||
className={styles.buttonImage}
|
|
||||||
src={mailIcon}
|
|
||||||
alt={intl.formatMessage(EXPLORE_COPY.COMMUNITY.SEND_FEEDBACK.IMG_ICON.ALT_TAG)}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</Button>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
</div>
|
{/* YES with Dot or NO with no Dot */}
|
||||||
|
<div className={styles.communityOfFocus}>
|
||||||
|
{isCommunityFocus ?
|
||||||
|
<>
|
||||||
|
<h3>{EXPLORE_COPY.COMMUNITY.OF_FOCUS}</h3>
|
||||||
|
<DisadvantageDot isDisadvantaged={isCommunityFocus} />
|
||||||
|
</> :
|
||||||
|
<h3>{EXPLORE_COPY.COMMUNITY.NOT_OF_FOCUS}</h3>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Number of categories exceeded */}
|
||||||
|
<div className={styles.showCategoriesExceed}>
|
||||||
|
{EXPLORE_COPY.numberOfCategoriesExceeded(properties[constants.COUNT_OF_CATEGORIES_DISADV])}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Number of thresholds exceeded */}
|
||||||
|
{/* <div className={styles.showThresholdExceed}>
|
||||||
|
{EXPLORE_COPY.numberOfThresholdsExceeded(properties[constants.TOTAL_NUMBER_OF_DISADVANTAGE_INDICATORS])}
|
||||||
|
</div> */}
|
||||||
|
{/* Send Feedback button */}
|
||||||
|
<a
|
||||||
|
className={styles.sendFeedbackLink}
|
||||||
|
// The mailto string must be on a single line otherwise the email does not display subject and body
|
||||||
|
href={`
|
||||||
|
mailto:${COMMON_COPY.FEEDBACK_EMAIL}?subject=${feedbackEmailSubject}&body=${feedbackEmailBody}
|
||||||
|
`}
|
||||||
|
target={"_blank"}
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
className={styles.sendFeedbackBtn}
|
||||||
|
>
|
||||||
|
<div className={styles.buttonContainer}>
|
||||||
|
<div className={styles.buttonText}>
|
||||||
|
{EXPLORE_COPY.COMMUNITY.SEND_FEEDBACK.TITLE}
|
||||||
|
</div>
|
||||||
|
<img
|
||||||
|
className={styles.buttonImage}
|
||||||
|
src={mailIcon}
|
||||||
|
alt={intl.formatMessage(EXPLORE_COPY.COMMUNITY.SEND_FEEDBACK.IMG_ICON.ALT_TAG)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Button>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<ul className={styles.censusRow}>
|
||||||
|
<li>
|
||||||
|
<span className={styles.censusLabel}>
|
||||||
|
{intl.formatMessage(EXPLORE_COPY.SIDE_PANEL_TRIBAL_INFO.LAND_AREA_NAME)}
|
||||||
|
</span>
|
||||||
|
<span className={styles.censusText}>{` ${landAreaName}`}</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
)}
|
||||||
|
|
||||||
|
|
||||||
{/* All category accordions in this component */}
|
{/* All category accordions in this component */}
|
||||||
<Accordion multiselectable={true} items={categoryItems} />
|
{isCensusLayerSelected && <Accordion multiselectable={true} items={categoryItems} />}
|
||||||
|
|
||||||
</aside>
|
</aside>
|
||||||
);
|
);
|
||||||
|
|
|
@ -5,6 +5,7 @@ import {LocalizedComponent} from '../../../test/testHelpers';
|
||||||
|
|
||||||
import * as constants from '../../../data/constants';
|
import * as constants from '../../../data/constants';
|
||||||
|
|
||||||
|
// Todo: Update tests to take into account tribal layer selected
|
||||||
describe('rendering of the AreaDetail', () => {
|
describe('rendering of the AreaDetail', () => {
|
||||||
const properties = {
|
const properties = {
|
||||||
[constants.POVERTY_BELOW_100_PERCENTILE]: .12,
|
[constants.POVERTY_BELOW_100_PERCENTILE]: .12,
|
||||||
|
@ -27,7 +28,7 @@ describe('rendering of the AreaDetail', () => {
|
||||||
it('checks if indicators for NATION is present', () => {
|
it('checks if indicators for NATION is present', () => {
|
||||||
const {asFragment} = render(
|
const {asFragment} = render(
|
||||||
<LocalizedComponent>
|
<LocalizedComponent>
|
||||||
<AreaDetail properties={properties} hash={hash}/>
|
<AreaDetail properties={properties} hash={hash} isCensusLayerSelected={true}/>
|
||||||
</LocalizedComponent>,
|
</LocalizedComponent>,
|
||||||
);
|
);
|
||||||
expect(asFragment()).toMatchSnapshot();
|
expect(asFragment()).toMatchSnapshot();
|
||||||
|
@ -41,7 +42,7 @@ describe('rendering of the AreaDetail', () => {
|
||||||
|
|
||||||
const {asFragment} = render(
|
const {asFragment} = render(
|
||||||
<LocalizedComponent>
|
<LocalizedComponent>
|
||||||
<AreaDetail properties={propertiesPR} hash={hash}/>
|
<AreaDetail properties={propertiesPR} hash={hash} isCensusLayerSelected={true}/>
|
||||||
</LocalizedComponent>,
|
</LocalizedComponent>,
|
||||||
);
|
);
|
||||||
expect(asFragment()).toMatchSnapshot();
|
expect(asFragment()).toMatchSnapshot();
|
||||||
|
@ -59,7 +60,7 @@ describe('rendering of the AreaDetail', () => {
|
||||||
|
|
||||||
const {asFragment} = render(
|
const {asFragment} = render(
|
||||||
<LocalizedComponent>
|
<LocalizedComponent>
|
||||||
<AreaDetail properties={propertiesIA} hash={hash}/>
|
<AreaDetail properties={propertiesIA} hash={hash} isCensusLayerSelected={true}/>
|
||||||
</LocalizedComponent>,
|
</LocalizedComponent>,
|
||||||
);
|
);
|
||||||
expect(asFragment()).toMatchSnapshot();
|
expect(asFragment()).toMatchSnapshot();
|
||||||
|
|
|
@ -85,6 +85,10 @@ const J40Map = ({location}: IJ40Interface) => {
|
||||||
const [geolocationInProgress, setGeolocationInProgress] = useState<boolean>(false);
|
const [geolocationInProgress, setGeolocationInProgress] = useState<boolean>(false);
|
||||||
const [isMobileMapState, setIsMobileMapState] = useState<boolean>(false);
|
const [isMobileMapState, setIsMobileMapState] = useState<boolean>(false);
|
||||||
const [censusSelected, setCensusSelected] = useState(true);
|
const [censusSelected, setCensusSelected] = useState(true);
|
||||||
|
|
||||||
|
// In order to detect that the layer has been toggled (between census and tribal),
|
||||||
|
// this state variable will hold that information
|
||||||
|
const [layerToggled, setLayerToggled] = useState<boolean>(false);
|
||||||
const {width: windowWidth} = useWindowSize();
|
const {width: windowWidth} = useWindowSize();
|
||||||
|
|
||||||
const mapRef = useRef<MapRef>(null);
|
const mapRef = useRef<MapRef>(null);
|
||||||
|
@ -156,6 +160,9 @@ const J40Map = ({location}: IJ40Interface) => {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// This else clause will fire when the ID is null or empty. This is the case where the map is clicked
|
// This else clause will fire when the ID is null or empty. This is the case where the map is clicked
|
||||||
|
|
||||||
|
setLayerToggled(false);
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const feature = event.features && event.features[0];
|
const feature = event.features && event.features[0];
|
||||||
|
|
||||||
|
@ -308,7 +315,11 @@ const J40Map = ({location}: IJ40Interface) => {
|
||||||
|
|
||||||
|
|
||||||
{/* This will allow to select between the census tract layer and the tribal lands layer */}
|
{/* This will allow to select between the census tract layer and the tribal lands layer */}
|
||||||
<LayerSelector censusSelected={censusSelected} setCensusSelected={setCensusSelected}/>
|
<LayerSelector
|
||||||
|
censusSelected={censusSelected}
|
||||||
|
setCensusSelected={setCensusSelected}
|
||||||
|
setLayerToggled={setLayerToggled}
|
||||||
|
/>
|
||||||
|
|
||||||
{/**
|
{/**
|
||||||
* The ReactMapGL component's props are grouped by the API's documentation. The component also has
|
* The ReactMapGL component's props are grouped by the API's documentation. The component also has
|
||||||
|
@ -356,9 +367,15 @@ const J40Map = ({location}: IJ40Interface) => {
|
||||||
|
|
||||||
{/* Load either the Tribal layer or census layer */}
|
{/* Load either the Tribal layer or census layer */}
|
||||||
{
|
{
|
||||||
censusSelected ?
|
censusSelected ?
|
||||||
<MapTractLayers selectedFeature={selectedFeature} selectedFeatureId={selectedFeatureId}/> :
|
<MapTractLayers
|
||||||
<MapTribalLayer />
|
selectedFeature={selectedFeature}
|
||||||
|
selectedFeatureId={selectedFeatureId}
|
||||||
|
/> :
|
||||||
|
<MapTribalLayer
|
||||||
|
selectedFeature={selectedFeature}
|
||||||
|
selectedFeatureId={selectedFeatureId}
|
||||||
|
/>
|
||||||
}
|
}
|
||||||
|
|
||||||
{/* This will add the navigation controls of the zoom in and zoom out buttons */}
|
{/* This will add the navigation controls of the zoom in and zoom out buttons */}
|
||||||
|
@ -392,7 +409,11 @@ const J40Map = ({location}: IJ40Interface) => {
|
||||||
onClose={setDetailViewData}
|
onClose={setDetailViewData}
|
||||||
captureScroll={true}
|
captureScroll={true}
|
||||||
>
|
>
|
||||||
<AreaDetail properties={detailViewData.properties} hash={zoomLatLngHash}/>
|
<AreaDetail
|
||||||
|
properties={detailViewData.properties}
|
||||||
|
hash={zoomLatLngHash}
|
||||||
|
isCensusLayerSelected={censusSelected}
|
||||||
|
/>
|
||||||
</Popup>
|
</Popup>
|
||||||
)}
|
)}
|
||||||
{'fs' in flags ? <FullscreenControl className={styles.fullscreenControl}/> :'' }
|
{'fs' in flags ? <FullscreenControl className={styles.fullscreenControl}/> :'' }
|
||||||
|
@ -406,6 +427,8 @@ const J40Map = ({location}: IJ40Interface) => {
|
||||||
featureProperties={detailViewData?.properties}
|
featureProperties={detailViewData?.properties}
|
||||||
selectedFeatureId={selectedFeature?.id}
|
selectedFeatureId={selectedFeature?.id}
|
||||||
hash={zoomLatLngHash}
|
hash={zoomLatLngHash}
|
||||||
|
isCensusLayerSelected={censusSelected}
|
||||||
|
layerToggled={layerToggled}
|
||||||
/>
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -7,7 +7,7 @@ describe('rendering of the LayerSelector', () => {
|
||||||
it('checks if component renders census tracts selected', () => {
|
it('checks if component renders census tracts selected', () => {
|
||||||
const {asFragment} = render(
|
const {asFragment} = render(
|
||||||
<LocalizedComponent>
|
<LocalizedComponent>
|
||||||
<LayerSelector censusSelected={true} setCensusSelected={() => {}}/>
|
<LayerSelector censusSelected={true} setCensusSelected={() => {}} setLayerToggled={() =>{}}/>
|
||||||
</LocalizedComponent>,
|
</LocalizedComponent>,
|
||||||
);
|
);
|
||||||
expect(asFragment()).toMatchSnapshot();
|
expect(asFragment()).toMatchSnapshot();
|
||||||
|
@ -16,7 +16,7 @@ describe('rendering of the LayerSelector', () => {
|
||||||
it('checks if component renders tribal selected', () => {
|
it('checks if component renders tribal selected', () => {
|
||||||
const {asFragment} = render(
|
const {asFragment} = render(
|
||||||
<LocalizedComponent>
|
<LocalizedComponent>
|
||||||
<LayerSelector censusSelected={false} setCensusSelected={() => {}}/>
|
<LayerSelector censusSelected={false} setCensusSelected={() => {}} setLayerToggled={()=> {}}/>
|
||||||
</LocalizedComponent>,
|
</LocalizedComponent>,
|
||||||
);
|
);
|
||||||
expect(asFragment()).toMatchSnapshot();
|
expect(asFragment()).toMatchSnapshot();
|
||||||
|
|
|
@ -10,9 +10,10 @@ import * as EXPLORE_COPY from '../../data/copy/explore';
|
||||||
interface ILayerSelector {
|
interface ILayerSelector {
|
||||||
censusSelected: boolean,
|
censusSelected: boolean,
|
||||||
setCensusSelected: Dispatch<boolean>,
|
setCensusSelected: Dispatch<boolean>,
|
||||||
|
setLayerToggled: Dispatch<boolean>,
|
||||||
}
|
}
|
||||||
|
|
||||||
const LayerSelector = ({censusSelected, setCensusSelected}:ILayerSelector) => {
|
const LayerSelector = ({censusSelected, setCensusSelected, setLayerToggled}:ILayerSelector) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -38,6 +39,13 @@ const LayerSelector = ({censusSelected, setCensusSelected}:ILayerSelector) => {
|
||||||
}
|
}
|
||||||
}, [width]);
|
}, [width]);
|
||||||
|
|
||||||
|
// Anytime the censusSelected state variable changes, set the LayerToggled state
|
||||||
|
// variable
|
||||||
|
useEffect( () => {
|
||||||
|
setLayerToggled(true);
|
||||||
|
}, [censusSelected]);
|
||||||
|
|
||||||
|
|
||||||
// Handles toggle of tracts and tribal layer selection
|
// Handles toggle of tracts and tribal layer selection
|
||||||
const buttonClickHandler = (event) => {
|
const buttonClickHandler = (event) => {
|
||||||
if (event.target.id === 'census' && !censusSelected) {
|
if (event.target.id === 'census' && !censusSelected) {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React, {useMemo} from 'react';
|
import React, {useMemo} from 'react';
|
||||||
import {Source, Layer} from 'react-map-gl';
|
import {Source, Layer} from 'react-map-gl';
|
||||||
|
import {AnyLayer} from 'mapbox-gl';
|
||||||
|
|
||||||
// Contexts:
|
// Contexts:
|
||||||
import {useFlags} from '../../contexts/FlagContext';
|
import {useFlags} from '../../contexts/FlagContext';
|
||||||
|
@ -7,10 +8,9 @@ import {useFlags} from '../../contexts/FlagContext';
|
||||||
import * as constants from '../../data/constants';
|
import * as constants from '../../data/constants';
|
||||||
import * as COMMON_COPY from '../../data/copy/common';
|
import * as COMMON_COPY from '../../data/copy/common';
|
||||||
|
|
||||||
// Todo: Update with real types if this works:
|
|
||||||
interface IMapTractLayers {
|
interface IMapTractLayers {
|
||||||
selectedFeatureId: any,
|
selectedFeatureId: AnyLayer,
|
||||||
selectedFeature: any
|
selectedFeature: AnyLayer,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -56,7 +56,10 @@ export const featureURLForTilesetName = (tilesetName: string): string => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const MapTractLayers = ({selectedFeatureId, selectedFeature}: IMapTractLayers) => {
|
const MapTractLayers = ({
|
||||||
|
selectedFeatureId,
|
||||||
|
selectedFeature,
|
||||||
|
}: IMapTractLayers) => {
|
||||||
const filter = useMemo(() => ['in', constants.GEOID_PROPERTY, selectedFeatureId], [selectedFeature]);
|
const filter = useMemo(() => ['in', constants.GEOID_PROPERTY, selectedFeatureId], [selectedFeature]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -1,8 +1,14 @@
|
||||||
import React from 'react';
|
import React, {useMemo} from 'react';
|
||||||
import {Source, Layer} from 'react-map-gl';
|
import {Source, Layer} from 'react-map-gl';
|
||||||
|
import {AnyLayer} from 'mapbox-gl';
|
||||||
|
|
||||||
import * as constants from '../../data/constants';
|
import * as constants from '../../data/constants';
|
||||||
|
|
||||||
|
interface IMapTribalLayers {
|
||||||
|
selectedFeatureId: AnyLayer,
|
||||||
|
selectedFeature: AnyLayer,
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function will determine the URL for the tribal tiles.
|
* This function will determine the URL for the tribal tiles.
|
||||||
* @return {string}
|
* @return {string}
|
||||||
|
@ -18,7 +24,12 @@ export const tribalURL = (): string => {
|
||||||
].join('/');
|
].join('/');
|
||||||
};
|
};
|
||||||
|
|
||||||
const MapTribalLayer = () => {
|
const MapTribalLayer = ({
|
||||||
|
selectedFeatureId,
|
||||||
|
selectedFeature,
|
||||||
|
}: IMapTribalLayers) => {
|
||||||
|
const tribalSelectionFilter = useMemo(() => ['in', constants.TRIBAL_ID, selectedFeatureId], [selectedFeature]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Source
|
<Source
|
||||||
id={constants.TRIBAL_SOURCE_NAME}
|
id={constants.TRIBAL_SOURCE_NAME}
|
||||||
|
@ -29,7 +40,7 @@ const MapTribalLayer = () => {
|
||||||
maxzoom={constants.TRIBAL_MAX_ZOOM}
|
maxzoom={constants.TRIBAL_MAX_ZOOM}
|
||||||
>
|
>
|
||||||
|
|
||||||
{/* Low zoom layer - prioritized features only */}
|
{/* Tribal layer */}
|
||||||
<Layer
|
<Layer
|
||||||
id={constants.TRIBAL_LAYER_ID}
|
id={constants.TRIBAL_LAYER_ID}
|
||||||
source-layer={constants.TRIBAL_SOURCE_LAYER}
|
source-layer={constants.TRIBAL_SOURCE_LAYER}
|
||||||
|
@ -48,7 +59,7 @@ const MapTribalLayer = () => {
|
||||||
source-layer={constants.SCORE_SOURCE_LAYER}
|
source-layer={constants.SCORE_SOURCE_LAYER}
|
||||||
type='line'
|
type='line'
|
||||||
paint={{
|
paint={{
|
||||||
'line-color': constants.TRIBAL_BORDER_COLOR,
|
'line-color': constants.FEATURE_BORDER_COLOR,
|
||||||
'line-width': constants.FEATURE_BORDER_WIDTH,
|
'line-width': constants.FEATURE_BORDER_WIDTH,
|
||||||
'line-opacity': constants.FEATURE_BORDER_OPACITY,
|
'line-opacity': constants.FEATURE_BORDER_OPACITY,
|
||||||
}}
|
}}
|
||||||
|
@ -58,8 +69,9 @@ const MapTribalLayer = () => {
|
||||||
|
|
||||||
{/* Tribal layer - border styling around the selected feature */}
|
{/* Tribal layer - border styling around the selected feature */}
|
||||||
<Layer
|
<Layer
|
||||||
id={constants.SELECTED_FEATURE_BORDER_LAYER_ID}
|
id={constants.SELECTED_TRIBAL_FEATURE_BORDER_LAYER_ID}
|
||||||
source-layer={constants.TRIBAL_SOURCE_NAME}
|
source-layer={constants.TRIBAL_SOURCE_LAYER}
|
||||||
|
filter={tribalSelectionFilter}
|
||||||
type='line'
|
type='line'
|
||||||
paint={{
|
paint={{
|
||||||
'line-color': constants.SELECTED_FEATURE_BORDER_COLOR,
|
'line-color': constants.SELECTED_FEATURE_BORDER_COLOR,
|
||||||
|
@ -67,6 +79,23 @@ const MapTribalLayer = () => {
|
||||||
}}
|
}}
|
||||||
minzoom={constants.TRIBAL_MIN_ZOOM}
|
minzoom={constants.TRIBAL_MIN_ZOOM}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{/* Alaska layer */}
|
||||||
|
{/* // Todo: Figure out why this isn't working */}
|
||||||
|
<Layer
|
||||||
|
id={constants.SELECTED_FEATURE_BORDER_LAYER_ID}
|
||||||
|
source-layer={constants.TRIBAL_SOURCE_NAME}
|
||||||
|
|
||||||
|
// Using other filter expressions, such as equality decisions here
|
||||||
|
// may cause the open-source to error out on circle not defined
|
||||||
|
filter={['geometry-type', 'Point']}
|
||||||
|
type='circle'
|
||||||
|
paint={{
|
||||||
|
'circle-radius': 100,
|
||||||
|
'circle-color': '#007cbf',
|
||||||
|
}}
|
||||||
|
minzoom={constants.TRIBAL_MIN_ZOOM}
|
||||||
|
/>
|
||||||
</Source>
|
</Source>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,13 +7,33 @@ interface IMapInfoPanelProps {
|
||||||
featureProperties: { [key:string]: string | number } | undefined,
|
featureProperties: { [key:string]: string | number } | undefined,
|
||||||
selectedFeatureId: string | number | undefined
|
selectedFeatureId: string | number | undefined
|
||||||
hash: string[],
|
hash: string[],
|
||||||
|
isCensusLayerSelected: boolean,
|
||||||
|
layerToggled: boolean, // indicates if census layer or tribal layer has been toggled
|
||||||
}
|
}
|
||||||
|
|
||||||
const MapInfoPanel = ({className, featureProperties, selectedFeatureId, hash}:IMapInfoPanelProps) => {
|
const MapInfoPanel = ({
|
||||||
|
className,
|
||||||
|
featureProperties,
|
||||||
|
selectedFeatureId,
|
||||||
|
hash,
|
||||||
|
isCensusLayerSelected,
|
||||||
|
layerToggled,
|
||||||
|
}:IMapInfoPanelProps) => {
|
||||||
return (
|
return (
|
||||||
<div className={className} >
|
<div className={className} >
|
||||||
{(featureProperties && selectedFeatureId ) ?
|
{/* The tertiary conditional statement below will control the side panel state. Currently
|
||||||
<AreaDetail properties={featureProperties} hash={hash}/> :
|
there are two states, namely showing the AreaDetail or SidePanelInfo. When a feature
|
||||||
|
is selected, on - for example - the census tract layer, and if the Tribal Layer is the selected
|
||||||
|
the Side Panel should revert back to the SidePanelInfo.
|
||||||
|
|
||||||
|
A new boolean called layerToggle captures that a layer has been selected and to render
|
||||||
|
the SidePanelInfo component */}
|
||||||
|
{(featureProperties && selectedFeatureId && !layerToggled) ?
|
||||||
|
<AreaDetail
|
||||||
|
properties={featureProperties}
|
||||||
|
hash={hash}
|
||||||
|
isCensusLayerSelected={isCensusLayerSelected}
|
||||||
|
/> :
|
||||||
<SidePanelInfo />
|
<SidePanelInfo />
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -27,6 +27,7 @@ export type J40Properties = { [key: string]: any };
|
||||||
|
|
||||||
// Tribal signals
|
// Tribal signals
|
||||||
export const TRIBAL_ID = 'tribalId';
|
export const TRIBAL_ID = 'tribalId';
|
||||||
|
export const LAND_AREA_NAME = 'landAreaName';
|
||||||
|
|
||||||
// Set the threshold percentile used by most indicators in the side panel
|
// Set the threshold percentile used by most indicators in the side panel
|
||||||
export const DEFAULT_THRESHOLD_PERCENTILE = 90;
|
export const DEFAULT_THRESHOLD_PERCENTILE = 90;
|
||||||
|
@ -202,6 +203,7 @@ export const LOW_ZOOM_LAYER_ID = 'low-zoom-layer-id';
|
||||||
export const FEATURE_BORDER_LAYER_ID = 'feature-border-layer-id';
|
export const FEATURE_BORDER_LAYER_ID = 'feature-border-layer-id';
|
||||||
export const SELECTED_FEATURE_BORDER_LAYER_ID = 'selected-feature-border-layer-id';
|
export const SELECTED_FEATURE_BORDER_LAYER_ID = 'selected-feature-border-layer-id';
|
||||||
export const TRIBAL_LAYER_ID = 'tribal-layer-id';
|
export const TRIBAL_LAYER_ID = 'tribal-layer-id';
|
||||||
|
export const SELECTED_TRIBAL_FEATURE_BORDER_LAYER_ID = 'selected-feature-tribal-border-layer-id';
|
||||||
|
|
||||||
// Used in layer filters:
|
// Used in layer filters:
|
||||||
export const SCORE_PROPERTY_LOW = 'M_SCORE';
|
export const SCORE_PROPERTY_LOW = 'M_SCORE';
|
||||||
|
@ -234,9 +236,9 @@ export const FEATURE_BORDER_COLOR = '#4EA5CF';
|
||||||
export const SELECTED_FEATURE_BORDER_COLOR = '#1A4480';
|
export const SELECTED_FEATURE_BORDER_COLOR = '#1A4480';
|
||||||
export const PRIORITIZED_FEATURE_FILL_COLOR = '#768FB3';
|
export const PRIORITIZED_FEATURE_FILL_COLOR = '#768FB3';
|
||||||
|
|
||||||
export const TRIBAL_BORDER_COLOR = '#0000FF';
|
export const TRIBAL_BORDER_COLOR = '##4EA5CF';
|
||||||
export const SELECTED_TRIBAL_BORDER_COLOR = '#FF0000';
|
export const SELECTED_TRIBAL_BORDER_COLOR = '#1A4480';
|
||||||
export const TRIBAL_FILL_COLOR = '#00FF00';
|
export const TRIBAL_FILL_COLOR = '#768FB3';
|
||||||
|
|
||||||
|
|
||||||
// Widths
|
// Widths
|
||||||
|
|
|
@ -300,6 +300,15 @@ export const SIDE_PANEL_CBG_INFO = defineMessages({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const SIDE_PANEL_TRIBAL_INFO = defineMessages({
|
||||||
|
LAND_AREA_NAME: {
|
||||||
|
id: 'explore.map.page.side.panel.tribalInfo.landAreaName',
|
||||||
|
defaultMessage: 'Land Area Name:',
|
||||||
|
description: `Navigate to the explore the map page. Click on Tribal Lands, when the map is in view,
|
||||||
|
click on the map. The side panel will show the land area name of the feature selected`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
export const COMMUNITY = {
|
export const COMMUNITY = {
|
||||||
OF_FOCUS: <FormattedMessage
|
OF_FOCUS: <FormattedMessage
|
||||||
id={'explore.map.page.side.panel.community.of.focus'}
|
id={'explore.map.page.side.panel.community.of.focus'}
|
||||||
|
|
|
@ -823,6 +823,10 @@
|
||||||
"defaultMessage": "AND",
|
"defaultMessage": "AND",
|
||||||
"description": "Navigate to the explore the map page. When the map is in view, click on the map. Click on a category to expand. This is the AND spacer around thresholds."
|
"description": "Navigate to the explore the map page. When the map is in view, click on the map. Click on a category to expand. This is the AND spacer around thresholds."
|
||||||
},
|
},
|
||||||
|
"explore.map.page.side.panel.tribalInfo.landAreaName": {
|
||||||
|
"defaultMessage": "Land Area Name:",
|
||||||
|
"description": "Navigate to the explore the map page. Click on Tribal Lands, when the map is in view, \n click on the map. The side panel will show the land area name of the feature selected"
|
||||||
|
},
|
||||||
"explore.map.page.side.panel.version.title": {
|
"explore.map.page.side.panel.version.title": {
|
||||||
"defaultMessage": "Methodology version {version}",
|
"defaultMessage": "Methodology version {version}",
|
||||||
"description": "Navigate to the explore the map page. When the map is in view, click on the map. The side panel will show the methodology version number"
|
"description": "Navigate to the explore the map page. When the map is in view, click on the map. The side panel will show the methodology version number"
|
||||||
|
|
Loading…
Add table
Reference in a new issue