From 522872037a4294c33b83a99d9555247f99ee024b Mon Sep 17 00:00:00 2001 From: Vim <86254807+vim-usds@users.noreply.github.com> Date: Thu, 16 Sep 2021 10:21:25 -0700 Subject: [PATCH] Website copy layout styling updates for Tuesday launch (#685) * Add basic accordion in AreaDetail * Refactor AreaDetail to use a Grid layout - adds useWindowSize to detect window resizes for mobile view - Map and AreaDetail to use Grid - removes some component styling from J40 - updates snapshot - MapWrapper to use Grid * Add custom Accordion styling - make J40 map a 9:3 Grid layout split - override native Accordion heading styles - make the Accordion multi-selectable - add some dummy data for indicators * Update AreaDetail to match design - remove styles in AreaDetail - increase height of MapInfoPanel - add Accordian items (indicators) - updates snapshot * Add a Beta Tag to the logo * Change the line height on indicators descriptions * Update package-lock after the rebase * Remove threshold from MapLegend - move feature selected border color to utils - remove all tooltip logic - remove all styles associated with tooltips - add legend label and descript to constants - refactor tests to be snapshots * Add borders between additional indicators * Modify copy and update styles - add the ordinal superscript back - update the copy - update the snapshots * Add additional indicators keys * Connect indicator keys to the UI - update the areaDetail snapshot * Render additional indicators accordion open onLoad - update snapshot * Update copy on About page * Update copy on indicator descriptions - update snapshots * Update the "How you can help section" - update the snapshot * Add a comma to "ZIP file will contain..." * Add the Datasets section to the methodology page - update snapshot * Update Methodology process list to trussworks - remove custom process list - remove custom CSS from global file - change copy * Modify layout of Methodology to using Grid - modify Dataset section to use Grid - remove outdated component CSS - update the snapshot * Update copy based on product feedback - update snapshots * Remove Accordions - updates snapshots - white CBG groups will show "Not community of focus" --- client/package-lock.json | 160 +++- client/package.json | 1 + client/src/components/AboutCard/AboutCard.tsx | 2 +- .../AreaDetail/areaDetail.module.scss | 96 +-- .../AreaDetail/areaDetail.module.scss.d.ts | 15 +- client/src/components/AreaDetail/index.tsx | 340 ++++++-- .../__snapshots__/areaDetail.test.tsx.snap | 395 ++++++--- .../AreaDetail/tests/areaDetail.test.tsx | 8 +- .../__snapshots__/datasetCard.test.tsx.snap | 12 +- .../DatasetContainer/dsContainer.module.scss | 29 +- .../dsContainer.module.scss.d.ts | 4 - .../src/components/DatasetContainer/index.tsx | 211 +++-- .../datasetContainer.test.tsx.snap | 792 +++++++++++++----- client/src/components/HowYouCanHelp/index.tsx | 8 +- .../__snapshots__/howYouCanHelp.test.tsx.snap | 8 +- client/src/components/J40Header.tsx | 2 + client/src/components/J40Map.module.scss | 14 +- client/src/components/J40Map.module.scss.d.ts | 1 - client/src/components/J40Map.tsx | 178 ++-- client/src/components/MapLegend/index.tsx | 109 +-- .../MapLegend/mapLegend.module.scss | 81 +- .../MapLegend/mapLegend.module.scss.d.ts | 9 - .../__snapshots__/mapLegend.test.tsx.snap | 19 + .../MapLegend/tests/mapLegend.test.tsx | 15 +- client/src/components/MapWrapper/index.tsx | 33 +- .../scoreStepsList.test.tsx.snap | 226 +++-- client/src/components/scoreStepsList.tsx | 167 ++-- client/src/components/utils.scss | 1 + client/src/data/constants.tsx | 23 +- client/src/pages/cejst.tsx | 26 +- client/src/pages/index.tsx | 84 +- client/src/pages/methodology.tsx | 23 +- client/src/styles/global.scss | 145 ++-- 33 files changed, 2029 insertions(+), 1208 deletions(-) create mode 100644 client/src/components/MapLegend/tests/__snapshots__/mapLegend.test.tsx.snap diff --git a/client/package-lock.json b/client/package-lock.json index 5875bd06..9cd6dfba 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -3465,6 +3465,11 @@ "pretty-format": "^26.0.0" } }, + "@types/js-cookie": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-2.2.7.tgz", + "integrity": "sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA==" + }, "@types/json-patch": { "version": "0.0.30", "resolved": "https://registry.npmjs.org/@types/json-patch/-/json-patch-0.0.30.tgz", @@ -4015,6 +4020,11 @@ "@xtuc/long": "4.2.2" } }, + "@xobotyi/scrollbar-width": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/@xobotyi/scrollbar-width/-/scrollbar-width-1.9.5.tgz", + "integrity": "sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==" + }, "@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -6464,6 +6474,14 @@ "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", "dev": true }, + "copy-to-clipboard": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.1.tgz", + "integrity": "sha512-i13qo6kIHTTpCm8/Wup+0b1mVWETvu2kIMzKoK8FpkLkFxlt0znUAHcMzox+T8sPlqtZXq3CulEjQHsYiGFJUw==", + "requires": { + "toggle-selection": "^1.0.6" + } + }, "copyfiles": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/copyfiles/-/copyfiles-2.4.1.tgz", @@ -6690,6 +6708,15 @@ "timsort": "^0.3.0" } }, + "css-in-js-utils": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-2.0.1.tgz", + "integrity": "sha512-PJF0SpJT+WdbVVt0AOYp9C8GnuruRlL/UFW7932nLWmFLQTaWEzTBQEx7/hn4BuV+WON75iAViSUJLiU3PKbpA==", + "requires": { + "hyphenate-style-name": "^1.0.2", + "isobject": "^3.0.1" + } + }, "css-loader": { "version": "5.2.6", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.2.6.tgz", @@ -6806,7 +6833,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", - "dev": true, "requires": { "mdn-data": "2.0.14", "source-map": "^0.6.1" @@ -8184,7 +8210,6 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.0.6.tgz", "integrity": "sha512-d51brTeqC+BHlwF0BhPtcYgF5nlzf9ZZ0ZIUQNZpc9ZB9qw5IJ2diTrBY9jlCJkTLITYPjmiX6OWCwH+fuyNgQ==", - "dev": true, "requires": { "stackframe": "^1.1.1" } @@ -9503,8 +9528,7 @@ "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "fast-glob": { "version": "3.2.6", @@ -9536,12 +9560,22 @@ "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", "dev": true }, + "fast-shallow-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-shallow-equal/-/fast-shallow-equal-1.0.0.tgz", + "integrity": "sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw==" + }, "fastest-levenshtein": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==", "dev": true }, + "fastest-stable-stringify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fastest-stable-stringify/-/fastest-stable-stringify-2.0.2.tgz", + "integrity": "sha512-bijHueCGd0LqqNK9b5oCMHc0MluJAx0cwqASgbWMvkO01lCYgIhacVRLcaDz3QnyYIRNJRDwMb41VuT6pHJ91Q==" + }, "fastq": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.11.0.tgz", @@ -12274,6 +12308,11 @@ "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", "dev": true }, + "hyphenate-style-name": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz", + "integrity": "sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==" + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -12477,6 +12516,14 @@ "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==", "dev": true }, + "inline-style-prefixer": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-6.0.0.tgz", + "integrity": "sha512-XTHvRUS4ZJNzC1GixJRmOlWSS45fSt+DJoyQC9ytj0WxQfcgofQtDtyKKYxHUqEsWCs+LIWftPF1ie7+i012Fg==", + "requires": { + "css-in-js-utils": "^2.0.0" + } + }, "inquirer": { "version": "7.3.3", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", @@ -13157,8 +13204,7 @@ "isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" }, "isomorphic-ws": { "version": "4.0.1", @@ -14595,6 +14641,11 @@ } } }, + "js-cookie": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz", + "integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==" + }, "js-levenshtein": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz", @@ -15580,8 +15631,7 @@ "mdn-data": { "version": "2.0.14", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", - "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", - "dev": true + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" }, "meant": { "version": "1.0.3", @@ -16139,6 +16189,21 @@ "dev": true, "optional": true }, + "nano-css": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/nano-css/-/nano-css-5.3.4.tgz", + "integrity": "sha512-wfcviJB6NOxDIDfr7RFn/GlaN7I/Bhe4d39ZRCJ3xvZX60LVe2qZ+rDqM49nm4YT81gAjzS+ZklhKP/Gnfnubg==", + "requires": { + "css-tree": "^1.1.2", + "csstype": "^3.0.6", + "fastest-stable-stringify": "^2.0.2", + "inline-style-prefixer": "^6.0.0", + "rtl-css-js": "^1.14.0", + "sourcemap-codec": "^1.4.8", + "stacktrace-js": "^2.0.2", + "stylis": "^4.0.6" + } + }, "nanoid": { "version": "3.1.23", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz", @@ -18459,6 +18524,32 @@ } } }, + "react-universal-interface": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/react-universal-interface/-/react-universal-interface-0.6.2.tgz", + "integrity": "sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw==" + }, + "react-use": { + "version": "17.3.1", + "resolved": "https://registry.npmjs.org/react-use/-/react-use-17.3.1.tgz", + "integrity": "sha512-hs7+tS4rRm1QLHPfanLCqXIi632tP4V7Sai1ENUP2WTufU6am++tU9uSw9YrNCFqbABiEv0ndKU1XCUcfu2tXA==", + "requires": { + "@types/js-cookie": "^2.2.6", + "@xobotyi/scrollbar-width": "^1.9.5", + "copy-to-clipboard": "^3.3.1", + "fast-deep-equal": "^3.1.3", + "fast-shallow-equal": "^1.0.0", + "js-cookie": "^2.2.1", + "nano-css": "^5.3.1", + "react-universal-interface": "^0.6.2", + "resize-observer-polyfill": "^1.5.1", + "screenfull": "^5.1.0", + "set-harmonic-interval": "^1.0.1", + "throttle-debounce": "^3.0.1", + "ts-easing": "^0.2.0", + "tslib": "^2.1.0" + } + }, "read": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", @@ -19396,6 +19487,14 @@ "inherits": "^2.0.1" } }, + "rtl-css-js": { + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.14.2.tgz", + "integrity": "sha512-t6Wc/wpqm8s3kuXAV6tL/T7VS6n0XszzX58CgCsLj3O2xi9ITSLfzYhtl+GKyxCi/3QEqVctOJQwCiDzb2vteQ==", + "requires": { + "@babel/runtime": "^7.1.2" + } + }, "run-async": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", @@ -19501,6 +19600,11 @@ "ajv-keywords": "^3.5.2" } }, + "screenfull": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/screenfull/-/screenfull-5.1.0.tgz", + "integrity": "sha512-dYaNuOdzr+kc6J6CFcBrzkLCfyGcMg+gWkJ8us93IQ7y1cevhQAugFsaCdMHb6lw8KV3xPzSxzH7zM1dQap9mA==" + }, "seed-random": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/seed-random/-/seed-random-2.2.0.tgz", @@ -19706,6 +19810,11 @@ "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, + "set-harmonic-interval": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-harmonic-interval/-/set-harmonic-interval-1.0.1.tgz", + "integrity": "sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g==" + }, "set-value": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", @@ -20147,8 +20256,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "source-map-js": { "version": "0.6.2", @@ -20185,8 +20293,7 @@ "sourcemap-codec": { "version": "1.4.8", "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "dev": true + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" }, "spdx-compare": { "version": "1.0.0", @@ -20351,7 +20458,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/stack-generator/-/stack-generator-2.0.5.tgz", "integrity": "sha512-/t1ebrbHkrLrDuNMdeAcsvynWgoH/i4o8EGGfX7dEYDoTXOYVAkEpFdtshlvabzc6JlJ8Kf9YdFEoz7JkzGN9Q==", - "dev": true, "requires": { "stackframe": "^1.1.1" } @@ -20382,14 +20488,12 @@ "stackframe": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.2.0.tgz", - "integrity": "sha512-GrdeshiRmS1YLMYgzF16olf2jJ/IzxXY9lhKOskuVziubpTYcYqyOwYeJKzQkwy7uN0fYSsbsC4RQaXf9LCrYA==", - "dev": true + "integrity": "sha512-GrdeshiRmS1YLMYgzF16olf2jJ/IzxXY9lhKOskuVziubpTYcYqyOwYeJKzQkwy7uN0fYSsbsC4RQaXf9LCrYA==" }, "stacktrace-gps": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/stacktrace-gps/-/stacktrace-gps-3.0.4.tgz", "integrity": "sha512-qIr8x41yZVSldqdqe6jciXEaSCKw1U8XTXpjDuy0ki/apyTn/r3w9hDAAQOhZdxvsC93H+WwwEu5cq5VemzYeg==", - "dev": true, "requires": { "source-map": "0.5.6", "stackframe": "^1.1.1" @@ -20398,8 +20502,7 @@ "source-map": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", - "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", - "dev": true + "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=" } } }, @@ -20407,7 +20510,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/stacktrace-js/-/stacktrace-js-2.0.2.tgz", "integrity": "sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==", - "dev": true, "requires": { "error-stack-parser": "^2.0.6", "stack-generator": "^2.0.5", @@ -20924,6 +21026,11 @@ "postcss-selector-parser": "^6.0.4" } }, + "stylis": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.0.10.tgz", + "integrity": "sha512-m3k+dk7QeJw660eIKRRn3xPF6uuvHs/FFzjX3HQ5ove0qYsiygoAhwn5a3IYKaZPo5LrYD0rfVmtv1gNY1uYwg==" + }, "subarg": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/subarg/-/subarg-1.0.0.tgz", @@ -21203,6 +21310,11 @@ "integrity": "sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==", "dev": true }, + "throttle-debounce": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-3.0.1.tgz", + "integrity": "sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==" + }, "throttleit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", @@ -21405,6 +21517,11 @@ "is-number": "^7.0.0" } }, + "toggle-selection": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", + "integrity": "sha1-bkWxJj8gF/oKzH2J14sVuL932jI=" + }, "toidentifier": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", @@ -21479,6 +21596,11 @@ "integrity": "sha512-0z3j8R7MCjy10kc/g+qg7Ln3alJTodw9aDuVWZa3uiWqfuBMKeAeP2ocWcxoyM3D73yz3Jt/Pu4qPr4wHSdB/Q==", "dev": true }, + "ts-easing": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ts-easing/-/ts-easing-0.2.0.tgz", + "integrity": "sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ==" + }, "ts-jest": { "version": "27.0.3", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-27.0.3.tgz", diff --git a/client/package.json b/client/package.json index 7790a764..37795144 100644 --- a/client/package.json +++ b/client/package.json @@ -85,6 +85,7 @@ "react-helmet": "^6.1.0", "react-intl": "^5.20.4", "react-map-gl": "^6.1.16", + "react-use": "^17.3.1", "uswds": "^2.10.3" }, "cypress-cucumber-preprocessor": { diff --git a/client/src/components/AboutCard/AboutCard.tsx b/client/src/components/AboutCard/AboutCard.tsx index 45b4fa3b..881aad43 100644 --- a/client/src/components/AboutCard/AboutCard.tsx +++ b/client/src/components/AboutCard/AboutCard.tsx @@ -29,7 +29,7 @@ const AboutCard = (props: React.PropsWithChildren) => {

{props.header}

-

{props.children}

+ {props.children}
diff --git a/client/src/components/AreaDetail/areaDetail.module.scss b/client/src/components/AreaDetail/areaDetail.module.scss index c29fac64..028617d9 100644 --- a/client/src/components/AreaDetail/areaDetail.module.scss +++ b/client/src/components/AreaDetail/areaDetail.module.scss @@ -1,7 +1,6 @@ @import "../utils.scss"; $sidePanelLabelFontColor: #171716; -$featureSelectBorderColor: #00bde3; @mixin sidePanelLabelStyle { font-size: small; @@ -14,60 +13,36 @@ $featureSelectBorderColor: #00bde3; width: 0.6rem; border-radius: 100%; align-self: center; - margin-top: 0.8rem; + margin-top: 1.8rem; margin-right: 0.5rem; opacity: 0.6; } +@mixin indicatorBox { + display: flex; + flex-direction: column; + padding: 0 1rem 1.5rem; + &:last-child { + border-bottom: none; + } +} + .areaDetailContainer { display: flex; flex-direction: column; } -// top row styles -.topRow { - display: flex; -} - -.cumulativeIndexScore, .categorization { display: flex; flex-direction: column; align-items: center; - height: 7.7rem; - border-bottom: $sidePanelBorder; - flex: 1 0 50%; - padding-top: 2rem; + padding-bottom: 2rem; } -.topRowTitle, .censusLabel { @include sidePanelLabelStyle; } -.topRowSubTitle { - font-size: small; - color: $sidePanelLabelFontColor; -} - -.score { - font-size: xx-large; - font-weight: bolder; -} - -.indicatorSuperscript { - top: -0.2em -} - -.scoreSuperscript { - font-size: large; - padding-bottom: 1rem; -} - -.categorization { - border-left: $sidePanelBorder; -} - .priority { display: flex; } @@ -98,14 +73,13 @@ $featureSelectBorderColor: #00bde3; .censusRow { display: flex; flex-direction: column; - border-bottom: $sidePanelBorder; list-style: none; margin: 0; } //census row styles .censusRow { - padding: 1rem; + padding: 1.2rem 1rem 0 1.2rem; } .censusText { @@ -117,33 +91,24 @@ $featureSelectBorderColor: #00bde3; @include sidePanelLabelStyle; display: flex; justify-content: space-between; - border-bottom: $sidePanelBorder; - padding: 0.3rem 0.5rem 0.3rem 1rem; - background-color: #edeef0; + padding: 0.3rem 0.5rem 0.3rem 1.2rem; + background-color: #DFE1E2; } //Indicator box styles -.indicatorBox { - display: flex; - padding: 0 1rem 1.5rem; +.indicatorBoxMain { + @include indicatorBox; border-bottom: $sidePanelBorder; - - @media screen and (max-width: $mobileBreakpoint) { - justify-content: space-between; - padding-top: 0.5rem; - padding-bottom: 0.5rem; - } } -.indicatorBox:last-child { - border-bottom: none; +.indicatorBoxAdditional { + @include indicatorBox; + border-bottom: 1px solid #1b1b1b; + background-color: #F3F3F3; } -.indicatorValue { - flex: 1 0 37%; - align-self: center; - padding-left: 2.4rem; - font-size: large; +.indicatorRow { + display: flex; @media screen and (max-width: $mobileBreakpoint) { flex: 1 0 40%; @@ -151,4 +116,21 @@ $featureSelectBorderColor: #00bde3; padding-left: 3rem; padding-top: 1rem; } + + .indicatorName { + flex: 0 1 77%; + } + + .indicatorValue { + margin-top: 1.2rem; + margin-left: 2.2rem; + } + + .indicatorDesc { + max-width: 10rem; + } +} + +.indicatorSuperscript { + top: -0.2em } diff --git a/client/src/components/AreaDetail/areaDetail.module.scss.d.ts b/client/src/components/AreaDetail/areaDetail.module.scss.d.ts index 9c78a6fa..e45a6d8b 100644 --- a/client/src/components/AreaDetail/areaDetail.module.scss.d.ts +++ b/client/src/components/AreaDetail/areaDetail.module.scss.d.ts @@ -1,11 +1,6 @@ declare namespace MapModuleScssNamespace { export interface IMapModuleScss { areaDetailContainer: string; - topRow:string; - cumulativeIndexScore:string; - scoreSuperscript: string; - topRowTitle:string; - topRowSubTitle:string; categorization:string; prioritized:string; threshold:string; @@ -16,10 +11,14 @@ declare namespace MapModuleScssNamespace { censusText: string; censusLabel:string; divider:string; - indicatorBox:string; + indicatorBoxMain:string; + indicatorBoxAdditional:string; + indicatorRow:string; indicatorValue:string; - score:string; - indicatorSuperscript: string; + indicatorName:string; + indicatorDesc:string; + indicatorBoxAdditional:string; + indicatorSuperscript:string; } } diff --git a/client/src/components/AreaDetail/index.tsx b/client/src/components/AreaDetail/index.tsx index 970d5e40..d1d9d33f 100644 --- a/client/src/components/AreaDetail/index.tsx +++ b/client/src/components/AreaDetail/index.tsx @@ -1,9 +1,11 @@ +/* eslint-disable quotes */ // External Libs: import * as React from 'react'; import {useIntl} from 'gatsby-plugin-intl'; import {defineMessages} from 'react-intl'; // Components: +// import {Accordion} from '@trussworks/react-uswds'; // Styles and constants import * as styles from './areaDetail.module.scss'; @@ -13,7 +15,6 @@ export const readablePercentile = (percentile: number) => { return Math.round(percentile * 100); }; - // Todo: Add internationalization to superscript ticket #582 const getSuperscriptOrdinal = (percentile: number) => { const englishOrdinalRules = new Intl.PluralRules('en', { @@ -30,18 +31,19 @@ const getSuperscriptOrdinal = (percentile: number) => { return suffixes[englishOrdinalRules.select(percentile)]; }; +// Todo VS: remove threshold data export const getCategorization = (percentile: number) => { let categorization; let categoryCircleStyle; if (percentile >= constants.SCORE_BOUNDARY_PRIORITIZED ) { - categorization = 'Prioritized'; + categorization = 'Community of focus'; categoryCircleStyle = styles.prioritized; } else if (constants.SCORE_BOUNDARY_THRESHOLD <= percentile && percentile < constants.SCORE_BOUNDARY_PRIORITIZED) { - categorization = 'Threshold'; + categorization = 'Not a community of focus'; categoryCircleStyle = styles.threshold; } else { - categorization = 'Non-prioritized'; + categorization = 'Not a community of focus'; categoryCircleStyle = styles.nonPrioritized; } return [categorization, categoryCircleStyle]; @@ -54,11 +56,6 @@ interface IAreaDetailProps { const AreaDetail = ({properties}:IAreaDetailProps) => { const intl = useIntl(); const messages = defineMessages({ - cumulativeIndexScore: { - id: 'areaDetail.priorityInfo.cumulativeIndexScore', - defaultMessage: 'Cumulative Index Score', - description: 'the cumulative score of the feature selected', - }, percentile: { id: 'areaDetail.priorityInfo.percentile', defaultMessage: 'percentile', @@ -91,7 +88,7 @@ const AreaDetail = ({properties}:IAreaDetailProps) => { }, indicatorColumnHeader: { id: 'areaDetail.indicators.indicatorColumnHeader', - defaultMessage: 'Indicators', + defaultMessage: 'Indicator', description: 'the population of the feature selected', }, percentileColumnHeader: { @@ -104,9 +101,14 @@ const AreaDetail = ({properties}:IAreaDetailProps) => { defaultMessage: 'Poverty', description: 'Household income is less than or equal to twice the federal "poverty level"', }, + areaMedianIncome: { + id: 'areaDetail.indicator.areaMedianIncome', + defaultMessage: 'Area Median Income', + description: 'calculated as percent of the area median income', + }, education: { id: 'areaDetail.indicator.education', - defaultMessage: 'Education', + defaultMessage: 'Education, less than high school', description: 'Percent of people age 25 or older that didn’t get a high school diploma', }, linguisticIsolation: { @@ -120,10 +122,71 @@ const AreaDetail = ({properties}:IAreaDetailProps) => { defaultMessage: 'Unemployment rate', description: 'Number of unemployed people as a percentage of the labor force', }, + asthma: { + id: 'areaDetail.indicator.asthma', + defaultMessage: 'Asthma', + description: 'have asthma or been diagnosed by a doctor to have asthma', + }, + diabetes: { + id: 'areaDetail.indicator.diabetes', + defaultMessage: 'Diabetes', + description: 'diabetes from dr or nurse', + }, + dieselPartMatter: { + id: 'areaDetail.indicator.dieselPartMatter', + defaultMessage: 'Diesel particulate matter', + description: 'Diesel particulate matter level in air', + }, + energyBurden: { + id: 'areaDetail.indicator.energyBurden', + defaultMessage: 'Energy burden', + description: 'Average annual energy cost ($) divided by household income', + }, + femaRisk: { + id: 'areaDetail.indicator.femaRisk', + defaultMessage: 'FEMA Risk index', + description: 'Risk based on 18 natural hazard types, in addition to a'+ + "community's social vulnerability and community resilience", + }, + heartDisease: { + id: 'areaDetail.indicator.heartDisease', + defaultMessage: 'Heart Disease', + description: 'People ages 18 and up who report ever having been told by a' + + 'doctor, nurse, or other health professionals that they had angina or coronary heart disease', + }, houseBurden: { id: 'areaDetail.indicator.houseBurden', - defaultMessage: 'Housing Burden', - description: 'Households that are low income and spend more than 30% of their income to housing costs', + defaultMessage: 'Housing cost burden', + description: 'People ages 18 and up who report having been told by a doctor,' + + ' nurse, or other health professionals that they have diabetes other than diabetes during pregnancy', + }, + leadPaint: { + id: 'areaDetail.indicator.leadPaint', + defaultMessage: 'Lead paint', + description: 'Housing units built pre-1960, used as an indicator of potential'+ + ' lead paint exposure in homes', + }, + lifeExpect: { + id: 'areaDetail.indicator.lifeExpect', + defaultMessage: 'Life expectancy', + description: 'Estimated years of life expectancy', + }, + pm25: { + id: 'areaDetail.indicator.pm25', + defaultMessage: 'PM2.5', + description: 'Fine inhalable particles, with diameters that are generally 2.5 micrometers and smaller', + }, + trafficVolume: { + id: 'areaDetail.indicator.trafficVolume', + defaultMessage: 'Traffic proximity and volume', + description: 'Count of vehicles (average annual daily traffic) at major roads within 500 meters,' + + ' divided by distance in meters', + }, + wasteWater: { + id: 'areaDetail.indicator.wasteWater', + defaultMessage: 'Wastewater discharge', + description: 'Toxic concentrations at stream segments within 500 meters divided by distance in' + + ' kilometers', }, }); @@ -140,9 +203,10 @@ const AreaDetail = ({properties}:IAreaDetailProps) => { } // Todo: Ticket #367 will be replacing descriptions with YAML file - const povertyInfo:indicatorInfo = { - label: intl.formatMessage(messages.poverty), - description: 'Household income is less than or equal to twice the federal "poverty level"', + const areaMedianIncome:indicatorInfo = { + label: intl.formatMessage(messages.areaMedianIncome), + description: 'Median income of the census block group calculated as a percent of the metropolitan'+ + " area’s or state's median income", value: properties[constants.POVERTY_PROPERTY_PERCENTILE], }; const eduInfo:indicatorInfo = { @@ -150,44 +214,102 @@ const AreaDetail = ({properties}:IAreaDetailProps) => { description: 'Percent of people age 25 or older that didn’t get a high school diploma', value: properties[constants.EDUCATION_PROPERTY_PERCENTILE], }; - const linIsoInfo:indicatorInfo = { - label: intl.formatMessage(messages.linguisticIsolation), - description: 'Households in which all members speak a non-English language and speak English less than "very well"', - value: properties[constants.LINGUISTIC_ISOLATION_PROPERTY_PERCENTILE], + const poverty:indicatorInfo = { + label: intl.formatMessage(messages.poverty), + description: 'Household income is less than or equal to the federal "poverty level"', + value: properties[constants.POVERTY_PROPERTY_PERCENTILE], }; - const umemployInfo:indicatorInfo = { - label: intl.formatMessage(messages.unemployment), - description: 'Number of unemployed people as a percentage of the labor force', - value: properties[constants.UNEMPLOYMENT_PROPERTY_PERCENTILE], + // const linIsoInfo:indicatorInfo = { + // label: intl.formatMessage(messages.linguisticIsolation), + // eslint-disable-next-line max-len + // description: 'Households in which all members speak a non-English language and speak English less than "very well"', + // value: properties[constants.LINGUISTIC_ISOLATION_PROPERTY_PERCENTILE], + // }; + // const umemployInfo:indicatorInfo = { + // label: intl.formatMessage(messages.unemployment), + // description: 'Number of unemployed people as a percentage of the labor force', + // value: properties[constants.UNEMPLOYMENT_PROPERTY_PERCENTILE], + // }; + const asthma:indicatorInfo = { + label: intl.formatMessage(messages.asthma), + description: 'People who answer “yes” to both of the questions: “Have you ever been told by' + + ' a doctor nurse, or other health professional that you have asthma?” and “Do you still have asthma?"', + value: properties[constants.ASTHMA_PERCENTILE], + }; + const diabetes:indicatorInfo = { + label: intl.formatMessage(messages.diabetes), + description: 'People ages 18 and up who report having been told by a doctor, nurse, or other' + + ' health professionals that they have diabetes other than diabetes during pregnancy', + value: properties[constants.DIABETES_PERCENTILE], + }; + const dieselPartMatter:indicatorInfo = { + label: intl.formatMessage(messages.dieselPartMatter), + description: 'Mixture of particles that is part of diesel exhaust in the air', + value: properties[constants.DIESEL_MATTER_PERCENTILE], + }; + const lifeExpect:indicatorInfo = { + label: intl.formatMessage(messages.lifeExpect), + description: 'Estimated years of life expectancy', + value: properties[constants.LIFE_PERCENTILE], + }; + const energyBurden:indicatorInfo = { + label: intl.formatMessage(messages.energyBurden), + description: 'Average annual energy cost ($) divided by household income', + value: properties[constants.ENERGY_PERCENTILE], + }; + const pm25:indicatorInfo = { + label: intl.formatMessage(messages.pm25), + description: 'Fine inhalable particles, with diameters that are generally 2.5 micrometers and smaller', + value: properties[constants.PM25_PERCENTILE], + }; + const leadPaint:indicatorInfo = { + label: intl.formatMessage(messages.leadPaint), + description: 'Housing units built pre-1960, used as an indicator of potential'+ + ' lead paint exposure in homes', + value: properties[constants.LEAD_PAINT_PERCENTILE], + }; + const trafficVolume:indicatorInfo = { + label: intl.formatMessage(messages.trafficVolume), + description: 'Count of vehicles (average annual daily traffic) at major roads within 500 meters,' + + ' divided by distance in meters', + value: properties[constants.TRAFFIC_PERCENTILE], + }; + const wasteWater:indicatorInfo = { + label: intl.formatMessage(messages.wasteWater), + description: 'Toxic concentrations at stream segments within 500 meters divided by distance in' + + ' kilometers', + value: properties[constants.WASTEWATER_PERCENTILE], + }; + const femaRisk:indicatorInfo = { + label: intl.formatMessage(messages.femaRisk), + description: 'Expected Annual Loss Score, which is the average economic loss in dollars' + + ' resulting from natural hazards each year.', + value: properties[constants.FEMA_PERCENTILE], + }; + const heartDisease:indicatorInfo = { + label: intl.formatMessage(messages.heartDisease), + description: 'People ages 18 and up who report ever having been told by a' + + ' doctor, nurse, or other health professionals that they had angina or coronary heart disease', + value: properties[constants.HEART_PERCENTILE], }; const houseBurden:indicatorInfo = { label: intl.formatMessage(messages.houseBurden), - description: 'Households that are low income and spend more than 30% of their income to housing costs', + description: 'People ages 18 and up who report having been told by a doctor,' + + ' nurse, or other health professionals that they have diabetes other than diabetes during pregnancy', value: properties[constants.HOUSING_BURDEN_PROPERTY_PERCENTILE], }; - const indicators = [povertyInfo, eduInfo, linIsoInfo, umemployInfo, houseBurden]; + + const indicators = [areaMedianIncome, eduInfo, poverty]; + const additionalIndicators = [ + asthma, diabetes, dieselPartMatter, energyBurden, femaRisk, heartDisease, + houseBurden, leadPaint, lifeExpect, pm25, trafficVolume, wasteWater, + ]; const [categorization, categoryCircleStyle] = getCategorization(score); return ( ); diff --git a/client/src/components/AreaDetail/tests/__snapshots__/areaDetail.test.tsx.snap b/client/src/components/AreaDetail/tests/__snapshots__/areaDetail.test.tsx.snap index cfb9c1ca..5be11a44 100644 --- a/client/src/components/AreaDetail/tests/__snapshots__/areaDetail.test.tsx.snap +++ b/client/src/components/AreaDetail/tests/__snapshots__/areaDetail.test.tsx.snap @@ -5,37 +5,6 @@ exports[`rendering of the AreaDetail checks if various text fields are visible 1 diff --git a/client/src/components/AreaDetail/tests/areaDetail.test.tsx b/client/src/components/AreaDetail/tests/areaDetail.test.tsx index 1c8ad96a..d41a1bc9 100644 --- a/client/src/components/AreaDetail/tests/areaDetail.test.tsx +++ b/client/src/components/AreaDetail/tests/areaDetail.test.tsx @@ -36,15 +36,15 @@ describe('tests the readablePercentile function', () => { }); describe('tests the getCategorization function', () => { - it(`should equal Prioritized for value >= ${constants.SCORE_BOUNDARY_LOW}`, () => { - expect(getCategorization(.756)).toEqual(['Prioritized', undefined]); + it(`should equal Community of focus for value >= ${constants.SCORE_BOUNDARY_LOW}`, () => { + expect(getCategorization(.756)).toEqual(['Community of focus', undefined]); }); it(`should equal Threshold for .60 <= value < ${constants.SCORE_BOUNDARY_THRESHOLD}`, () => { - expect(getCategorization(.65)).toEqual(['Threshold', undefined]); + expect(getCategorization(.65)).toEqual(['Not a community of focus', undefined]); }); it(`should equal Non-prioritized for value < ${constants.SCORE_BOUNDARY_PRIORITIZED}`, () => { - expect(getCategorization(.53)).toEqual(['Non-prioritized', undefined]); + expect(getCategorization(.53)).toEqual(['Not a community of focus', undefined]); }); }); diff --git a/client/src/components/DatasetCard/tests/__snapshots__/datasetCard.test.tsx.snap b/client/src/components/DatasetCard/tests/__snapshots__/datasetCard.test.tsx.snap index bc66c3d5..8aecdcf6 100644 --- a/client/src/components/DatasetCard/tests/__snapshots__/datasetCard.test.tsx.snap +++ b/client/src/components/DatasetCard/tests/__snapshots__/datasetCard.test.tsx.snap @@ -4,14 +4,14 @@ exports[`rendering of the DatasetCard checks if component renders 1`] = `

- Poverty + Area Median Income

What is it?
- Percent of a block group's population in households where the household - income is less than or equal to twice the federal "poverty level" + Median income of the census block group calculated as a percent + of the metropolitan area’s or state's median income.
diff --git a/client/src/components/DatasetContainer/dsContainer.module.scss b/client/src/components/DatasetContainer/dsContainer.module.scss index 64b04235..e08ed44a 100644 --- a/client/src/components/DatasetContainer/dsContainer.module.scss +++ b/client/src/components/DatasetContainer/dsContainer.module.scss @@ -1,32 +1,5 @@ -@import "../utils.scss"; - -.datasetContainer { - background-color: #eef6fb; -} -.datasetContainerHeader { - font-size: 1.8rem; - margin-bottom: 0.4rem; - color: $headingFontColor; -} - -.datasetContainerSubTitle { - width: 50%; - line-height: 1.7rem; - margin-top: 0; - margin-bottom: 1.4rem; - color: $headingFontColor; - - @media screen and (max-width: 700px) { - width: 90%; - } -} - .datasetCardsContainer { display: flex; justify-content: space-between; flex-wrap: wrap; -} - -.j40AlertContainer { - background-color: $j40AlertWarningColor; -} +} \ No newline at end of file diff --git a/client/src/components/DatasetContainer/dsContainer.module.scss.d.ts b/client/src/components/DatasetContainer/dsContainer.module.scss.d.ts index b443ce05..dfd243b4 100644 --- a/client/src/components/DatasetContainer/dsContainer.module.scss.d.ts +++ b/client/src/components/DatasetContainer/dsContainer.module.scss.d.ts @@ -1,10 +1,6 @@ declare namespace DatasetContainerScssNamespace { export interface IDatasetContainerScss { - datasetContainer:string; datasetCardsContainer: string; - datasetContainerHeader: string; - datasetContainerSubTitle: string; - j40AlertContainer: string; } } diff --git a/client/src/components/DatasetContainer/index.tsx b/client/src/components/DatasetContainer/index.tsx index 796d836d..953b2547 100644 --- a/client/src/components/DatasetContainer/index.tsx +++ b/client/src/components/DatasetContainer/index.tsx @@ -1,57 +1,154 @@ import React from 'react'; import {useIntl} from 'gatsby-plugin-intl'; import {defineMessages} from 'react-intl'; +import {Grid} from '@trussworks/react-uswds'; + import DatasetCard from '../DatasetCard'; -import * as styles from './dsContainer.module.scss'; import AlertWrapper from '../AlertWrapper'; +import * as styles from './dsContainer.module.scss'; + export const cards = [ { - indicator: 'Poverty', - description: `Percent of a block group's population in households where the household - income is less than or equal to twice the federal "poverty level"`, + indicator: 'Area Median Income', + description: `Median income of the census block group calculated as a percent + of the metropolitan area’s or state's median income.`, + dataResolution: `Census block group`, + dataSourceLabel: `Census's American Community Survey`, + dataSourceURL: `https://www.census.gov/programs-surveys/acs`, + dataDateRange: `2015-2019`, + }, + { + indicator: 'Households below 100% of the federal poverty line', + description: `Percent of a block group's population in households where the + household income is at or below 100% the federal "poverty level."`, + dataResolution: `Census block group`, + dataSourceLabel: `Census's American Community Survey`, + dataSourceURL: `https://www.census.gov/programs-surveys/acs`, + dataDateRange: `2015-2019`, + }, + { + indicator: 'Education. less than high school education', + description: `Percent of people age 25 or older in a block group whose + education is short of a high school diploma.`, + dataResolution: `Census block group`, + dataSourceLabel: `Census's American Community Survey`, + dataSourceURL: `https://www.census.gov/programs-surveys/acs`, + dataDateRange: `2015-2019`, + }, + { + indicator: 'Diabetes', + description: `People ages 18 years and up who report having ever been + told by a doctor, nurse, or other health professionals that they have + diabetes other than diabetes during pregnancy.`, + dataResolution: `Census tract`, + dataSourceLabel: `Centers for Disease Control and Prevention (CDC) PLACES`, + dataSourceURL: `https://www.cdc.gov/places/index.html`, + dataDateRange: `2016-2019`, + }, + { + indicator: 'Asthma', + description: `Weighted number of respondents people who answer “yes” both + to both of the following questions: “Have you ever been told by a doctor, + nurse, or other health professional that you have asthma?” and the question + “Do you still have asthma?”`, + dataResolution: `Census tract`, + dataSourceLabel: `Centers for Disease Control and Prevention (CDC) PLACES`, + dataSourceURL: `https://www.cdc.gov/places/index.html`, + dataDateRange: `2016-2019`, + }, + { + indicator: 'Heart disase', + description: `People ages 18 years and up who report ever having been told + by a doctor, nurse, or other health professionals that they had angina or + coronary heart disease.`, + dataResolution: `Census tract`, + dataSourceLabel: `Centers for Disease Control and Prevention (CDC) PLACES`, + dataSourceURL: `https://www.cdc.gov/places/index.html`, + dataDateRange: `2016-2019`, + }, + { + indicator: 'Life expectancy', + description: `Estimated years of life expectancy.`, + dataResolution: `Census tract`, + dataSourceLabel: `Centers for Disease Control and Prevention (CDC) + US Small-area Life Expectancy Estimates Project`, + dataSourceURL: `https://www.cdc.gov/nchs/nvss/usaleep/usaleep.html#data`, + dataDateRange: `2010-2015`, + }, + { + indicator: 'Traffic proximity and volume', + description: `Count of vehicles (average annual daily traffic) at major roads + within 500 meters, divided by distance in meters (not km).`, + dataResolution: `Census block group`, + dataSourceLabel: `Department of Transportation (DOT) traffic data`, + dataSourceURL: `#`, + dataDateRange: `2017`, + }, + { + indicator: 'FEMA Risk Index Expected Annual Loss Score', + description: `Average economic loss in dollars resulting from natural + hazards each year. It is calculated for each hazard type and quantifies + loss for relevant consequence types: buildings, people, and agriculture.`, + dataResolution: `Census tract`, + dataSourceLabel: `Federal Emergency Management Agency (FEMA)`, + dataSourceURL: `https://hazards.fema.gov/nri/expected-annual-loss`, + dataDateRange: `2014-2017`, + }, + { + indicator: 'Energy burden', + description: `Average annual energy cost ($) divided by household income.`, + dataResolution: `Census tract`, + dataSourceLabel: `Department of Energy (DOE) LEAD Score`, + dataSourceURL: `https://www.energy.gov/eere/slsc/low-income-energy-affordability-data-lead-tool`, + dataDateRange: `2018`, + }, + { + indicator: 'Housing cost burden', + description: `Households that are low income and spend more than 30% of their + income to housing costs.`, + dataResolution: `Census tract`, + dataSourceLabel: `Department of Housing & Urban Development’s + (HUD) Comprehensive Housing Affordability Strategy dataset`, + dataSourceURL: `https://www.huduser.gov/portal/datasets/cp.html`, + dataDateRange: `2013-2017`, + }, + { + indicator: 'Wastewater discharge', + description: `RSEI modeled Toxic Concentrations at stream segments within 500 + meters, divided by distance in kilometers (km).`, + dataResolution: `Census block group`, + dataSourceLabel: `Environmental Protection Agency (EPA) Risk-Screening + Environmental Indicators (RSEI) Model`, + dataSourceURL: `https://www.epa.gov/rsei`, + dataDateRange: `2020`, + }, + { + indicator: 'Lead paint', + description: `Percent of housing units built pre-1960, used as an + indicator of potential lead paint exposure in homes.`, + dataResolution: `Census block group`, + dataSourceLabel: `Census's American Community Survey`, + dataSourceURL: `https://www.census.gov/programs-surveys/acs`, + dataDateRange: `2015-2019`, + }, + { + indicator: 'Diesel particulate matter', + description: `Mixture of particles that is part of diesel exhaust in the air.`, dataResolution: `Census block group`, dataSourceLabel: `U.S. Census Bureau`, dataSourceURL: `https://www.census.gov/`, dataDateRange: `5-year estimates, 2015-2019`, }, { - indicator: 'Education (less than high school)', - description: `Percent of people age 25 or older in a block group whose education is short of a high school diploma`, + indicator: 'PM2.5', + description: `Fine inhalable particles, with diameters that are generally + 2.5 micrometers and smaller.`, dataResolution: `Census block group`, - dataSourceLabel: `U.S. Census Bureau`, - dataSourceURL: `https://www.census.gov/`, - dataDateRange: `5-year estimates, 2015-2019`, - }, - { - indicator: 'Linguistic isolation', - description: `Percent of people in a block group living in linguistically - isolated households — a linguistically isolated household is a household in - which all members aged 14 years and over speak a non-English language and also speak - English less than "very well" (i.e., have difficulty with English)`, - dataResolution: `Census block group`, - dataSourceLabel: `U.S. Census Bureau`, - dataSourceURL: `https://www.census.gov/`, - dataDateRange: `5-year estimates, 2015-2019`, - }, - { - indicator: 'Unemployment rate', - description: `Unemployment rate (people who are unemployed divided by the total population of - people in the labor force over 16 years old)`, - dataResolution: `Census block group`, - dataSourceLabel: `U.S. Census Bureau`, - dataSourceURL: `https://www.census.gov/`, - dataDateRange: `5-year estimates, 2015-2019`, - }, - { - indicator: 'Housing burden', - description: `Percent of households in a census tract that are both low income (making less - than 80% of the HUD Area Median Family Income) and severely burdened by housing costs - (paying greater than 30% of their income to housing costs)`, - dataResolution: `Census block group`, - dataSourceLabel: `U.S. Census Bureau`, - dataSourceURL: `https://www.census.gov/`, - dataDateRange: `5-year estimates, 2015-2019`, + dataSourceLabel: `Environmental Protection Agency (EPA) Office of Air + and Radiation (OAR) fusion of model and monitor data`, + dataSourceURL: `https://www.epa.gov/aboutepa/about-office-air-and-radiation-oar`, + dataDateRange: `2017`, }, ]; @@ -61,32 +158,40 @@ const DatasetContainer = () => { const messages = defineMessages({ cumulativeScore: { id: 'datasetContainer.header.cumulativeScore', - defaultMessage: 'Datasets used in cumulative score', + defaultMessage: 'Datasets used methodology', description: 'section label of which datasets are used in cumulative score', }, subTitle: { id: 'datasetContainer.subTitle', - defaultMessage: 'The datasets come from a variety of sources and ' + - 'were selected after considering relevance, availability, recency and quality.', + defaultMessage: 'The datasets come from a variety of sources and were selected' + + ' based on relevance, availability, recency, and quality. The datasets seek to' + + ' identify a range of human health, environmental, climate-related, and other' + + ' cumulative impacts on disadvantaged communities.', description: 'description of the dataset section', }, }); // JSX return value: return ( -
-
-

{intl.formatMessage(messages.cumulativeScore)}

- + <> + + + +

{intl.formatMessage(messages.cumulativeScore)}

+
+
-

{intl.formatMessage(messages.subTitle)}

-
- {cards.map((card) => )} -
+ + +

{intl.formatMessage(messages.subTitle)}

+
+
+
+ {cards.map((card) => )}
-
+ ); }; diff --git a/client/src/components/DatasetContainer/tests/__snapshots__/datasetContainer.test.tsx.snap b/client/src/components/DatasetContainer/tests/__snapshots__/datasetContainer.test.tsx.snap index fcbe6ccf..19324299 100644 --- a/client/src/components/DatasetContainer/tests/__snapshots__/datasetContainer.test.tsx.snap +++ b/client/src/components/DatasetContainer/tests/__snapshots__/datasetContainer.test.tsx.snap @@ -3,14 +3,13 @@ exports[`rendering of the DatasetContainer checks if various text fields are visible 1`] = `
-

- Datasets used in cumulative score -

+

+ Datasets used methodology +

+
+
+
+

- The datasets come from a variety of sources and were selected after considering relevance, availability, recency and quality. + The datasets come from a variety of sources and were selected based on relevance, availability, recency, and quality. The datasets seek to identify a range of human health, environmental, climate-related, and other cumulative impacts on disadvantaged communities.

+
+
+
+
+

+ Area Median Income +

-
-

- Poverty -

-
- What is it? -
-
- Percent of a block group's population in households where the household - income is less than or equal to twice the federal "poverty level" -
-
    -
  • - - Data resolution: - - Census block group -
  • -
  • - - Data source: - - - U.S. Census Bureau - -
  • -
  • - - Data date range: - - 5-year estimates, 2015-2019 -
  • -
-
-
-

- Education (less than high school) -

-
- What is it? -
-
- Percent of people age 25 or older in a block group whose education is short of a high school diploma -
-
    -
  • - - Data resolution: - - Census block group -
  • -
  • - - Data source: - - - U.S. Census Bureau - -
  • -
  • - - Data date range: - - 5-year estimates, 2015-2019 -
  • -
-
-
-

- Linguistic isolation -

-
- What is it? -
-
- Percent of people in a block group living in linguistically - isolated households — a linguistically isolated household is a household in - which all members aged 14 years and over speak a non-English language and also speak - English less than "very well" (i.e., have difficulty with English) -
-
    -
  • - - Data resolution: - - Census block group -
  • -
  • - - Data source: - - - U.S. Census Bureau - -
  • -
  • - - Data date range: - - 5-year estimates, 2015-2019 -
  • -
-
-
-

- Unemployment rate -

-
- What is it? -
-
- Unemployment rate (people who are unemployed divided by the total population of - people in the labor force over 16 years old) -
-
    -
  • - - Data resolution: - - Census block group -
  • -
  • - - Data source: - - - U.S. Census Bureau - -
  • -
  • - - Data date range: - - 5-year estimates, 2015-2019 -
  • -
-
-
-

- Housing burden -

-
- What is it? -
-
- Percent of households in a census tract that are both low income (making less - than 80% of the HUD Area Median Family Income) and severely burdened by housing costs - (paying greater than 30% of their income to housing costs) -
-
    -
  • - - Data resolution: - - Census block group -
  • -
  • - - Data source: - - - U.S. Census Bureau - -
  • -
  • - - Data date range: - - 5-year estimates, 2015-2019 -
  • -
-
+ What is it?
+
+ Median income of the census block group calculated as a percent + of the metropolitan area’s or state's median income. +
+ +
+
+

+ Households below 100% of the federal poverty line +

+
+ What is it? +
+
+ Percent of a block group's population in households where the + household income is at or below 100% the federal "poverty level." +
+ +
+
+

+ Education. less than high school education +

+
+ What is it? +
+
+ Percent of people age 25 or older in a block group whose + education is short of a high school diploma. +
+ +
+
+

+ Diabetes +

+
+ What is it? +
+
+ People ages 18 years and up who report having ever been + told by a doctor, nurse, or other health professionals that they have + diabetes other than diabetes during pregnancy. +
+ +
+
+

+ Asthma +

+
+ What is it? +
+
+ Weighted number of respondents people who answer “yes” both + to both of the following questions: “Have you ever been told by a doctor, + nurse, or other health professional that you have asthma?” and the question + “Do you still have asthma?” +
+ +
+
+

+ Heart disase +

+
+ What is it? +
+
+ People ages 18 years and up who report ever having been told + by a doctor, nurse, or other health professionals that they had angina or + coronary heart disease. +
+ +
+
+

+ Life expectancy +

+
+ What is it? +
+
+ Estimated years of life expectancy. +
+ +
+
+

+ Traffic proximity and volume +

+
+ What is it? +
+
+ Count of vehicles (average annual daily traffic) at major roads + within 500 meters, divided by distance in meters (not km). +
+ +
+
+

+ FEMA Risk Index Expected Annual Loss Score +

+
+ What is it? +
+
+ Average economic loss in dollars resulting from natural + hazards each year. It is calculated for each hazard type and quantifies + loss for relevant consequence types: buildings, people, and agriculture. +
+ +
+
+

+ Energy burden +

+
+ What is it? +
+
+ Average annual energy cost ($) divided by household income. +
+ +
+
+

+ Housing cost burden +

+
+ What is it? +
+
+ Households that are low income and spend more than 30% of their + income to housing costs. +
+ +
+
+

+ Wastewater discharge +

+
+ What is it? +
+
+ RSEI modeled Toxic Concentrations at stream segments within 500 + meters, divided by distance in kilometers (km). +
+ +
+
+

+ Lead paint +

+
+ What is it? +
+
+ Percent of housing units built pre-1960, used as an + indicator of potential lead paint exposure in homes. +
+ +
+
+

+ Diesel particulate matter +

+
+ What is it? +
+
+ Mixture of particles that is part of diesel exhaust in the air. +
+
    +
  • + + Data resolution: + + Census block group +
  • +
  • + + Data source: + + + U.S. Census Bureau + +
  • +
  • + + Data date range: + + 5-year estimates, 2015-2019 +
  • +
+
+
+

+ PM2.5 +

+
+ What is it? +
+
+ Fine inhalable particles, with diameters that are generally + 2.5 micrometers and smaller. +
+
diff --git a/client/src/components/HowYouCanHelp/index.tsx b/client/src/components/HowYouCanHelp/index.tsx index 7a7b3156..f342039b 100644 --- a/client/src/components/HowYouCanHelp/index.tsx +++ b/client/src/components/HowYouCanHelp/index.tsx @@ -15,12 +15,12 @@ const HowYouCanHelp = () => { }, youCanHelpInfoText: { id: 'youCanHelpInfoText.list.element.prefix', - defaultMessage: 'If you have helpful information, we’d love to', + defaultMessage: 'If you have helpful information, we would love to', description: 'you can help info text ', }, youCanHelpInfoLinkText: { id: 'youCanHelpInfoLink.link.text', - defaultMessage: 'get an email from you', + defaultMessage: 'recieve an email from you', description: 'you can help info text ', }, youCanHelpDataMethPrefixText: { @@ -30,7 +30,7 @@ const HowYouCanHelp = () => { }, youCanHelpDataMethLinkText: { id: 'youCanHelpDataMethLinkText.link.text', - defaultMessage: 'Data & methodology', + defaultMessage: 'Data and methodology', description: 'Data & methodology link', }, youCanHelpDataMethSuffixText: { @@ -40,7 +40,7 @@ const HowYouCanHelp = () => { }, youCanHelpSharingPrefixText: { id: 'youCanHelpSharingPrefixText.link.prefix.text', - defaultMessage: 'Find your community and', + defaultMessage: 'Find your community of interest and', description: 'find your community', }, youCanHelpSharingLinkText: { diff --git a/client/src/components/HowYouCanHelp/tests/__snapshots__/howYouCanHelp.test.tsx.snap b/client/src/components/HowYouCanHelp/tests/__snapshots__/howYouCanHelp.test.tsx.snap index 52147d80..a29f8de0 100644 --- a/client/src/components/HowYouCanHelp/tests/__snapshots__/howYouCanHelp.test.tsx.snap +++ b/client/src/components/HowYouCanHelp/tests/__snapshots__/howYouCanHelp.test.tsx.snap @@ -9,11 +9,11 @@ exports[`rendering of the HowYouCanHelp checks if various text fields are visibl
  • - Find your community and + Find your community of interest and diff --git a/client/src/components/J40Header.tsx b/client/src/components/J40Header.tsx index d1254f79..0d5a6120 100644 --- a/client/src/components/J40Header.tsx +++ b/client/src/components/J40Header.tsx @@ -5,6 +5,7 @@ import { NavMenuButton, PrimaryNav, GovBanner, + Tag, } from '@trussworks/react-uswds'; import {defineMessages} from 'react-intl'; // @ts-ignore @@ -120,6 +121,7 @@ const J40Header = () => { {titleL1}
    {titleL2} + Beta
    { const [transitionInProgress, setTransitionInProgress] = useState(false); const [geolocationInProgress, setGeolocationInProgress] = useState(false); const [isMobileMapState, setIsMobileMapState] = useState(false); + const {width: windowWidth} = useWindowSize(); const mapRef = useRef(null); const flags = useFlags(); @@ -170,94 +173,99 @@ const J40Map = ({location}: IJ40Interface) => { }; return ( -
    - - + + - - - - - {('fs' in flags && detailViewData && !transitionInProgress) && ( - - - - )} - + + + + {('fs' in flags && detailViewData && !transitionInProgress) && ( + + + + )} + + {'gl' in flags ? : ''} + {geolocationInProgress ?
    Geolocation in progress...
    : ''} + + {'fs' in flags ? :'' } +
    +
    + + + - {'gl' in flags ? : ''} - {geolocationInProgress ?
    Geolocation in progress...
    : ''} - - {'fs' in flags ? :'' } -
    - -
    + + ); }; diff --git a/client/src/components/MapLegend/index.tsx b/client/src/components/MapLegend/index.tsx index 6e477f31..55e1f4e5 100644 --- a/client/src/components/MapLegend/index.tsx +++ b/client/src/components/MapLegend/index.tsx @@ -1,114 +1,21 @@ import React from 'react'; import {useIntl} from 'gatsby-plugin-intl'; -import {Tooltip} from '@trussworks/react-uswds'; import * as styles from './mapLegend.module.scss'; import * as constants from '../../data/constants'; -// @ts-ignore -import infoIcon from '/node_modules/uswds/dist/img/usa-icons/info_outline.svg'; - -// Todo VS: This information will be used in the re-design of the tool-tip -// const getToolTipContent = (type:string) => { -// const intl = useIntl(); -// const messages = defineMessages({ -// priorityHeader: { -// id: 'tooltip.info.priority.header', -// defaultMessage: constants.PRIORITIZED_COMMUNITY, -// description: 'the header of the prioritized community tooltip', -// }, -// thresholdHeader: { -// id: 'tooltip.info.threshold.header', -// defaultMessage: constants.THRESHOLD_COMMUNITY, -// description: 'the header of the threshold community tooltip', -// }, -// priorityText: { -// id: 'tooltip.info.priority.text', -// defaultMessage: 'A prioritized community is one that has a cumulative index score of Xth ' + -// 'percentile and above. 40% of the benefits from investments outlined by the ' + -// 'Justice40 Initiative should go to prioritized communities.', -// description: 'the text of the prioritized community tooltip', -// }, -// thresholdText: { -// id: 'tooltip.info.threshold.text', -// defaultMessage: 'Communities with a cumulative index score between Y - X.99th percentile are ' + -// 'considered threshold communities. While these communities are currently not considered a ' + -// 'prioritized community, this may change based on updates to the scoring method.', -// description: 'the text of the threshold community tooltip', -// }, -// }); - -// return (type === 'prioritized') ? -// ( -//
    -//

    {intl.formatMessage(messages.priorityHeader)}

    -//

    {intl.formatMessage(messages.priorityText)}

    -//
    -// ) : -// ( -//
    -//

    {intl.formatMessage(messages.thresholdHeader)}

    -//

    {intl.formatMessage(messages.thresholdText)}

    -//
    -// ); -// }; - const MapLegend = () => { const intl = useIntl(); - - // Type definitions required for @trussworks tooltip. This type defines the div that wraps the icon. - // This allows to pass children and other attributes. - type IconWrapperProps = React.PropsWithChildren<{ - className?: string - }> & - JSX.IntrinsicElements['div'] & - React.RefAttributes - const IconWrapper: React.ForwardRefExoticComponent = React.forwardRef( - ({className, children, ...tooltipProps}: IconWrapperProps, ref) => ( -
    - {children} -
    - ), - ); - IconWrapper.displayName = 'custom info wrapper'; - return (
    -
    {intl.formatMessage(constants.EXPLORE_TOOL_PAGE_TEXT.LEGEND_LABEL)}
    -
    -
    -
    - {intl.formatMessage(constants.EXPLORE_TOOL_PAGE_TEXT.PRIORITY_LABEL)} - - {/* Using @trussworks tooltip */} - - label={` - Communities that have cumulative - index score of Xth percentile - and above - `} - position='left' - asCustom={IconWrapper}> - - - -
    -
    -
    - {intl.formatMessage(constants.EXPLORE_TOOL_PAGE_TEXT.THRESHOLD_LABEL)} - - {/* Using @trussworks tooltip */} - - label={` - Communities with a cumulative - index score between Y - X.99th - percentile - `} - position='left' - asCustom={IconWrapper}> - - -
    +
    +
    +

    + {intl.formatMessage(constants.EXPLORE_TOOL_PAGE_TEXT.PRIORITY_LABEL)} +

    +

    + {intl.formatMessage(constants.EXPLORE_TOOL_PAGE_TEXT.PRIORITY_DESCRIPT)} +

    ); diff --git a/client/src/components/MapLegend/mapLegend.module.scss b/client/src/components/MapLegend/mapLegend.module.scss index ac80148d..779e6ff2 100644 --- a/client/src/components/MapLegend/mapLegend.module.scss +++ b/client/src/components/MapLegend/mapLegend.module.scss @@ -6,88 +6,23 @@ $max-color: rgba(26, 68, 128, 0.6); $alertInfoColor: #e7f6f8; .legendContainer { - margin: 1rem 1.2rem 1rem 2.5rem; - font-size: 0.8em; - border: 1px solid #8c9297; - padding: 1rem 1.8rem 0; - flex: 1; - color: $headingFontColor; - - .legendTooltipText { - max-width: 14rem; - font-size: medium; - } - - @media screen and (max-width: $mobileBreakpoint) { - margin: 1rem 0; - } -} - - -.swatchContainer { display: flex; - flex-direction: row; - justify-content: space-between; + margin: 1rem 0 1rem 2.5rem; + border: 1px solid #DFE1E2; + padding: .5rem 1.5rem 1rem 1.5rem; - @media screen and (max-width: $mobileBreakpoint) { - flex-wrap: wrap; - } -} - -.legendItem { - display: flex; - flex-direction: row; - align-items: center; - - span { - font-size: medium; - } - - .infoIconWrapper { - margin-left: 0.8rem; - .infoIcon { - width: 2rem; - height: 2rem; - margin-top: 0.4rem; - } - } - - @media screen and (max-width: $mobileBreakpoint) { - padding-left: 3rem; + @media screen and (max-width: 640px) { + margin: 1rem 0 0; } } .colorSwatch { + flex: 1 0 2rem; box-sizing: border-box; height: 1.7rem; width: 1.7rem; - margin-right: 10px; + margin: 2rem 1.5rem 2rem 0; border-radius: 50%; -} - -#prioritized { background-color: $max-color; -} - -#threshold { - background-color: $med-color; -} - -#nonPrioritized { - background-color: $min-color; -} - -.legendTooltipTheme { - color: $headingFontColor !important; - background-color: white !important; - opacity: 1 !important; - border: $sidePanelBorder !important; - box-shadow: 0 0 11px rgba(33, 33, 33, 0.2) !important; - &.place-top { - &:after { - border-top-color: white !important; - border-top-style: solid !important; - border-top-width: 6px !important; - } - } + border: 2px solid $featureSelectBorderColor; } diff --git a/client/src/components/MapLegend/mapLegend.module.scss.d.ts b/client/src/components/MapLegend/mapLegend.module.scss.d.ts index b7f45548..2c5b0db0 100644 --- a/client/src/components/MapLegend/mapLegend.module.scss.d.ts +++ b/client/src/components/MapLegend/mapLegend.module.scss.d.ts @@ -1,16 +1,7 @@ declare namespace HowYouCanHelpModuleScssNamespace { export interface IHowYouCanHelpModuleScss { legendContainer: string; - swatchContainer: string; colorSwatch: string; - prioritized: string, - threshold: string, - nonPrioritized: string, - legendItem: string, - infoIcon: string, - legendTooltipText: string, - legendTooltipTheme: string, - infoIconWrapper: string, } } diff --git a/client/src/components/MapLegend/tests/__snapshots__/mapLegend.test.tsx.snap b/client/src/components/MapLegend/tests/__snapshots__/mapLegend.test.tsx.snap new file mode 100644 index 00000000..c395c189 --- /dev/null +++ b/client/src/components/MapLegend/tests/__snapshots__/mapLegend.test.tsx.snap @@ -0,0 +1,19 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`rendering of the MapLegend checks if snapshots have changed 1`] = ` + +
    +
    +
    +

    + Draft community of focus +

    +

    + These communities are identified as experiencing disadvantages that merit the focus of certain Federal investments, including through the Justice40 Initiative +

    +
    +
    + +`; diff --git a/client/src/components/MapLegend/tests/mapLegend.test.tsx b/client/src/components/MapLegend/tests/mapLegend.test.tsx index f537736e..90c04fed 100644 --- a/client/src/components/MapLegend/tests/mapLegend.test.tsx +++ b/client/src/components/MapLegend/tests/mapLegend.test.tsx @@ -3,23 +3,16 @@ import {render} from '@testing-library/react'; import {LocalizedComponent} from '../../../test/testHelpers'; import MapLegend from '../index'; -import * as constants from '../../../data/constants'; + describe('rendering of the MapLegend', () => { - const {getAllByText} = render( + const {asFragment} = render( , ); - // Snapshot testing was unusable as the Tooltip lib rendered hash based class - // names on each render - - const intlPriorityLabel = constants.EXPLORE_TOOL_PAGE_TEXT.PRIORITY_LABEL.defaultMessage; - const intlThresholdLabel = constants.EXPLORE_TOOL_PAGE_TEXT.THRESHOLD_LABEL.defaultMessage; - - it('checks if various objects in the component rendered', () => { - expect(getAllByText(intlPriorityLabel)[0]).toHaveTextContent(intlPriorityLabel); - expect(getAllByText(intlThresholdLabel)[0]).toHaveTextContent(intlThresholdLabel); + it('checks if snapshots have changed', () => { + expect(asFragment()).toMatchSnapshot(); }); }); diff --git a/client/src/components/MapWrapper/index.tsx b/client/src/components/MapWrapper/index.tsx index d2226f02..b7b828dc 100644 --- a/client/src/components/MapWrapper/index.tsx +++ b/client/src/components/MapWrapper/index.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; import {useIntl} from 'gatsby-plugin-intl'; import {defineMessages} from 'react-intl'; +import {Grid} from '@trussworks/react-uswds'; import J40Map from '../J40Map'; @@ -17,25 +18,37 @@ const MapWrapper = ({location}: IMapWrapperProps) => { const messages = defineMessages({ downloadLinkText: { id: 'mapwrapper.download.link', - defaultMessage: 'Download the draft list of prioritized communities (pre-decisional) and datasets used', + defaultMessage: 'Download the draft list of communities of focus and datasets used', description: 'download link for datasets', }, downloadContents: { id: 'mapwrapper.download.contents', - defaultMessage: 'ZIP file will contain one .xlsx, one .csv and one .pdf (30 MB).', + defaultMessage: 'ZIP file will contain one .xlsx, one .csv, and one .pdf (30 MB).', description: 'download link contents', }, }); return ( <> - - -
    -
    {intl.formatMessage(messages.downloadContents)}
    + + + + + + + + + + + + + +
    {intl.formatMessage(messages.downloadContents)}
    +
    +
    ); }; diff --git a/client/src/components/__snapshots__/scoreStepsList.test.tsx.snap b/client/src/components/__snapshots__/scoreStepsList.test.tsx.snap index d60630ab..c7f4436d 100644 --- a/client/src/components/__snapshots__/scoreStepsList.test.tsx.snap +++ b/client/src/components/__snapshots__/scoreStepsList.test.tsx.snap @@ -2,122 +2,120 @@ exports[`rendering of the component should match the snapshot of the MapIntroduction component 1`] = ` +

    + Methodology +

    -
      -
    • -
      -

      - Gather datasets -

      -

      - Data inputs -

      -

      - The cumulative index score includes the following equally weighted inputs. -

      -
        -
      • - Poverty -
      • -
      • - Less than high school education -
      • -
      • - Linguistic isolation -
      • -
      • - Unemployment rate -
      • -
      • - Housing burden -
      • -
      -

      - Combining data from different geographic units -

      -

      - Some data is not available at the census block group level and is instead only available for larger units such as census tracts or counties. In these cases, all census block groups will get an even contribution from the larger unit. For example, if a census tract scores 90th percentile on an indicator, then all census block groups within that tract will receive a value of 90th percentile. -

      -

      - Normalizing data -

      -

      - The range of the data that makes up the score varies, so the data must be normalized so that each data indicator can be more equally weighted. Min-max normalization is utilized, where the minimum value in the range of values for each dataset is set at 0, the maximum value is set at 1, and every other value is transformed into a decimal between 0 and 1. For example, if the minimum value for unemployment was 10 and the maximum value was 30, a value of 20 would be transformed to 0.5 since it is halfway between 10 and 30. -

      -
      -
    • -
    • -
      -

      - Calculate cumulative index score -

      -

      - To combine all variables into a single cumulative index score, we average the normalized values across indicators. -

      -
      -
      -
      -
      - Dataset 1 + Dataset 2 + ... + Dataset N -
      -
      - # of datasets -
      -
      -
      - = -
      -
      - Cumulative index score -
      -
      -
      -
      -
    • -
    • -
      -

      - Assign priority -

      -

      - Census block groups are sorted by their cumulative index score from highest to lowest. Census block groups that are in the top 25 percentile (i.e. have a cumulative index score in the 75 - 100th percentile) will be considered the prioritized communities. -

      -
      -
    • -
    +
    +

    + The methodology for identifying communities of focus is calculated at the census block group level. Census block geographical boundaries are determined by the U.S. Census Bureau once every ten years. This tool utilizes the census block boundaries from 2010. +

    +

    + The following describes the process for identifying disadvantaged communities. +

    +
    +
      +
    1. +

      + Gather datasets +

      +

      + +

      +

      + Data inputs +

      +

      + The methodology includes the following inputs that are equally weighted. +

      +

      + Percent of Area Median Income +

      +

      + If a census block group is in a metropolitan area, this value is the median income of the census block group calculated as a percent of the metropolitan area’s median income. +

      +

      + If a census block group is not in a metropolitan area, this value is the median income of the census block group calculated as a percent of the state’s median income. +

      +

      + Percent of households below or at 100% of the federal poverty line +

      +

      + This is the percent of households in a state with a household income below or at 100% of the + + federal poverty line + + . This federal poverty line is calculated based on the composition of each household (e.g., based on household size), but it does not vary geographically. +

      +

      + The high school degree achievement rate for adults 25 years and older +

      +

      + The percent of individuals who are 25 or older who have received a high school degree. +

      +
    2. +
    3. +

      + Current Formula +

      +

      + +

      +

      + Under the existing formula, a census block group will be considered a community of focus if: +

      +

      + (The median income is <80% of the area median income OR +

      +

      + households living in poverty (at or below 100% of the federal poverty level) is >20%) +

      +

      + AND +

      +

      + The high school degree achievement rate for adults 25 years and older is <95% +

      +
    4. +
    `; diff --git a/client/src/components/scoreStepsList.tsx b/client/src/components/scoreStepsList.tsx index def3be76..b2597a88 100644 --- a/client/src/components/scoreStepsList.tsx +++ b/client/src/components/scoreStepsList.tsx @@ -1,99 +1,96 @@ import React from 'react'; -import {GridContainer, Grid} from '@trussworks/react-uswds'; +import { + ProcessList, + ProcessListItem, + ProcessListHeading, + Grid, +} from '@trussworks/react-uswds'; const ScoreStepsList = () => { return ( <> -
    -
      -
    • -
      -

      Gather datasets

      -

      Data inputs

      -

      - The cumulative index score includes the following equally - weighted inputs. -

      +

      Methodology

      + + +

      + The methodology for identifying communities of focus is calculated at the + census block group level. Census block geographical boundaries are determined + by the U.S. Census Bureau once every ten years. This tool utilizes the census + block boundaries from 2010. +

      +

      + The following describes the process for identifying disadvantaged communities. +

      +
      +
      -
        -
      • Poverty
      • -
      • Less than high school education
      • -
      • Linguistic isolation
      • -
      • Unemployment rate
      • -
      • Housing burden
      • -
      + + + Gather datasets +

      {' '}

      +

      + Data inputs +

      +

      + The methodology includes the following inputs that are equally weighted. +

      -

      - Combining data from different geographic units -

      -

      - Some data is not available at the census block group level and - is instead only available for larger units such as census tracts - or counties. In these cases, all census block groups will get an - even contribution from the larger unit. For example, if a census - tract scores 90th percentile on an indicator, then all census - block groups within that tract will receive a value of 90th - percentile. -

      -

      Normalizing data

      -

      - The range of the data that makes up the score varies, so the - data must be normalized so that each data indicator can be more - equally weighted. Min-max normalization is utilized, where the - minimum value in the range of values for each dataset is set at - 0, the maximum value is set at 1, and every other value is - transformed into a decimal between 0 and 1. For example, if the - minimum value for unemployment was 10 and the maximum value was - 30, a value of 20 would be transformed to 0.5 since it is - halfway between 10 and 30. -

      -
      -
    • +

      + Percent of Area Median Income +

      +

      + If a census block group is in a metropolitan area, this value is the + median income of the census block group calculated as a percent of + the metropolitan area’s median income. +

      +

      + If a census block group is not in a metropolitan area, this value is + the median income of the census block group calculated as a percent + of the state’s median income. +

      -
    • -
      -

      Calculate cumulative index score

      -

      - To combine all variables into a single cumulative index score, - we average the normalized values across indicators. -

      +

      + Percent of households below or at 100% of the federal poverty line +

      +

      + This is the percent of households in a state with a household income + below or at 100% of the federal poverty line. This federal poverty line is + calculated based on the composition of each household (e.g., based on + household size), but it does not vary geographically. +

      +

      + The high school degree achievement rate for adults 25 years and older +

      +

      + The percent of individuals who are 25 or older who have received a high school degree. +

      + - - - -
      - Dataset 1 + Dataset 2 + ... + Dataset N -
      -
      - # of datasets -
      -
      - - = - - - Cumulative index score - -
      -
      -
      -
    • + + + Current Formula + +

      {' '}

      +

      + Under the existing formula, a census block group will be considered a + community of focus if: +

      +

      + (The median income is <80% of the area median income OR +

      +

      + households living in poverty (at or below 100% of the federal poverty level) is >20%) +

      +

      + AND +

      +

      + The high school degree achievement rate for adults 25 years and older is <95% +

      +
      -
    • -
      -

      Assign priority

      -

      - Census block groups are sorted by their cumulative index score - from highest to lowest. Census block groups that are in the top - 25 percentile (i.e. have a cumulative index score in the 75 - - 100th percentile) will be considered the prioritized - communities. -

      -
      -
    • -
    -
    + ); }; diff --git a/client/src/components/utils.scss b/client/src/components/utils.scss index d4f916b2..36a24a6c 100644 --- a/client/src/components/utils.scss +++ b/client/src/components/utils.scss @@ -9,6 +9,7 @@ $sidePanelBorderColor: #f2f2f2; $sidePanelBorder: 2px solid $sidePanelBorderColor; $mobileBreakpoint: 400px; +$featureSelectBorderColor: #00bde3; //Styles with Dataset container $datasetContainerColor: #eef6fb; diff --git a/client/src/data/constants.tsx b/client/src/data/constants.tsx index 8509b448..0d8c4f15 100644 --- a/client/src/data/constants.tsx +++ b/client/src/data/constants.tsx @@ -48,6 +48,17 @@ export const EDUCATION_PROPERTY_PERCENTILE = `Percent individuals age 25 or over with less than high school degree (percentile)`; export const COUNTY_NAME = 'County Name'; export const STATE_NAME = 'State Name'; +export const DIABETES_PERCENTILE = 'Diagnosed diabetes among adults aged >=18 years (percentile)'; +export const ASTHMA_PERCENTILE = 'Current asthma among adults aged >=18 years (percentile)'; +export const HEART_PERCENTILE = 'Coronary heart disease among adults aged >=18 years (percentile)'; +export const LIFE_PERCENTILE = 'Life expectancy (years) (percentile)'; +export const TRAFFIC_PERCENTILE = 'Traffic proximity and volume (percentile)'; +export const FEMA_PERCENTILE = 'FEMA Risk Index Expected Annual Loss Score (percentile)'; +export const ENERGY_PERCENTILE = 'Energy burden (percentile)'; +export const WASTEWATER_PERCENTILE = 'Wastewater discharge (percentile)'; +export const LEAD_PAINT_PERCENTILE = 'Percent pre-1960s housing (lead paint indicator) (percentile)'; +export const DIESEL_MATTER_PERCENTILE = 'Diesel particulate matter (percentile)'; +export const PM25_PERCENTILE = 'Particulate matter (PM2.5) (percentile)'; // The name of the layer within the tiles that contains the score @@ -133,19 +144,15 @@ export const SCORE_BOUNDARY_PRIORITIZED = 0.75; export const EXPLORE_TOOL_PAGE_TEXT = defineMessages({ PRIORITY_LABEL: { id: 'legend.info.priority.label', - defaultMessage: 'Prioritized community', + defaultMessage: 'Draft community of focus', description: 'the label of the prioritized community legend', }, - THRESHOLD_LABEL: { + PRIORITY_DESCRIPT: { id: 'legend.info.threshold.label', - defaultMessage: 'Threshold community', + defaultMessage: 'These communities are identified as experiencing disadvantages that merit' + + ' the focus of certain Federal investments, including through the Justice40 Initiative', description: 'the label of the threshold community legend', }, - LEGEND_LABEL: { - id: 'legend.colorkey.label', - defaultMessage: 'Color key', - description: 'the label of the key in the legend', - }, }); export const isMobile = isMobileReactDeviceDetect; diff --git a/client/src/pages/cejst.tsx b/client/src/pages/cejst.tsx index 19a765d8..61a574e1 100644 --- a/client/src/pages/cejst.tsx +++ b/client/src/pages/cejst.tsx @@ -31,15 +31,6 @@ const CEJSTPage = ({location}: IMapPageProps) => { defaultMessage: 'Explore the tool', description: 'explore the tool heading text', }, - exploreToolPageText: { - id: 'exploreTool.page.text', - defaultMessage: 'Zoom into the map to see which communities the tool has currently'+ - 'identified as prioritized (the top 25% of communities) or on the'+ - 'threshold. Learn more about the formula and datasets that were'+ - 'used to prioritize these communities on the', - description: 'explore the tool page text', - }, - }); return ( @@ -53,7 +44,10 @@ const CEJSTPage = ({location}: IMapPageProps) => {

    - {intl.formatMessage(messages.exploreToolPageText)} + Zoom into the map to see communities of focus that can help Federal agencies + identify disadvantaged communities and to provide socioeconomic, + environmental, and climate information and data. Learn more about the methodology + and datasets that were used to determine these communities of focus on the {` `} Data & methodology {` `} @@ -65,15 +59,13 @@ const CEJSTPage = ({location}: IMapPageProps) => { + - - -

    - -
    - - + + + +
    diff --git a/client/src/pages/index.tsx b/client/src/pages/index.tsx index 11166247..e3a6c510 100644 --- a/client/src/pages/index.tsx +++ b/client/src/pages/index.tsx @@ -43,7 +43,7 @@ const IndexPage = ({location}: IndexPageProps) => { }, presidentalLinkLabel: { id: 'index.presidentalLinkLabel', - defaultMessage: 'Executive Order on Tackling the Climate Crisis at Home and Abroad.', + defaultMessage: 'Executive Order 14008 on Tackling the Climate Crisis at Home and Abroad', description: 'Link url to presidential actions executive order. Part of paragraph 3', }, transparentLabel: { @@ -87,20 +87,32 @@ const IndexPage = ({location}: IndexPageProps) => { imgSrc={aboutUSMapImg} header={intl.formatMessage(messages.aboutScreenToolHeading)}> - + +

    +

    + +

    @@ -110,18 +122,22 @@ const IndexPage = ({location}: IndexPageProps) => { imgSrc={aboutJ40Img} header={intl.formatMessage(messages.aboutJustice40Heading)}> - +

    + +

    { header={'Federal program managers'} actionText={'Go to data & methodology'} actionUrl={'./methodology'}> - Download the screening tool’s draft list of prioritized - communities and information on how to use it for your program in - the future on the data and methodology page. + Download the screening tool’s draft list of communities of focus. + Explore data that may be useful to your program, and provide + feedback on the tool. { header={'Community members'} actionText={'Explore the tool'} actionUrl={'./cejst'}> - Find your community or communities that you may be familiar with - and check their prioritization information on the map. + Explore data about communities of focus in your area, and help + provide feedback on the tool. @@ -184,8 +200,8 @@ const IndexPage = ({location}: IndexPageProps) => { header={'Send Feedback'} actionText={'Email: screeningtool.feedback@usds.gov'} actionUrl={'mailto:screeningtool.feedback@usds.gov'}> - Have ideas about how to acknowledge the on-the-ground experiences - of your community? + Have ideas about how this tool can be improved to better + reflect the on-the-ground experiences of your community? { actionUrl={'https://github.com/usds/justice40-tool'} actionOpenInNewTab={true}> The screening tool’s code is open source, which means it is - available for the public to view and contribute to. Anyone can - view and contribute on GitHub. + available for the public to view and contribute to. Anyone + can view and contribute on GitHub. diff --git a/client/src/pages/methodology.tsx b/client/src/pages/methodology.tsx index 996cb59b..1f517c49 100644 --- a/client/src/pages/methodology.tsx +++ b/client/src/pages/methodology.tsx @@ -4,11 +4,11 @@ import {useIntl} from 'gatsby-plugin-intl'; import {defineMessages} from 'react-intl'; import AlertWrapper from '../components/AlertWrapper'; -// import DatasetContainer from '../components/DatasetContainer'; +import DatasetContainer from '../components/DatasetContainer'; import DownloadPacket from '../components/DownloadPacket'; import J40MainGridContainer from '../components/J40MainGridContainer'; import Layout from '../components/layout'; -// import ScoreStepsList from '../components/scoreStepsList'; +import ScoreStepsList from '../components/scoreStepsList'; interface MethodPageProps { location: Location; @@ -30,8 +30,8 @@ const IndexPage = ({location}: MethodPageProps) => { }, methodologyPagep1: { id: 'methodology.page.paragraph.first', - defaultMessage: 'The methodology for determining disadvantaged communities for the purposes of '+ - ' the Justice40 Initiative is currently in progress.', + defaultMessage: 'The methodology for identifying communities of focus is currently ' + + 'in a draft, pre-decisional form that may change over time as more datasets become available.', description: 'methodology page paragraph 1', }, }); @@ -45,7 +45,7 @@ const IndexPage = ({location}: MethodPageProps) => {

    {intl.formatMessage(messages.methodologyPageHeader)}

    - +

    @@ -59,13 +59,10 @@ const IndexPage = ({location}: MethodPageProps) => { - {/* // Temporarily removed while the app is demo'd to stakeholders - - - - - - + + + + @@ -74,7 +71,7 @@ const IndexPage = ({location}: MethodPageProps) => { - */} + ); }; diff --git a/client/src/styles/global.scss b/client/src/styles/global.scss index 8088c60f..ae295008 100644 --- a/client/src/styles/global.scss +++ b/client/src/styles/global.scss @@ -37,6 +37,7 @@ There are 3 things that should be included in this file: $primary-color: #112f4e; $j40-blue-background-color: #EFF6FB; +$sidePanelBorderColor: #f2f2f2; // The j40-element mixin is used to create any font element. E.g.

    ,

    tags, etc. // Arguments to the mixins must be tokens from USWDS @@ -76,7 +77,11 @@ p { } p.secondary { - @include j40-element('3xs', 4, 'normal', .5); + @include j40-element('3xs', 2, 'normal', .5); +} + +p.flush { + @include j40-element('sm', 4, 'normal', 0); } // 40 pixel margin-bottom @@ -176,6 +181,10 @@ components include: } } +.usa-tag.j40 { + background: orange; + margin-left: 1rem; +} /* ****************************** @@ -237,6 +246,7 @@ This section will outline styles that are component specific - map - timeline - about +- accordion /* ****************************** @@ -380,6 +390,14 @@ This section will outline styles that are component specific } } +//Area Detail Component +p.secondary.j40-indicator { + max-width: 10rem; + + @media screen and (max-width: 1024px) { + max-width: 80%; + } +} /* *************************************** @@ -387,97 +405,8 @@ This section will outline styles that are component specific *************************************** */ -/* the > is for child only syntax in css. This is required so that lists that are nested under the - list are not affected (e.g.

      • not styled

      • */ -.j40-process-list-wrapper > { - $j40-steps-list-color: #002D3F; - - ul { - margin-top: 3rem; - margin-bottom: 1rem; - padding-inline-start: 0; - - > li { - list-style-type: none; - position: relative; - margin-left: 2.5rem; - /* do the lines */ - border-left: .2rem solid $j40-steps-list-color; - padding-left: 1.88rem; - /* removes gap between line and circle */ - margin-top: -1rem; - padding-bottom: 2rem; - } - - > li:before { - content: " "; - border: 1rem solid $j40-steps-list-color; - border-radius: 100rem; - height: 0; /* it's all controlled by the border */ - width: 0; - margin-top: -0.5rem; - margin-left: -3rem; - position: absolute; - } - - > li:last-child { - /* no line on last item */ - border-left: .2rem solid transparent; - margin-top: -1.9rem; - } - } -} - -/* The math equation on the methodology page.. which is a royal pain */ -.j40-math-division-container { - > .j40-math-eq-left-side { - text-align: right; - justify-content: center; - align-items: center; - padding: 0.5rem; - - > .j40-math-eq-numerator { - border-bottom: solid 3px black; - text-align: center; - width: 90%; - } - - > .j40-math-eq-denominator { - text-align: center; - width: 90%; - } - } - - > .j40-math-eq-middle { - display: inline-flex; - justify-content: center; - align-items: center; - padding: 0.25rem; - } - - > .j40-math-eq-right-side { - display: inline-flex; - align-items: center; - padding: 0.25rem; - } -} - -ul.j40-process-nested-list { - margin-bottom: 2rem; - > li { - list-style-type: disc; /* without this, we get hollow circles */ - } -} - -/* these are currently used in the list, but it seems like they should be globally consistent with the rest of the site */ -.j40-item-list-title { - margin-block-end: auto; -} - -.j40-item-list-subtitle { - margin-block-start: auto; - margin-block-end: auto; - font-style: italic; +.usa-process-list__heading{ + border-left-color: $j40-blue-background-color; } @@ -529,3 +458,35 @@ ul.j40-process-nested-list { } } + +/* +****************************** +* ACCORDION STYLES +****************************** +*/ + +.usa-accordion__heading button.usa-accordion__button { + @include j40-element('3xs', 1, 'normal', 0); + border-bottom: 1px solid $sidePanelBorderColor; +} +.usa-accordion__heading:first-child button.usa-accordion__button { + @include j40-element('3xs', 1, 'normal', 0); + background-color: white; +} +.usa-accordion__heading button.usa-accordion__button { + @include j40-element('3xs', 1, 'normal', 0); + background-color: #F3F3F3; +} + +.usa-accordion__heading:not(:first-child){ + @include u-margin-top(0); +} + +#prioritization-indicators, #additional-indicators { + padding-top: 0; + padding-bottom: 0; +} + +#additional-indicators { + background-color:#F3F3F3; +} \ No newline at end of file