diff --git a/.github/workflows/Publish_Backend_Package.yml b/.github/workflows/Publish_Backend_Package.yml index 82d95e215..358a54c9f 100644 --- a/.github/workflows/Publish_Backend_Package.yml +++ b/.github/workflows/Publish_Backend_Package.yml @@ -47,4 +47,4 @@ jobs: env: HEROKU_API_KEY: ${{ secrets.HEROKU_API_KEY }} run: | - heroku config:set -a hackforla-311 PROJECT_URL=${{ secrets.PROJECT_URL }} GITHUB_TOKEN=${{ secrets.GH_ISSUES_TOKEN }} TOKEN=${{ secrets.SOCRATA_TOKEN }} + heroku config:set -a hackforla-311 PROJECT_URL=${{ secrets.PROJECT_URL }} GITHUB_TOKEN=${{ secrets.GH_ISSUES_TOKEN }} TOKEN=${{ secrets.SOCRATA_TOKEN }} GITHUB_SHA=${{ github.sha }} diff --git a/package.json b/package.json index 86ed55eb3..4438a22da 100644 --- a/package.json +++ b/package.json @@ -58,16 +58,16 @@ "devDependencies": { "@babel/core": "^7.8.4", "@babel/plugin-proposal-class-properties": "^7.7.0", - "@babel/preset-env": "^7.8.4", + "@babel/preset-env": "^7.9.5", "@babel/preset-react": "^7.8.3", - "babel-eslint": "^10.0.3", + "babel-eslint": "^10.1.0", "babel-loader": "^8.0.6", - "css-loader": "^3.2.0", + "css-loader": "^3.5.1", "enzyme": "^3.10.0", "enzyme-adapter-react-16": "^1.15.1", "eslint": "^6.7.2", "eslint-config-airbnb": "^18.0.1", - "eslint-plugin-import": "^2.19.1", + "eslint-plugin-import": "^2.20.2", "eslint-plugin-jsx-a11y": "^6.2.3", "eslint-plugin-react": "^7.17.0", "eslint-plugin-react-hooks": "^1.7.0", diff --git a/server/src/services/feedbackService.py b/server/src/services/feedbackService.py index bc2ea727d..28e6b1630 100644 --- a/server/src/services/feedbackService.py +++ b/server/src/services/feedbackService.py @@ -43,18 +43,18 @@ async def create_issue(self, response = await session.post(self.issues_url, data=payload, headers=headers) + response.raise_for_status() response_content = loads(response.content) issue_id = response_content['id'] - response.raise_for_status() return issue_id except requests.exceptions.HTTPError as errh: - return "An Http Error occurred:" + repr(errh) + return errh except requests.exceptions.ConnectionError as errc: - return "An Error Connecting to the API occurred:" + repr(errc) + return errc except requests.exceptions.Timeout as errt: - return "A Timeout Error occurred:" + repr(errt) + return errt except requests.exceptions.RequestException as err: - return "An Unknown Error occurred" + repr(err) + return err async def add_issue_to_project(self, issue_id, content_type='Issue'): """ @@ -83,10 +83,10 @@ async def add_issue_to_project(self, issue_id, content_type='Issue'): response.raise_for_status() return response.status_code except requests.exceptions.HTTPError as errh: - return "An Http Error occurred:" + repr(errh) + return errh except requests.exceptions.ConnectionError as errc: - return "An Error Connecting to the API occurred:" + repr(errc) + return errc except requests.exceptions.Timeout as errt: - return "A Timeout Error occurred:" + repr(errt) + return errt except requests.exceptions.RequestException as err: - return "An Unknown Error occurred" + repr(err) + return err diff --git a/src/assets/contact_bg.png b/src/assets/contact_bg.png new file mode 100644 index 000000000..50775f7f8 Binary files /dev/null and b/src/assets/contact_bg.png differ diff --git a/src/components/Comparison/FrequencyComparison.jsx b/src/components/Comparison/FrequencyComparison.jsx index cbc397e66..d7a4724aa 100644 --- a/src/components/Comparison/FrequencyComparison.jsx +++ b/src/components/Comparison/FrequencyComparison.jsx @@ -2,19 +2,18 @@ import React from 'react'; import PropTypes from 'proptypes'; import { connect } from 'react-redux'; import moment from 'moment'; -import { DISTRICT_TYPES } from '@components/common/CONSTANTS'; +import { DISTRICT_TYPES, COMPARISON_SETS } from '@components/common/CONSTANTS'; import Chart from '@components/Chart'; import ChartExportSelect from '@components/export/ChartExportSelect'; const FrequencyComparison = ({ bins, - set1, - set2, + sets, }) => { /* /// DATA /// */ - const getDataSet = set => { - const { district, counts } = set; + const getDataSet = setId => { + const { district, counts } = sets[setId]; const totals = Array.from({ length: bins.length - 1 }).map((_, idx) => ( Object.keys(counts).reduce((acc, name) => ( @@ -22,8 +21,9 @@ const FrequencyComparison = ({ ), 0) )); - const color = DISTRICT_TYPES.find(t => t.id === district)?.color; - const label = DISTRICT_TYPES.find(t => t.id === district)?.name; + const { color, name: setName } = COMPARISON_SETS[setId]; + const label = DISTRICT_TYPES.find(t => t.id === district)?.name + .replace(' District', ` (${setName})`); return { data: totals, @@ -38,8 +38,8 @@ const FrequencyComparison = ({ const chartData = { labels: bins.slice(0, -1).map(bin => moment(bin).format('MMM D')), datasets: [ - getDataSet(set1), - getDataSet(set2), + getDataSet('set1'), + getDataSet('set2'), ], }; @@ -108,20 +108,24 @@ const FrequencyComparison = ({ const mapStateToProps = state => ({ bins: state.comparisonData.frequency.bins, - set1: state.comparisonData.frequency.set1, - set2: state.comparisonData.frequency.set2, + sets: { + set1: state.comparisonData.frequency.set1, + set2: state.comparisonData.frequency.set2, + }, }); export default connect(mapStateToProps)(FrequencyComparison); FrequencyComparison.propTypes = { bins: PropTypes.arrayOf(PropTypes.string).isRequired, - set1: PropTypes.shape({ - district: PropTypes.string, - counts: PropTypes.shape({}).isRequired, - }).isRequired, - set2: PropTypes.shape({ - district: PropTypes.string, - counts: PropTypes.shape({}).isRequired, + sets: PropTypes.shape({ + set1: PropTypes.shape({ + district: PropTypes.string, + counts: PropTypes.shape({}), + }), + set2: PropTypes.shape({ + district: PropTypes.string, + counts: PropTypes.shape({}), + }), }).isRequired, }; diff --git a/src/components/Comparison/TimeToCloseComparison.jsx b/src/components/Comparison/TimeToCloseComparison.jsx index 907e62078..d1c02e8b5 100644 --- a/src/components/Comparison/TimeToCloseComparison.jsx +++ b/src/components/Comparison/TimeToCloseComparison.jsx @@ -2,37 +2,33 @@ import React from 'react'; import PropTypes from 'proptypes'; import { connect } from 'react-redux'; import Chart, { ChartTooltip as Tooltip } from '@components/Chart'; -import { DISTRICT_TYPES, COUNCILS } from '@components/common/CONSTANTS'; +import { COUNCILS, COMPARISON_SETS } from '@components/common/CONSTANTS'; import ChartExportSelect from '@components/export/ChartExportSelect'; const TimeToCloseComparison = ({ - timeToClose: { set1, set2 }, + timeToClose, }) => { /* /// DATA /// */ - const boxColors = { - nc: DISTRICT_TYPES.find(t => t.id === 'nc')?.color, - cc: DISTRICT_TYPES.find(t => t.id === 'cc')?.color, - }; - const boxLabels = { nc: id => COUNCILS.find(c => parseInt(id, 10) === c.id).name, cc: name => `District ${name}`, }; - const getBoxes = ({ district, data }) => ( - Object.keys(data) + const getBoxes = setId => { + const { district, data } = timeToClose[setId]; + return Object.keys(data) .filter(name => data[name].count !== 0) .map(name => ({ label: boxLabels[district](name), - color: boxColors[district], + color: COMPARISON_SETS[setId].color, stats: { ...data[name], outliers: [] }, - })) - ); + })); + }; const boxes = [ - ...getBoxes(set1), - ...getBoxes(set2), + ...getBoxes('set1'), + ...getBoxes('set2'), ]; const chartData = { diff --git a/src/components/Comparison/TotalRequestsComparison.jsx b/src/components/Comparison/TotalRequestsComparison.jsx index 0c9a2b03f..e0f31f69e 100644 --- a/src/components/Comparison/TotalRequestsComparison.jsx +++ b/src/components/Comparison/TotalRequestsComparison.jsx @@ -2,19 +2,18 @@ import React from 'react'; import PropTypes from 'proptypes'; import { connect } from 'react-redux'; import moment from 'moment'; -import { DISTRICT_TYPES } from '@components/common/CONSTANTS'; +import { DISTRICT_TYPES, COMPARISON_SETS } from '@components/common/CONSTANTS'; import Chart from '@components/Chart'; import ChartExportSelect from '@components/export/ChartExportSelect'; const TotalRequestsComparison = ({ bins, - set1, - set2, + sets, }) => { /* /// DATA /// */ - const getDataSet = set => { - const { district, counts } = set; + const getDataSet = setId => { + const { district, counts } = sets[setId]; const totals = Array.from({ length: bins.length - 1 }).map((_, idx) => ( Object.keys(counts).reduce((acc, name) => ( @@ -22,8 +21,9 @@ const TotalRequestsComparison = ({ ), 0) )); - const color = DISTRICT_TYPES.find(t => t.id === district)?.color; - const label = DISTRICT_TYPES.find(t => t.id === district)?.name; + const { color, name: setName } = COMPARISON_SETS[setId]; + const label = DISTRICT_TYPES.find(t => t.id === district)?.name + .replace(' District', ` (${setName})`); return { data: totals, @@ -38,8 +38,8 @@ const TotalRequestsComparison = ({ const chartData = { labels: bins.slice(0, -1).map(bin => moment(bin).format('MMM D')), datasets: [ - getDataSet(set1), - getDataSet(set2), + getDataSet('set1'), + getDataSet('set2'), ], }; @@ -108,20 +108,24 @@ const TotalRequestsComparison = ({ const mapStateToProps = state => ({ bins: state.comparisonData.frequency.bins, - set1: state.comparisonData.frequency.set1, - set2: state.comparisonData.frequency.set2, + sets: { + set1: state.comparisonData.frequency.set1, + set2: state.comparisonData.frequency.set2, + }, }); export default connect(mapStateToProps)(TotalRequestsComparison); TotalRequestsComparison.propTypes = { bins: PropTypes.arrayOf(PropTypes.string).isRequired, - set1: PropTypes.shape({ - district: PropTypes.string, - counts: PropTypes.shape({}).isRequired, - }).isRequired, - set2: PropTypes.shape({ - district: PropTypes.string, - counts: PropTypes.shape({}).isRequired, + sets: PropTypes.shape({ + set1: PropTypes.shape({ + district: PropTypes.string, + counts: PropTypes.shape({}), + }), + set2: PropTypes.shape({ + district: PropTypes.string, + counts: PropTypes.shape({}), + }), }).isRequired, }; diff --git a/src/components/PinMap/PinMap.jsx b/src/components/PinMap/PinMap.jsx index db8296d9b..68ba20934 100644 --- a/src/components/PinMap/PinMap.jsx +++ b/src/components/PinMap/PinMap.jsx @@ -296,6 +296,17 @@ class PinMap extends Component { if (link) link.click(); }} /> +