diff --git a/src/DateIntervals.jsx b/src/DateIntervals.jsx
index 418845c46..a34645509 100644
--- a/src/DateIntervals.jsx
+++ b/src/DateIntervals.jsx
@@ -11,14 +11,17 @@ export class DateIntervals extends React.Component {
}
_btnClassName( dateInterval ) {
- const btnClass = 'date-selector ';
- return dateInterval === this.props.dateInterval ?
- btnClass + 'selected' : btnClass;
+ const classes = [ 'date-selector', 'interval-' + dateInterval ]
+ if ( dateInterval === this.props.dateInterval ) {
+ classes.push( 'selected' )
+ }
+ return classes.join( ' ' )
}
render() {
return (
+ Date range (Click to modify range)
{ dateIntervals.map( dateInterval =>
+
{
describe('addStateFilter', () => {
@@ -15,6 +16,19 @@ describe('action:map', () => {
})
})
+ describe('dataNormalizationChanged', () => {
+ it('creates a simple action', () => {
+ const expectedAction = {
+ type: sut.DATA_NORMALIZATION_SELECTED,
+ requery: REQUERY_NEVER,
+ value: 'foo'
+ }
+ const action = sut.dataNormalizationChanged( 'foo' )
+ expect(action).toEqual(expectedAction)
+ })
+ })
+
+
describe('removeStateFilter', () => {
it('creates a simple action', () => {
const expectedAction = {
diff --git a/src/actions/map.jsx b/src/actions/map.jsx
index 7ae876d49..489a81316 100644
--- a/src/actions/map.jsx
+++ b/src/actions/map.jsx
@@ -1,9 +1,24 @@
-import { REQUERY_ALWAYS } from '../constants'
+import { REQUERY_ALWAYS, REQUERY_NEVER } from '../constants'
+export const DATA_NORMALIZATION_SELECTED = 'DATA_NORMALIZATION_SELECTED'
export const STATE_COMPLAINTS_SHOWN = 'STATE_COMPLAINTS_SHOWN'
export const STATE_FILTER_ADDED = 'STATE_FILTER_ADDED'
export const STATE_FILTER_REMOVED = 'STATE_FILTER_REMOVED'
+
+/**
+ * Indicates data normalization (yes, per capita) value was selected
+ * @param {object} value of the data normalization
+ * @returns {object} a packaged payload to be used by Redux reducers
+ */
+export function dataNormalizationChanged( value ) {
+ return {
+ type: DATA_NORMALIZATION_SELECTED,
+ requery: REQUERY_NEVER,
+ value
+ };
+}
+
/**
* Creates an action in response after state tile clicked
*
diff --git a/src/constants/index.jsx b/src/constants/index.jsx
index 385ef2d87..750d019bd 100644
--- a/src/constants/index.jsx
+++ b/src/constants/index.jsx
@@ -14,6 +14,10 @@ export const MODE_MAP = 'Map'
export const MODE_LIST = 'List'
export const MODE_TRENDS = 'Trends'
+// map normalization modes
+export const GEO_NORM_NONE = 'None'
+export const GEO_NORM_PER1000 = 'Per 1000 pop.'
+
// Useful constants
export const NARRATIVE_SEARCH_FIELD = 'complaint_what_happened'
@@ -183,3 +187,323 @@ export const TILE_MAP_STATES = [
'WV',
'WY'
]
+
+// 2017 ACS census via the census API:
+// https://api.census.gov/data/2017/acs/acs5?get=B01003_001E,NAME&for=state
+//
+// B01003_001E is defined as TOTAL POPULATION
+// (detailed here: https://api.census.gov/data/2016/acs/acs5/variables.html)
+export const STATE_DATA = [
+ {
+ abbr: 'AL',
+ name: 'Alabama',
+ population: '4850771',
+ id: '01'
+ },
+ {
+ abbr: 'AK',
+ name: 'Alaska',
+ population: '738565',
+ id: '02'
+ },
+ {
+ abbr: 'AZ',
+ name: 'Arizona',
+ population: '6809946',
+ id: '04'
+ },
+ {
+ abbr: 'AR',
+ name: 'Arkansas',
+ population: '2977944',
+ id: '05'
+ },
+ {
+ abbr: 'CA',
+ name: 'California',
+ population: '38982847',
+ id: '06'
+ },
+ {
+ abbr: 'CO',
+ name: 'Colorado',
+ population: '5436519',
+ id: '08'
+ },
+ {
+ abbr: 'CT',
+ name: 'Connecticut',
+ population: '3594478',
+ id: '09'
+ },
+ {
+ abbr: 'DE',
+ name: 'Delaware',
+ population: '943732',
+ id: '10'
+ },
+ {
+ abbr: 'DC',
+ name: 'District of Columbia',
+ population: '672391',
+ id: '11'
+ },
+ {
+ abbr: 'FL',
+ name: 'Florida',
+ population: '20278447',
+ id: '12'
+ },
+ {
+ abbr: 'GA',
+ name: 'Georgia',
+ population: '10201635',
+ id: '13'
+ },
+ {
+ abbr: 'HI',
+ name: 'Hawaii',
+ population: '1421658',
+ id: '15'
+ },
+ {
+ abbr: 'ID',
+ name: 'Idaho',
+ population: '1657375',
+ id: '16'
+ },
+ {
+ abbr: 'IL',
+ name: 'Illinois',
+ population: '12854526',
+ id: '17'
+ },
+ {
+ abbr: 'IN',
+ name: 'Indiana',
+ population: '6614418',
+ id: '18'
+ },
+ {
+ abbr: 'IA',
+ name: 'Iowa',
+ population: '3118102',
+ id: '19'
+ },
+ {
+ abbr: 'KS',
+ name: 'Kansas',
+ population: '2903820',
+ id: '20'
+ },
+ {
+ abbr: 'KY',
+ name: 'Kentucky',
+ population: '4424376',
+ id: '21'
+ },
+ {
+ abbr: 'LA',
+ name: 'Louisiana',
+ population: '4663461',
+ id: '22'
+ },
+ {
+ abbr: 'ME',
+ name: 'Maine',
+ population: '1330158',
+ id: '23'
+ },
+ {
+ abbr: 'MD',
+ name: 'Maryland',
+ population: '5996079',
+ id: '24'
+ },
+ {
+ abbr: 'MA',
+ name: 'Massachusetts',
+ population: '6789319',
+ id: '25'
+ },
+ {
+ abbr: 'MI',
+ name: 'Michigan',
+ population: '9925568',
+ id: '26'
+ },
+ {
+ abbr: 'MN',
+ name: 'Minnesota',
+ population: '5490726',
+ id: '27'
+ },
+ {
+ abbr: 'MS',
+ name: 'Mississippi',
+ population: '2986220',
+ id: '28'
+ },
+ {
+ abbr: 'MO',
+ name: 'Missouri',
+ population: '6075300',
+ id: '29'
+ },
+ {
+ abbr: 'MT',
+ name: 'Montana',
+ population: '1029862',
+ id: '30'
+ },
+ {
+ abbr: 'NE',
+ name: 'Nebraska',
+ population: '1893921',
+ id: '31'
+ },
+ {
+ abbr: 'NV',
+ name: 'Nevada',
+ population: '2887725',
+ id: '32'
+ },
+ {
+ abbr: 'NH',
+ name: 'New Hampshire',
+ population: '1331848',
+ id: '33'
+ },
+ {
+ abbr: 'NJ',
+ name: 'New Jersey',
+ population: '8960161',
+ id: '34'
+ },
+ {
+ abbr: 'NM',
+ name: 'New Mexico',
+ population: '2084828',
+ id: '35'
+ },
+ {
+ abbr: 'NY',
+ name: 'New York',
+ population: '19798228',
+ id: '36'
+ },
+ {
+ abbr: 'NC',
+ name: 'North Carolina',
+ population: '10052564',
+ id: '37'
+ },
+ {
+ abbr: 'ND',
+ name: 'North Dakota',
+ population: '745475',
+ id: '38'
+ },
+ {
+ abbr: 'OH',
+ name: 'Ohio',
+ population: '11609756',
+ id: '39'
+ },
+ {
+ abbr: 'OK',
+ name: 'Oklahoma',
+ population: '3896251',
+ id: '40'
+ },
+ {
+ abbr: 'OR',
+ name: 'Oregon',
+ population: '4025127',
+ id: '41'
+ },
+ {
+ abbr: 'PA',
+ name: 'Pennsylvania',
+ population: '12790505',
+ id: '42'
+ },
+ {
+ abbr: 'PR',
+ name: 'Puerto Rico',
+ population: '3468963',
+ id: '72'
+ },
+ {
+ abbr: 'RI',
+ name: 'Rhode Island',
+ population: '1056138',
+ id: '44'
+ },
+ {
+ abbr: 'SC',
+ name: 'South Carolina',
+ population: '4893444',
+ id: '45'
+ },
+ {
+ abbr: 'SD',
+ name: 'South Dakota',
+ population: '855444',
+ id: '46'
+ },
+ {
+ abbr: 'TN',
+ name: 'Tennessee',
+ population: '6597381',
+ id: '47'
+ },
+ {
+ abbr: 'TX',
+ name: 'Texas',
+ population: '27419612',
+ id: '48'
+ },
+ {
+ abbr: 'UT',
+ name: 'Utah',
+ population: '2993941',
+ id: '49'
+ },
+ {
+ abbr: 'VT',
+ name: 'Vermont',
+ population: '624636',
+ id: '50'
+ },
+ {
+ abbr: 'VA',
+ name: 'Virginia',
+ population: '8365952',
+ id: '51'
+ },
+ {
+ abbr: 'WA',
+ name: 'Washington',
+ population: '7169967',
+ id: '53'
+ },
+ {
+ abbr: 'WV',
+ name: 'West Virginia',
+ population: '1836843',
+ id: '54'
+ },
+ {
+ abbr: 'WI',
+ name: 'Wisconsin',
+ population: '5763217',
+ id: '55'
+ },
+ {
+ abbr: 'WY',
+ name: 'Wyoming',
+ population: '583200',
+ id: '56'
+ }
+]
diff --git a/src/reducers/__tests__/map.spec.jsx b/src/reducers/__tests__/map.spec.jsx
index 3bbcbb689..1b6cd68b6 100644
--- a/src/reducers/__tests__/map.spec.jsx
+++ b/src/reducers/__tests__/map.spec.jsx
@@ -1,8 +1,11 @@
-import target, { processAggregations, processStateAggregations } from '../map'
-import * as complaintActions from '../../actions/complaints'
-import * as mapActions from '../../actions/map'
+import target, {
+ defaultState,
+ processAggregations,
+ processStateAggregations
+} from '../map'
+import actions from '../../actions'
import stateAggs from '../__fixtures__/stateAggs'
-import { TILE_MAP_STATES } from '../../constants'
+import { GEO_NORM_NONE, TILE_MAP_STATES } from '../../constants'
describe( 'reducer:map', () => {
let action
@@ -10,6 +13,7 @@ describe( 'reducer:map', () => {
describe( 'reducer', () => {
it( 'has a default state', () => {
expect( target( undefined, {} ) ).toEqual( {
+ dataNormalization: GEO_NORM_NONE,
isLoading: false,
issue: [],
product: [],
@@ -19,9 +23,19 @@ describe( 'reducer:map', () => {
} )
} )
+ describe('handles DATA_NORMALIZATION_SELECTED', ()=>{
+ action = {
+ type: actions.DATA_NORMALIZATION_SELECTED,
+ value: 'FooBar'
+ }
+ expect( target( {}, action ) ).toEqual( {
+ dataNormalization: 'FooBar'
+ } )
+ })
+
describe( 'handles STATES_API_CALLED actions', () => {
action = {
- type: complaintActions.STATES_API_CALLED,
+ type: actions.STATES_API_CALLED,
url: 'http://www.example.org'
}
expect( target( {}, action ) ).toEqual( {
@@ -33,7 +47,7 @@ describe( 'reducer:map', () => {
describe( 'STATES_RECEIVED actions', () => {
beforeEach( () => {
action = {
- type: complaintActions.STATES_RECEIVED,
+ type: actions.STATES_RECEIVED,
data: {
aggregations: stateAggs
}
@@ -195,7 +209,7 @@ describe( 'reducer:map', () => {
describe( 'STATES_FAILED actions', () => {
it( 'handles failed error messages', () => {
action = {
- type: complaintActions.STATES_FAILED,
+ type: actions.STATES_FAILED,
error: 'foo bar'
}
expect( target( {
@@ -222,7 +236,7 @@ describe( 'reducer:map', () => {
describe( 'STATE_FILTER_ADDED actions', () => {
it( 'adds filter', () => {
action = {
- type: mapActions.STATE_FILTER_ADDED,
+ type: actions.STATE_FILTER_ADDED,
selectedState: { abbr: 'FO', stateName: 'Foo Bar' }
}
expect( target( { selectedState: false }, action ) ).toEqual( {
@@ -234,7 +248,7 @@ describe( 'reducer:map', () => {
describe( 'STATE_FILTER_REMOVED actions', () => {
it( 'adds filter', () => {
action = {
- type: mapActions.STATE_FILTER_REMOVED,
+ type: actions.STATE_FILTER_REMOVED,
stateAbbr: 'FO'
}
expect( target( { selectedState: false }, action ) ).toEqual( {
@@ -243,6 +257,29 @@ describe( 'reducer:map', () => {
} )
} )
+ describe( 'URL_CHANGED actions', () => {
+ let action
+ let state
+ beforeEach( () => {
+ action = {
+ type: actions.URL_CHANGED,
+ params: {}
+ }
+
+ state = { ...defaultState }
+ } )
+
+ it( 'handles empty params', () => {
+ expect( target( state, action ) ).toEqual( state )
+ } )
+
+ it( 'handles dataNormalization params', () => {
+ action.params = { dataNormalization: 'hello' }
+ const actual = target( state, action )
+ expect( actual.dataNormalization ).toEqual( 'hello' )
+ } )
+ } )
+
describe( 'helper functions', () => {
describe( 'processAggregations', () => {
it( 'calculates percentages properly', () => {
diff --git a/src/reducers/map.jsx b/src/reducers/map.jsx
index b05623481..7176373c6 100644
--- a/src/reducers/map.jsx
+++ b/src/reducers/map.jsx
@@ -1,13 +1,11 @@
// reducer for the Map Tab
-import { STATE_FILTER_ADDED, STATE_FILTER_REMOVED } from '../actions/map'
-import {
- STATES_API_CALLED, STATES_FAILED, STATES_RECEIVED
-} from '../actions/complaints'
-import { TILE_MAP_STATES } from '../constants'
+import { GEO_NORM_NONE, TILE_MAP_STATES } from '../constants'
+import actions from '../actions'
export const defaultState = {
isLoading: false,
issue: [],
+ dataNormalization: GEO_NORM_NONE,
product: [],
selectedState: false,
state: []
@@ -152,6 +150,40 @@ export function selectState( state, action ) {
}
}
+/**
+ * Handler for the update data normalization action
+ *
+ * @param {object} state the current state in the Redux store
+ * @param {object} action the command being executed
+ * @returns {object} the new state for the Redux store
+ */
+export function updateDataNormalization( state, action ) {
+ return {
+ ...state,
+ dataNormalization: action.value
+ };
+}
+
+/**
+ * Processes an object of key/value strings into the correct internal format
+ *
+ * @param {object} state the current state in the Redux store
+ * @param {object} action the payload containing the key/value pairs
+ * @returns {object} a filtered set of key/value pairs with the values set to
+ * the correct type
+ */
+function processParams( state, action ) {
+ const params = action.params
+ const processed = Object.assign( {}, defaultState )
+
+ // Handle flag filters
+ if ( params.dataNormalization ) {
+ processed.dataNormalization = params.dataNormalization
+ }
+
+ return processed
+}
+
// ----------------------------------------------------------------------------
// Action Handlers
@@ -162,11 +194,15 @@ export function selectState( state, action ) {
*/
export function _buildHandlerMap() {
const handlers = {}
- handlers[STATES_API_CALLED] = statesCallInProcess
- handlers[STATES_RECEIVED] = processStatesResults
- handlers[STATES_FAILED] = processStatesError
- handlers[STATE_FILTER_ADDED] = selectState
- handlers[STATE_FILTER_REMOVED] = deselectState
+
+ handlers[actions.DATA_NORMALIZATION_SELECTED] = updateDataNormalization
+ handlers[actions.STATES_API_CALLED] = statesCallInProcess
+ handlers[actions.STATES_RECEIVED] = processStatesResults
+ handlers[actions.STATES_FAILED] = processStatesError
+ handlers[actions.STATE_FILTER_ADDED] = selectState
+ handlers[actions.STATE_FILTER_REMOVED] = deselectState
+ handlers[actions.URL_CHANGED] = processParams
+
return handlers
}