diff --git a/src/components/app.tsx b/src/components/app.tsx index ef33265..5e5ae99 100644 --- a/src/components/app.tsx +++ b/src/components/app.tsx @@ -39,8 +39,8 @@ function App() { } }, [selectedOptions]); - const handleSetSelectedOptions = (option: string, value: string | string[]) => { - const newSelectedOptions = {...selectedOptions, [option]: value}; + const handleSetSelectedOptions = (newState: Partial) => { + const newSelectedOptions = {...selectedOptions, ...newState}; setSelectedOptions(newSelectedOptions); }; diff --git a/src/components/attribute-options.tsx b/src/components/attribute-options.tsx index a60328e..6751255 100644 --- a/src/components/attribute-options.tsx +++ b/src/components/attribute-options.tsx @@ -7,7 +7,7 @@ import { IStateOptions } from "../constants/types"; import css from "./options.scss"; interface IProps { - handleSetSelectedOptions: (option: string, value: string|string[]) => void; + handleSetSelectedOptions: (newState: Partial) => void; selectedOptions: IStateOptions; } diff --git a/src/components/dropdown.tsx b/src/components/dropdown.tsx index 6eea11a..63859f4 100644 --- a/src/components/dropdown.tsx +++ b/src/components/dropdown.tsx @@ -7,11 +7,12 @@ import { YearsOptions } from "./years-options"; import { Summary } from "./summary"; import css from "./dropdown.scss"; +import { IStateOptions } from "../constants/types"; interface IProps { category: string sectionAltText: string - handleSetSelectedOptions: (option: string, value: string|string[]) => void + handleSetSelectedOptions: (newState: Partial) => void selectedOptions: typeof defaultSelectedOptions; } diff --git a/src/components/options.tsx b/src/components/options.tsx index 043c217..563e062 100644 --- a/src/components/options.tsx +++ b/src/components/options.tsx @@ -7,7 +7,7 @@ export interface IOptions { options: string[], selectedOptions: IStateOptions, inputType: "radio" | "checkbox", - handleSetSelectedOptions: (option: string, value: string|string[]) => void, + handleSetSelectedOptions: (newState: Partial) => void optionKey: OptionKey } @@ -25,20 +25,21 @@ export const Options: React.FC = (props) => { const handleSelectState = (e: React.ChangeEvent) => { if (Array.isArray(selectedOptions[optionKey])) { - let newArray = [...selectedOptions[optionKey]]; + const newArray = [...selectedOptions[optionKey]]; + const newSelection: any = {[optionKey]: newArray}; if (e.currentTarget.checked) { - newArray.push(e.target.value); + newSelection[optionKey].push(e.target.value); // If user selects "Age", "Gender", or "Race", auto-select "Total Farmers" as well if (optionKey === "farmerDemographics" && !newArray.includes("Total Farmers")) { - newArray.push("Total Farmers"); + newSelection.farmDemographics.push("Total Farmers"); } // If user selects a state, de-select "All States" if (optionKey === "states" && newArray.includes("All States")) { - newArray = newArray.filter((state) => state !== "All States"); + newSelection.states = newArray.filter((state) => state !== "All States"); } newArray.sort(); if (optionKey === "years") { - newArray.reverse(); + newSelection.years.reverse(); } } else { if (isOptionSelected(e.target.value)) { @@ -47,16 +48,23 @@ export const Options: React.FC = (props) => { if (optionKey === "farmerDemographics" && e.target.value === "Total Farmers") { const shouldFilter = !includes("Race") && !includes("Gender") && !includes("Age"); if (shouldFilter) { - newArray = newArray.filter((o) => o !== e.target.value); + newSelection[optionKey] = newArray.filter((o) => o !== e.target.value); + } + } else if (selectedOptions.crops.includes(e.target.value)) { + // If user is de-selecting a crop, check that there are crops still selected - + // Otherwise deselect crop units, too + newSelection.crops = newArray.filter((o) => o !== e.target.value); + if (newSelection.crops.length === 0) { + newSelection.cropUnits = ""; } } else { - newArray = newArray.filter((o) => o !== e.target.value); + newSelection[optionKey] = newArray.filter((o) => o !== e.target.value); } } } - handleSetSelectedOptions(optionKey, newArray); + handleSetSelectedOptions(newSelection); } else if (optionKey === "geographicLevel" || optionKey === "cropUnits") { - handleSetSelectedOptions(optionKey, e.target.value); + handleSetSelectedOptions({[optionKey]: e.target.value}); } }; diff --git a/src/components/place-options.tsx b/src/components/place-options.tsx index 25d9012..6764bf1 100644 --- a/src/components/place-options.tsx +++ b/src/components/place-options.tsx @@ -6,7 +6,7 @@ import { Options } from "./options"; import css from "./options.scss"; interface IProps { - handleSetSelectedOptions: (option: string, value: string|string[]) => void; + handleSetSelectedOptions: (newState: Partial) => void; selectedOptions: IStateOptions; } @@ -18,7 +18,7 @@ export const PlaceOptions: React.FC = (props) => { }; const handleSelectAllStates = () => { - handleSetSelectedOptions("states", ["All States"]); + handleSetSelectedOptions({states: ["All States"]}); }; return ( diff --git a/src/components/years-options.tsx b/src/components/years-options.tsx index a23c8ae..8a9c6d4 100644 --- a/src/components/years-options.tsx +++ b/src/components/years-options.tsx @@ -9,7 +9,7 @@ import classnames from "classnames"; import css from "./options.scss"; interface IProps { - handleSetSelectedOptions: (option: string, value: string|string[]) => void; + handleSetSelectedOptions: (newState: Partial) => void; selectedOptions: IStateOptions; } @@ -46,15 +46,11 @@ export const YearsOptions: React.FC = (props) => { selectionsNotAvailable.forEach((year) => { newSelectedYears.splice(newSelectedYears.indexOf(year), 1); }); - handleSetSelectedOptions("years", newSelectedYears); + handleSetSelectedOptions({years: newSelectedYears}); } }, [selectedOptions, handleSetSelectedOptions]); - const handleSelectYear = (yearKey: string, years: string|string[]) => { - handleSetSelectedOptions(yearKey, years); - }; - return (
{availableYearOptions.length === 0 ? @@ -65,7 +61,7 @@ export const YearsOptions: React.FC = (props) => { optionKey={yearsOptions.key} inputType={"checkbox"} selectedOptions={selectedOptions} - handleSetSelectedOptions={handleSelectYear} + handleSetSelectedOptions={handleSetSelectedOptions} />}
); diff --git a/src/constants/codapMetadata.ts b/src/constants/codapMetadata.ts index 6a122c9..56370df 100644 --- a/src/constants/codapMetadata.ts +++ b/src/constants/codapMetadata.ts @@ -140,7 +140,7 @@ export const attrToCODAPColumnName: IAttrToCodapColumn = { "attributeNameInCodapTable": "Corn Area Harvested", "unitInCodapTable": "Acres Harvested" }, - "COTTON, - YIELD, MEASURED IN LB / ACRE": { + "COTTON - YIELD, MEASURED IN LB / ACRE": { "attributeNameInCodapTable": "Cotton Yield", "unitInCodapTable": "LB/Acre" }, @@ -164,7 +164,7 @@ export const attrToCODAPColumnName: IAttrToCodapColumn = { "attributeNameInCodapTable": "Oats Area Harvested", "unitInCodapTable": "Acres Harvested" }, - "SOYBEANS - YIELD MEASURED IN BU / ACRE": { + "SOYBEANS - YIELD, MEASURED IN BU / ACRE": { "attributeNameInCodapTable": "Soybeans Yield", "unitInCodapTable": "BU/Acre" }, @@ -172,7 +172,7 @@ export const attrToCODAPColumnName: IAttrToCodapColumn = { "attributeNameInCodapTable": "Soybeans Area Harvested", "unitInCodapTable": "Acres Harvested" }, - "WHEAT - YIELD MEASURED IN BU / ACRE": { + "WHEAT - YIELD, MEASURED IN BU / ACRE": { "attributeNameInCodapTable": "Wheat Yield", "unitInCodapTable": "BU/Acre" }, diff --git a/src/constants/counties.ts b/src/constants/counties.ts index abd1d50..f9a4405 100644 --- a/src/constants/counties.ts +++ b/src/constants/counties.ts @@ -53,7 +53,7 @@ export const countyData: {[state: string]: string[]} = { "MONTGOMERY", "MORGAN", - "OTHER COUNTIES", + "PERRY", "PICKENS", "PIKE", @@ -77,7 +77,7 @@ export const countyData: {[state: string]: string[]} = { "JUNEAU", "KENAI PENINSULA", - "OTHER COUNTIES" + ], "Arizona": [ "APACHE", @@ -91,7 +91,7 @@ export const countyData: {[state: string]: string[]} = { "MOHAVE", "NAVAJO", - "OTHER COUNTIES", + "PIMA", "PINAL", "SANTA CRUZ", @@ -151,7 +151,7 @@ export const countyData: {[state: string]: string[]} = { "NEVADA", "NEWTON", - "OTHER COUNTIES", + "OUACHITA", "PERRY", "PHILLIPS", @@ -209,7 +209,7 @@ export const countyData: {[state: string]: string[]} = { "NEVADA", "ORANGE", - "OTHER COUNTIES", + "PLACER", "PLUMAS", "RIVERSIDE", @@ -287,7 +287,7 @@ export const countyData: {[state: string]: string[]} = { "MORGAN", "OTERO", - "OTHER COUNTIES", + "OURAY", "PARK", "PHILLIPS", @@ -315,14 +315,14 @@ export const countyData: {[state: string]: string[]} = { "NEW HAVEN", "NEW LONDON", - "OTHER COUNTIES", + "TOLLAND", "WINDHAM" ], "Delaware": [ "KENT", "NEW CASTLE", - "OTHER COUNTIES", + "SUSSEX" ], "Florida": [ @@ -376,7 +376,7 @@ export const countyData: {[state: string]: string[]} = { "ORANGE", "OSCEOLA", - "OTHER COUNTIES", + "PALM BEACH", "PASCO", "PINELLAS", @@ -507,7 +507,7 @@ export const countyData: {[state: string]: string[]} = { "OCONEE", "OGLETHORPE", - "OTHER COUNTIES", + "PAULDING", "PEACH", "PICKENS", @@ -565,7 +565,7 @@ export const countyData: {[state: string]: string[]} = { "KAUAI", "MAUI & KALWAO", - "OTHER COUNTIES" + ], "Idaho": [ "ADA", @@ -605,7 +605,7 @@ export const countyData: {[state: string]: string[]} = { "NEZ PERCE", "ONEIDA", - "OTHER COUNTIES", + "OWYHEE", "PAYETTE", "POWER", @@ -688,7 +688,7 @@ export const countyData: {[state: string]: string[]} = { "MOULTRIE", "OGLE", - "OTHER COUNTIES", + "PEORIA", "PERRY", "PIATT", @@ -782,7 +782,7 @@ export const countyData: {[state: string]: string[]} = { "OHIO", "ORANGE", - "OTHER COUNTIES", + "OWEN", "PARKE", "PERRY", @@ -891,7 +891,7 @@ export const countyData: {[state: string]: string[]} = { "O BRIEN", "OSCEOLA", - "OTHER COUNTIES", + "PAGE", "PALO ALTO", "PLYMOUTH", @@ -993,7 +993,7 @@ export const countyData: {[state: string]: string[]} = { "OSAGE", "OSBORNE", - "OTHER COUNTIES", + "OTTAWA", "PAWNEE", "PHILLIPS", @@ -1124,7 +1124,7 @@ export const countyData: {[state: string]: string[]} = { "OHIO", "OLDHAM", - "OTHER COUNTIES", + "OWEN", "OWSLEY", "PENDLETON", @@ -1191,7 +1191,7 @@ export const countyData: {[state: string]: string[]} = { "NATCHITOCHES", "ORLEANS", - "OTHER COUNTIES", + "OUACHITA", "PLAQUEMINES", "POINTE COUPEE", @@ -1231,7 +1231,7 @@ export const countyData: {[state: string]: string[]} = { "KNOX", "LINCOLN", - "OTHER COUNTIES", + "OXFORD", "PENOBSCOT", "PISCATAQUIS", @@ -1258,7 +1258,7 @@ export const countyData: {[state: string]: string[]} = { "KENT", "MONTGOMERY", - "OTHER COUNTIES", + "PRINCE GEORGES", "QUEEN ANNES", "SOMERSET", @@ -1281,7 +1281,7 @@ export const countyData: {[state: string]: string[]} = { "NANTUCKET", "NORFOLK", - "OTHER COUNTIES", + "PLYMOUTH", "SUFFOLK", "WORCESTER" @@ -1356,7 +1356,7 @@ export const countyData: {[state: string]: string[]} = { "OSCEOLA", "OSCODA", - "OTHER COUNTIES", + "OTSEGO", "OTTAWA", "PRESQUE ISLE", @@ -1430,7 +1430,7 @@ export const countyData: {[state: string]: string[]} = { "NORMAN", "OLMSTED", - "OTHER COUNTIES", + "OTTER TAIL", "PENNINGTON", "PINE", @@ -1519,7 +1519,7 @@ export const countyData: {[state: string]: string[]} = { "NOXUBEE", "OKTIBBEHA", - "OTHER COUNTIES", + "PANOLA", "PEARL RIVER", "PERRY", @@ -1628,7 +1628,7 @@ export const countyData: {[state: string]: string[]} = { "OREGON", "OSAGE", - "OTHER COUNTIES", + "OZARK", "PEMISCOT", "PERRY", @@ -1704,7 +1704,7 @@ export const countyData: {[state: string]: string[]} = { "MISSOULA", "MUSSELSHELL", - "OTHER COUNTIES", + "PARK", "PETROLEUM", "PHILLIPS", @@ -1796,7 +1796,7 @@ export const countyData: {[state: string]: string[]} = { "NEMAHA", "NUCKOLLS", - "OTHER COUNTIES", + "OTOE", "PAWNEE", "PERKINS", @@ -1842,7 +1842,7 @@ export const countyData: {[state: string]: string[]} = { "NYE", "ORMSBY", - "OTHER COUNTIES", + "PERSHING", "STOREY", "WASHOE", @@ -1857,7 +1857,7 @@ export const countyData: {[state: string]: string[]} = { "HILLSBOROUGH", "MERRIMACK", - "OTHER COUNTIES", + "ROCKINGHAM", "STRAFFORD", "SULLIVAN" @@ -1879,7 +1879,7 @@ export const countyData: {[state: string]: string[]} = { "MORRIS", "OCEAN", - "OTHER COUNTIES", + "PASSAIC", "SALEM", "SOMERSET", @@ -1909,7 +1909,7 @@ export const countyData: {[state: string]: string[]} = { "MORA", "OTERO", - "OTHER COUNTIES", + "QUAY", "RIO ARRIBA", "ROOSEVELT", @@ -1964,7 +1964,7 @@ export const countyData: {[state: string]: string[]} = { "ORLEANS", "OSWEGO", - "OTHER COUNTIES", + "OTSEGO", "PUTNAM", "QUEENS", @@ -2060,7 +2060,7 @@ export const countyData: {[state: string]: string[]} = { "ONSLOW", "ORANGE", - "OTHER COUNTIES", + "PAMLICO", "PASQUOTANK", "PENDER", @@ -2129,7 +2129,7 @@ export const countyData: {[state: string]: string[]} = { "NELSON", "OLIVER", - "OTHER COUNTIES", + "PEMBINA", "PIERCE", "RAMSEY", @@ -2214,7 +2214,7 @@ export const countyData: {[state: string]: string[]} = { "MUSKINGUM", "NOBLE", - "OTHER COUNTIES", + "OTTAWA", "PAULDING", "PERRY", @@ -2302,7 +2302,7 @@ export const countyData: {[state: string]: string[]} = { "OKMULGEE", "OSAGE", - "OTHER COUNTIES", + "OTTAWA", "PAWNEE", "PAYNE", @@ -2352,7 +2352,7 @@ export const countyData: {[state: string]: string[]} = { "MORROW", "MULTNOMAH", - "OTHER COUNTIES", + "POLK", "SHERMAN", "TILLAMOOK", @@ -2415,7 +2415,7 @@ export const countyData: {[state: string]: string[]} = { "NORTHAMPTON", "NORTHUMBERLAND", - "OTHER COUNTIES", + "PERRY", "PHILADELPHIA", "PIKE", @@ -2482,7 +2482,7 @@ export const countyData: {[state: string]: string[]} = { "OCONEE", "ORANGEBURG", - "OTHER COUNTIES", + "PICKENS", "RICHLAND", "SALUDA", @@ -2545,7 +2545,7 @@ export const countyData: {[state: string]: string[]} = { "MOODY", "OGLALA LAKOTA", - "OTHER COUNTIES", + "PENNINGTON", "PERKINS", "POTTER", @@ -2632,7 +2632,7 @@ export const countyData: {[state: string]: string[]} = { "MORGAN", "OBION", - "OTHER COUNTIES", + "OVERTON", "PERRY", "PICKETT", @@ -2846,7 +2846,7 @@ export const countyData: {[state: string]: string[]} = { "OLDHAM", "ORANGE", - "OTHER COUNTIES", + "PALO PINTO", "PANOLA", "PARKER", @@ -2938,7 +2938,7 @@ export const countyData: {[state: string]: string[]} = { "MILLARD", "MORGAN", - "OTHER COUNTIES", + "PIUTE", "RICH", "SALT LAKE", @@ -2966,7 +2966,7 @@ export const countyData: {[state: string]: string[]} = { "ORANGE", "ORLEANS", - "OTHER COUNTIES", + "RUTLAND", "WASHINGTON", "WINDHAM", @@ -3044,7 +3044,7 @@ export const countyData: {[state: string]: string[]} = { "NOTTOWAY", "ORANGE", - "OTHER COUNTIES", + "PAGE", "PATRICK", "PITTSYLVANIA", @@ -3103,7 +3103,7 @@ export const countyData: {[state: string]: string[]} = { "MASON", "OKANOGAN", - "OTHER COUNTIES", + "PACIFIC", "PEND OREILLE", "PIERCE", @@ -3157,7 +3157,7 @@ export const countyData: {[state: string]: string[]} = { "NICHOLAS", "OHIO", - "OTHER COUNTIES", + "PENDLETON", "PLEASANTS", "POCAHONTAS", @@ -3225,7 +3225,7 @@ export const countyData: {[state: string]: string[]} = { "OCONTO", "ONEIDA", - "OTHER COUNTIES", + "OUTAGAMIE", "OZAUKEE", "PEPIN", @@ -3271,7 +3271,7 @@ export const countyData: {[state: string]: string[]} = { "NATRONA", "NIOBRARA", - "OTHER COUNTIES", + "PARK", "PLATTE", "SHERIDAN", diff --git a/src/constants/queryHeaders.ts b/src/constants/queryHeaders.ts index 1d56b40..a33d426 100644 --- a/src/constants/queryHeaders.ts +++ b/src/constants/queryHeaders.ts @@ -47,8 +47,8 @@ export const queryData: Array = [ ...sharedDemographicHeaders, short_desc: ["PRODUCERS, (ALL) - NUMBER OF PRODUCERS"], years: { - "County": ["2017"], - "State": ["2017"] + "County": ["2017", "2012", "2007", "2002"], + "State": ["2017", "2012", "2007", "2002"] } }, { @@ -251,7 +251,7 @@ export const queryData: Array = [ commodity_desc: "Soybeans", short_desc: { ["Area Harvested"]: ["SOYBEANS - ACRES HARVESTED"], - ["Yield"]: ["SOYBEANS - YIELD MEASURED IN BU / ACRE"] + ["Yield"]: ["SOYBEANS - YIELD, MEASURED IN BU / ACRE"] }, ...sharedCropHeaders }, @@ -262,7 +262,7 @@ export const queryData: Array = [ short_desc: { ["Area Harvested"]: ["WHEAT - ACRES HARVESTED"], - ["Yield"]: ["WHEAT - YIELD MEASURED IN BU / ACRE"] + ["Yield"]: ["WHEAT - YIELD, MEASURED IN BU / ACRE"] }, ...sharedCropHeaders } diff --git a/src/scripts/api.ts b/src/scripts/api.ts index 6238561..8aaefeb 100644 --- a/src/scripts/api.ts +++ b/src/scripts/api.ts @@ -9,20 +9,13 @@ import { attrToCODAPColumnName } from "../constants/codapMetadata"; const baseURL = `https://quickstats.nass.usda.gov/api/api_GET/?key=9ED0BFB8-8DDD-3609-9940-A2341ED6A9E3`; -interface IRequestParams { +interface IGetAttrDataParams { attribute: string, geographicLevel: string, + cropUnits?: keyof ICropDataItem, location: string, - year: string, - cropCategory?: keyof ICropDataItem, - state?: string -} - -interface IGetItemParams { - requestString: string, - countyOrState: string, - geographicLevel: string, year: string + state?: string } export const fetchDataWithRetry = async (req: string, maxRetries = 3) => { @@ -41,7 +34,7 @@ export const fetchDataWithRetry = async (req: string, maxRetries = 3) => { throw new Error(`Request failed after ${maxRetries} attempts`); }; -export const createRequest = ({attribute, geographicLevel, location, year, cropCategory, state}: IRequestParams) => { +export const createRequest = ({attribute, geographicLevel, location, year, cropUnits, state}: IGetAttrDataParams) => { const queryParams = getQueryParams(attribute); if (!queryParams) { @@ -57,11 +50,11 @@ export const createRequest = ({attribute, geographicLevel, location, year, cropC short_desc, } = queryParams; - const item = cropCategory ? - (queryParams?.short_desc as ICropDataItem)[cropCategory] : + const item = cropUnits ? + (queryParams?.short_desc as ICropDataItem)[cropUnits] : short_desc as string[]; - const cat = cropCategory ? - (queryParams?.statisticcat_desc as ICropCategory)[cropCategory] : + const cat = cropUnits ? + (queryParams?.statisticcat_desc as ICropCategory)[cropUnits] : statisticcat_desc; const locationHeader = geographicLevel === "REGION : MULTI-STATE" ? "region_desc" : geographicLevel === "County" ? "county_name" : "state_name"; @@ -78,14 +71,29 @@ export const createRequest = ({attribute, geographicLevel, location, year, cropC let req = baseReq; + item.forEach(subItem => { + req = req + `&short_desc=${encodeURIComponent(subItem)}`; + }); + + // hacky but we need to custom-build the req in this one case + if (attribute === "Total Farmers" && year !== "2017") { + req = `${baseURL}` + + `§_desc=${encodeURIComponent("DEMOGRAPHICS")}` + + `&group_desc=${encodeURIComponent("OPERATORS")}` + + `&commodity_desc=${encodeURIComponent("OPERATORS")}` + + `&statisticcat_desc=${encodeURIComponent("OPERATORS")}` + + `&domain_desc=${encodeURIComponent("TOTAL")}` + + `&agg_level_desc=${encodeURIComponent(geographicLevel)}` + + `&${locationHeader}=${encodeURIComponent(location)}` + + `&year=${year}` + + `&short_desc=${encodeURIComponent("OPERATORS, (ALL) - NUMBER OF OPERATORS")}`; + } + // if we are creating a request at the county level, we need to also pass in a state if (state) { req += `&state_name=${state}`; } - item.forEach(subItem => { - req = req + `&short_desc=${encodeURIComponent(subItem)}`; - }); return req; }; @@ -132,16 +140,12 @@ export const createTableFromSelections = async (selectedOptions: IStateOptions) const {geographicLevel} = selectedOptions; try { const allAttrs = getAllAttrs(selectedOptions); - const requests = getAllRequests(selectedOptions); - const promises = []; - for (const req of requests) { - const {requestString, year, countyOrState} = req; - const res = getItem({requestString, year, countyOrState, geographicLevel: req.geographicLevel}); - promises.push(res); - } - const items = await Promise.all(promises); + const items = await Promise.all(getItems(selectedOptions)); await connect.getNewDataContext(); - await connect.createTopCollection(geographicLevel); + await connect.createStateCollection(geographicLevel === "State"); + if (geographicLevel === "County") { + await connect.createCountyCollection(); + } await connect.createSubCollection(geographicLevel, allAttrs); await connect.createItems(items); await connect.makeCaseTableAppear(); @@ -153,7 +157,7 @@ export const createTableFromSelections = async (selectedOptions: IStateOptions) } }; -const getAllRequests = (selectedOptions: IStateOptions) => { +const getItems = (selectedOptions: IStateOptions) => { let {states, years} = selectedOptions; const countySelected = selectedOptions.geographicLevel === "County"; @@ -161,36 +165,29 @@ const getAllRequests = (selectedOptions: IStateOptions) => { states = fiftyStates; } - const requests = []; + const items = []; for (const state of states) { const locations = countySelected ? countyData[state] : [state]; for (const year of years) { for (const location of locations) { - const req = getRequest(selectedOptions, location, year, state); - if (req) { - requests.push(req); - } + const item = getDataForSingleYearAndState(selectedOptions, location, year, state); + items.push(item); } } } - return requests; -}; - -const getItem = async ({requestString, countyOrState, geographicLevel, year}: IGetItemParams) => { - const attrData = await getAttrData(requestString); - if (Object.keys(attrData).length) { - return { - [geographicLevel]: countyOrState, - "Year": year, - ...attrData - }; - } + return items; }; -const getRequest = (selectedOptions: IStateOptions, countyOrState: string, year: string, state?: string) => { +const getDataForSingleYearAndState = async (selectedOptions: IStateOptions, countyOrState: string, year: string, state?: string) => { const {geographicLevel, states, years, cropUnits, ...subOptions} = selectedOptions; + + let item: any = { + [geographicLevel]: countyOrState, + "Year": year, + }; + for (const key in subOptions) { const value = subOptions[key as keyof typeof subOptions]; for (const attribute of value) { @@ -199,33 +196,45 @@ const getRequest = (selectedOptions: IStateOptions, countyOrState: string, year: const isMultiStateRegion = queryParams?.geographicAreas[0] === "REGION : MULTI-STATE"; const geoLevel = isMultiStateRegion ? "REGION : MULTI-STATE" : geographicLevel; if (yearAvailable) { + let location = countyOrState; + if (isMultiStateRegion) { const itemToCheck = state ? state : countyOrState; const regData = multiRegions.find((region) => region.States.includes(itemToCheck)); location = regData?.Region ? regData.Region : countyOrState; } - const params: IRequestParams = {attribute, geographicLevel: geoLevel, location, year}; - if (geoLevel === "County") { - params.state = state; - } + + const params: IGetAttrDataParams = {attribute, geographicLevel: geoLevel, location, year}; + if (cropOptions.options.includes(attribute) && cropUnits) { - params.cropCategory = cropUnits as keyof ICropDataItem; + params.cropUnits = cropUnits as keyof ICropDataItem; } - return { - requestString: createRequest(params), - countyOrState, - geographicLevel, - year - }; + + if (geoLevel === "County") { + item.State = state; + } + + const attrData = await getAttrData(params); + item = {...item, ...attrData}; } } } + + return item; }; -const getAttrData = async (req: string) => { +const getAttrData = async (params: IGetAttrDataParams) => { + const {attribute, geographicLevel, location, year, cropUnits, state} = params; + const reqParams: IGetAttrDataParams = {attribute, geographicLevel, location, year, state}; + + if (cropOptions.options.includes(attribute) && cropUnits) { + reqParams.cropUnits = cropUnits; + } + + const req = createRequest(reqParams); const res = await fetchDataWithRetry(req); const values: any = {}; if (res) { diff --git a/src/scripts/connect.js b/src/scripts/connect.js index 8676f21..6b70777 100644 --- a/src/scripts/connect.js +++ b/src/scripts/connect.js @@ -10,7 +10,8 @@ export const connect = { makeCODAPAttributeDef: function (attr) { return { - name: attr + name: attr, + type: "numeric" } }, @@ -48,20 +49,43 @@ export const connect = { return res; }, - createTopCollection: async function(geoLevel) { - const plural = geoLevel === "State" ? "States" : "Counties"; + createStateCollection: async function (createBoundaries) { + const attrs = [{"name": "State"}]; + + if (createBoundaries) { + attrs.push({ + "name": "Boundary", + "formula": `lookupBoundary(US_state_boundaries, State)`, + "formulaDependents": "State" + }); + } + const message = { "action": "create", "resource": `dataContext[${dataSetName}].collection`, "values": { - "name": plural, + "name": "States", "parent": "_root_", + "attributes": attrs + } + }; + + await codapInterface.sendRequest(message); + }, + + createCountyCollection: async function() { + const message = { + "action": "create", + "resource": `dataContext[${dataSetName}].collection`, + "values": { + "name": "Counties", + "parent": "States", "attributes": [{ - "name": geoLevel, + "name": "County", }, { "name": "Boundary", - "formula": `lookupBoundary(US_${geoLevel.toLowerCase()}_boundaries, ${geoLevel})`, + "formula": `lookupBoundary(US_county_boundaries, County, State)`, "formulaDependents": "State" }] }