Skip to content

Commit

Permalink
feat: implement use phasing radio buttons
Browse files Browse the repository at this point in the history
#6 & #5
  • Loading branch information
stdavis committed Jun 17, 2022
1 parent b140956 commit abd980f
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 16 deletions.
22 changes: 15 additions & 7 deletions src/components/AdvancedControls.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { faChevronDown, faChevronUp } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import PropTypes from 'prop-types';
import { Button, Col, Collapse, Container, FormGroup, Input, Label, Row } from 'reactstrap';
import { Button, Col, Collapse, Container, Row } from 'reactstrap';
import config from '../services/config';
import Checkbox from './Checkbox';
import UsePhasing from './UsePhasing';

const numPossibleProjectTypes = {
road: Object.keys(config.projectTypes.road).length,
Expand All @@ -21,6 +22,7 @@ export default function AdvancedControls({
isOpen,
toggle,
phases,
phaseField,
}) {
const getHeaderChecked = (mode) => {
const selectedTypesForMode = selectedProjectTypes[mode];
Expand All @@ -42,12 +44,12 @@ export default function AdvancedControls({

return (
<>
<div className="d-flex justify-content-center">
<div className="d-flex justify-content-center mt-2">
<Button onClick={toggle} size="sm" outline title="Advanced Filter" className="py-0">
<FontAwesomeIcon icon={isOpen ? faChevronDown : faChevronUp} />
</Button>
</div>
<Collapse isOpen={isOpen}>
<Collapse isOpen={isOpen} className="mt-2">
<Container fluid className="p-0">
<b>Filter By Project Type:</b>
<Row className="mb-2">
Expand Down Expand Up @@ -159,21 +161,21 @@ export default function AdvancedControls({
<Col>
<Checkbox
uniqueId="phase-1"
label="Phase 1 (2023-2032)"
label={config.labels.phase.one}
checked={phases.includes(config.symbolValues.phase.one)}
onChange={() => dispatch({ type: 'simple', payload: config.symbolValues.phase.one, meta: 'phase' })}
disabled={disabled}
/>
<Checkbox
uniqueId="phase-2"
label="Phase 2 (2033-2042)"
label={config.labels.phase.two}
checked={phases.includes(config.symbolValues.phase.two)}
onChange={() => dispatch({ type: 'simple', payload: config.symbolValues.phase.two, meta: 'phase' })}
disabled={disabled}
/>
<Checkbox
uniqueId="phase-3"
label="Phase 3 (2043-2050)"
label={config.labels.phase.three}
checked={phases.includes(config.symbolValues.phase.three)}
onChange={() =>
dispatch({ type: 'simple', payload: config.symbolValues.phase.three, meta: 'phase' })
Expand All @@ -182,14 +184,19 @@ export default function AdvancedControls({
/>
<Checkbox
uniqueId="phase-4"
label="Unfunded"
label={config.labels.phase.unfunded}
checked={phases.includes(config.symbolValues.phase.unfunded)}
onChange={() =>
dispatch({ type: 'simple', payload: config.symbolValues.phase.unfunded, meta: 'phase' })
}
disabled={disabled}
/>
</Col>
{phaseField ? (
<Col>
<UsePhasing phaseField={phaseField} disabled={disabled} dispatch={dispatch} />
</Col>
) : null}
</Row>
</>
) : null}
Expand All @@ -209,4 +216,5 @@ AdvancedControls.propTypes = {
isOpen: PropTypes.bool.isRequired,
toggle: PropTypes.func.isRequired,
phases: PropTypes.array,
phaseField: PropTypes.string,
};
33 changes: 25 additions & 8 deletions src/components/Filter.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { addOrRemove, getLabelColor, useMapLayers } from './utils';

export function getQuery(draft, geometryType) {
// phase is a numeric field
const phaseQuery = `${config.fieldNames.phase} IN (${draft.phase.join(',')})`;
const phaseQuery = `${draft.phaseField} IN (${draft.phase.join(',')})`;
// mode is a text field
const modeQuery = `${config.fieldNames.mode} IN ('${draft.mode.join("','")}')`;

Expand Down Expand Up @@ -84,6 +84,11 @@ function reducer(draft, action) {

break;

case 'usePhasing':
draft.phaseField = action.payload;

break;

default:
throw new Error(`Unhandled action type: ${action.type}`);
}
Expand All @@ -106,6 +111,7 @@ const initialState = {
phasePoints: null,
phaseLines: null,
},
phaseField: config.fieldNames.phase,
};

function ErrorFallback({ error }) {
Expand Down Expand Up @@ -142,6 +148,7 @@ export default function Filter({ mapView }) {
}
}, [layers, state.display]);

// filter layers
React.useEffect(() => {
if (layers) {
for (const layerKey of Object.keys(layers)) {
Expand All @@ -153,6 +160,14 @@ export default function Filter({ mapView }) {
}
}, [layers, state.layerDefinitions]);

// update phasing layers renderer
React.useEffect(() => {
if (layers) {
layers.phasePoints.layer.renderer.field = state.phaseField;
layers.phaseLines.layer.renderer.field = state.phaseField;
}
}, [layers, state.phaseField]);

return (
<>
<div className="esri-widget--button" ref={buttonDiv} onClick={toggle} title="Toggle Filter">
Expand Down Expand Up @@ -202,19 +217,19 @@ export default function Filter({ mapView }) {
linear: layers?.modeLines,
point: layers?.modePoints,
value: config.symbolValues.mode.road,
label: 'Road',
label: config.labels.mode.road,
},
{
linear: layers?.modeLines,
point: layers?.modePoints,
value: config.symbolValues.mode.transit,
label: 'Transit',
label: config.labels.mode.transit,
},
{
linear: layers?.modeLines,
point: layers?.modePoints,
value: config.symbolValues.mode.activeTransportation,
label: 'Active Transportation',
label: config.labels.mode.activeTransportation,
},
]}
disabled={!layers}
Expand All @@ -232,6 +247,7 @@ export default function Filter({ mapView }) {
isOpen={isAdvancedOpen}
toggle={toggleAdvanced}
phases={state.phase}
phaseField={state.phaseField}
/>
</TabPane>
<TabPane tabId={PHASE}>
Expand All @@ -244,28 +260,29 @@ export default function Filter({ mapView }) {
linear: layers?.phaseLines,
point: layers?.phasePoints,
value: config.symbolValues.phase.one,
label: 'Phase 1 (2023-2030)',
label: config.labels.phase.one,
},
{
linear: layers?.phaseLines,
point: layers?.phasePoints,
value: config.symbolValues.phase.two,
label: 'Phase 2 (2031-2040)',
label: config.labels.phase.two,
},
{
linear: layers?.phaseLines,
point: layers?.phasePoints,
value: config.symbolValues.phase.three,
label: 'Phase 3 (2041-2050)',
label: config.labels.phase.three,
},
{
linear: layers?.phaseLines,
point: layers?.phasePoints,
value: config.symbolValues.phase.unfunded,
label: 'Unfunded',
label: config.labels.phase.unfunded,
},
]}
disabled={!layers}
phaseField={state.phaseField}
/>
<AdvancedControls
projectTypes={config.projectTypes}
Expand Down
11 changes: 10 additions & 1 deletion src/components/SimpleControls.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ import PropTypes from 'prop-types';
import { Col, Container, Row } from 'reactstrap';
import Checkbox from './Checkbox';
import Swatch from './Swatch';
import UsePhasing from './UsePhasing';
import { getSymbol } from './utils';

const firstColWidth = 7;

export default function SimpleControls({ type, state, dispatch, groups, disabled }) {
export default function SimpleControls({ type, state, dispatch, groups, disabled, phaseField }) {
const toggle = (value) => {
dispatch({ type: 'simple', payload: value, meta: type });
};
Expand Down Expand Up @@ -42,6 +43,13 @@ export default function SimpleControls({ type, state, dispatch, groups, disabled
</Row>
);
})}
{phaseField ? (
<Row>
<Col>
<UsePhasing phaseField={phaseField} disabled={disabled} inline dispatch={dispatch} />
</Col>
</Row>
) : null}
</Container>
);
}
Expand All @@ -58,4 +66,5 @@ SimpleControls.propTypes = {
),
dispatch: PropTypes.func.isRequired,
disabled: PropTypes.bool.isRequired,
phaseField: PropTypes.string,
};
48 changes: 48 additions & 0 deletions src/components/UsePhasing.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import PropTypes from 'prop-types';
import { FormGroup, Input, Label } from 'reactstrap';
import config from '../services/config';

export default function UsePhasing({ phaseField, disabled, inline, dispatch }) {
const handleChange = (event) => dispatch({ type: 'usePhasing', payload: event.target.value });

return (
<>
<b className="me-3">Use Phasing:</b>
<FormGroup check inline={inline}>
<Input
id="use-phasing-constrained"
name={`phasing-${inline}`}
type="radio"
value={config.fieldNames.phase}
checked={phaseField === config.fieldNames.phase}
disabled={disabled}
onChange={handleChange}
/>
<Label check for="use-phasing-constrained">
Financially Constrained
</Label>
</FormGroup>
<FormGroup check inline>
<Input
id="use-phasing-needs"
name={`phasing-${inline}`}
type="radio"
value={config.fieldNames.phaseNeeded}
checked={phaseField === config.fieldNames.phaseNeeded}
disabled={disabled}
onChange={handleChange}
/>
<Label check for="use-phasing-needs">
Needs
</Label>
</FormGroup>
</>
);
}

UsePhasing.propTypes = {
phaseField: PropTypes.string.isRequired,
disabled: PropTypes.bool.isRequired,
inline: PropTypes.bool,
dispatch: PropTypes.func.isRequired,
};
14 changes: 14 additions & 0 deletions src/services/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,22 @@ const config = {
},
fieldNames: {
phase: 'phase',
phaseNeeded: 'phase_needed',
mode: 'mode',
},
labels: {
phase: {
one: 'Phase 1 (2023-2032)',
two: 'Phase 2 (2033-2042)',
three: 'Phase 3 (2043-2050)',
unfunded: 'Unfunded',
},
mode: {
road: 'Road',
transit: 'Transit',
activeTransportation: 'Active Transportation',
},
},
outFields: ['OBJECTID', 'phase', 'mode', 'improvement_type', 'plan_id', 'breakout', 'bike_type_text'],
projectTypes: {
road: {
Expand Down

0 comments on commit abd980f

Please sign in to comment.